@snack-uikit/chips 0.12.9 → 0.13.0

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 (73) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +22 -104
  3. package/dist/components/ChipAssist/styles.module.css +1 -1
  4. package/dist/components/ChipChoice/components/ChipChoiceBase/ChipChoiceBase.d.ts +20 -0
  5. package/dist/components/ChipChoice/components/ChipChoiceBase/ChipChoiceBase.js +65 -0
  6. package/dist/components/ChipChoice/components/ChipChoiceBase/index.d.ts +1 -0
  7. package/dist/components/ChipChoice/components/ChipChoiceBase/index.js +1 -0
  8. package/dist/components/ChipChoice/components/{ChipChoiceCustom → ChipChoiceBase}/styles.module.css +18 -10
  9. package/dist/components/ChipChoice/components/ChipChoiceCustom.d.ts +25 -0
  10. package/dist/components/ChipChoice/components/ChipChoiceCustom.js +38 -0
  11. package/dist/components/ChipChoice/components/ChipChoiceDate.d.ts +3 -2
  12. package/dist/components/ChipChoice/components/ChipChoiceDate.js +19 -9
  13. package/dist/components/ChipChoice/components/ChipChoiceDateRange.d.ts +3 -2
  14. package/dist/components/ChipChoice/components/ChipChoiceDateRange.js +18 -8
  15. package/dist/components/ChipChoice/components/ChipChoiceMultiple.d.ts +8 -0
  16. package/dist/components/ChipChoice/components/ChipChoiceMultiple.js +87 -0
  17. package/dist/components/ChipChoice/components/ChipChoiceSingle.d.ts +7 -13
  18. package/dist/components/ChipChoice/components/ChipChoiceSingle.js +64 -22
  19. package/dist/components/ChipChoice/components/index.d.ts +1 -1
  20. package/dist/components/ChipChoice/components/index.js +1 -1
  21. package/dist/components/ChipChoice/constants.d.ts +3 -2
  22. package/dist/components/ChipChoice/constants.js +2 -1
  23. package/dist/components/ChipChoice/hooks.d.ts +11 -0
  24. package/dist/components/ChipChoice/hooks.js +35 -0
  25. package/dist/components/ChipChoice/index.d.ts +5 -4
  26. package/dist/components/ChipChoice/index.js +3 -2
  27. package/dist/components/ChipChoice/styles.module.css +9 -5
  28. package/dist/components/ChipChoice/types.d.ts +55 -7
  29. package/dist/components/ChipChoice/utils/index.d.ts +2 -0
  30. package/dist/components/ChipChoice/utils/index.js +2 -0
  31. package/dist/components/ChipChoice/utils/options.d.ts +9 -0
  32. package/dist/components/ChipChoice/utils/options.js +32 -0
  33. package/dist/components/ChipChoice/utils/typeGuards.d.ts +6 -0
  34. package/dist/components/ChipChoice/utils/typeGuards.js +15 -0
  35. package/dist/components/ChipChoice/utils/utils.d.ts +18 -0
  36. package/dist/components/ChipChoice/utils/utils.js +29 -0
  37. package/dist/components/ChipChoiceRow/components/constants.d.ts +2 -1
  38. package/dist/components/ChipChoiceRow/components/constants.js +2 -1
  39. package/dist/components/ChipChoiceRow/types.d.ts +11 -5
  40. package/dist/components/ChipToggle/styles.module.css +1 -1
  41. package/package.json +13 -7
  42. package/src/components/ChipChoice/components/ChipChoiceBase/ChipChoiceBase.tsx +149 -0
  43. package/src/components/ChipChoice/components/ChipChoiceBase/index.ts +1 -0
  44. package/src/components/ChipChoice/components/{ChipChoiceCustom → ChipChoiceBase}/styles.module.scss +11 -5
  45. package/src/components/ChipChoice/components/ChipChoiceCustom.tsx +89 -0
  46. package/src/components/ChipChoice/components/ChipChoiceDate.tsx +42 -18
  47. package/src/components/ChipChoice/components/ChipChoiceDateRange.tsx +43 -18
  48. package/src/components/ChipChoice/components/ChipChoiceMultiple.tsx +157 -0
  49. package/src/components/ChipChoice/components/ChipChoiceSingle.tsx +123 -62
  50. package/src/components/ChipChoice/components/index.ts +1 -1
  51. package/src/components/ChipChoice/constants.ts +3 -2
  52. package/src/components/ChipChoice/hooks.ts +61 -0
  53. package/src/components/ChipChoice/index.ts +7 -13
  54. package/src/components/ChipChoice/styles.module.scss +11 -5
  55. package/src/components/ChipChoice/types.ts +105 -7
  56. package/src/components/ChipChoice/utils/index.ts +3 -0
  57. package/src/components/ChipChoice/utils/options.tsx +58 -0
  58. package/src/components/ChipChoice/utils/typeGuards.ts +35 -0
  59. package/src/components/ChipChoice/utils/utils.ts +60 -0
  60. package/src/components/ChipChoiceRow/components/constants.ts +2 -1
  61. package/src/components/ChipChoiceRow/types.ts +18 -10
  62. package/dist/components/ChipChoice/components/ChipChoiceCustom/ChipChoiceCustom.d.ts +0 -23
  63. package/dist/components/ChipChoice/components/ChipChoiceCustom/ChipChoiceCustom.js +0 -75
  64. package/dist/components/ChipChoice/components/ChipChoiceCustom/index.d.ts +0 -1
  65. package/dist/components/ChipChoice/components/ChipChoiceCustom/index.js +0 -1
  66. package/dist/components/ChipChoice/components/ChipChoiceMulti.d.ts +0 -14
  67. package/dist/components/ChipChoice/components/ChipChoiceMulti.js +0 -44
  68. package/dist/components/ChipChoice/utils.d.ts +0 -14
  69. package/dist/components/ChipChoice/utils.js +0 -26
  70. package/src/components/ChipChoice/components/ChipChoiceCustom/ChipChoiceCustom.tsx +0 -188
  71. package/src/components/ChipChoice/components/ChipChoiceCustom/index.ts +0 -1
  72. package/src/components/ChipChoice/components/ChipChoiceMulti.tsx +0 -90
  73. package/src/components/ChipChoice/utils.ts +0 -48
