@snack-uikit/chips 0.12.9 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +71 -20
  3. package/dist/components/ChipAssist/ChipAssist.js +1 -1
  4. package/dist/components/ChipAssist/styles.module.css +1 -1
  5. package/dist/components/ChipChoice/components/ChipChoiceBase/ChipChoiceBase.d.ts +20 -0
  6. package/dist/components/ChipChoice/components/ChipChoiceBase/ChipChoiceBase.js +65 -0
  7. package/dist/components/ChipChoice/components/ChipChoiceBase/index.d.ts +1 -0
  8. package/dist/components/ChipChoice/components/ChipChoiceBase/index.js +1 -0
  9. package/dist/components/ChipChoice/components/{ChipChoiceCustom → ChipChoiceBase}/styles.module.css +18 -10
  10. package/dist/components/ChipChoice/components/ChipChoiceCustom.d.ts +25 -0
  11. package/dist/components/ChipChoice/components/ChipChoiceCustom.js +38 -0
  12. package/dist/components/ChipChoice/components/ChipChoiceDate.d.ts +3 -2
  13. package/dist/components/ChipChoice/components/ChipChoiceDate.js +19 -9
  14. package/dist/components/ChipChoice/components/ChipChoiceDateRange.d.ts +3 -2
  15. package/dist/components/ChipChoice/components/ChipChoiceDateRange.js +18 -8
  16. package/dist/components/ChipChoice/components/ChipChoiceMultiple.d.ts +8 -0
  17. package/dist/components/ChipChoice/components/ChipChoiceMultiple.js +88 -0
  18. package/dist/components/ChipChoice/components/ChipChoiceSingle.d.ts +7 -13
  19. package/dist/components/ChipChoice/components/ChipChoiceSingle.js +64 -22
  20. package/dist/components/ChipChoice/components/index.d.ts +1 -1
  21. package/dist/components/ChipChoice/components/index.js +1 -1
  22. package/dist/components/ChipChoice/constants.d.ts +3 -2
  23. package/dist/components/ChipChoice/constants.js +2 -1
  24. package/dist/components/ChipChoice/hooks.d.ts +11 -0
  25. package/dist/components/ChipChoice/hooks.js +35 -0
  26. package/dist/components/ChipChoice/index.d.ts +5 -4
  27. package/dist/components/ChipChoice/index.js +3 -2
  28. package/dist/components/ChipChoice/styles.module.css +9 -5
  29. package/dist/components/ChipChoice/types.d.ts +55 -7
  30. package/dist/components/ChipChoice/utils/index.d.ts +2 -0
  31. package/dist/components/ChipChoice/utils/index.js +2 -0
  32. package/dist/components/ChipChoice/utils/options.d.ts +9 -0
  33. package/dist/components/ChipChoice/utils/options.js +32 -0
  34. package/dist/components/ChipChoice/utils/typeGuards.d.ts +6 -0
  35. package/dist/components/ChipChoice/utils/typeGuards.js +15 -0
  36. package/dist/components/ChipChoice/utils/utils.d.ts +18 -0
  37. package/dist/components/ChipChoice/utils/utils.js +29 -0
  38. package/dist/components/ChipChoiceRow/components/constants.d.ts +2 -1
  39. package/dist/components/ChipChoiceRow/components/constants.js +2 -1
  40. package/dist/components/ChipChoiceRow/types.d.ts +11 -5
  41. package/dist/components/ChipToggle/styles.module.css +1 -1
  42. package/package.json +13 -7
  43. package/src/components/ChipAssist/ChipAssist.tsx +1 -0
  44. package/src/components/ChipChoice/components/ChipChoiceBase/ChipChoiceBase.tsx +149 -0
  45. package/src/components/ChipChoice/components/ChipChoiceBase/index.ts +1 -0
  46. package/src/components/ChipChoice/components/{ChipChoiceCustom → ChipChoiceBase}/styles.module.scss +11 -5
  47. package/src/components/ChipChoice/components/ChipChoiceCustom.tsx +89 -0
  48. package/src/components/ChipChoice/components/ChipChoiceDate.tsx +42 -18
  49. package/src/components/ChipChoice/components/ChipChoiceDateRange.tsx +43 -18
  50. package/src/components/ChipChoice/components/ChipChoiceMultiple.tsx +157 -0
  51. package/src/components/ChipChoice/components/ChipChoiceSingle.tsx +123 -62
  52. package/src/components/ChipChoice/components/index.ts +1 -1
  53. package/src/components/ChipChoice/constants.ts +3 -2
  54. package/src/components/ChipChoice/hooks.ts +61 -0
  55. package/src/components/ChipChoice/index.ts +7 -13
  56. package/src/components/ChipChoice/styles.module.scss +11 -5
  57. package/src/components/ChipChoice/types.ts +105 -7
  58. package/src/components/ChipChoice/utils/index.ts +3 -0
  59. package/src/components/ChipChoice/utils/options.tsx +58 -0
  60. package/src/components/ChipChoice/utils/typeGuards.ts +35 -0
  61. package/src/components/ChipChoice/utils/utils.ts +60 -0
  62. package/src/components/ChipChoiceRow/components/constants.ts +2 -1
  63. package/src/components/ChipChoiceRow/types.ts +18 -10
  64. package/dist/components/ChipChoice/components/ChipChoiceCustom/ChipChoiceCustom.d.ts +0 -23
  65. package/dist/components/ChipChoice/components/ChipChoiceCustom/ChipChoiceCustom.js +0 -75
  66. package/dist/components/ChipChoice/components/ChipChoiceCustom/index.d.ts +0 -1
  67. package/dist/components/ChipChoice/components/ChipChoiceCustom/index.js +0 -1
  68. package/dist/components/ChipChoice/components/ChipChoiceMulti.d.ts +0 -14
  69. package/dist/components/ChipChoice/components/ChipChoiceMulti.js +0 -44
  70. package/dist/components/ChipChoice/utils.d.ts +0 -14
  71. package/dist/components/ChipChoice/utils.js +0 -26
  72. package/src/components/ChipChoice/components/ChipChoiceCustom/ChipChoiceCustom.tsx +0 -188
  73. package/src/components/ChipChoice/components/ChipChoiceCustom/index.ts +0 -1
  74. package/src/components/ChipChoice/components/ChipChoiceMulti.tsx +0 -90
  75. package/src/components/ChipChoice/utils.ts +0 -48
