Skip to content

Commit

Permalink
feat(ChipsSelect): add prop sortFn
Browse files Browse the repository at this point in the history
  • Loading branch information
EldarMuhamethanov committed Dec 23, 2024
1 parent c059b04 commit d5939d6
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 2 deletions.
32 changes: 32 additions & 0 deletions packages/vkui/src/components/ChipsSelect/ChipsSelect.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,38 @@ describe('ChipsSelect', () => {
expect(within(dropdownLocator).getByRole('option', { name: 'Синий' })).toBeTruthy();
});

it('should sort options by sortFn prop', async () => {
type Option = { label: string; value: number };
const options: Option[] = [
{ label: '1', value: 1 },
{ label: '3', value: 3 },
{ label: '2', value: 2 },
];
const byAsc = (a: Option, b: Option) => a.label.localeCompare(b.label);
const byDesc = (a: Option, b: Option) => b.label.localeCompare(a.label);

const checkOptionsOrder = async (order: string[]) => {
await userEvent.click(screen.getByRole('combobox'));
const dropdownLocator = screen.getByTestId('dropdown');
const optionsValues = within(dropdownLocator)
.getAllByRole('option')
.map((element) => element.textContent);
expect(optionsValues).toEqual(order);
};

// Сортируем по возрастанию
const { rerender } = render(
<ChipsSelect options={options} defaultValue={[]} sortFn={byAsc} dropdownTestId="dropdown" />,
);
await checkOptionsOrder(['1', '2', '3']);

// Сортируем по убыванию
rerender(
<ChipsSelect options={options} defaultValue={[]} sortFn={byDesc} dropdownTestId="dropdown" />,
);
await checkOptionsOrder(['3', '2', '1']);
});

it('shows spinner if fetching', async () => {
const result = render(<ChipsSelect fetching defaultValue={[]} dropdownTestId="dropdown" />);
await userEvent.click(result.getByRole('combobox'));
Expand Down
2 changes: 2 additions & 0 deletions packages/vkui/src/components/ChipsSelect/ChipsSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export const ChipsSelect = <Option extends ChipOption>({
forceDropdownPortal,
noMaxHeight = false,
filterFn = defaultFilterFn,
sortFn = false,
dropdownTestId,
onClose,
onOpen,
Expand Down Expand Up @@ -231,6 +232,7 @@ export const ChipsSelect = <Option extends ChipOption>({
emptyText,
creatable,
filterFn,
sortFn,
selectedBehavior,
onClose,
onOpen,
Expand Down
17 changes: 15 additions & 2 deletions packages/vkui/src/components/ChipsSelect/useChipsSelect.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { isEqual } from '@vkontakte/vkjs';
import { type SimulateReactInputTargetState } from '../../lib/react';
import { defaultFilterFn, type FilterFn } from '../../lib/select';
import { defaultFilterFn, type FilterFn, type SortFn } from '../../lib/select';
import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';
import {
transformValue,
Expand Down Expand Up @@ -39,6 +39,7 @@ export interface UseChipsSelectProps<O extends ChipOption = ChipOption>
*/
selectedBehavior?: 'hide' | 'highlight';
filterFn?: false | FilterFn<O>;
sortFn?: false | SortFn<O>;
/**
* Будет вызвано в момент скрытия выпадающего списка
*/
Expand Down Expand Up @@ -70,6 +71,7 @@ export const useChipsSelect = <O extends ChipOption>({
creatable = false,
emptyText = DEFAULT_EMPTY_TEXT,
filterFn = defaultFilterFn,
sortFn = false,

Check warning on line 74 in packages/vkui/src/components/ChipsSelect/useChipsSelect.ts

View check run for this annotation

Codecov / codecov/patch

packages/vkui/src/components/ChipsSelect/useChipsSelect.ts#L74

Added line #L74 was not covered by tests
selectedBehavior = DEFAULT_SELECTED_BEHAVIOR,
options: optionsProp = DEFAULT_VALUE,
onClose,
Expand Down Expand Up @@ -130,6 +132,7 @@ export const useChipsSelect = <O extends ChipOption>({
emptyText,
creatable,
filterFn,
sortFn,
options: optionsProp,
selectedBehavior,
})
Expand Down Expand Up @@ -173,6 +176,7 @@ export const useChipsSelect = <O extends ChipOption>({
emptyText,
creatable,
filterFn,
sortFn,
options: optionsProp,
selectedBehavior,
});
Expand All @@ -194,6 +198,7 @@ export const useChipsSelect = <O extends ChipOption>({
creatable,
selectedBehavior,
filterFn,
sortFn,
],
);

Expand Down Expand Up @@ -225,6 +230,7 @@ function transformOptions<O extends ChipOption>({
inputValue = DEFAULT_INPUT_VALUE,
emptyText = DEFAULT_EMPTY_TEXT,
creatable = false,
sortFn = false,

Check warning on line 233 in packages/vkui/src/components/ChipsSelect/useChipsSelect.ts

View check run for this annotation

Codecov / codecov/patch

packages/vkui/src/components/ChipsSelect/useChipsSelect.ts#L233

Added line #L233 was not covered by tests
filterFn = defaultFilterFn,
options: optionsProp = DEFAULT_VALUE,
selectedBehavior = DEFAULT_SELECTED_BEHAVIOR,
Expand All @@ -237,6 +243,7 @@ function transformOptions<O extends ChipOption>({
| 'emptyText'
| 'creatable'
| 'filterFn'
| 'sortFn'
| 'options'
| 'selectedBehavior'
>) {
Expand All @@ -251,7 +258,13 @@ function transformOptions<O extends ChipOption>({
return [{ placeholder: emptyText }];
}

const parsedOptions = transformValue(filteredOptionsProp, getOptionValue, getOptionLabel);
const sortedOptions = sortFn
? [...filteredOptionsProp].sort((optionA, optionB) => {
return sortFn(optionA, optionB, inputValue);
})
: filteredOptionsProp;

const parsedOptions = transformValue(sortedOptions, getOptionValue, getOptionLabel);

if (selectedBehavior === 'hide') {
const selected = value.map((item) => item.value);
Expand Down
2 changes: 2 additions & 0 deletions packages/vkui/src/lib/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export type FilterFn<O extends Option> = (
getOptionsLabel?: GetOptionLabel<O>,
) => boolean;

export type SortFn<O extends Option> = (optionA: O, optionB: O, inputValue: string) => number;

function getOptionLabelDefault<O extends Option>(option: O): O['label'] {
return option.label;
}
Expand Down

0 comments on commit d5939d6

Please sign in to comment.