@@ -0,0 +1,58 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ import { ItemContent, ItemId, ItemProps } from '@snack-uikit/list';
4
+
5
+ import { BaseOption, ContentRenderProps, FilterOption } from '../types';
6
+ import { isAccordionOption, isGroupOption, isGroupSelectOption, isNextListOption } from './typeGuards';
7
+
8
+ export function transformOptionsToItems<T extends ContentRenderProps = ContentRenderProps>(
9
+ options: FilterOption<T>[],
10
+ contentRender?: (option: { label: ItemId; value?: ItemId; contentRenderProps?: T; disabled?: boolean }) => ReactNode,
11
+ ): ItemProps[] {
12
+ return options.map(option => {
13
+ if (isAccordionOption<T>(option) || isNextListOption<T>(option)) {
14
+ const { label, options, id, contentRenderProps, disabled, ...rest } = option;
15
+
16
+ return {
17
+ ...rest,
18
+ id,
19
+ content: contentRender ? (
20
+ contentRender({ label, contentRenderProps })
21
+ ) : (
22
+ <ItemContent option={label} {...contentRenderProps} disabled={disabled} />
23
+ ),
24
+ items: transformOptionsToItems<T>(options),
25
+ };
26
+ }
27
+
28
+ if (isGroupSelectOption<T>(option)) {
29
+ const { options, ...rest } = option;
30
+
31
+ return {
32
+ ...rest,
33
+ items: transformOptionsToItems<T>(options),
34
+ };
35
+ }
36
+
37
+ if (isGroupOption(option)) {
38
+ const { options, ...rest } = option;
39
+
40
+ return {
41
+ ...rest,
42
+ items: transformOptionsToItems(options),
43
+ };
44
+ }
45
+
46
+ const { label, value, contentRenderProps, disabled, ...rest } = option as BaseOption<T>;
47
+
48
+ return {
49
+ ...rest,
50
+ id: value,
51
+ content: contentRender ? (
52
+ contentRender({ label, contentRenderProps })
53
+ ) : (
54
+ <ItemContent option={label} {...contentRenderProps} disabled={disabled} />
55
+ ),
56
+ };
57
+ });
58
+ }
@@ -0,0 +1,35 @@
1
+ import {
2
+ AccordionOption,
3
+ AnyType,
4
+ BaseOption,
5
+ ContentRenderProps,
6
+ GroupOption,
7
+ GroupSelectOption,
8
+ NestListOption,
9
+ } from '../types';
10
+
11
+ export function isBaseOption<T extends ContentRenderProps = ContentRenderProps>(
12
+ option: AnyType,
13
+ ): option is BaseOption<T> {
14
+ return !('options' in option);
15
+ }
16
+ export function isAccordionOption<T extends ContentRenderProps = ContentRenderProps>(
17
+ option: AnyType,
18
+ ): option is AccordionOption<T> {
19
+ return option && 'options' in option && option['type'] === 'collapse';
20
+ }
21
+ export function isNextListOption<T extends ContentRenderProps = ContentRenderProps>(
22
+ option: AnyType,
23
+ ): option is NestListOption<T> {
24
+ return option && 'options' in option && option['type'] === 'next-list';
25
+ }
26
+ export function isGroupOption<T extends ContentRenderProps = ContentRenderProps>(
27
+ option: AnyType,
28
+ ): option is GroupOption<T> {
29
+ return option && 'options' in option && option['type'] === 'group';
30
+ }
31
+ export function isGroupSelectOption<T extends ContentRenderProps = ContentRenderProps>(
32
+ option: AnyType,
33
+ ): option is GroupSelectOption<T> {
34
+ return option && 'options' in option && option['type'] === 'group-select';
35
+ }
@@ -0,0 +1,60 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ import { ItemId } from '@snack-uikit/list';
4
+
5
+ import { ContentRenderProps, FilterOption } from '../types';
6
+ import { isBaseOption } from './typeGuards';
7
+
8
+ export type FlattenOption<T extends ContentRenderProps = ContentRenderProps> = {
9
+ value: ItemId;
10
+ label: ItemId;
11
+ contentRenderProps?: T;
12
+ disabled?: boolean;
13
+ afterContent?: ReactNode;
14
+ beforeContent?: ReactNode;
15
+ };
16
+
17
+ type KindFlattenOptionsProps<T extends ContentRenderProps = ContentRenderProps> = {
18
+ options: FilterOption<T>[];
19
+ };
20
+
21
+ export function kindFlattenOptions<T extends ContentRenderProps = ContentRenderProps>({
22
+ options,
23
+ }: KindFlattenOptionsProps<T>): {
24
+ flattenOptions: Record<string, FlattenOption<T>>;
25
+ } {
26
+ const flattenOptions: Record<string, FlattenOption<T>> = {};
27
+
28
+ function flatten(option: FilterOption<T>) {
29
+ if (isBaseOption<T>(option)) {
30
+ const { value, label, contentRenderProps, disabled, afterContent, beforeContent } = option;
31
+
32
+ flattenOptions[value] = {
33
+ value,
34
+ label,
35
+ contentRenderProps,
36
+ disabled,
37
+ afterContent,
38
+ beforeContent,
39
+ };
40
+
41
+ return;
42
+ }
43
+
44
+ const { options } = option;
45
+
46
+ for (let idx = 0; idx < options.length; idx++) {
47
+ flatten(options[idx]);
48
+ }
49
+
50
+ return;
51
+ }
52
+
53
+ for (let idx = 0; idx < options.length; idx++) {
54
+ flatten(options[idx]);
55
+ }
56
+
57
+ return {
58
+ flattenOptions,
59
+ };
60
+ }
@@ -3,7 +3,8 @@ import { CHIP_CHOICE_TYPE } from '../../ChipChoice/constants';
3
3
 
