@snack-uikit/fields 0.16.1-preview-3bc93fc3.0 → 0.16.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## 0.16.1 (2024-02-27)
7
+
8
+ ### Only dependencies have been changed
9
+ * [@snack-uikit/list@0.5.0](https://github.com/cloud-ru-tech/snack-uikit/blob/master/packages/list/CHANGELOG.md)
10
+
11
+
12
+
13
+
14
+
6
15
  # 0.16.0 (2024-02-26)
7
16
 
8
17
 
package/README.md CHANGED
@@ -337,20 +337,9 @@ const [isOpen, setIsOpen] = useState(false);
337
337
  | footer | `ReactNode` | - | |
338
338
  | search | `SearchState` | - | |
339
339
  | autocomplete | `boolean` | - | |
340
- | addOptionByEnter | `boolean` | - | |
341
- | open | `boolean` | - | |
342
- | onOpenChange | `(open: boolean) => void` | - | |
343
- | dataError | `boolean` | - | |
344
- | noDataState | `EmptyStateProps` | - | Экран при отстутствии данных |
345
- | noResultsState | `EmptyStateProps` | - | Экран при отстутствии результатов поиска или фильтров |
346
- | errorDataState | `EmptyStateProps` | - | Экран при ошибке запроса |
347
- | pinTop | `ItemProps[]` | - | Элементы списка, закрепленные сверху |
348
- | pinBottom | `ItemProps[]` | - | Элементы списка, закрепленные снизу |
349
- | dataFiltered | `boolean` | - | |
350
340
  | selection | "single" \| "multiple" | - | |
351
341
  | ref | `Ref<HTMLInputElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom |
352
342
  | key | `Key` | - | |
353
- | removeByBackspace | `boolean` | - | |
354
343
  ## FieldStepper
355
344
  ### Props
356
345
  | name | type | default value | description |
@@ -2,8 +2,6 @@
2
2
  export declare const FieldSelectMultiple: import("react").ForwardRefExoticComponent<import("./types").InputProps & import("./types").WrapperProps & {
3
3
  options: import("./types").OptionProps[];
4
4
  loading?: boolean | undefined;
5
- } & {
6
- removeByBackspace?: boolean | undefined;
7
5
  } & Omit<import("@snack-uikit/list").SelectionMultipleState, "mode"> & Omit<{
8
6
  'data-test-id'?: string | undefined;
9
7
  } & import("react").AriaAttributes & {
@@ -16,7 +14,4 @@ export declare const FieldSelectMultiple: import("react").ForwardRefExoticCompon
16
14
  footer?: import("react").ReactNode;
17
15
  search?: import("./types").SearchState | undefined;
18
16
  autocomplete?: boolean | undefined;
19
- addOptionByEnter?: boolean | undefined;
20
- open?: boolean | undefined;
21
- onOpenChange?(open: boolean): void;
22
- } & Pick<import("@snack-uikit/list").ListProps, "dataError" | "noDataState" | "noResultsState" | "errorDataState" | "pinTop" | "pinBottom" | "dataFiltered">, "showCopyButton"> & import("react").RefAttributes<HTMLInputElement>>;
17
+ }, "showCopyButton"> & import("react").RefAttributes<HTMLInputElement>>;
@@ -12,7 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
13
13
  import cn from 'classnames';
14
14
  import mergeRefs from 'merge-refs';
15
- import { forwardRef, useMemo, useRef } from 'react';
15
+ import { forwardRef, useMemo, useRef, useState } from 'react';
16
16
  import { InputPrivate } from '@snack-uikit/input-private';
17
17
  import { Droplist, useFuzzySearch } from '@snack-uikit/list';
18
18
  import { Tag } from '@snack-uikit/tag';
@@ -20,29 +20,26 @@ import { extractSupportProps } from '@snack-uikit/utils';
20
20
  import { FieldContainerPrivate } from '../../helperComponents';
21
21
  import { useValueControl } from '../../hooks';
22
22
  import { FieldDecorator } from '../FieldDecorator';
23
- import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
24
23
  import { useButtons, useHandleDeleteItem, useHandleOnKeyDown, useSearchInput } from './hooks';
25
24
  import styles from './styles.module.css';
26
- import { extractListProps, findSelectedOptions, getArrowIcon, transformOptionsToItems } from './utils';
25
+ import { extractSelectedMultipleOptions, getArrowIcon, transformOptionsToItems } from './utils';
27
26
  const BASE_MIN_WIDTH = 4;
28
27
  export const FieldSelectMultiple = forwardRef((_a, ref) => {
29
- var _b;
30
- var { id, name, placeholder, size = 's', options, value: valueProp, defaultValue, onChange: onChangeProp, disabled = false, readonly = false, searchable = true, showClearButton = true, onKeyDown: onInputKeyDownProp, validationState = 'default', search, autocomplete = false, prefixIcon, removeByBackspace = false, addOptionByEnter = false, open: openProp, onOpenChange } = _a, rest = __rest(_a, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "disabled", "readonly", "searchable", "showClearButton", "onKeyDown", "validationState", "search", "autocomplete", "prefixIcon", "removeByBackspace", "addOptionByEnter", "open", "onOpenChange"]);
28
+ var { id, name, placeholder, size = 's', options, value: valueProp, defaultValue, onChange: onChangeProp, loading, disabled = false, readonly = false, searchable = true, showClearButton = true, onKeyDown: onInputKeyDownProp, label, labelTooltip, labelTooltipPlacement, required = false, hint, showHintIcon, validationState = 'default', footer, search, autocomplete = false, prefixIcon, error } = _a, rest = __rest(_a, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "loading", "disabled", "readonly", "searchable", "showClearButton", "onKeyDown", "label", "labelTooltip", "labelTooltipPlacement", "required", "hint", "showHintIcon", "validationState", "footer", "search", "autocomplete", "prefixIcon", "error"]);
31
29
  const localRef = useRef(null);
32
30
  const inputPlugRef = useRef(null);
33
31
  const contentRef = useRef(null);
34
- const [open = false, setOpen] = useValueControl({ value: openProp, onChange: onOpenChange });
32
+ const [open, setOpen] = useState(false);
35
33
  const items = useMemo(() => transformOptionsToItems(options), [options]);
36
34
  const [value, setValue] = useValueControl({
37
35
  value: valueProp,
38
36
  defaultValue,
39
37
  onChange: onChangeProp,
40
38
  });
41
- const { selected, itemsWithPlaceholder } = useMemo(() => {
42
- const [notSortSelectedOption, placeholder] = findSelectedOptions(items, value);
43
- const selectedWithPlaceholder = notSortSelectedOption || placeholder ? (placeholder !== null && placeholder !== void 0 ? placeholder : []).concat(notSortSelectedOption !== null && notSortSelectedOption !== void 0 ? notSortSelectedOption : []) : undefined;
44
- const selected = selectedWithPlaceholder
45
- ? selectedWithPlaceholder.sort((a, b) => {
39
+ const selectedOption = useMemo(() => {
40
+ const notSortSelectedOption = extractSelectedMultipleOptions(options, value);
41
+ if (notSortSelectedOption) {
42
+ return notSortSelectedOption.sort((a, b) => {
46
43
  if (b.disabled && !a.disabled) {
47
44
  return 1;
48
45
  }
@@ -50,15 +47,10 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
50
47
  return -1;
51
48
  }
52
49
  return 0;
53
- })
54
- : undefined;
55
- const placeholderItems = placeholder ? placeholder : [];
56
- return {
57
- selected,
58
- itemsWithPlaceholder: placeholderItems.concat(items),
59
- };
60
- }, [items, value]);
61
- const { inputValue, onInputValueChange, prevInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: '' }));
50
+ });
51
+ }
52
+ }, [options, value]);
53
+ const { inputValue, onInputValueChange, prevInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: String(selectedOption !== null && selectedOption !== void 0 ? selectedOption : '') }));
62
54
  const onClear = () => {
63
55
  var _a;
64
56
  setValue(undefined);
@@ -70,7 +62,7 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
70
62
  const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
71
63
  readonly,
72
64
  size,
73
- showClearButton: showClearButton && !disabled && !readonly && Boolean(value === null || value === void 0 ? void 0 : value.length),
65
+ showClearButton: showClearButton && Boolean(value),
74
66
  showCopyButton: false,
75
67
  inputRef: localRef,
76
68
  onClear,
@@ -82,20 +74,11 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
82
74
  });
83
75
  const handleItemDelete = useHandleDeleteItem(setValue);
84
76
  const handleOnKeyDown = (onKeyDown) => (e) => {
85
- if (removeByBackspace && e.code === 'Backspace' && inputValue === '') {
86
- if ((selected === null || selected === void 0 ? void 0 : selected.length) && !selected.slice(-1)[0].disabled) {
87
- handleItemDelete(selected.pop())();
77
+ if (e.code === 'Backspace' && inputValue === '') {
78
+ if ((selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.length) && !selectedOption.slice(-1)[0].disabled) {
79
+ handleItemDelete(selectedOption.pop())();
88
80
  }
89
81
  }
90
- if (e.code === 'Enter') {
91
- e.stopPropagation();
92
- e.preventDefault();
93
- }
94
- if (addOptionByEnter && e.code === 'Enter' && inputValue !== '') {
95
- setValue((value) => (value !== null && value !== void 0 ? value : []).concat(inputValue));
96
- onInputValueChange('');
97
- prevInputValue.current = '';
98
- }
99
82
  if (!open && prevInputValue.current !== inputValue) {
100
83
  setOpen(true);
101
84
  }
@@ -105,16 +88,10 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
105
88
  if (!readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
106
89
  setOpen(open);
107
90
  if (!open) {
108
- onInputValueChange('');
109
- prevInputValue.current = '';
110
- if (inputPlugRef.current) {
111
- inputPlugRef.current.style.width = BASE_MIN_WIDTH + 'px';
112
- }
91
+ prevInputValue.current = inputValue;
113
92
  }
114
93
  if (open) {
115
- if (inputPlugRef.current) {
116
- inputPlugRef.current.style.width = 'unset';
117
- }
94
+ prevInputValue.current = '';
118
95
  }
119
96
  }
120
97
  };
@@ -125,21 +102,19 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
125
102
  }
126
103
  (_a = rest === null || rest === void 0 ? void 0 : rest.onBlur) === null || _a === void 0 ? void 0 : _a.call(rest, e);
127
104
  };
128
- const fuzzySearch = useFuzzySearch(itemsWithPlaceholder);
129
- const result = autocomplete || !searchable || prevInputValue.current === inputValue
130
- ? itemsWithPlaceholder
131
- : fuzzySearch(inputValue);
132
- return (_jsx(FieldDecorator, Object.assign({}, extractSupportProps(rest), extractFieldDecoratorProps(rest), { labelFor: id, size: size, validationState: validationState, children: _jsx(Droplist, Object.assign({}, extractListProps(rest), { items: result, triggerElemRef: localRef, selection: {
105
+ const fuzzySearch = useFuzzySearch(items);
106
+ const result = autocomplete ? items : fuzzySearch(prevInputValue.current !== inputValue ? inputValue : '');
107
+ return (_jsx(FieldDecorator, Object.assign({}, extractSupportProps(rest), { error: error, required: required, readonly: readonly, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, hint: hint, disabled: disabled, showHintIcon: showHintIcon, size: size, validationState: validationState, children: _jsx(Droplist, { trigger: 'clickAndFocusVisible', placement: 'bottom', "data-test-id": 'field-select__list', items: result, triggerElemRef: localRef, scroll: true, marker: true, footer: footer, selection: {
133
108
  mode: 'multiple',
134
109
  value: value,
135
110
  onChange: setValue,
136
- }, dataFiltered: (_b = rest.dataFiltered) !== null && _b !== void 0 ? _b : Boolean(inputValue.length), size: size, open: !disabled && !readonly && open, onOpenChange: handleOpenChange, children: ({ onKeyDown }) => {
111
+ }, size: size, open: !disabled && !readonly && open, onOpenChange: handleOpenChange, loading: loading, children: ({ onKeyDown }) => {
137
112
  var _a, _b, _c, _d;
138
- return (_jsx(FieldContainerPrivate, { className: cn(styles.container, styles.tagContainer), validationState: validationState, disabled: disabled, readonly: readonly, focused: open, variant: 'single-line-container', inputRef: localRef, size: size, prefix: prefixIcon, children: _jsxs(_Fragment, { children: [_jsxs("div", { className: styles.contentWrapper, ref: contentRef, children: [selected &&
139
- selected.map(option => (_jsx(Tag, { size: size === 'l' ? 's' : 'xs', tabIndex: -1, label: String(option.content.option), onDelete: !option.disabled && !disabled && !readonly ? handleItemDelete(option) : undefined }, option.id))), _jsx("div", { className: styles.inputWrapper, style: {
113
+ return (_jsx(FieldContainerPrivate, { className: cn(styles.container, styles.tagContainer), validationState: validationState, disabled: disabled, readonly: readonly, focused: open, variant: 'single-line-container', inputRef: localRef, size: size, prefix: prefixIcon, children: _jsxs(_Fragment, { children: [_jsxs("div", { className: styles.contentWrapper, ref: contentRef, children: [selectedOption &&
114
+ selectedOption.map(option => (_jsx(Tag, { size: size === 'l' ? 's' : 'xs', tabIndex: -1, label: String(option.option), onDelete: !option.disabled && !disabled ? handleItemDelete(option) : undefined }, option.value))), _jsx("div", { className: styles.inputWrapper, style: {
140
115
  minWidth: value
141
116
  ? Math.min((_b = (_a = contentRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth) !== null && _b !== void 0 ? _b : BASE_MIN_WIDTH, (_d = (_c = inputPlugRef.current) === null || _c === void 0 ? void 0 : _c.clientWidth) !== null && _d !== void 0 ? _d : BASE_MIN_WIDTH)
142
117
  : '100%',
143
- }, children: _jsx(InputPrivate, { id: id, name: name, type: 'text', disabled: disabled, placeholder: !selected || !selected.length ? placeholder : undefined, ref: mergeRefs(ref, localRef), onChange: searchable ? onInputValueChange : undefined, value: searchable ? inputValue : '', readonly: !searchable || readonly, "data-test-id": 'field-select__input', onKeyDown: handleOnKeyDown(onKeyDown), onBlur: handleBlur, className: styles.input }) })] }), _jsxs("div", { className: styles.postfix, children: [buttons, _jsx(ArrowIcon, { size: arrowIconSize, className: styles.arrowIcon })] }), _jsx("span", { ref: inputPlugRef, className: styles.inputPlug, children: inputValue })] }) }));
144
- } })) })));
118
+ }, children: _jsx(InputPrivate, { id: id, name: name, type: 'text', disabled: disabled, placeholder: !selectedOption ? placeholder : undefined, ref: mergeRefs(ref, localRef), onChange: searchable ? onInputValueChange : undefined, value: searchable ? inputValue : '', readonly: !searchable || readonly, "data-test-id": 'field-select__input', onKeyDown: handleOnKeyDown(onKeyDown), onBlur: handleBlur, className: styles.input }) })] }), _jsxs("div", { className: styles.postfix, children: [buttons, _jsx(ArrowIcon, { size: arrowIconSize, className: styles.arrowIcon })] }), _jsx("span", { ref: inputPlugRef, className: styles.inputPlug, children: inputValue })] }) }));
119
+ } }) })));
145
120
  });
@@ -14,7 +14,4 @@ export declare const FieldSelectSingle: import("react").ForwardRefExoticComponen
14
14
  footer?: import("react").ReactNode;
15
15
  search?: import("./types").SearchState | undefined;
16
16
  autocomplete?: boolean | undefined;
17
- addOptionByEnter?: boolean | undefined;
18
- open?: boolean | undefined;
19
- onOpenChange?(open: boolean): void;
20
- } & Pick<import("@snack-uikit/list").ListProps, "dataError" | "noDataState" | "noResultsState" | "errorDataState" | "pinTop" | "pinBottom" | "dataFiltered"> & import("react").RefAttributes<HTMLInputElement>>;
17
+ } & import("react").RefAttributes<HTMLInputElement>>;
@@ -11,49 +11,38 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import mergeRefs from 'merge-refs';
14
- import { forwardRef, useEffect, useMemo, useRef } from 'react';
14
+ import { forwardRef, useEffect, useMemo, useRef, useState } from 'react';
15
15
  import { InputPrivate } from '@snack-uikit/input-private';
16
16
  import { Droplist, useFuzzySearch } from '@snack-uikit/list';
17
17
  import { extractSupportProps } from '@snack-uikit/utils';
18
18
  import { FieldContainerPrivate } from '../../helperComponents';
19
19
  import { useValueControl } from '../../hooks';
20
20
  import { FieldDecorator } from '../FieldDecorator';
21
- import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
22
21
  import { useButtons, useHandleOnKeyDown, useSearchInput } from './hooks';
23
22
  import styles from './styles.module.css';
24
- import { extractListProps, findSelectedOption, getArrowIcon, transformOptionsToItems } from './utils';
23
+ import { extractSelectedOptions, getArrowIcon, transformOptionsToItems } from './utils';
25
24
  export const FieldSelectSingle = forwardRef((_a, ref) => {
26
- var _b, _c;
27
- var { id, name, placeholder, size = 's', options, value: valueProp, defaultValue, onChange: onChangeProp, disabled = false, readonly = false, searchable = true, showCopyButton = true, showClearButton = true, onKeyDown: onInputKeyDownProp, required = false, validationState = 'default', search, autocomplete = false, prefixIcon, addOptionByEnter = false, open: openProp, onOpenChange } = _a, rest = __rest(_a, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "disabled", "readonly", "searchable", "showCopyButton", "showClearButton", "onKeyDown", "required", "validationState", "search", "autocomplete", "prefixIcon", "addOptionByEnter", "open", "onOpenChange"]);
25
+ var _b;
26
+ var { id, name, placeholder, size = 's', options, value: valueProp, defaultValue, onChange: onChangeProp, loading, disabled = false, readonly = false, searchable = true, showCopyButton = true, showClearButton = true, onKeyDown: onInputKeyDownProp, label, labelTooltip, labelTooltipPlacement, required = false, hint, showHintIcon, validationState = 'default', footer, search, autocomplete = false, prefixIcon, error } = _a, rest = __rest(_a, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "loading", "disabled", "readonly", "searchable", "showCopyButton", "showClearButton", "onKeyDown", "label", "labelTooltip", "labelTooltipPlacement", "required", "hint", "showHintIcon", "validationState", "footer", "search", "autocomplete", "prefixIcon", "error"]);
28
27
  const localRef = useRef(null);
29
- const [open = false, setOpen] = useValueControl({ value: openProp, onChange: onOpenChange });
28
+ const [open, setOpen] = useState(false);
30
29
  const [value, setValue] = useValueControl({
31
30
  value: valueProp,
32
31
  defaultValue,
33
32
  onChange: onChangeProp,
34
33
  });
35
34
  const items = useMemo(() => transformOptionsToItems(options), [options]);
36
- const { selected, itemsWithPlaceholder } = useMemo(() => {
37
- const [fonded, placeholder] = findSelectedOption(items, value);
38
- return {
39
- selected: fonded !== null && fonded !== void 0 ? fonded : placeholder,
40
- itemsWithPlaceholder: (placeholder ? [placeholder] : []).concat(items),
41
- };
42
- }, [items, value]);
43
- const { inputValue, onInputValueChange, prevInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: (_b = selected === null || selected === void 0 ? void 0 : selected.content.option) !== null && _b !== void 0 ? _b : '' }));
35
+ const selectedOption = useMemo(() => extractSelectedOptions(options, value), [options, value]);
36
+ const { inputValue, onInputValueChange, prevInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: String(selectedOption !== null && selectedOption !== void 0 ? selectedOption : '') }));
37
+ useEffect(() => {
38
+ var _a;
39
+ !open && onInputValueChange(String((_a = selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.option) !== null && _a !== void 0 ? _a : ''));
40
+ }, [onInputValueChange, open, selectedOption]);
44
41
  useEffect(() => {
45
- if ((selected === null || selected === void 0 ? void 0 : selected.content.option) && prevInputValue.current !== (selected === null || selected === void 0 ? void 0 : selected.content.option)) {
46
- onInputValueChange(selected.content.option);
47
- prevInputValue.current = selected === null || selected === void 0 ? void 0 : selected.content.option;
48
- }
49
- }, [onInputValueChange, selected === null || selected === void 0 ? void 0 : selected.content.option, prevInputValue]);
50
- const handleBlur = (e) => {
51
42
  var _a, _b;
52
- if (!open && (selected === null || selected === void 0 ? void 0 : selected.content.option) !== inputValue) {
53
- onInputValueChange((_a = selected === null || selected === void 0 ? void 0 : selected.content.option) !== null && _a !== void 0 ? _a : '');
54
- }
55
- (_b = rest === null || rest === void 0 ? void 0 : rest.onBlur) === null || _b === void 0 ? void 0 : _b.call(rest, e);
56
- };
43
+ onInputValueChange(String((_a = selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.option) !== null && _a !== void 0 ? _a : ''));
44
+ prevInputValue.current = String((_b = selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.option) !== null && _b !== void 0 ? _b : '');
45
+ }, [prevInputValue, onInputValueChange, selectedOption]);
57
46
  const onClear = () => {
58
47
  var _a;
59
48
  setValue('');
@@ -65,11 +54,11 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
65
54
  const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
66
55
  readonly,
67
56
  size,
68
- showClearButton: showClearButton && !disabled && !readonly && Boolean(value),
57
+ showClearButton: showClearButton && Boolean(value),
69
58
  showCopyButton,
70
59
  inputRef: localRef,
71
60
  onClear,
72
- valueToCopy: (_c = selected === null || selected === void 0 ? void 0 : selected.content.option) !== null && _c !== void 0 ? _c : '',
61
+ valueToCopy: String((_b = selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.option) !== null && _b !== void 0 ? _b : ''),
73
62
  });
74
63
  const commonHandleOnKeyDown = useHandleOnKeyDown({
75
64
  inputKeyDownNavigationHandler,
@@ -80,13 +69,6 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
80
69
  if (!open && prevInputValue.current !== inputValue) {
81
70
  setOpen(true);
82
71
  }
83
- if (e.code === 'Enter') {
84
- e.stopPropagation();
85
- e.preventDefault();
86
- }
87
- if (addOptionByEnter && e.code === 'Enter' && inputValue !== '') {
88
- setValue(inputValue);
89
- }
90
72
  commonHandleOnKeyDown(onKeyDown)(e);
91
73
  };
92
74
  const handleSelectionChange = (newValue) => {
@@ -98,22 +80,15 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
98
80
  }
99
81
  };
100
82
  const handleOpenChange = (open) => {
101
- var _a, _b;
102
83
  if (!readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
103
84
  setOpen(open);
104
- if (!open) {
105
- onInputValueChange((_a = selected === null || selected === void 0 ? void 0 : selected.content.option) !== null && _a !== void 0 ? _a : '');
106
- prevInputValue.current = (_b = selected === null || selected === void 0 ? void 0 : selected.content.option) !== null && _b !== void 0 ? _b : '';
107
- }
108
85
  }
109
86
  };
110
- const fuzzySearch = useFuzzySearch(itemsWithPlaceholder);
111
- const result = autocomplete || !searchable || prevInputValue.current === inputValue
112
- ? itemsWithPlaceholder
113
- : fuzzySearch(inputValue);
114
- return (_jsx(FieldDecorator, Object.assign({}, extractSupportProps(rest), extractFieldDecoratorProps(rest), { validationState: validationState, required: required, readonly: readonly, labelFor: id, disabled: disabled, size: size, children: _jsx(Droplist, Object.assign({}, extractListProps(rest), { items: result, selection: {
87
+ const fuzzySearch = useFuzzySearch(items);
88
+ const result = autocomplete ? items : fuzzySearch(prevInputValue.current !== inputValue ? inputValue : '');
89
+ return (_jsx(FieldDecorator, Object.assign({}, extractSupportProps(rest), { error: error, required: required, readonly: readonly, label: label, labelTooltip: labelTooltip, labelTooltipPlacement: labelTooltipPlacement, labelFor: id, hint: hint, disabled: disabled, showHintIcon: showHintIcon, size: size, validationState: validationState, children: _jsx(Droplist, { trigger: 'clickAndFocusVisible', placement: 'bottom', "data-test-id": 'field-select__list', items: result, triggerElemRef: localRef, scroll: true, marker: true, footer: footer, selection: {
115
90
  mode: 'single',
116
91
  value: value,
117
92
  onChange: handleSelectionChange,
118
- }, size: size, open: open, onOpenChange: handleOpenChange, triggerElemRef: localRef, children: ({ onKeyDown }) => (_jsxs(FieldContainerPrivate, { className: styles.container, validationState: validationState, disabled: disabled, readonly: readonly, focused: open, variant: 'single-line-container', inputRef: localRef, size: size, prefix: prefixIcon, children: [_jsx(InputPrivate, { id: id, name: name, type: 'text', disabled: disabled, placeholder: placeholder, ref: mergeRefs(ref, localRef), onChange: searchable ? onInputValueChange : undefined, value: inputValue, readonly: !searchable || readonly, "data-test-id": 'field-select__input', onKeyDown: handleOnKeyDown(onKeyDown), onBlur: handleBlur }), _jsxs("div", { className: styles.postfix, children: [buttons, _jsx(ArrowIcon, { size: arrowIconSize, className: styles.arrowIcon })] })] })) })) })));
93
+ }, size: size, open: open, onOpenChange: handleOpenChange, loading: loading, children: ({ onKeyDown }) => (_jsxs(FieldContainerPrivate, { className: styles.container, validationState: validationState, disabled: disabled, readonly: readonly, focused: open, variant: 'single-line-container', inputRef: localRef, size: size, prefix: prefixIcon, children: [_jsx(InputPrivate, { id: id, name: name, type: 'text', disabled: disabled, placeholder: placeholder, ref: mergeRefs(ref, localRef), onChange: searchable ? onInputValueChange : undefined, value: inputValue, readonly: !searchable || readonly, "data-test-id": 'field-select__input', onKeyDown: handleOnKeyDown(onKeyDown) }), _jsxs("div", { className: styles.postfix, children: [buttons, _jsx(ArrowIcon, { size: arrowIconSize, className: styles.arrowIcon })] })] })) }) })));
119
94
  });
@@ -1,6 +1,6 @@
1
1
  import { KeyboardEvent, KeyboardEventHandler, RefObject } from 'react';
2
2
  import { Handler } from 'uncontrollable';
3
- import { ItemWithId, SearchState } from './types';
3
+ import { OptionProps, SearchState } from './types';
4
4
  type UseHandleOnKeyDownProps = {
5
5
  inputKeyDownNavigationHandler: KeyboardEventHandler<HTMLInputElement>;
6
6
  onInputKeyDownProp: KeyboardEventHandler<HTMLInputElement> | undefined;
@@ -26,5 +26,5 @@ export declare function useSearchInput({ value, onChange, defaultValue }: Search
26
26
  onInputValueChange: Handler;
27
27
  prevInputValue: import("react").MutableRefObject<string>;
28
28
  };
29
- export declare function useHandleDeleteItem(setValue: Handler): (item?: ItemWithId) => () => void;
29
+ export declare function useHandleDeleteItem(setValue: Handler): (option?: OptionProps) => () => void;
30
30
  export {};
@@ -1,8 +1,9 @@
1
1
  import { useCallback, useMemo, useRef } from 'react';
2
+ import { useUncontrolledProp } from 'uncontrollable';
2
3
  import { useButtonNavigation, useClearButton } from '@snack-uikit/input-private';
3
- import { extractChildIds, isAccordionItemProps, isNextListItemProps, } from '@snack-uikit/list';
4
- import { useCopyButton, useValueControl } from '../../hooks';
5
- import { isBaseOptionProps } from './utils';
4
+ import { extractChildIds } from '@snack-uikit/list/dist/utils';
5
+ import { useCopyButton } from '../../hooks';
6
+ import { isAccordionOptionProps, isBaseOptionProps, isNextListOptionProps, transformOptionsToItems } from './utils';
6
7
  export function useHandleOnKeyDown({ setOpen, inputKeyDownNavigationHandler, onInputKeyDownProp, }) {
7
8
  return useCallback((onKeyDown) => (e) => {
8
9
  if (e.code === 'Space') {
@@ -50,23 +51,22 @@ export function useButtons({ readonly, showClearButton, showCopyButton, size, on
50
51
  return { buttons, inputKeyDownNavigationHandler, buttonsRefs };
51
52
  }
52
53
  export function useSearchInput({ value, onChange, defaultValue }) {
53
- const [inputValue = '', onInputValueChange] = useValueControl({ value, onChange, defaultValue });
54
+ const [inputValue, onInputValueChange] = useUncontrolledProp(value, defaultValue !== null && defaultValue !== void 0 ? defaultValue : '', onChange);
54
55
  const prevInputValue = useRef(inputValue);
55
56
  return { inputValue, onInputValueChange, prevInputValue };
56
57
  }
57
58
  export function useHandleDeleteItem(setValue) {
58
- return useCallback((item) => () => {
59
- var _a;
60
- if (!item) {
59
+ return useCallback((option) => () => {
60
+ if (!option) {
61
61
  return;
62
62
  }
63
- if (isAccordionItemProps(item) || isNextListItemProps(item)) {
64
- const removeIds = extractChildIds({ items: item.items }).concat((_a = item.id) !== null && _a !== void 0 ? _a : '');
63
+ if (isAccordionOptionProps(option) || isNextListOptionProps(option)) {
64
+ const removeIds = extractChildIds({ items: transformOptionsToItems(option.options) }).concat(option.value);
65
65
  setValue((value) => value === null || value === void 0 ? void 0 : value.filter(v => !removeIds.includes(v !== null && v !== void 0 ? v : '')));
66
66
  return;
67
67
  }
68
- if (isBaseOptionProps(item)) {
69
- setValue((value) => value === null || value === void 0 ? void 0 : value.filter(v => v !== item.id));
68
+ if (isBaseOptionProps(option)) {
69
+ setValue((value) => value === null || value === void 0 ? void 0 : value.filter(v => v !== option.value));
70
70
  }
71
71
  }, [setValue]);
72
72
  }
@@ -48,18 +48,12 @@ type FiledSelectCommonProps = WithSupportProps<{
48
48
  footer?: ListProps['footer'];
49
49
  search?: SearchState;
50
50
  autocomplete?: boolean;
51
- addOptionByEnter?: boolean;
52
- open?: boolean;
53
- onOpenChange?(open: boolean): void;
54
- }> & Pick<ListProps, 'dataError' | 'noDataState' | 'noResultsState' | 'errorDataState' | 'pinTop' | 'pinBottom' | 'dataFiltered'>;
51
+ }>;
55
52
  export type FieldSelectSingleProps = FieldSelectPrivateProps & Omit<SelectionSingleState, 'mode'> & WrapperProps & FiledSelectCommonProps;
56
- export type FieldSelectMultipleProps = FieldSelectPrivateProps & {
57
- removeByBackspace?: boolean;
58
- } & Omit<SelectionMultipleState, 'mode'> & Omit<FiledSelectCommonProps, 'showCopyButton'>;
53
+ export type FieldSelectMultipleProps = FieldSelectPrivateProps & Omit<SelectionMultipleState, 'mode'> & Omit<FiledSelectCommonProps, 'showCopyButton'>;
59
54
  export type FieldSelectProps = (FieldSelectSingleProps & {
60
55
  selection?: 'single';
61
56
  }) | (FieldSelectMultipleProps & {
62
57
  selection: 'multiple';
63
58
  });
64
- export type ItemWithId = BaseItemProps | AccordionItemProps | NextListItemProps;
65
59
  export {};
@@ -1,13 +1,13 @@
1
1
  import { Size } from '@snack-uikit/input-private';
2
- import { DroplistProps, ItemProps, SelectionSingleValueType } from '@snack-uikit/list';
3
- import { AccordionOptionProps, BaseOptionProps, FieldSelectMultipleProps, FieldSelectProps, FieldSelectSingleProps, GroupOptionProps, ItemWithId, NestListOptionProps, OptionProps } from './types';
2
+ import { ItemProps } from '@snack-uikit/list';
3
+ import { AccordionOptionProps, BaseOptionProps, FieldSelectMultipleProps, FieldSelectSingleProps, GroupOptionProps, NestListOptionProps, OptionProps, OptionWithoutGroup } from './types';
4
4
  export declare function isBaseOptionProps(option: any): option is BaseOptionProps;
5
5
  export declare function isAccordionOptionProps(option: any): option is AccordionOptionProps;
6
6
  export declare function isNextListOptionProps(option: any): option is NestListOptionProps;
7
7
  export declare function isGroupOptionProps(option: any): option is GroupOptionProps;
8
8
  export declare function transformOptionsToItems(options: OptionProps[]): ItemProps[];
9
- export declare function findSelectedOption(items: ItemProps[], value: SelectionSingleValueType): [ItemWithId | undefined, ItemWithId | undefined];
10
- export declare function findSelectedOptions(items: ItemProps[], value: SelectionSingleValueType[] | undefined): [ItemWithId[] | undefined, ItemWithId[] | undefined];
9
+ export declare function extractSelectedOptions(options: OptionProps[], value: string | number | undefined): OptionWithoutGroup | undefined;
10
+ export declare function extractSelectedMultipleOptions(options: OptionProps[], value?: (string | number | undefined)[]): OptionWithoutGroup[] | undefined;
11
11
  export declare function isFieldSelectMultipleProps(props: any): props is FieldSelectMultipleProps;
12
12
  export declare function isFieldSelectSingleProps(props: any): props is FieldSelectSingleProps;
13
13
  export declare function getArrowIcon({ size, open }: {
@@ -17,4 +17,3 @@ export declare function getArrowIcon({ size, open }: {
17
17
  ArrowIcon: ({ size, ...props }: import("@snack-uikit/icons/dist/components/interface-icons/chevronUp").ISvgIconProps) => import("react/jsx-runtime").JSX.Element;
18
18
  arrowIconSize: 16 | 24;
19
19
  };
20
- export declare function extractListProps({ dataError, noDataState, noResultsState, errorDataState, pinTop, pinBottom, dataFiltered, loading, }: Partial<FieldSelectProps>): Partial<DroplistProps>;
@@ -11,7 +11,6 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  };
12
12
  import { ChevronDownSVG, ChevronUpSVG } from '@snack-uikit/icons';
13
13
  import { ICON_SIZE, SIZE } from '@snack-uikit/input-private';
14
- import { flattenItems } from '@snack-uikit/list';
15
14
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
15
  export function isBaseOptionProps(option) {
17
16
  return !('options' in option);
@@ -42,34 +41,60 @@ export function transformOptionsToItems(options) {
42
41
  return Object.assign(Object.assign({ 'data-test-id': 'field-select__list-option-' + option.value }, rest), { id: value, content: { option: contentOption, caption, description } });
43
42
  });
44
43
  }
45
- export function findSelectedOption(items, value) {
46
- const flatten = flattenItems(items);
47
- if (!value) {
48
- return [undefined, undefined];
44
+ export function extractSelectedOptions(options, value) {
45
+ for (let i = 0; i < options.length; i++) {
46
+ const option = options[i];
47
+ if (isAccordionOptionProps(option) || isNextListOptionProps(option)) {
48
+ const { value: optionValue } = option;
49
+ if (optionValue === value) {
50
+ return option;
51
+ }
52
+ const selectedOptionFromNestedOptions = extractSelectedOptions(option.options, value);
53
+ if (selectedOptionFromNestedOptions) {
54
+ return selectedOptionFromNestedOptions;
55
+ }
56
+ }
57
+ if (isGroupOptionProps(option)) {
58
+ const selectedOptionFromNestedOptions = extractSelectedOptions(option.options, value);
59
+ if (selectedOptionFromNestedOptions) {
60
+ return selectedOptionFromNestedOptions;
61
+ }
62
+ }
63
+ if (isBaseOptionProps(option)) {
64
+ if (option.value === value) {
65
+ return option;
66
+ }
67
+ }
49
68
  }
50
- const foundItem = flatten.find(item => String(item.id) === String(value));
51
- const placeholderItem = { id: value, content: { option: String(value) } };
52
- return [foundItem, !foundItem ? placeholderItem : undefined];
69
+ return undefined;
53
70
  }
54
- export function findSelectedOptions(items, value) {
55
- const flatten = flattenItems(items);
56
- if (!value || !(value === null || value === void 0 ? void 0 : value.length)) {
57
- return [undefined, undefined];
58
- }
59
- let foundItems;
60
- let placeholderItems;
61
- value.forEach(value => {
62
- if (flatten) {
63
- const [found, placeholder] = findSelectedOption(flatten, value);
64
- if (found || foundItems) {
65
- foundItems = (foundItems !== null && foundItems !== void 0 ? foundItems : []).concat(found !== null && found !== void 0 ? found : []);
71
+ export function extractSelectedMultipleOptions(options, value) {
72
+ let selectedOptions = [];
73
+ for (let i = 0; i < options.length; i++) {
74
+ const option = options[i];
75
+ if (isAccordionOptionProps(option) || isNextListOptionProps(option)) {
76
+ const { value: optionValue } = option;
77
+ if (value === null || value === void 0 ? void 0 : value.includes(optionValue)) {
78
+ selectedOptions.push(option);
66
79
  }
67
- if (placeholder || placeholderItems) {
68
- placeholderItems = (placeholderItems !== null && placeholderItems !== void 0 ? placeholderItems : []).concat(placeholder !== null && placeholder !== void 0 ? placeholder : []);
80
+ const selectedOptionFromNestedOptions = extractSelectedMultipleOptions(option.options, value);
81
+ if (selectedOptionFromNestedOptions) {
82
+ selectedOptions = selectedOptions.concat(selectedOptionFromNestedOptions);
69
83
  }
70
84
  }
71
- });
72
- return [foundItems, placeholderItems];
85
+ if (isGroupOptionProps(option)) {
86
+ const selectedOptionFromNestedOptions = extractSelectedMultipleOptions(option.options, value);
87
+ if (selectedOptionFromNestedOptions) {
88
+ selectedOptions = selectedOptions.concat(selectedOptionFromNestedOptions);
89
+ }
90
+ }
91
+ if (isBaseOptionProps(option)) {
92
+ if (value === null || value === void 0 ? void 0 : value.includes(option.value)) {
93
+ selectedOptions.push(option);
94
+ }
95
+ }
96
+ }
97
+ return selectedOptions.length ? selectedOptions : undefined;
73
98
  }
74
99
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
100
  export function isFieldSelectMultipleProps(props) {
@@ -85,20 +110,3 @@ export function getArrowIcon({ size, open }) {
85
110
  arrowIconSize: size === SIZE.S ? ICON_SIZE.Xs : ICON_SIZE.S,
86
111
  };
87
112
  }
88
- export function extractListProps({ dataError, noDataState, noResultsState, errorDataState, pinTop, pinBottom, dataFiltered, loading, }) {
89
- return {
90
- dataError,
91
- noDataState,
92
- noResultsState,
93
- errorDataState,
94
- pinTop,
95
- pinBottom,
96
- dataFiltered,
97
- loading,
98
- trigger: 'clickAndFocusVisible',
99
- placement: 'bottom',
100
- 'data-test-id': 'field-select__list',
101
- scroll: true,
102
- marker: true,
103
- };
104
- }
@@ -1,6 +1,6 @@
1
1
  import { useUncontrolledProp } from 'uncontrollable';
2
2
  export function useValueControl({ value, onChange, defaultValue }) {
3
- return useUncontrolledProp(value, defaultValue, (newValue) => {
3
+ return useUncontrolledProp(value, value !== null && value !== void 0 ? value : defaultValue, (newValue) => {
4
4
  const newState = typeof newValue === 'function' ? newValue(value) : newValue;
5
5
  onChange === null || onChange === void 0 ? void 0 : onChange(newState);
6
6
  });
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "Fields",
7
- "version": "0.16.1-preview-3bc93fc3.0",
7
+ "version": "0.16.1",
8
8
  "sideEffects": [
9
9
  "*.css",
10
10
  "*.woff",
@@ -34,13 +34,13 @@
34
34
  "dependencies": {
35
35
  "@snack-uikit/button": "0.16.1",
36
36
  "@snack-uikit/calendar": "0.7.6",
37
- "@snack-uikit/droplist": "0.13.9-preview-3bc93fc3.0",
37
+ "@snack-uikit/droplist": "0.13.8",
38
38
  "@snack-uikit/icons": "0.20.1",
39
39
  "@snack-uikit/input-private": "3.1.1",
40
- "@snack-uikit/list": "0.4.2-preview-3bc93fc3.0",
40
+ "@snack-uikit/list": "0.5.0",
41
41
  "@snack-uikit/scroll": "0.5.2",
42
42
  "@snack-uikit/slider": "0.1.4",
43
- "@snack-uikit/tag": "0.8.1-preview-3bc93fc3.0",
43
+ "@snack-uikit/tag": "0.8.0",
44
44
  "@snack-uikit/tooltip": "0.12.1",
45
45
  "@snack-uikit/truncate-string": "0.4.9",
46
46
  "@snack-uikit/utils": "3.2.0",
@@ -56,5 +56,5 @@
56
56
  "peerDependencies": {
57
57
  "@snack-uikit/locale": "*"
58
58
  },
59
- "gitHead": "a2fa7717157c8a23fa1fc6b64c67c7b2d9dfc39c"
59
+ "gitHead": "bfdd4a8e3c077eab0d45e177172a62b6dcbda06b"
60
60
  }