Skip to content

Commit

Permalink
chore: add usage example
Browse files Browse the repository at this point in the history
  • Loading branch information
korvin89 committed Feb 15, 2024
1 parent 27ab00f commit 3e7b7a0
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 20 deletions.
24 changes: 5 additions & 19 deletions src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import {
activateFirstClickableItem,
findItemIndexByQuickSearch,
getActiveItem,
// getFilteredFlattenOptions,
// getFlattenOptions,
getListItems,
getOptionsFromChildren,
getSelectedOptionsContent,
Expand Down Expand Up @@ -113,7 +111,10 @@ export const Select = React.forwardRef<HTMLButtonElement, SelectProps>(function
onOpenChange?.(open);

if (!open && filterable) {
handleFilterChange('');
// FIXME: rework after https://github.com/gravity-ui/uikit/issues/1354
setTimeout(() => {
handleFilterChange('');
}, 100);
}
},
[filterable, onOpenChange, handleFilterChange],
Expand All @@ -139,7 +140,6 @@ export const Select = React.forwardRef<HTMLButtonElement, SelectProps>(function
});
const uniqId = useUniqId();
const selectId = id ?? uniqId;
// const options = props.options || getOptionsFromChildren(props.children);
const propsOptions = React.useMemo(() => {
return props.options || getOptionsFromChildren(props.children);
}, [props.options, props.children]);
Expand All @@ -149,21 +149,7 @@ export const Select = React.forwardRef<HTMLButtonElement, SelectProps>(function
filterable,
filterOption,
});
// const flattenOptions = getFlattenOptions(options);
// const filteredFlattenOptions = filterable
// ? getFilteredFlattenOptions({
// options: flattenOptions,
// filter,
// filterOption,
// })
// : flattenOptions;
const selectedOptionsContent = getSelectedOptionsContent(
// flattenOptions,
options,
value,
renderSelectedOption,
);
// const virtualized = filteredFlattenOptions.length >= virtualizationThreshold;
const selectedOptionsContent = getSelectedOptionsContent(options, value, renderSelectedOption);
const virtualized = filteredOptions.length >= virtualizationThreshold;

const {errorMessage, errorPlacement, validationState} = errorPropsMapper({
Expand Down
5 changes: 5 additions & 0 deletions src/components/Select/__stories__/Select.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {SelectProps} from '..';

import {SelectPopupWidthShowcase} from './SelectPopupWidthShowcase';
import {SelectShowcase} from './SelectShowcase';
import {UseSelectOptionsShowcase} from './UseSelectOptionsShowcase';

export default {
title: 'Components/Inputs/Select',
Expand All @@ -25,9 +26,13 @@ const ShowcaseTemplate: StoryFn<SelectProps> = (args: SelectProps) => <SelectSho
const SelectPopupWidthShowcaseTemplate: StoryFn<SelectProps> = (args) => (
<SelectPopupWidthShowcase {...args} />
);
const UseSelectOptionsShowcaseTemplate = () => {
return <UseSelectOptionsShowcase />;
};
export const Default = DefaultTemplate.bind({});
export const Showcase = ShowcaseTemplate.bind({});
export const PopupWidth = SelectPopupWidthShowcaseTemplate.bind({});
export const UseSelectOptions = UseSelectOptionsShowcaseTemplate.bind({});

Showcase.args = {
view: 'normal',
Expand Down
113 changes: 113 additions & 0 deletions src/components/Select/__stories__/UseSelectOptionsShowcase.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import React from 'react';

import {Button} from '../../Button';
import {TextInput} from '../../controls';
import {Select, useSelectOptions} from '../index';
import type {SelectOption, SelectProps} from '../index';

export const UseSelectOptionsShowcase = () => {
const [value, setValue] = React.useState<string[]>([]);
const [filter, setFilter] = React.useState('');
const filterable = true;
const {options, filteredOptions} = useSelectOptions({
options: [
{
label: 'Group 1',
options: [
{value: 'val1', content: 'Value 1'},
{value: 'val2', content: 'Value 2'},
{value: 'val3', content: 'Value 3'},
{value: 'val4', content: 'Value 4'},
],
},
{
label: 'Group 2',
options: [
{value: 'val5', content: 'Value 5'},
{value: 'val6', content: 'Value 6'},
{value: 'val7', content: 'Value 7'},
{value: 'val8', content: 'Value 8'},
],
},
],
filter,
filterable,
});

const renderFilter: SelectProps['renderFilter'] = ({
value: filterValue,
ref,
onChange,
onKeyDown,
}) => {
const optionsWithoutGroupLabels = options.filter(
(option) => !('label' in option),
) as SelectOption[];
const filteredOptionsWithoutGroupLabels = filteredOptions.filter(
(option) => !('label' in option),
) as SelectOption[];
const allOptionsSelected = Boolean(
value.length && optionsWithoutGroupLabels.length === value.length,
);
const allVisibleOptionsSelected = Boolean(
value.length &&
filteredOptionsWithoutGroupLabels
.map((o) => o.value)
.every((o) => value.includes(o)),
);

const handleAllOptionsButtonClick = () => {
const nextValue = allOptionsSelected
? []
: optionsWithoutGroupLabels.map((option) => option.value);
setValue(nextValue);
};

const handleAllVisibleOptionsButtonClick = () => {
const nextValue = allVisibleOptionsSelected
? []
: filteredOptionsWithoutGroupLabels.map((option) => option.value);
setValue(nextValue);
};

return (
<div
style={{
display: 'flex',
flexDirection: 'column',
rowGap: 4,
padding: '4px 4px 0 4px',
}}
>
<TextInput
controlRef={ref}
controlProps={{size: 1}}
value={filterValue}
onUpdate={onChange}
onKeyDown={onKeyDown}
/>
<Button
disabled={!filteredOptionsWithoutGroupLabels.length}
onClick={handleAllVisibleOptionsButtonClick}
>
{allVisibleOptionsSelected ? 'Deselect all visible' : 'Select all visible'}
</Button>
<Button onClick={handleAllOptionsButtonClick}>
{allOptionsSelected ? 'Deselect all' : 'Select all'}
</Button>
</div>
);
};

return (
<Select
value={value}
options={options}
filterable={filterable}
multiple={true}
renderFilter={renderFilter}
onFilterChange={setFilter}
onUpdate={setValue}
/>
);
};
1 change: 1 addition & 0 deletions src/components/Select/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './Select';
export * from './types';
export {SelectQa} from './constants';
export * from './hooks-public';
3 changes: 2 additions & 1 deletion src/components/Select/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {InputControlPin, InputControlSize, InputControlView} from '../contr
import type {ControlGroupOption, ControlGroupProps, QAProps} from '../types';

import type {Option, OptionGroup} from './tech-components';
import type {FlattenOption} from './utils';

export type SelectRenderClearArgs = {
renderIcon?: () => React.ReactNode;
Expand Down Expand Up @@ -87,7 +88,7 @@ export type SelectProps<T = any> = QAProps &
filterPlaceholder?: string;
value?: string[];
defaultValue?: string[];
options?: (SelectOption<T> | SelectOptionGroup<T>)[];
options?: (SelectOption<T> | SelectOptionGroup<T> | FlattenOption)[];
/**
* @deprecated Prop `error` has a lower priority than `errorMessage`. Use `errorMessage` instead
*/
Expand Down

0 comments on commit 3e7b7a0

Please sign in to comment.