4
4
  export const MAP_CHIP_TYPE_TO_COMPONENT = {
5
5
  [CHIP_CHOICE_TYPE.Single]: ChipChoice.Single,
6
- [CHIP_CHOICE_TYPE.Multi]: ChipChoice.Multi,
6
+ [CHIP_CHOICE_TYPE.Multiple]: ChipChoice.Multiple,
7
7
  [CHIP_CHOICE_TYPE.Date]: ChipChoice.Date,
8
8
  [CHIP_CHOICE_TYPE.DateRange]: ChipChoice.DateRange,
9
+ [CHIP_CHOICE_TYPE.Custom]: ChipChoice.Custom,
9
10
  };
@@ -1,19 +1,17 @@
1
1
  import { ValueOf } from '@snack-uikit/utils';
2
2
 
3
- import {
4
- ChipChoiceDateProps,
5
- ChipChoiceDateRangeProps,
6
- ChipChoiceMultiProps,
7
- ChipChoiceSingleProps,
8
- } from '../ChipChoice';
3
+ import { ChipChoiceCustomProps } from '../ChipChoice/components';
4
+ import { ChipChoiceDateProps } from '../ChipChoice/components/ChipChoiceDate';
5
+ import { ChipChoiceDateRangeProps } from '../ChipChoice/components/ChipChoiceDateRange';
9
6
  import { CHIP_CHOICE_TYPE } from '../ChipChoice/constants';
