import { map, isNil, escapeRegExp } from 'lodash'; import React, { useState } from 'react'; import { Meta } from '@storybook/react'; import SearchableSelect from './SearchableSelect'; import Underline from '../Underline/Underline'; //πŸ‘‡ Provide Storybook with the component name, 'section', any subcomponents and a description export default { title: 'Controls/SearchableSelect', component: SearchableSelect, subcomponents: { 'SearchableSelect.Placeholder': SearchableSelect.Placeholder, 'SearchableSelect.Option': SearchableSelect.Option, 'SearchableSelect.Option.Selected': SearchableSelect.Option.Selected, 'SearchableSelect.OptionGroup': SearchableSelect.OptionGroup, 'SearchableSelect.SearchField': SearchableSelect.SearchField, 'SearchableSelect.NullOption': SearchableSelect.NullOption, 'SearchableSelect.FixedOption': SearchableSelect.FixedOption, }, parameters: { docs: { description: { component: SearchableSelect.peek.description, }, }, }, } as Meta; //πŸ‘‡ Destructure any child components that we will need const { Option, OptionGroup, SearchField } = SearchableSelect; //πŸ‘‡ Add a key prop to each element of the array function addKeys(children: any) { return map(children, (child, index) => ({ ...child, key: index })); } //πŸ‘‡ Create a β€œtemplate” of how args map to rendering const Template: any = (args) => { const [selectedIndex, setSelectedIndex] = useState(null); const handleSelect = (optionIndex: number | null) => { setSelectedIndex(optionIndex); }; return (
{!isNil(selectedIndex) && (
Selected Index: {JSON.stringify(selectedIndex)}
)}
); }; //πŸ‘‡ Each story then reuses that template /** Basic */ export const Basic = Template.bind({}); Basic.args = { Placeholder: 'Select State', maxMenuHeight: '200', children: addKeys([ , , PST , MST , CST , EST , ]), }; /** Loading */ export const Loading = Template.bind({}); Loading.args = { ...Basic.args, isLoading: true, children: addKeys([ , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ]), }; /** Custom Search Placeholder */ export const CustomSearchPlaceholder = Template.bind({}); CustomSearchPlaceholder.args = { ...Basic.args, Placeholder: 'Select Color', children: addKeys([ , , , , , ]), }; /** Invisible */ export const Invisible = Template.bind({}); Invisible.args = { ...Basic.args, isInvisible: true, }; /** Formatted Options */ const OptionCols = ({ col1, col2, textMatch, }: { col1: string; col2: string; textMatch?: string | undefined; }) => (
{col1}
{col2}
); const optionFilter = ( searchText: string, { filterText }: { filterText: string } ) => { if (filterText) { return new RegExp(escapeRegExp(searchText), 'i').test(filterText); } return true; }; export const FormattedOptions = Template.bind({}); FormattedOptions.args = { ...Basic.args, Placeholder: 'Select Color', optionFilter: optionFilter, children: addKeys([ , ]), }; FormattedOptions.parameters = { docs: { description: { story: `Use multiple columns of data in your dropdown when additional information is needed to make a selection. `, }, }, }; /** Invalid */ export const Invalid: any = (args) => { const [selectedIndex, setSelectedIndex] = useState(null); const handleSelect = (optionIndex: number | null) => { setSelectedIndex(optionIndex); }; return (
{!isNil(selectedIndex) && (
Selected Index: {JSON.stringify(selectedIndex)}
)}
); }; Invalid.args = { ...Basic.args, };