Forms migration: Old Select to Legacy namespace (#23200)

* Export other components as Legacy

* More Select Legacy

* Add namespacing to more files

* Export new elements

* Move Legacy Select folder

* Let's not forget the scss file

* Move new Select folder

* Move new Select from Forms namespace

* Little oopsie

* Fix errors

* Fix merge issues
This commit is contained in:
Tobias Skarhed
2020-04-02 10:57:35 +02:00
committed by GitHub
parent 15bff3114f
commit b34281e250
97 changed files with 1118 additions and 1066 deletions

View File

@ -1,101 +1,300 @@
import React, { useState, useCallback } from 'react';
import { action } from '@storybook/addon-actions';
import { withKnobs, object } from '@storybook/addon-knobs';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { UseState } from '../../utils/storybook/UseState';
import React, { useState } from 'react';
import { Select, AsyncSelect, MultiSelect, AsyncMultiSelect } from './Select';
import { withCenteredStory, withHorizontallyCenteredStory } from '../../utils/storybook/withCenteredStory';
import { SelectableValue } from '@grafana/data';
import { Select, AsyncSelect } from './Select';
import { getAvailableIcons, IconType } from '../Icon/types';
import { select, boolean } from '@storybook/addon-knobs';
import { Icon } from '../Icon/Icon';
import { Button } from '../Button';
import { ButtonSelect } from './ButtonSelect';
import { getIconKnob } from '../../utils/storybook/knobs';
import kebabCase from 'lodash/kebabCase';
import { generateOptions } from './mockOptions';
export default {
title: 'General/Select/Select',
title: 'Forms/Select',
component: Select,
decorators: [withCenteredStory, withKnobs],
decorators: [withCenteredStory, withHorizontallyCenteredStory],
};
const intialState: SelectableValue<string> = { label: 'A label', value: 'A value' };
const loadAsyncOptions = () => {
return new Promise<Array<SelectableValue<string>>>(resolve => {
setTimeout(() => {
resolve(generateOptions());
}, 2000);
});
};
const options = object<Array<SelectableValue<string>>>('Options:', [
intialState,
{ label: 'Another label', value: 'Another value 1' },
{ label: 'Another label', value: 'Another value 2' },
{ label: 'Another label', value: 'Another value 3' },
{ label: 'Another label', value: 'Another value 4' },
{ label: 'Another label', value: 'Another value 5' },
{ label: 'Another label', value: 'Another value ' },
]);
const getKnobs = () => {
const BEHAVIOUR_GROUP = 'Behaviour props';
const disabled = boolean('Disabled', false, BEHAVIOUR_GROUP);
const invalid = boolean('Invalid', false, BEHAVIOUR_GROUP);
const loading = boolean('Loading', false, BEHAVIOUR_GROUP);
const prefixSuffixOpts = {
None: null,
Text: '$',
...getAvailableIcons().reduce<Record<string, string>>((prev, c) => {
return {
...prev,
[`Icon: ${c}`]: `icon-${c}`,
};
}, {}),
};
const VISUAL_GROUP = 'Visual options';
// ---
const prefix = select('Prefix', prefixSuffixOpts, null, VISUAL_GROUP);
let prefixEl: any = prefix;
if (prefix && prefix.match(/icon-/g)) {
prefixEl = <Icon name={prefix.replace(/icon-/g, '') as IconType} />;
}
return {
disabled,
invalid,
loading,
prefixEl,
};
};
const getDynamicProps = () => {
const knobs = getKnobs();
return {
disabled: knobs.disabled,
isLoading: knobs.loading,
invalid: knobs.invalid,
prefix: knobs.prefixEl,
};
};
export const basic = () => {
const value = object<SelectableValue<string>>('Selected Value:', intialState);
const [value, setValue] = useState<SelectableValue<string>>();
return (
<UseState initialState={value}>
{(value, updateValue) => {
return (
<Select
placeholder="Choose..."
options={options}
width={20}
onChange={value => {
action('onChanged fired')(value);
updateValue(value);
}}
/>
);
}}
</UseState>
<>
<Select
options={generateOptions()}
value={value}
onChange={v => {
setValue(v);
}}
size="md"
{...getDynamicProps()}
/>
</>
);
};
export const withAllowCustomValue = () => {
// @ts-ignore
const value = object<SelectableValue<string>>('Selected Value:', null);
/**
* Uses plain values instead of SelectableValue<T>
*/
export const basicSelectPlainValue = () => {
const [value, setValue] = useState<string>();
return (
<UseState initialState={value}>
{(value, updateValue) => {
return (
<Select
// value={value}
placeholder="Choose..."
options={options}
width={20}
allowCustomValue={true}
onChange={value => {
action('onChanged fired')(value);
updateValue(value);
}}
/>
);
}}
</UseState>
<>
<Select
options={generateOptions()}
value={value}
onChange={v => {
setValue(v.value);
}}
size="md"
{...getDynamicProps()}
/>
</>
);
};
export const asyncSelect = () => {
const [isLoading, setIsLoading] = useState<boolean>(true);
const [value, setValue] = useState();
const loadAsyncOptions = useCallback(
inputValue => {
return new Promise<Array<SelectableValue<string>>>(resolve => {
setTimeout(() => {
setIsLoading(false);
resolve(options.filter(option => option.label && option.label.includes(inputValue)));
}, 1000);
});
/**
* Uses plain values instead of SelectableValue<T>
*/
export const SelectWithOptionDescriptions = () => {
// TODO this is not working with new Select
const [value, setValue] = useState<number>();
const options = [
{ label: 'Basic option', value: 0 },
{ label: 'Option with description', value: 1, description: 'this is a description' },
{
label: 'Option with description and image',
value: 2,
description: 'This is a very elaborate description, describing all the wonders in the world.',
imgUrl: 'https://placekitten.com/40/40',
},
[value]
);
];
return (
<AsyncSelect
value={value}
defaultOptions
width={20}
isLoading={isLoading}
<>
<Select
options={options}
value={value}
onChange={v => {
setValue(v.value);
}}
size="md"
{...getDynamicProps()}
/>
</>
);
};
/**
* Uses plain values instead of SelectableValue<T>
*/
export const multiPlainValue = () => {
const [value, setValue] = useState<string[]>();
return (
<>
<MultiSelect
options={generateOptions()}
value={value}
onChange={v => {
setValue(v.map((v: any) => v.value));
}}
size="md"
{...getDynamicProps()}
/>
</>
);
};
export const multiSelect = () => {
const [value, setValue] = useState<Array<SelectableValue<string>>>([]);
return (
<>
<MultiSelect
options={generateOptions()}
value={value}
onChange={v => {
setValue(v);
}}
size="md"
{...getDynamicProps()}
/>
</>
);
};
export const multiSelectAsync = () => {
const [value, setValue] = useState<Array<SelectableValue<string>>>();
return (
<AsyncMultiSelect
loadOptions={loadAsyncOptions}
onChange={value => {
action('onChange')(value);
setValue(value);
defaultOptions
value={value}
onChange={v => {
setValue(v);
}}
size="md"
allowCustomValue
{...getDynamicProps()}
/>
);
};
export const buttonSelect = () => {
const [value, setValue] = useState<SelectableValue<string>>();
const icon = getIconKnob();
return (
<ButtonSelect
placeholder="Select all the things..."
value={value}
options={generateOptions()}
onChange={v => {
setValue(v);
}}
size="md"
allowCustomValue
icon={icon}
{...getDynamicProps()}
/>
);
};
export const basicSelectAsync = () => {
const [value, setValue] = useState<SelectableValue<string>>();
return (
<AsyncSelect
loadOptions={loadAsyncOptions}
defaultOptions
value={value}
onChange={v => {
setValue(v);
}}
size="md"
{...getDynamicProps()}
/>
);
};
export const customizedControl = () => {
const [value, setValue] = useState<SelectableValue<string>>();
return (
<Select
options={generateOptions()}
value={value}
onChange={v => {
setValue(v);
}}
size="md"
renderControl={React.forwardRef(({ isOpen, value, ...otherProps }, ref) => {
return (
<Button {...otherProps} ref={ref}>
{' '}
{isOpen ? 'Open' : 'Closed'}
</Button>
);
})}
{...getDynamicProps()}
/>
);
};
export const autoMenuPlacement = () => {
const [value, setValue] = useState<SelectableValue<string>>();
return (
<>
<div style={{ height: '95vh', display: 'flex', alignItems: 'flex-end' }}>
<Select
options={generateOptions()}
value={value}
onChange={v => {
setValue(v);
}}
size="md"
{...getDynamicProps()}
/>
</div>
</>
);
};
export const customValueCreation = () => {
const [value, setValue] = useState<SelectableValue<string>>();
const [customOptions, setCustomOptions] = useState<Array<SelectableValue<string>>>([]);
const options = generateOptions();
return (
<>
<Select
options={[...options, ...customOptions]}
value={value}
onChange={v => {
setValue(v);
}}
size="md"
allowCustomValue
onCreateOption={v => {
const customValue: SelectableValue<string> = { value: kebabCase(v), label: v };
setCustomOptions([...customOptions, customValue]);
setValue(customValue);
}}
{...getDynamicProps()}
/>
</>
);
};