7
+ import { ChipChoiceMultipleProps, ChipChoiceSingleProps } from '../ChipChoice/types';
10
8
  import { CHIP_CHOICE_ROW_SIZE } from './constants';
11
9
 
12
10
  export type ChipChoiceRowSize = ValueOf<typeof CHIP_CHOICE_ROW_SIZE>;
13
11
 
14
- type ChipChoiceMultiType = {
15
- type: typeof CHIP_CHOICE_TYPE.Multi;
16
- } & ChipChoiceMultiProps;
12
+ type ChipChoiceMultipleType = {
13
+ type: typeof CHIP_CHOICE_TYPE.Multiple;
14
+ } & ChipChoiceMultipleProps;
17
15
 
18
16
  type ChipChoiceSingleType = {
19
17
  type: typeof CHIP_CHOICE_TYPE.Single;
@@ -27,9 +25,19 @@ type ChipChoiceDateRangeType = {
27
25
  type: typeof CHIP_CHOICE_TYPE.DateRange;
28
26
  } & ChipChoiceDateRangeProps;
29
27
 
28
+ type ChipChoiceCustomType = {
29
+ type: typeof CHIP_CHOICE_TYPE.Custom;
30
+ } & ChipChoiceCustomProps;
31
+
30
32
  export type ChipChoiceProps = {
31
33
  id: string;
32
- } & (ChipChoiceMultiType | ChipChoiceSingleType | ChipChoiceDateType | ChipChoiceDateRangeType);
34
+ } & (
35
+ | ChipChoiceMultipleType
36
+ | ChipChoiceSingleType
37
+ | ChipChoiceDateType
38
+ | ChipChoiceDateRangeType
39
+ | ChipChoiceCustomType
40
+ );
33
41
 
34
42
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
43
  export type OmitBetter<T, K extends keyof any> = T extends any ? Pick<T, Exclude<keyof T, K>> : never;