@@ -0,0 +1,157 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+
3
+ import { Droplist, ItemId, SelectionSingleValueType } from '@snack-uikit/list';
4
+ import { useLocale } from '@snack-uikit/locale';
5
+ import { useValueControl } from '@snack-uikit/utils';
6
+
7
+ import { CHIP_CHOICE_TEST_IDS, SIZE } from '../../../constants';
8
+ import { DROPLIST_SIZE_MAP } from '../constants';
9
+ import { useFuzzySearch, useHandleOnKeyDown } from '../hooks';
10
+ import { ChipChoiceMultipleProps, ContentRenderProps } from '../types';
11
+ import { FlattenOption, kindFlattenOptions } from '../utils';
12
+ import { transformOptionsToItems } from '../utils/options';
13
+ import { ChipChoiceBase } from './ChipChoiceBase';
14
+
15
+ export type ChipChoiceMultipleValueFormatterProps<T extends ContentRenderProps = ContentRenderProps> = {
16
+ value: FlattenOption<T>[];
17
+ total: number;
18
+ allLabel: string;
19
+ };
20
+
21
+ const defaultMultiValueLabelFormatter = ({ value, total, allLabel }: ChipChoiceMultipleValueFormatterProps): ItemId => {
22
+ const len = value.length;
23
+
24
+ if ([0, total].includes(len) && total !== len) {
25
+ return allLabel;
26
+ }
27
+
28
+ if (len === 1) {
29
+ return value[0].label;
30
+ }
31
+
32
+ return `${len.toString()}/${total}`;
33
+ };
34
+
35
+ export function ChipChoiceMultiple<T extends ContentRenderProps = ContentRenderProps>({
36
+ value: valueProp,
37
+ defaultValue,
38
+ options,
39
+ onChange: onChangeProp,
40
+ valueRender,
41
+ size = SIZE.S,
42
+ label,
43
+ searchable,
44
+ contentRender,
45
+ dropDownClassName,
46
+ showClearButton = true,
47
+ ...rest
48
+ }: ChipChoiceMultipleProps<T>) {
49
+ const [value, setValue] = useValueControl<SelectionSingleValueType[]>({
50
+ value: valueProp,
51
+ defaultValue,
52
+ onChange: onChangeProp,
53
+ });
54
+
55
+ const flattenOptions = useMemo(() => {
56
+ const { flattenOptions } = kindFlattenOptions<T>({ options });
57
+
58
+ return flattenOptions;
59
+ }, [options]);
60
+
61
+ const [searchValue = '', setSearchValue] = useState<string>('');
62
+
63
+ const { t } = useLocale('Chips');
64
+
65
+ const [open, setOpen] = useState<boolean>(false);
66
+ const handleOnKeyDown = useHandleOnKeyDown({ setOpen });
67
+
68
+ const flatMapOptions = useMemo(() => Object.values(flattenOptions), [flattenOptions]);
69
+
70
+ const selectedOptions = useMemo(
71
+ () => (value && value.length ? value.map(id => flattenOptions[id]).filter(Boolean) : ([] as FlattenOption<T>[])),
72
+ [flattenOptions, value],
73
+ );
74
+
75
+ const valueToRender = valueRender
76
+ ? valueRender(selectedOptions)
77
+ : defaultMultiValueLabelFormatter({
78
+ value: selectedOptions ?? [],
79
+ total: Object.keys(flattenOptions).length,
80
+ allLabel: t('allLabel'),
81
+ });
82
+
83
+ const fuzzySearch = useFuzzySearch(options, flatMapOptions);
84
+
85
+ const result = useMemo(
86
+ () => (!searchable || valueToRender === searchValue ? options : fuzzySearch(searchValue)),
87
+ [fuzzySearch, options, searchValue, searchable, valueToRender],
88
+ );
89
+ const items = useMemo(() => transformOptionsToItems<T>(result, contentRender), [contentRender, result]);
90
+
91
+ const clearValue = () => setValue([]);
92
+ const chipRef = useRef<HTMLDivElement>(null);
93
+
94
+ const handleSelectionChange = useCallback(
95
+ (newValue?: SelectionSingleValueType) => {
96
+ if (newValue !== undefined) {
97
+ setValue(newValue);
98
+ setSearchValue('');
99
+ }
100
+ },
101
+ [setValue],
102
+ );
103
+
104
+ useEffect(() => {
105
+ if (searchValue && !open) {
106
+ setSearchValue('');
107
+ }
108
+ }, [searchable, open, searchValue]);
109
+
110
+ return (
111
+ <Droplist
112
+ {...rest}
113
+ items={items}
114
+ selection={{
115
+ value,
116
+ onChange: handleSelectionChange,
117
+ mode: 'multiple',
118
+ }}
119
+ trigger='clickAndFocusVisible'
120
+ placement='bottom-start'
121
+ widthStrategy='gte'
122
+ size={DROPLIST_SIZE_MAP[size]}
123
+ data-test-id={CHIP_CHOICE_TEST_IDS.droplist}
124
+ open={open}
125
+ triggerElemRef={chipRef}
126
+ onOpenChange={open => {
127
+ if (!open) {
128
+ setSearchValue('');
129
+ }
130
+ setOpen(open);
131
+ }}
132
+ scroll
133
+ className={dropDownClassName}
134
+ search={
135
+ searchable
136
+ ? {
137
+ value: searchValue,
138
+ onChange: setSearchValue,
139
+ }
140
+ : undefined
141
+ }
142
+ >
143
+ <ChipChoiceBase
144
+ {...rest}
145
+ ref={chipRef}
146
+ onClearButtonClick={clearValue}
147
+ value={value}
148
+ showClearButton={showClearButton && !(Array.isArray(value) && [0].includes(value.length))}
149
+ valueToRender={valueToRender}
150
+ label={label}
151
+ loading={rest.loading}
152
+ size={size}
153
+ onKeyDown={handleOnKeyDown()}
154
+ />
155
+ </Droplist>
156
+ );
157
+ }
@@ -1,82 +1,143 @@
1
- import { useMemo } from 'react';
2
- import { useUncontrolledProp } from 'uncontrollable';
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
2
 
