import React, { useState } from 'react'; import type { Meta, StoryObj } from '@storybook/react-vite'; import { Strong } from '../../Typography/Strong/Strong'; import { Text } from '../../Typography/Text/Text'; import citiesFixture from './fixtures/cities.json'; import fruitsFixture from './fixtures/fruits.json'; import type { SingleSelectFieldProps } from './SingleSelectField'; import { SingleSelectField } from './SingleSelectField'; const { Option } = SingleSelectField; const meta: Meta = { title: 'UI kit/Form/SingleSelectField', component: SingleSelectField, tags: ['autodocs'], }; export default meta; type Story = StoryObj; type CityOption = { id: string; name: string; country: string; }; const cityOptions: Array = citiesFixture; function getCityTextValue(option: CityOption) { return `${option.name}, ${option.country}`; } function getCityOption(query: string | null) { if (query === null || !query.trim()) { return cityOptions; } return cityOptions.filter(option => getCityTextValue(option).toLowerCase().includes(query.toLowerCase())); } const getOptionId = (option: { id: string }) => option.id; const renderOption: SingleSelectFieldProps['renderOption'] = ( option: CityOption, { screenSize: layoutSize } ) => layoutSize === 'large' ? ( ) : ( ); function ControlledStory(args: Story['args']) { const [query, setQuery] = useState(null); const [value, setValue] = useState(null); return ( {...(args as SingleSelectFieldProps)} name='selectCity' options={getCityOption(query)} value={value} getOptionValue={getOptionId} getOptionLabel={getCityTextValue} renderOption={renderOption} onChange={setValue} onQueryChange={value => setQuery(value)} /> ); } function UncontrolledStory(args: Story['args']) { return ( {...(args as SingleSelectFieldProps)} getOptionValue={getOptionId} getOptionLabel={getCityTextValue} renderOption={renderOption} onChange={undefined} /> ); } export const Default: Story = { args: { label: 'Select city:', placeholder: 'Choose value...', }, render: ControlledStory, }; export const Uncontrolled: Story = { args: { label: 'Select city:', placeholder: 'Choose value...', options: cityOptions, }, render: UncontrolledStory, }; export const UncontrolledEmptyOptions: Story = { args: { label: 'Select city:', placeholder: 'Choose value...', options: [], }, render: UncontrolledStory, }; export const WithoutIcon: Story = { args: { label: 'Select city:', placeholder: 'Search...', icon: false, }, render: ControlledStory, }; WithoutIcon.storyName = 'Without icon'; export const SimpleFruitsSelect: Story = { args: { label: 'Search fruit:', placeholder: 'Choose value...', }, render: ControlledStory, }; type FruitOption = { id: string; name: string; }; const fruitOptions: Array = fruitsFixture; function getFruitTextValue(option: FruitOption) { return option.name; } function getFruitOption(query: string | null) { if (query === null || !query.trim()) { return fruitOptions; } return fruitOptions.filter(option => getFruitTextValue(option).toLowerCase().includes(query.toLowerCase())); } const renderSimpleFruitOption = (option: FruitOption) => ; function SimpleFruitsSelectStory(args: Story['args']) { const [query, setQuery] = useState(null); const [value, setValue] = useState(null); return ( {...(args as SingleSelectFieldProps)} options={getFruitOption(query)} value={value} getOptionValue={getOptionId} getOptionLabel={getFruitTextValue} renderOption={renderSimpleFruitOption} onChange={setValue} onQueryChange={event => setQuery(event)} /> ); } export const SimpleSelect: Story = { args: { label: 'Select fruit:', placeholder: 'Choose value...', }, render: SimpleFruitsSelectStory, }; const nestedOptions = [ { value: 'all', label: 'Flora', }, { label: 'Fruits', options: [ { value: 'apple', label: 'Apple' }, { value: 'banana', label: 'Banana' }, { value: 'orange', label: 'Orange' }, ], }, { label: 'Vegetables', options: [ { value: 'carrot', label: 'Carrot' }, { value: 'cucumber', label: 'Cucumber' }, { value: 'tomato', label: 'Tomato' }, ], }, ]; type NestedStory = StoryObj>; const UncontrolledNestedStory = (args: NestedStory['args']) => { return ( option.value ?? option.label} getOptionLabel={option => option.label} getGroupOptions={option => option.options} renderOption={option => } /> ); }; export const NestedSelect: NestedStory = { args: { label: 'Select city:', placeholder: 'Choose value...', }, render: UncontrolledNestedStory, }; type ValueNumberStory = StoryObj>; const valueNumberOptions = [ { value: 1, label: 'One' }, { value: 2, label: 'Two' }, { value: 3, label: 'Three' }, ]; const UncontrolledValueNumberStory = (args: ValueNumberStory['args']) => { return ( option.value} getOptionLabel={option => option.label} renderOption={option => } /> ); }; export const ValueNumber: ValueNumberStory = { args: { label: 'Select item:', placeholder: 'Choose value...', }, render: UncontrolledValueNumberStory, }; const ControlledValueNumberStory = (args: ValueNumberStory['args']) => { const [value, setValue] = useState(null); return ( option.value} getOptionLabel={option => option.label} renderOption={option => } onChange={setValue} /> ); }; export const ControlledValueNumber = { args: { label: 'Select item:', placeholder: 'Choose value...', }, render: ControlledValueNumberStory, }; type FruitType = 'apple' | 'banana' | 'orange'; type Fruit = { value: FruitType; label: string; }; const valueStringUnionOptions: Fruit[] = [ { value: 'apple', label: 'Apple' }, { value: 'banana', label: 'Banana' }, { value: 'orange', label: 'Orange' }, ]; type ValueStringUnionStory = StoryObj>; const UncontrolledValueStringUnionStory = (args: ValueStringUnionStory['args']) => { return ( option.value} getOptionLabel={option => option.label} renderOption={option => } /> ); }; export const ValueStringUnion: ValueStringUnionStory = { args: { label: 'Select item:', placeholder: 'Choose value...', onChange: value => { // Value is of type FruitType console.log('Selected value:', value); }, }, render: UncontrolledValueStringUnionStory, }; export const NullableOption: Story = { args: { label: 'Select fruit:', placeholder: 'Choose value...', nullable: true, }, render: SimpleFruitsSelectStory, };