@@ -1,23 +0,0 @@
1
- import { MouseEventHandler, ReactNode } from 'react';
2
- import { Droplist } from '@snack-uikit/droplist';
3
- import { ChipChoiceCommonProps } from '../../types';
4
- export type ChipChoiceCustomProps = ChipChoiceCommonProps & {
5
- /** Отображаемое значение */
6
- valueToRender?: ReactNode;
7
- /** Фактическое значение. Используется для отображения кнопки очистки, если свойство <strong>showClearButton=true</strong> */
8
- value?: string | Date | string[] | [Date, Date];
9
- /** Колбек для клика по кнопке очистки */
10
- onClearButtonClick?: MouseEventHandler<HTMLButtonElement>;
11
- /** Контент выпадающего меню
12
- <br>
13
- <br> Принимает <strong>ReactNode</strong>
14
- <br> Или функцию с аргументами:
15
- <br> <strong>handleDroplistItemKeyDown</strong>: Обработчик нажатия клавиши на элемент выпадающего меню
16
- <br> <strong>closeDroplist</strong>: Метод для закрытия выпадающего меню
17
- */
18
- children?: ReactNode | ((props: {
19
- handleDroplistItemKeyDown: ReturnType<typeof Droplist.useKeyboardNavigation>['handleDroplistItemKeyDown'];
20
- closeDroplist(): void;
21
- }) => ReactNode);
22
- };
23
- export declare function ChipChoiceCustom({ size, disabled, loading, icon, label, valueToRender, value, onClick, className, tabIndex, placement, widthStrategy, onClearButtonClick, showClearButton: showClearButtonProp, children, 'data-test-id': testId, ...rest }: ChipChoiceCustomProps): import("react/jsx-runtime").JSX.Element;
@@ -1,75 +0,0 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- import cn from 'classnames';
14
- import { useCallback, useRef, useState } from 'react';
15
- import { Droplist } from '@snack-uikit/droplist';
16
- import { Sun } from '@snack-uikit/loaders';
17
- import { extractSupportProps } from '@snack-uikit/utils';
18
- import { CHIP_CHOICE_TEST_IDS, SIZE, VARIANT } from '../../../../constants';
19
- import { ButtonClearValue } from '../../../../helperComponents';
20
- import { BUTTON_CLEAR_VALUE_SIZE_MAP, DROPLIST_SIZE_MAP } from '../../constants';
21
- import styles from './styles.module.css';
22
- export function ChipChoiceCustom(_a) {
23
- var { size = SIZE.S, disabled, loading, icon, label, valueToRender, value, onClick, className, tabIndex = 0, placement = 'bottom-start', widthStrategy = 'gte', onClearButtonClick, showClearButton: showClearButtonProp = true, children, 'data-test-id': testId } = _a, rest = __rest(_a, ["size", "disabled", "loading", "icon", "label", "valueToRender", "value", "onClick", "className", "tabIndex", "placement", "widthStrategy", "onClearButtonClick", "showClearButton", "children", 'data-test-id']);
24
- const variant = icon && size !== SIZE.Xs ? VARIANT.IconBefore : VARIANT.LabelOnly;
25
- const spinnerSize = size === SIZE.Xs ? 'xs' : 's';
26
- const clearButtonRef = useRef(null);
27
- const [isDroplistOpened, setIsDroplistOpened] = useState(false);
28
- const { firstElementRefCallback, triggerElementRef, handleDroplistFocusLeave, handleTriggerKeyDown, handleDroplistItemKeyDown, } = Droplist.useKeyboardNavigation({
29
- setDroplistOpen: setIsDroplistOpened,
30
- });
31
- const handleChipClick = e => {
32
- if (loading || disabled)
33
- return;
34
- onClick === null || onClick === void 0 ? void 0 : onClick(e);
35
- !isDroplistOpened && setIsDroplistOpened(true);
36
- };
37
- const handleChipKeyDown = e => {
38
- var _a;
39
- if (e.key === 'ArrowRight') {
40
- (_a = clearButtonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
41
- }
42
- handleTriggerKeyDown(e);
43
- };
44
- const onOpenChangeHandler = (opened) => !opened && setIsDroplistOpened(false);
45
- const closeDroplist = useCallback(() => {
46
- setIsDroplistOpened(false);
47
- // TODO: same bug as in FieldDate
48
- setTimeout(() => {
49
- var _a;
50
- (_a = triggerElementRef.current) === null || _a === void 0 ? void 0 : _a.focus();
51
- }, 0);
52
- }, [triggerElementRef]);
53
- const handleClearButtonClick = e => {
54
- onClearButtonClick === null || onClearButtonClick === void 0 ? void 0 : onClearButtonClick(e);
55
- closeDroplist();
56
- };
57
- const handleClearButtonKeyDown = e => {
58
- var _a;
59
- switch (e.key) {
60
- case 'ArrowLeft': {
61
- (_a = triggerElementRef.current) === null || _a === void 0 ? void 0 : _a.focus();
62
- return;
63
- }
64
- case 'Enter':
65
- case ' ': {
66
- e.stopPropagation();
67
- return;
68
- }
69
- default:
70
- break;
71
- }
72
- };
73
- const showClearButton = showClearButtonProp && (value instanceof Date || Boolean(value === null || value === void 0 ? void 0 : value.length));
74
- return (_jsx(Droplist, { trigger: 'click', open: isDroplistOpened, firstElementRefCallback: firstElementRefCallback, onOpenChange: onOpenChangeHandler, onFocusLeave: handleDroplistFocusLeave, triggerClassName: styles.triggerClassName, widthStrategy: widthStrategy, placement: placement, size: DROPLIST_SIZE_MAP[size], "data-test-id": CHIP_CHOICE_TEST_IDS.droplist, triggerElement: _jsxs("div", Object.assign({}, extractSupportProps(rest), { role: 'button', ref: triggerElementRef, className: cn(styles.choiceChip, className), "data-size": size, "data-variant": variant, "data-loading": loading || undefined, "data-test-id": testId || undefined, "data-disabled": (!loading && disabled) || undefined, onClick: handleChipClick, onKeyDown: handleChipKeyDown, tabIndex: tabIndex, children: [variant === VARIANT.IconBefore && (_jsx("span", { className: styles.icon, "data-test-id": CHIP_CHOICE_TEST_IDS.icon, children: icon })), _jsxs("span", { className: styles.labelLayout, children: [label && (_jsx("span", { className: styles.label, "data-test-id": CHIP_CHOICE_TEST_IDS.label, children: label + ': ' })), loading ? (_jsx("span", { className: styles.spinner, "data-test-id": CHIP_CHOICE_TEST_IDS.spinner, children: _jsx(Sun, { size: spinnerSize }) })) : (_jsx("span", { className: styles.value, "data-test-id": CHIP_CHOICE_TEST_IDS.value, children: valueToRender }))] }), !disabled && !loading && showClearButton && (_jsx(ButtonClearValue, { size: BUTTON_CLEAR_VALUE_SIZE_MAP[size], onClick: handleClearButtonClick, "data-test-id": CHIP_CHOICE_TEST_IDS.clearButton, onKeyDown: handleClearButtonKeyDown, ref: clearButtonRef }))] })), children: typeof children === 'function' ? children({ handleDroplistItemKeyDown, closeDroplist }) : children }));
75
- }
@@ -1 +0,0 @@
1
- export * from './ChipChoiceCustom';
@@ -1 +0,0 @@
1
- export * from './ChipChoiceCustom';
@@ -1,14 +0,0 @@
1
- import { ChipChoiceCommonProps, FilterOption } from '../types';
2
- export type ChipChoiceMultiProps = ChipChoiceCommonProps & {
3
- /** Массив опций */
4
- options: FilterOption[];
5
- /** Значение компонента */
6
- value?: string[];
7
- /** Значение компонента по умолчанию */
8
- defaultValue?: string[];
9
- /** Колбек смены значения */
10
- onChange?(value: string[]): void;
11
- /** Колбек формирующий строковое представление выбранного значения. Принимает массив выбранных значений. По умолчанию для отображения используется кол-во выбранных значений. */
12
- valueFormatter?(options: FilterOption[]): string;
13
- };
14
- export declare function ChipChoiceMulti({ value, defaultValue, options, onChange, valueFormatter, size, 'data-test-id': dataTestId, ...rest }: ChipChoiceMultiProps): import("react/jsx-runtime").JSX.Element;
@@ -1,44 +0,0 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
- import { jsx as _jsx } from "react/jsx-runtime";
13
- import { createElement as _createElement } from "react";
14
- import { useMemo } from 'react';
15
- import { useUncontrolledProp } from 'uncontrollable';
16
- import { Droplist } from '@snack-uikit/droplist';
17
- import { useLocale } from '@snack-uikit/locale';
18
- import { SIZE } from '../../../constants';
19
- import { defaultMultiValueLabelFormatter, normalizeValueForMultiChoice } from '../utils';
20
- import { ChipChoiceCustom } from './ChipChoiceCustom';
21
- export function ChipChoiceMulti(_a) {
22
- var { value, defaultValue, options, onChange, valueFormatter, size = SIZE.S, 'data-test-id': dataTestId } = _a, rest = __rest(_a, ["value", "defaultValue", "options", "onChange", "valueFormatter", "size", 'data-test-id']);
23
- const [selectedValue, setSelectedValue] = useUncontrolledProp(normalizeValueForMultiChoice(options, value), normalizeValueForMultiChoice(options, defaultValue) || [], onChange);
24
- const selectedOptions = useMemo(() => options.filter(({ value }) => selectedValue === null || selectedValue === void 0 ? void 0 : selectedValue.includes(value)), [options, selectedValue]);
25
- const { t } = useLocale('Chips');
26
- const valueToRender = valueFormatter
27
- ? valueFormatter(selectedOptions)
28
- : defaultMultiValueLabelFormatter({ value: selectedOptions, total: options.length, allLabel: t('allLabel') });
29
- const clearValue = () => setSelectedValue([]);
30
- return (_jsx(ChipChoiceCustom, Object.assign({ size: size, onClearButtonClick: clearValue, valueToRender: valueToRender, value: selectedValue, "data-test-id": dataTestId }, rest, { children: ({ handleDroplistItemKeyDown }) => options.map((_a) => {
31
- var { label, value } = _a, rest = __rest(_a, ["label", "value"]);
32
- const selected = selectedValue || [];
33
- const checked = selected.includes(value);
34
- const onChangeHandler = () => {
35
- if (checked) {
36
- setSelectedValue(selected.filter(selected => selected !== value));
37
- }
38
- else {
39
- setSelectedValue([...selected, value]);
40
- }
41
- };
42
- return (_createElement(Droplist.ItemMultiple, Object.assign({}, rest, { key: value, option: label, checked: checked, onChange: onChangeHandler, onKeyDown: handleDroplistItemKeyDown, "data-test-id": dataTestId && `${dataTestId}__option` })));
43
- }) })));
44
- }
@@ -1,14 +0,0 @@
1
- import { FilterOption } from './types';
2
- export declare const normalizeValueForMultiChoice: (options: FilterOption[], value?: string[]) => string[] | undefined;
3
- export declare const normalizeValueForSingleChoice: (options: FilterOption[], value?: string) => string | undefined;
4
- export type ChipChoiceMultipleValueFormatterProps = {
5
- value: FilterOption[];
6
- total: number;
7
- allLabel: string;
8
- };
9
- export declare const defaultMultiValueLabelFormatter: ({ value, total, allLabel, }: ChipChoiceMultipleValueFormatterProps) => string;
10
- export type ChipChoiceSingleValueFormatterProps = {
11
- value?: FilterOption;
12
- allLabel?: string;
13
- };
14
- export declare function defaultSingleValueFormatter({ value, allLabel }: ChipChoiceSingleValueFormatterProps): string | undefined;
@@ -1,26 +0,0 @@
1
- export const normalizeValueForMultiChoice = (options, value) => {
2
- if (!value) {
3
- return undefined;
4
- }
5
- return value.filter(val => options.some(option => val === option.value));
6
- };
7
- export const normalizeValueForSingleChoice = (options, value) => {
8
- var _a;
9
- if (!value) {
10
- return undefined;
11
- }
12
- return (_a = options.find(option => value === option.value)) === null || _a === void 0 ? void 0 : _a.value;
13
- };
14
- export const defaultMultiValueLabelFormatter = ({ value, total, allLabel, }) => {
15
- if (value.length === 0 || value.length === total) {
16
- return allLabel;
17
- }
18
- if (value.length === 1) {
19
- return value[0].label;
20
- }
21
- return `${value.length.toString()}/${total}`;
22
- };
23
- export function defaultSingleValueFormatter({ value, allLabel }) {
24
- var _a;
25
- return (_a = value === null || value === void 0 ? void 0 : value.label) !== null && _a !== void 0 ? _a : allLabel;
26
- }
@@ -1,188 +0,0 @@
1
- import cn from 'classnames';
2
- import { KeyboardEventHandler, MouseEventHandler, ReactNode, useCallback, useRef, useState } from 'react';
3
-
4
- import { Droplist } from '@snack-uikit/droplist';
5
- import { Sun, SunProps } from '@snack-uikit/loaders';
6
- import { extractSupportProps } from '@snack-uikit/utils';
7
-
8
- import { CHIP_CHOICE_TEST_IDS, SIZE, VARIANT } from '../../../../constants';
9
- import { ButtonClearValue } from '../../../../helperComponents';
10
- import { BUTTON_CLEAR_VALUE_SIZE_MAP, DROPLIST_SIZE_MAP } from '../../constants';
11
- import { ChipChoiceCommonProps } from '../../types';
12
- import styles from './styles.module.scss';
13
-
14
- export type ChipChoiceCustomProps = ChipChoiceCommonProps & {
15
- /** Отображаемое значение */
16
- valueToRender?: ReactNode;
17
- /** Фактическое значение. Используется для отображения кнопки очистки, если свойство <strong>showClearButton=true</strong> */
18
- value?: string | Date | string[] | [Date, Date];
19
- /** Колбек для клика по кнопке очистки */
20
- onClearButtonClick?: MouseEventHandler<HTMLButtonElement>;
21
- /** Контент выпадающего меню
22
- <br>
23
- <br> Принимает <strong>ReactNode</strong>
24
- <br> Или функцию с аргументами:
25
- <br> <strong>handleDroplistItemKeyDown</strong>: Обработчик нажатия клавиши на элемент выпадающего меню
26
- <br> <strong>closeDroplist</strong>: Метод для закрытия выпадающего меню
27
- */
28
- children?:
29
- | ReactNode
30
- | ((props: {
31
- handleDroplistItemKeyDown: ReturnType<typeof Droplist.useKeyboardNavigation>['handleDroplistItemKeyDown'];
32
- closeDroplist(): void;
33
- }) => ReactNode);
34
- };
35
-
36
- export function ChipChoiceCustom({
37
- size = SIZE.S,
38
- disabled,
39
- loading,
40
- icon,
41
- label,
42
- valueToRender,
43
- value,
44
- onClick,
45
- className,
46
- tabIndex = 0,
47
- placement = 'bottom-start',
48
- widthStrategy = 'gte',
49
- onClearButtonClick,
50
- showClearButton: showClearButtonProp = true,
51
- children,
52
- 'data-test-id': testId,
53
- ...rest
54
- }: ChipChoiceCustomProps) {
55
- const variant = icon && size !== SIZE.Xs ? VARIANT.IconBefore : VARIANT.LabelOnly;
56
- const spinnerSize: SunProps['size'] = size === SIZE.Xs ? 'xs' : 's';
57
-
58
- const clearButtonRef = useRef<HTMLButtonElement>(null);
59
-
60
- const [isDroplistOpened, setIsDroplistOpened] = useState(false);
61
-
62
- const {
63
- firstElementRefCallback,
64
- triggerElementRef,
65
- handleDroplistFocusLeave,
66
- handleTriggerKeyDown,
67
- handleDroplistItemKeyDown,
68
- } = Droplist.useKeyboardNavigation<HTMLDivElement>({
69
- setDroplistOpen: setIsDroplistOpened,
70
- });
71
-
72
- const handleChipClick: MouseEventHandler<HTMLDivElement> = e => {
73
- if (loading || disabled) return;
74
-
75
- onClick?.(e);
76
-
77
- !isDroplistOpened && setIsDroplistOpened(true);
78
- };
79
-
80
- const handleChipKeyDown: KeyboardEventHandler<HTMLDivElement> = e => {
81
- if (e.key === 'ArrowRight') {
82
- clearButtonRef.current?.focus();
83
- }
84
-
85
- handleTriggerKeyDown(e);
86
- };
87
-
88
- const onOpenChangeHandler = (opened: boolean) => !opened && setIsDroplistOpened(false);
89
-
90
- const closeDroplist = useCallback(() => {
91
- setIsDroplistOpened(false);
92
-
93
- // TODO: same bug as in FieldDate
94
- setTimeout(() => {
95
- triggerElementRef.current?.focus();
96
- }, 0);
97
- }, [triggerElementRef]);
98
-
99
- const handleClearButtonClick: MouseEventHandler<HTMLButtonElement> = e => {
100
- onClearButtonClick?.(e);
101
- closeDroplist();
102
- };
103
-
104
- const handleClearButtonKeyDown: KeyboardEventHandler<HTMLButtonElement> = e => {
105
- switch (e.key) {
106
- case 'ArrowLeft': {
107
- triggerElementRef.current?.focus();
108
- return;
109
- }
110
- case 'Enter':
111
- case ' ': {
112
- e.stopPropagation();
113
- return;
114
- }
115
- default:
116
- break;
117
- }
118
- };
119
-
120
- const showClearButton = showClearButtonProp && (value instanceof Date || Boolean(value?.length));
121
-
122
- return (
123
- <Droplist
124
- trigger='click'
125
- open={isDroplistOpened}
126
- firstElementRefCallback={firstElementRefCallback}
127
- onOpenChange={onOpenChangeHandler}
128
- onFocusLeave={handleDroplistFocusLeave}
129
- triggerClassName={styles.triggerClassName}
130
- widthStrategy={widthStrategy}
131
- placement={placement}
132
- size={DROPLIST_SIZE_MAP[size]}
133
- data-test-id={CHIP_CHOICE_TEST_IDS.droplist}
134
- triggerElement={
135
- <div
136
- {...extractSupportProps(rest)}
137
- role='button'
138
- ref={triggerElementRef}
139
- className={cn(styles.choiceChip, className)}
140
- data-size={size}
141
- data-variant={variant}
142
- data-loading={loading || undefined}
143
- data-test-id={testId || undefined}
144
- data-disabled={(!loading && disabled) || undefined}
145
- onClick={handleChipClick}
146
- onKeyDown={handleChipKeyDown}
147
- tabIndex={tabIndex}
148
- >
149
- {variant === VARIANT.IconBefore && (
150
- <span className={styles.icon} data-test-id={CHIP_CHOICE_TEST_IDS.icon}>
151
- {icon}
152
- </span>
153
- )}
154
-
155
- <span className={styles.labelLayout}>
156
- {label && (
157
- <span className={styles.label} data-test-id={CHIP_CHOICE_TEST_IDS.label}>
158
- {label + ': '}
159
- </span>
160
- )}
161
-
162
- {loading ? (
163
- <span className={styles.spinner} data-test-id={CHIP_CHOICE_TEST_IDS.spinner}>
164
- <Sun size={spinnerSize} />
165
- </span>
166
- ) : (
167
- <span className={styles.value} data-test-id={CHIP_CHOICE_TEST_IDS.value}>
168
- {valueToRender}
169
- </span>
170
- )}
171
- </span>
172
-
173
- {!disabled && !loading && showClearButton && (
174
- <ButtonClearValue
175
- size={BUTTON_CLEAR_VALUE_SIZE_MAP[size]}
176
- onClick={handleClearButtonClick}
177
- data-test-id={CHIP_CHOICE_TEST_IDS.clearButton}
178
- onKeyDown={handleClearButtonKeyDown}
179
- ref={clearButtonRef}
180
- />
181
- )}
182
- </div>
183
- }
184
- >
185
- {typeof children === 'function' ? children({ handleDroplistItemKeyDown, closeDroplist }) : children}
186
- </Droplist>
187
- );
188
- }
@@ -1 +0,0 @@
1
- export * from './ChipChoiceCustom';