4
- import { Droplist } from '@snack-uikit/droplist';
3
+ import { Droplist, ItemId, SelectionSingleValueType } from '@snack-uikit/list';
5
4
  import { useLocale } from '@snack-uikit/locale';
5
+ import { useValueControl } from '@snack-uikit/utils';
6
6
 
7
- import { SIZE } from '../../../constants';
8
- import { ChipChoiceCommonProps, FilterOption } from '../types';
9
- import { defaultSingleValueFormatter, normalizeValueForSingleChoice } from '../utils';
10
- import { ChipChoiceCustom } from './ChipChoiceCustom';
11
-
12
- export type ChipChoiceSingleProps = ChipChoiceCommonProps & {
13
- /** Массив опций */
14
- options: FilterOption[];
15
- /** Значение компонента */
16
- value?: string;
17
- /** Значение компонента по умолчанию */
18
- defaultValue?: string;
19
- /** Колбек смены значения */
20
- onChange?(value: string): void;
21
- /** Колбек формирующий строковое представление выбранного значения. Принимает выбранное значение. По умолчанию для отображения используется FilterOption.label */
22
- valueFormatter?(option?: FilterOption): string;
7
+ import { CHIP_CHOICE_TEST_IDS, SIZE } from '../../../constants';
8
+ import { DROPLIST_SIZE_MAP } from '../constants';
9
+ import { useFuzzySearch, useHandleOnKeyDown } from '../hooks';
10
+ import { ChipChoiceSingleProps, ContentRenderProps } from '../types';
11
+ import { FlattenOption, kindFlattenOptions } from '../utils';
12
+ import { transformOptionsToItems } from '../utils/options';
13
+ import { ChipChoiceBase } from './ChipChoiceBase';
14
+
15
+ export type ChipChoiceSingleValueFormatterProps = {
16
+ label?: ItemId;
17
+ allLabel?: string;
23
18
  };
24
19
 
25
- export function ChipChoiceSingle({
26
- value,
20
+ export function defaultSingleValueFormatter({ label, allLabel }: ChipChoiceSingleValueFormatterProps) {
21
+ return label ?? allLabel;
22
+ }
23
+
24
+ export function ChipChoiceSingle<T extends ContentRenderProps = ContentRenderProps>({
25
+ value: valueProp,
27
26
  defaultValue,
28
27
  options,
29
- onChange,
30
- valueFormatter,
28
+ onChange: onChangeProp,
29
+ valueRender,
31
30
  size = SIZE.S,
32
- 'data-test-id': dataTestId,
31
+ label,
32
+ searchable,
33
+ contentRender,
34
+ dropDownClassName,
33
35
  ...rest
34
- }: ChipChoiceSingleProps) {
35
- const [selectedValue, setSelectedValue] = useUncontrolledProp<string>(
36
- normalizeValueForSingleChoice(options, value),
37
- normalizeValueForSingleChoice(options, defaultValue),
38
- onChange,
39
- );
36
+ }: ChipChoiceSingleProps<T>) {
37
+ const [value, setValue] = useValueControl<SelectionSingleValueType>({
38
+ value: valueProp,
39
+ defaultValue,
40
+ onChange: onChangeProp,
41
+ });
42
+
43
+ const flattenOptions = useMemo(() => {
44
+ const { flattenOptions } = kindFlattenOptions<T>({ options });
45
+
46
+ return flattenOptions;
47
+ }, [options]);
40
48
 
41
49
  const { t } = useLocale('Chips');
42
50
 
43
- const selectedOption = useMemo(() => options.find(({ value }) => value === selectedValue), [options, selectedValue]);
51
+ const [open, setOpen] = useState<boolean>(false);
52
+ const handleOnKeyDown = useHandleOnKeyDown({ setOpen });
53
+
54
+ const flatMapOptions = useMemo(() => Object.values(flattenOptions), [flattenOptions]);
55
+
56
+ const selectedOption = useMemo(
57
+ () => (value ? flattenOptions[value] : ({} as FlattenOption<T>)),
58
+ [flattenOptions, value],
59
+ );
60
+
61
+ const [searchValue, setSearchValue] = useState<string>('');
44
62
 
45
- const valueToRender = valueFormatter
46
- ? valueFormatter(selectedOption)
47
- : defaultSingleValueFormatter({ value: selectedOption, allLabel: t('allLabel') });
63
+ const valueToRender = valueRender
64
+ ? valueRender(selectedOption)
65
+ : defaultSingleValueFormatter({ label: selectedOption?.label, allLabel: t('allLabel') });
48
66
 
49
- const clearValue = () => setSelectedValue(undefined);
67
+ const fuzzySearch = useFuzzySearch(options, flatMapOptions);
68
+
69
+ const result = useMemo(
70
+ () => (!searchable || valueToRender === searchValue ? options : fuzzySearch(searchValue)),
71
+ [fuzzySearch, options, searchValue, searchable, valueToRender],
72
+ );
73
+ const items = useMemo(() => transformOptionsToItems<T>(result, contentRender), [contentRender, result]);
74
+
75
+ const clearValue = () => setValue(undefined);
76
+ const chipRef = useRef<HTMLDivElement>(null);
77
+
78
+ const handleSelectionChange = useCallback(
79
+ (newValue?: SelectionSingleValueType) => {
80
+ if (newValue !== undefined) {
81
+ chipRef.current?.focus();
82
+
83
+ setOpen(false);
84
+ setValue(newValue);
85
+ setSearchValue('');
86
+ }
87
+ },
88
+ [setSearchValue, setValue],
89
+ );
90
+
91
+ useEffect(() => {
92
+ if (searchValue && !open) {
93
+ setSearchValue('');
94
+ }
95
+ }, [searchable, open, searchValue]);
50
96
 
51
97
  return (
52
- <ChipChoiceCustom
53
- onClearButtonClick={clearValue}
54
- value={selectedValue}
55
- valueToRender={valueToRender}
56
- data-test-id={dataTestId}
57
- size={size}
98
+ <Droplist
58
99
  {...rest}
59
- >
60
- {({ handleDroplistItemKeyDown, closeDroplist }) =>
61
- options.map(({ label, value, ...rest }) => {
62
- const onChangeHandler = () => {
63
- setSelectedValue(value);
64
- closeDroplist();
65
- };
66
-
67
- return (
68
- <Droplist.ItemSingle
69
- {...rest}
70
- key={value}
71
- option={label}
72
- checked={selectedValue === value}
73
- onChange={onChangeHandler}
74
- onKeyDown={handleDroplistItemKeyDown}
75
- data-test-id={dataTestId && `${dataTestId}__option`}
76
- />
77
- );
78
- })
100
+ items={items}
101
+ selection={{
102
+ value,
103
+ onChange: handleSelectionChange,
104
+ mode: 'single',
105
+ }}
106
+ data-test-id={CHIP_CHOICE_TEST_IDS.droplist}
107
+ size={DROPLIST_SIZE_MAP[size]}
108
+ trigger='click'
109
+ placement='bottom-start'
110
+ className={dropDownClassName}
111
+ widthStrategy='gte'
112
+ open={open}
113
+ triggerElemRef={chipRef}
114
+ onOpenChange={open => {
115
+ if (!open) {
116
+ setSearchValue('');
117
+ }
118
+ setOpen(open);
119
+ }}
120
+ scroll
121
+ search={
122
+ searchable
123
+ ? {
124
+ value: searchValue,
125
+ onChange: setSearchValue,
126
+ }
127
+ : undefined
79
128
  }
80
- </ChipChoiceCustom>
129
+ >
130
+ <ChipChoiceBase
131
+ {...rest}
132
+ ref={chipRef}
133
+ onClearButtonClick={clearValue}
134
+ value={value}
135
+ valueToRender={valueToRender}
136
+ label={label}
137
+ loading={rest.loading}
138
+ size={size}
139
+ onKeyDown={handleOnKeyDown()}
140
+ />
141
+ </Droplist>
81
142
  );
82
143
  }
@@ -1,5 +1,5 @@
1
1
  export * from './ChipChoiceCustom';
2
2
  export * from './ChipChoiceSingle';
3
- export * from './ChipChoiceMulti';
3
+ export * from './ChipChoiceMultiple';
4
4
  export * from './ChipChoiceDate';
5
5
  export * from './ChipChoiceDateRange';
@@ -1,5 +1,5 @@
1
1
  import { CalendarProps } from '@snack-uikit/calendar';
2
- import { DroplistProps } from '@snack-uikit/droplist';
2
+ import { DroplistProps } from '@snack-uikit/list';
3
3
 
4
4
  import { BUTTON_SIZE, SIZE } from '../../constants';
5
5
  import { Size } from '../../types';
@@ -26,8 +26,9 @@ export const DROPLIST_SIZE_MAP: Record<Size, DroplistProps['size']> = {
26
26
  };
27
27
 
28
28
  export const CHIP_CHOICE_TYPE = {
29
- Multi: 'multi',
29
+ Multiple: 'multiple',
30
30
  Date: 'date',
31
31
  DateRange: 'date-range',
32
32
  Single: 'single',
33
+ Custom: 'custom',
33
34
  } as const;
@@ -0,0 +1,61 @@
1
+ import FuzzySearch from 'fuzzy-search';
2
+ import { KeyboardEvent, KeyboardEventHandler, useCallback } from 'react';
3
+
4
+ import { AccordionOption, BaseOption, ContentRenderProps, FilterOption, NestListOption } from './types';
5
+
6
+ type UseHandleOnKeyDownProps = {
7
+ setOpen(open: boolean): void;
8
+ };
9
+
10
+ export function useHandleOnKeyDown({ setOpen }: UseHandleOnKeyDownProps) {
11
+ return useCallback(
12
+ (onKeyDown?: KeyboardEventHandler<HTMLElement>) => (e: KeyboardEvent<HTMLDivElement>) => {
13
+ if (e.code === 'Space') {
14
+ e.stopPropagation();
15
+ } else {
16
+ onKeyDown?.(e);
17
+ }
18
+
19
+ if (['ArrowDown'].includes(e.key)) {
20
+ e.preventDefault();
21
+ setOpen(true);
22
+ }
23
+
24
+ if (['ArrowUp'].includes(e.key)) {
25
+ e.preventDefault();
26
+ setOpen(false);
27
+ }
28
+
29
+ if (e.key === 'Tab') {
30
+ setOpen(false);
31
+ }
32
+ },
33
+ [setOpen],
34
+ );
35
+ }
36
+
37
+ const DEFAULT_MIN_SEARCH_INPUT_LENGTH = 2;
38
+
39
+ /**
40
+ * Нечеткий поиск среди айтемов по полям 'content.option', 'content.caption', 'content.description', 'label'
41
+ */
42
+ export function useFuzzySearch<T extends ContentRenderProps = ContentRenderProps>(
43
+ options: FilterOption<T>[],
44
+ flatMapOptions: (BaseOption<T> | AccordionOption<T> | NestListOption<T>)[],
45
+ minSearchInputLength?: number,
46
+ ) {
47
+ return useCallback(
48
+ (search: string) => {
49
+ const searcher = new FuzzySearch(
50
+ flatMapOptions,
51
+ ['label', 'contentRenderProps.description', 'contentRenderProps.caption'],
52
+ {},
53
+ );
54
+
55
+ return search.length > (minSearchInputLength ?? DEFAULT_MIN_SEARCH_INPUT_LENGTH)
56
+ ? searcher.search(search)
57
+ : options;
58
+ },
59
+ [flatMapOptions, minSearchInputLength, options],
60
+ );
61
+ }
@@ -5,26 +5,20 @@ import {
5
5
  ChipChoiceDateProps,
6
6
  ChipChoiceDateRange,
7
7
  ChipChoiceDateRangeProps,
8
- ChipChoiceMulti,
9
- ChipChoiceMultiProps,
8
+ ChipChoiceMultiple,
10
9
  ChipChoiceSingle,
11
- ChipChoiceSingleProps,
10
+ CustomContentRenderProps,
12
11
  } from './components';
13
12
 
14
- export type { FilterOption } from './types';
15
-
16
- export type {
17
- ChipChoiceCustomProps,
18
- ChipChoiceMultiProps,
19
- ChipChoiceSingleProps,
20
- ChipChoiceDateProps,
21
- ChipChoiceDateRangeProps,
22
- };
13
+ export type { FilterOption, ChipChoiceMultipleProps, ChipChoiceSingleProps, ContentRenderProps } from './types';
14
+ export type { ChipChoiceCustomProps, ChipChoiceDateProps, ChipChoiceDateRangeProps, CustomContentRenderProps };
23
15
 
24
16
  export namespace ChipChoice {
25
17
  export const Custom = ChipChoiceCustom;
26
18
  export const Single = ChipChoiceSingle;
27
- export const Multi = ChipChoiceMulti;
19
+ export const Multiple = ChipChoiceMultiple;
28
20
  export const Date = ChipChoiceDate;
29
21
  export const DateRange = ChipChoiceDateRange;
30
22
  }
23
+
24
+ export { isAccordionOption, isBaseOption, isGroupOption, isGroupSelectOption, isNextListOption } from './utils';
@@ -18,7 +18,8 @@ $valueTypography: (
18
18
  'l': $sans-label-l,
19
19
  );
20
20
 
21
- .label, .value {
21
+ .label,
22
+ .value {
22
23
  display: inline-flex;
23
24
  align-items: center;
24
25
  }
@@ -30,7 +31,8 @@ $valueTypography: (
30
31
  background-color: $sys-neutral-background1-level;
31
32
  border-color: $sys-neutral-decor-default;
32
33
 
33
- .label, .value {
34
+ .label,
35
+ .value {
34
36
  color: $sys-neutral-text-support;
35
37
  }
36
38
 
@@ -46,7 +48,9 @@ $valueTypography: (
46
48
  }
47
49
  }
48
50
 
49
- &:hover, &:active, &:focus-visible {
51
+ &:hover,
52
+ &:active,
53
+ &:focus-visible {
50
54
  background-color: $sys-neutral-background2-level;
51
55
  border-color: $sys-neutral-decor-hovered;
52
56
 
@@ -68,7 +72,8 @@ $valueTypography: (
68
72
  background-color: $sys-neutral-background;
69
73
  border-color: $sys-neutral-decor-disabled;
70
74
 
71
- .label, .value {
75
+ .label,
76
+ .value {
72
77
  color: $sys-neutral-text-light;
73
78
  }
74
79
  }
@@ -79,7 +84,8 @@ $valueTypography: (
79
84
  background-color: $sys-neutral-background;
80
85
  border-color: $sys-neutral-decor-activated;
81
86
 
82
- .label, .value {
87
+ .label,
88
+ .value {
83
89
  color: $sys-neutral-text-support;
84
90
  }
85
91
  }
@@ -1,13 +1,71 @@
1
- import { MouseEventHandler } from 'react';
1
+ import { MouseEventHandler, ReactNode } from 'react';
2
2
 
3
- import { DroplistProps, ItemSingleProps } from '@snack-uikit/droplist';
3
+ import { DropdownProps } from '@snack-uikit/dropdown';
4
+ import {
5
+ BaseItemProps,
6
+ DroplistProps,
7
+ GroupItemProps,
8
+ GroupSelectItemProps,
9
+ ItemContentProps,
10
+ ItemId,
11
+ NextListItemProps,
12
+ SelectionMultipleState,
13
+ SelectionSingleState,
14
+ } from '@snack-uikit/list';
4
15
  import { WithSupportProps } from '@snack-uikit/utils';
5
16
 
6
17
  import { BaseChipProps, Size } from '../../types';
7
18
 
8
- export type FilterOption = Pick<ItemSingleProps, 'caption' | 'description' | 'tagLabel' | 'icon' | 'avatar'> & {
9
- label: string;
10
- value: string;
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ export type AnyType = any;
21
+
22
+ export type ContentRenderProps = Omit<ItemContentProps, 'option' | 'disabled'>;
23
+
24
+ export type FilterOption<T extends ContentRenderProps = ContentRenderProps> =
25
+ // eslint-disable-next-line no-use-before-define
26
+ | BaseOption<T>
27
+ // eslint-disable-next-line no-use-before-define
28
+ | AccordionOption<T>
29
+ // eslint-disable-next-line no-use-before-define
30
+ | GroupOption<T>
31
+ // eslint-disable-next-line no-use-before-define
32
+ | GroupSelectOption<T>
33
+ // eslint-disable-next-line no-use-before-define
34
+ | NestListOption<T>;
35
+
36
+ export type BaseOption<T extends ContentRenderProps = ContentRenderProps> = Omit<BaseItemProps, 'content' | 'id'> & {
37
+ value: ItemId;
38
+ label: ItemId;
39
+ contentRenderProps?: T;
40
+ };
41
+
42
+ export type AccordionOption<T extends ContentRenderProps = ContentRenderProps> = Omit<
43
+ BaseOption<T>,
44
+ 'switch' | 'inactive' | 'value'
45
+ > & {
46
+ id?: ItemId;
47
+ type: 'collapse';
48
+ options: FilterOption<T>[];
49
+ };
50
+
51
+ export type GroupOption<T extends ContentRenderProps = ContentRenderProps> = Omit<GroupItemProps, 'items'> & {
52
+ options: FilterOption<T>[];
53
+ };
54
+
55
+ export type GroupSelectOption<T extends ContentRenderProps = ContentRenderProps> = Omit<
56
+ GroupSelectItemProps,
57
+ 'items'
58
+ > & {
59
+ options: FilterOption<T>[];
60
+ };
61
+
62
+ export type NestListOption<T extends ContentRenderProps = ContentRenderProps> = Omit<
63
+ NextListItemProps,
64
+ 'items' | 'content'
65
+ > & {
66
+ label: ItemId;
67
+ contentRenderProps?: T;
68
+ options: FilterOption<T>[];
11
69
  };
12
70
 
13
71
  export type ChipChoiceCommonProps = WithSupportProps<
@@ -19,7 +77,7 @@ export type ChipChoiceCommonProps = WithSupportProps<
19
77
  /** Отображение кнопки очистки значения @default true*/
20
78
  showClearButton?: boolean;
21
79
  /** Расположение выпадающего меню */
22
- placement?: DroplistProps['placement'];
80
+ placement?: DropdownProps['placement'];
23
81
  /**
24
82
  * Стратегия управления шириной контейнера поповера
25
83
  * <br> - `auto` - соответствует ширине контента,
@@ -27,6 +85,46 @@ export type ChipChoiceCommonProps = WithSupportProps<
27
85
  * <br> - `eq` - Equal, строго равен ширине таргета.
28
86
  * @default gte
29
87
  */
30
- widthStrategy?: DroplistProps['widthStrategy'];
88
+ widthStrategy?: DropdownProps['widthStrategy'];
89
+ dropDownClassName?: string;
31
90
  }
32
91
  >;
92
+
93
+ export type ChipChoiceSelectCommonProps<T extends ContentRenderProps = ContentRenderProps> = ChipChoiceCommonProps & {
94
+ options: FilterOption<T>[];
95
+
96
+ contentRender?(option: { label: ItemId; value?: ItemId; contentRenderProps?: T }): ReactNode;
97
+ filterFn?(option: { label: ItemId; value?: ItemId; contentRenderProps?: T }): boolean;
98
+
99
+ searchable?: boolean;
100
+ } & Pick<
101
+ DroplistProps,
102
+ | 'selection'
103
+ | 'scrollRef'
104
+ | 'scrollContainerRef'
105
+ | 'noDataState'
106
+ | 'footer'
107
+ | 'footerActiveElementsRefs'
108
+ | 'dataError'
109
+ | 'errorDataState'
110
+ | 'dataFiltered'
111
+ | 'noResultsState'
112
+ | 'loading'
113
+ >;
114
+
115
+ export type ChipChoiceSingleProps<T extends ContentRenderProps = ContentRenderProps> = ChipChoiceSelectCommonProps<T> &
116
+ Omit<SelectionSingleState, 'mode'> & {
117
+ /** Массив опций */
118
+ options: FilterOption<T>[];
119
+ /** Колбек формирующий отображение выбранного значения. Принимает выбранное значение. По умолчанию для отображения используется FilterOption.label */
120
+ valueRender?(option?: BaseOption<T>): ReactNode;
121
+ };
122
+
123
+ export type ChipChoiceMultipleProps<T extends ContentRenderProps = ContentRenderProps> =
124
+ ChipChoiceSelectCommonProps<T> &
125
+ Omit<SelectionMultipleState, 'mode'> & {
126
+ /** Массив опций */
127
+ options: FilterOption<T>[];
128
+ /** Колбек формирующий отображение выбранного значения. Принимает выбранное значение. По умолчанию для отображения используется FilterOption.label */
129
+ valueRender?(option?: BaseOption<T>[]): ReactNode;
130
+ };
@@ -0,0 +1,3 @@
1
+ export * from './typeGuards';
2
+
3
+ export * from './utils';