@snack-uikit/fields 0.17.13 → 0.17.14-preview-b0dbf1fa.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.
- package/dist/components/FieldSelect/FieldSelectMultiple.js +27 -51
- package/dist/components/FieldSelect/FieldSelectSingle.js +34 -43
- package/dist/components/FieldSelect/hooks.d.ts +3 -1
- package/dist/components/FieldSelect/hooks.js +8 -2
- package/dist/components/FieldSelect/types.d.ts +4 -1
- package/dist/components/FieldSelect/utils/extractListProps.d.ts +3 -0
- package/dist/components/FieldSelect/utils/extractListProps.js +17 -0
- package/dist/components/FieldSelect/utils/getArrowIcon.d.ts +8 -0
- package/dist/components/FieldSelect/utils/getArrowIcon.js +8 -0
- package/dist/components/FieldSelect/utils/index.d.ts +5 -0
- package/dist/components/FieldSelect/utils/index.js +5 -0
- package/dist/components/FieldSelect/utils/options.d.ts +8 -0
- package/dist/components/FieldSelect/utils/options.js +56 -0
- package/dist/components/FieldSelect/utils/typeGuards.d.ts +7 -0
- package/dist/components/FieldSelect/utils/typeGuards.js +24 -0
- package/dist/components/FieldSelect/utils/updateItems.d.ts +32 -0
- package/dist/components/FieldSelect/utils/updateItems.js +67 -0
- package/dist/helperComponents/FieldContainerPrivate/styles.module.css +4 -7
- package/dist/hooks/useValueControl.d.ts +1 -1
- package/package.json +7 -7
- package/src/components/FieldSelect/FieldSelectMultiple.tsx +28 -68
- package/src/components/FieldSelect/FieldSelectSingle.tsx +51 -46
- package/src/components/FieldSelect/hooks.ts +12 -2
- package/src/components/FieldSelect/types.ts +4 -1
- package/src/components/FieldSelect/utils/extractListProps.ts +30 -0
- package/src/components/FieldSelect/utils/getArrowIcon.ts +9 -0
- package/src/components/FieldSelect/utils/index.ts +5 -0
- package/src/components/FieldSelect/utils/options.ts +87 -0
- package/src/components/FieldSelect/utils/typeGuards.ts +38 -0
- package/src/components/FieldSelect/utils/updateItems.ts +105 -0
- package/src/helperComponents/FieldContainerPrivate/styles.module.scss +6 -6
- package/dist/components/FieldSelect/utils.d.ts +0 -22
- package/dist/components/FieldSelect/utils.js +0 -122
- package/src/components/FieldSelect/utils.ts +0 -187
|
@@ -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,
|
|
15
|
+
import { forwardRef, useLayoutEffect, 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';
|
|
@@ -23,58 +23,35 @@ import { FieldDecorator } from '../FieldDecorator';
|
|
|
23
23
|
import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
|
|
24
24
|
import { useButtons, useHandleDeleteItem, useHandleOnKeyDown, useSearchInput } from './hooks';
|
|
25
25
|
import styles from './styles.module.css';
|
|
26
|
-
import { extractListProps,
|
|
26
|
+
import { extractListProps, getArrowIcon, updateMultipleItems } from './utils';
|
|
27
27
|
const BASE_MIN_WIDTH = 4;
|
|
28
28
|
export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
29
|
-
var _b
|
|
29
|
+
var _b;
|
|
30
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"]);
|
|
31
31
|
const localRef = useRef(null);
|
|
32
32
|
const inputPlugRef = useRef(null);
|
|
33
33
|
const contentRef = useRef(null);
|
|
34
34
|
const [open = false, setOpen] = useValueControl({ value: openProp, onChange: onOpenChange });
|
|
35
|
-
const items = useMemo(() => transformOptionsToItems(options), [options]);
|
|
36
|
-
const mapItemsToTagAppearance = useMemo(() => mapOptionToAppearance(options), [options]);
|
|
37
35
|
const [value, setValue] = useValueControl({
|
|
38
36
|
value: valueProp,
|
|
39
37
|
defaultValue,
|
|
40
38
|
onChange: onChangeProp,
|
|
41
39
|
});
|
|
42
|
-
const {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (b.disabled && !a.disabled) {
|
|
48
|
-
return 1;
|
|
49
|
-
}
|
|
50
|
-
if (a.disabled && !b.disabled) {
|
|
51
|
-
return -1;
|
|
52
|
-
}
|
|
53
|
-
return 0;
|
|
54
|
-
})
|
|
55
|
-
: undefined;
|
|
56
|
-
const placeholderItems = placeholder ? placeholder : [];
|
|
57
|
-
const disabledSelected = selected === null || selected === void 0 ? void 0 : selected.filter((item) => item.disabled);
|
|
58
|
-
return {
|
|
59
|
-
selected,
|
|
60
|
-
disabledSelected,
|
|
61
|
-
itemsWithPlaceholder: placeholderItems.concat(items),
|
|
62
|
-
};
|
|
63
|
-
}, [items, value]);
|
|
64
|
-
const { inputValue, onInputValueChange, prevInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: '' }));
|
|
40
|
+
const [{ selectedItems, items = [] }, setItems] = useState(() => updateMultipleItems({ options, value, currentItems: [], selectedItems: undefined }));
|
|
41
|
+
const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: '' }));
|
|
42
|
+
useLayoutEffect(() => {
|
|
43
|
+
setItems(({ selectedItems }) => updateMultipleItems({ options, value, selectedItems }));
|
|
44
|
+
}, [options, value]);
|
|
65
45
|
const onClear = () => {
|
|
66
46
|
var _a;
|
|
67
|
-
|
|
68
|
-
setValue(disabledValues);
|
|
69
|
-
onInputValueChange('');
|
|
47
|
+
setValue(selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.filter(item => item.disabled).map(item => item.id));
|
|
70
48
|
(_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
71
|
-
setOpen(true);
|
|
72
49
|
};
|
|
73
50
|
const { ArrowIcon, arrowIconSize } = getArrowIcon({ size, open });
|
|
74
51
|
const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
|
|
75
52
|
readonly,
|
|
76
53
|
size,
|
|
77
|
-
showClearButton: showClearButton && !disabled && !readonly && (
|
|
54
|
+
showClearButton: showClearButton && !disabled && !readonly && Boolean(selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.find(item => !item.disabled)),
|
|
78
55
|
showCopyButton: false,
|
|
79
56
|
inputRef: localRef,
|
|
80
57
|
onClear,
|
|
@@ -87,8 +64,8 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
|
87
64
|
const handleItemDelete = useHandleDeleteItem(setValue);
|
|
88
65
|
const handleOnKeyDown = (onKeyDown) => (e) => {
|
|
89
66
|
if (removeByBackspace && e.code === 'Backspace' && inputValue === '') {
|
|
90
|
-
if ((
|
|
91
|
-
handleItemDelete(
|
|
67
|
+
if ((selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.length) && !selectedItems.slice(-1)[0].disabled) {
|
|
68
|
+
handleItemDelete(selectedItems.pop())();
|
|
92
69
|
}
|
|
93
70
|
}
|
|
94
71
|
if (e.code === 'Enter') {
|
|
@@ -97,8 +74,7 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
|
97
74
|
}
|
|
98
75
|
if (addOptionByEnter && e.code === 'Enter' && inputValue !== '') {
|
|
99
76
|
setValue((value) => (value !== null && value !== void 0 ? value : []).concat(inputValue));
|
|
100
|
-
|
|
101
|
-
prevInputValue.current = '';
|
|
77
|
+
updateInputValue();
|
|
102
78
|
}
|
|
103
79
|
if (!open && prevInputValue.current !== inputValue) {
|
|
104
80
|
setOpen(true);
|
|
@@ -109,8 +85,7 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
|
109
85
|
if (!readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
110
86
|
setOpen(open);
|
|
111
87
|
if (!open) {
|
|
112
|
-
|
|
113
|
-
prevInputValue.current = '';
|
|
88
|
+
updateInputValue();
|
|
114
89
|
if (inputPlugRef.current) {
|
|
115
90
|
inputPlugRef.current.style.width = BASE_MIN_WIDTH + 'px';
|
|
116
91
|
}
|
|
@@ -124,26 +99,27 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
|
124
99
|
};
|
|
125
100
|
const handleBlur = (e) => {
|
|
126
101
|
var _a;
|
|
127
|
-
if (!open) {
|
|
128
|
-
onInputValueChange('');
|
|
129
|
-
}
|
|
130
102
|
(_a = rest === null || rest === void 0 ? void 0 : rest.onBlur) === null || _a === void 0 ? void 0 : _a.call(rest, e);
|
|
131
103
|
};
|
|
132
|
-
const fuzzySearch = useFuzzySearch(
|
|
133
|
-
const result = autocomplete || !searchable || prevInputValue.current === inputValue
|
|
134
|
-
? itemsWithPlaceholder
|
|
135
|
-
: fuzzySearch(inputValue);
|
|
104
|
+
const fuzzySearch = useFuzzySearch(items);
|
|
105
|
+
const result = autocomplete || !searchable || prevInputValue.current === inputValue ? items : fuzzySearch(inputValue);
|
|
136
106
|
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: {
|
|
137
107
|
mode: 'multiple',
|
|
138
108
|
value: value,
|
|
139
|
-
onChange:
|
|
140
|
-
|
|
109
|
+
onChange: value => {
|
|
110
|
+
updateInputValue();
|
|
111
|
+
setValue(value);
|
|
112
|
+
},
|
|
113
|
+
}, dataFiltered: (_b = rest.dataFiltered) !== null && _b !== void 0 ? _b : Boolean(inputValue.length), size: size, open: !disabled && !readonly && open, onOpenChange: handleOpenChange, children: ({ onKeyDown }) => {
|
|
141
114
|
var _a, _b, _c, _d;
|
|
142
|
-
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: [
|
|
143
|
-
|
|
115
|
+
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: [selectedItems &&
|
|
116
|
+
selectedItems.map(option => {
|
|
117
|
+
var _a;
|
|
118
|
+
return (_jsx(Tag, { size: size === 'l' ? 's' : 'xs', tabIndex: -1, label: String(option.content.option), appearance: (_a = option.appearance) !== null && _a !== void 0 ? _a : 'neutral', onDelete: !option.disabled && !disabled && !readonly ? handleItemDelete(option) : undefined }, option.id));
|
|
119
|
+
}), _jsx("div", { className: styles.inputWrapper, style: {
|
|
144
120
|
minWidth: value
|
|
145
121
|
? 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)
|
|
146
122
|
: '100%',
|
|
147
|
-
}, children: _jsx(InputPrivate, { id: id, name: name, type: 'text', disabled: disabled, placeholder: !
|
|
123
|
+
}, children: _jsx(InputPrivate, { id: id, name: name, type: 'text', disabled: disabled, placeholder: !selectedItems || !selectedItems.length ? placeholder : undefined, ref: mergeRefs(ref, localRef), onChange: searchable ? setInputValue : 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 })] }) }));
|
|
148
124
|
} })) })));
|
|
149
125
|
});
|
|
@@ -11,7 +11,7 @@ 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,
|
|
14
|
+
import { forwardRef, useCallback, useEffect, useLayoutEffect, 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';
|
|
@@ -21,7 +21,7 @@ import { FieldDecorator } from '../FieldDecorator';
|
|
|
21
21
|
import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
|
|
22
22
|
import { useButtons, useHandleOnKeyDown, useSearchInput } from './hooks';
|
|
23
23
|
import styles from './styles.module.css';
|
|
24
|
-
import { extractListProps,
|
|
24
|
+
import { extractListProps, getArrowIcon, updateItems } from './utils';
|
|
25
25
|
export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
26
26
|
var _b, _c;
|
|
27
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"]);
|
|
@@ -32,35 +32,27 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
|
32
32
|
defaultValue,
|
|
33
33
|
onChange: onChangeProp,
|
|
34
34
|
});
|
|
35
|
-
const items =
|
|
36
|
-
const {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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 [{ selectedItem, items = [] }, setItems] = useState(() => updateItems({ options, value, currentItems: [], selectedItem: undefined }));
|
|
36
|
+
const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: (_b = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.content.option) !== null && _b !== void 0 ? _b : '' }));
|
|
37
|
+
useLayoutEffect(() => {
|
|
38
|
+
setItems(({ selectedItem }) => updateItems({ options, value, selectedItem }));
|
|
39
|
+
}, [options, value]);
|
|
44
40
|
useEffect(() => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
}, [onInputValueChange, selected === null || selected === void 0 ? void 0 : selected.content.option, prevInputValue]);
|
|
41
|
+
updateInputValue(selectedItem);
|
|
42
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
43
|
+
}, [selectedItem]);
|
|
50
44
|
const handleBlur = (e) => {
|
|
51
|
-
var _a
|
|
52
|
-
if (!open
|
|
53
|
-
|
|
45
|
+
var _a;
|
|
46
|
+
if (!open) {
|
|
47
|
+
updateInputValue(selectedItem);
|
|
54
48
|
}
|
|
55
|
-
(
|
|
49
|
+
(_a = rest === null || rest === void 0 ? void 0 : rest.onBlur) === null || _a === void 0 ? void 0 : _a.call(rest, e);
|
|
56
50
|
};
|
|
57
|
-
const onClear = () => {
|
|
51
|
+
const onClear = useCallback(() => {
|
|
58
52
|
var _a;
|
|
59
|
-
setValue(
|
|
60
|
-
onInputValueChange('');
|
|
53
|
+
setValue(undefined);
|
|
61
54
|
(_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
62
|
-
|
|
63
|
-
};
|
|
55
|
+
}, [setValue]);
|
|
64
56
|
const { ArrowIcon, arrowIconSize } = getArrowIcon({ size, open });
|
|
65
57
|
const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
|
|
66
58
|
readonly,
|
|
@@ -69,13 +61,21 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
|
69
61
|
showCopyButton,
|
|
70
62
|
inputRef: localRef,
|
|
71
63
|
onClear,
|
|
72
|
-
valueToCopy: (_c =
|
|
64
|
+
valueToCopy: (_c = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.content.option) !== null && _c !== void 0 ? _c : '',
|
|
73
65
|
});
|
|
74
66
|
const commonHandleOnKeyDown = useHandleOnKeyDown({
|
|
75
67
|
inputKeyDownNavigationHandler,
|
|
76
68
|
onInputKeyDownProp,
|
|
77
69
|
setOpen,
|
|
78
70
|
});
|
|
71
|
+
const handleSelectionChange = useCallback((newValue) => {
|
|
72
|
+
var _a;
|
|
73
|
+
setValue(newValue);
|
|
74
|
+
(_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
75
|
+
if (newValue) {
|
|
76
|
+
setOpen(false);
|
|
77
|
+
}
|
|
78
|
+
}, [setOpen, setValue]);
|
|
79
79
|
const handleOnKeyDown = (onKeyDown) => (e) => {
|
|
80
80
|
if (!open && prevInputValue.current !== inputValue) {
|
|
81
81
|
setOpen(true);
|
|
@@ -85,35 +85,26 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
|
85
85
|
e.preventDefault();
|
|
86
86
|
}
|
|
87
87
|
if (addOptionByEnter && e.code === 'Enter' && inputValue !== '') {
|
|
88
|
-
|
|
88
|
+
handleSelectionChange(inputValue);
|
|
89
89
|
}
|
|
90
90
|
commonHandleOnKeyDown(onKeyDown)(e);
|
|
91
91
|
};
|
|
92
|
-
const handleSelectionChange = (newValue) => {
|
|
93
|
-
var _a;
|
|
94
|
-
setValue(newValue);
|
|
95
|
-
(_a = localRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
96
|
-
if (newValue) {
|
|
97
|
-
setOpen(false);
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
92
|
const handleOpenChange = (open) => {
|
|
101
|
-
var _a, _b;
|
|
102
93
|
if (!readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
103
94
|
setOpen(open);
|
|
104
95
|
if (!open) {
|
|
105
|
-
|
|
106
|
-
prevInputValue.current = (_b = selected === null || selected === void 0 ? void 0 : selected.content.option) !== null && _b !== void 0 ? _b : '';
|
|
96
|
+
updateInputValue(selectedItem);
|
|
107
97
|
}
|
|
108
98
|
}
|
|
109
99
|
};
|
|
110
|
-
const fuzzySearch = useFuzzySearch(
|
|
111
|
-
const result = autocomplete || !searchable || prevInputValue.current === inputValue
|
|
112
|
-
? itemsWithPlaceholder
|
|
113
|
-
: fuzzySearch(inputValue);
|
|
100
|
+
const fuzzySearch = useFuzzySearch(items);
|
|
101
|
+
const result = autocomplete || !searchable || prevInputValue.current === inputValue ? items : fuzzySearch(inputValue);
|
|
114
102
|
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: {
|
|
115
103
|
mode: 'single',
|
|
116
104
|
value: value,
|
|
117
105
|
onChange: handleSelectionChange,
|
|
118
|
-
}, size: size, open: open, onOpenChange: handleOpenChange, triggerElemRef: localRef, children: ({ onKeyDown }) =>
|
|
106
|
+
}, size: size, open: open, onOpenChange: handleOpenChange, triggerElemRef: localRef, children: ({ onKeyDown }) => {
|
|
107
|
+
var _a;
|
|
108
|
+
return (_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 ? setInputValue : undefined, value: searchable ? inputValue : (_a = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.content.option) !== null && _a !== void 0 ? _a : '', 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 })] })] }));
|
|
109
|
+
} })) })));
|
|
119
110
|
});
|
|
@@ -23,8 +23,10 @@ export declare function useButtons({ readonly, showClearButton, showCopyButton,
|
|
|
23
23
|
};
|
|
24
24
|
export declare function useSearchInput({ value, onChange, defaultValue }: SearchState): {
|
|
25
25
|
inputValue: string;
|
|
26
|
-
|
|
26
|
+
setInputValue: (value: any, ...args: any[]) => any;
|
|
27
27
|
prevInputValue: import("react").MutableRefObject<string>;
|
|
28
|
+
onInputValueChange: (value: any, ...args: any[]) => any;
|
|
29
|
+
updateInputValue: (selectedItem?: ItemWithId) => void;
|
|
28
30
|
};
|
|
29
31
|
export declare function useHandleDeleteItem(setValue: Handler): (item?: ItemWithId) => (e?: MouseEvent<HTMLButtonElement>) => void;
|
|
30
32
|
export {};
|
|
@@ -50,9 +50,15 @@ export function useButtons({ readonly, showClearButton, showCopyButton, size, on
|
|
|
50
50
|
return { buttons, inputKeyDownNavigationHandler, buttonsRefs };
|
|
51
51
|
}
|
|
52
52
|
export function useSearchInput({ value, onChange, defaultValue }) {
|
|
53
|
-
const [inputValue = '',
|
|
53
|
+
const [inputValue = '', setInputValue] = useValueControl({ value, onChange, defaultValue });
|
|
54
54
|
const prevInputValue = useRef(inputValue);
|
|
55
|
-
|
|
55
|
+
const updateInputValue = useCallback((selectedItem) => {
|
|
56
|
+
var _a;
|
|
57
|
+
const newInputValue = (_a = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.content.option) !== null && _a !== void 0 ? _a : '';
|
|
58
|
+
setInputValue(() => newInputValue);
|
|
59
|
+
prevInputValue.current = newInputValue;
|
|
60
|
+
}, [prevInputValue, setInputValue]);
|
|
61
|
+
return { inputValue, setInputValue, prevInputValue, onInputValueChange: setInputValue, updateInputValue };
|
|
56
62
|
}
|
|
57
63
|
export function useHandleDeleteItem(setValue) {
|
|
58
64
|
return useCallback((item) => (e) => {
|
|
@@ -62,5 +62,8 @@ export type FieldSelectProps = (FieldSelectSingleProps & {
|
|
|
62
62
|
}) | (FieldSelectMultipleProps & {
|
|
63
63
|
selection: 'multiple';
|
|
64
64
|
});
|
|
65
|
-
export type ItemWithId = BaseItemProps | AccordionItemProps | NextListItemProps
|
|
65
|
+
export type ItemWithId = (BaseItemProps | AccordionItemProps | NextListItemProps) & {
|
|
66
|
+
placeholder?: boolean;
|
|
67
|
+
appearance?: TagProps['appearance'];
|
|
68
|
+
};
|
|
66
69
|
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { DroplistProps } from '@snack-uikit/list';
|
|
2
|
+
import { FieldSelectProps } from '../types';
|
|
3
|
+
export declare function extractListProps({ dataError, noDataState, noResultsState, errorDataState, pinTop, pinBottom, dataFiltered, loading, }: Partial<FieldSelectProps>): Partial<DroplistProps>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function extractListProps({ dataError, noDataState, noResultsState, errorDataState, pinTop, pinBottom, dataFiltered, loading, }) {
|
|
2
|
+
return {
|
|
3
|
+
dataError,
|
|
4
|
+
noDataState,
|
|
5
|
+
noResultsState,
|
|
6
|
+
errorDataState,
|
|
7
|
+
pinTop,
|
|
8
|
+
pinBottom,
|
|
9
|
+
dataFiltered,
|
|
10
|
+
loading,
|
|
11
|
+
trigger: 'clickAndFocusVisible',
|
|
12
|
+
placement: 'bottom',
|
|
13
|
+
'data-test-id': 'field-select__list',
|
|
14
|
+
scroll: true,
|
|
15
|
+
marker: true,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Size } from '@snack-uikit/input-private';
|
|
2
|
+
export declare function getArrowIcon({ size, open }: {
|
|
3
|
+
size: Size;
|
|
4
|
+
open: boolean;
|
|
5
|
+
}): {
|
|
6
|
+
ArrowIcon: ({ size, ...props }: import("@snack-uikit/icons/dist/components/interface-icons/chevronUp").ISvgIconProps) => import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
arrowIconSize: 16 | 24;
|
|
8
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ChevronDownSVG, ChevronUpSVG } from '@snack-uikit/icons';
|
|
2
|
+
import { ICON_SIZE, SIZE } from '@snack-uikit/input-private';
|
|
3
|
+
export function getArrowIcon({ size, open }) {
|
|
4
|
+
return {
|
|
5
|
+
ArrowIcon: open ? ChevronUpSVG : ChevronDownSVG,
|
|
6
|
+
arrowIconSize: size === SIZE.S ? ICON_SIZE.Xs : ICON_SIZE.S,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ItemProps, SelectionSingleValueType } from '@snack-uikit/list';
|
|
2
|
+
import { TagProps } from '@snack-uikit/tag';
|
|
3
|
+
import { ItemWithId, OptionProps } from '../types';
|
|
4
|
+
export declare function transformOptionsToItems(options: OptionProps[]): (ItemProps & {
|
|
5
|
+
appearance?: TagProps['appearance'];
|
|
6
|
+
})[];
|
|
7
|
+
export declare function findSelectedOption(items: ItemProps[], value: SelectionSingleValueType): [ItemWithId | undefined, ItemWithId | undefined];
|
|
8
|
+
export declare function findSelectedOptions(items: ItemProps[], value: SelectionSingleValueType[] | undefined): [ItemWithId[] | undefined, ItemWithId[] | undefined];
|
|
@@ -0,0 +1,56 @@
|
|
|
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 { flattenItems } from '@snack-uikit/list';
|
|
13
|
+
import { isAccordionOptionProps, isGroupOptionProps, isNextListOptionProps } from './typeGuards';
|
|
14
|
+
export function transformOptionsToItems(options) {
|
|
15
|
+
return options.map(option => {
|
|
16
|
+
if (isAccordionOptionProps(option) || isNextListOptionProps(option)) {
|
|
17
|
+
const { description, option: contentOption, caption, options, value } = option, rest = __rest(option, ["description", "option", "caption", "options", "value"]);
|
|
18
|
+
return Object.assign(Object.assign({ 'data-test-id': 'field-select__list-option-' + option.value }, rest), { id: value, content: { option: contentOption, caption, description }, items: transformOptionsToItems(options) });
|
|
19
|
+
}
|
|
20
|
+
if (isGroupOptionProps(option)) {
|
|
21
|
+
const { options } = option, rest = __rest(option, ["options"]);
|
|
22
|
+
return Object.assign(Object.assign({}, rest), { items: transformOptionsToItems(options) });
|
|
23
|
+
}
|
|
24
|
+
const _a = option, { description, option: contentOption, caption, value, appearance } = _a, rest = __rest(_a, ["description", "option", "caption", "value", "appearance"]);
|
|
25
|
+
return Object.assign(Object.assign({ 'data-test-id': 'field-select__list-option-' + option.value }, rest), { id: value, appearance: appearance, content: { option: contentOption, caption, description } });
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
export function findSelectedOption(items, value) {
|
|
29
|
+
const flatten = flattenItems(items);
|
|
30
|
+
if (!value) {
|
|
31
|
+
return [undefined, undefined];
|
|
32
|
+
}
|
|
33
|
+
const foundItem = flatten.find(item => String(item.id) === String(value));
|
|
34
|
+
const placeholderItem = { id: value, content: { option: String(value) } };
|
|
35
|
+
return [foundItem, !foundItem ? placeholderItem : undefined];
|
|
36
|
+
}
|
|
37
|
+
export function findSelectedOptions(items, value) {
|
|
38
|
+
const flatten = flattenItems(items);
|
|
39
|
+
if (!value || !(value === null || value === void 0 ? void 0 : value.length)) {
|
|
40
|
+
return [undefined, undefined];
|
|
41
|
+
}
|
|
42
|
+
let foundItems;
|
|
43
|
+
let placeholderItems;
|
|
44
|
+
value.forEach(value => {
|
|
45
|
+
if (flatten) {
|
|
46
|
+
const [found, placeholder] = findSelectedOption(flatten, value);
|
|
47
|
+
if (found || foundItems) {
|
|
48
|
+
foundItems = (foundItems !== null && foundItems !== void 0 ? foundItems : []).concat(found !== null && found !== void 0 ? found : []);
|
|
49
|
+
}
|
|
50
|
+
if (placeholder || placeholderItems) {
|
|
51
|
+
placeholderItems = (placeholderItems !== null && placeholderItems !== void 0 ? placeholderItems : []).concat(placeholder !== null && placeholder !== void 0 ? placeholder : []);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return [foundItems, placeholderItems];
|
|
56
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { AccordionOptionProps, BaseOptionProps, FieldSelectMultipleProps, FieldSelectSingleProps, GroupOptionProps, NestListOptionProps } from '../types';
|
|
2
|
+
export declare function isBaseOptionProps(option: any): option is BaseOptionProps;
|
|
3
|
+
export declare function isAccordionOptionProps(option: any): option is AccordionOptionProps;
|
|
4
|
+
export declare function isNextListOptionProps(option: any): option is NestListOptionProps;
|
|
5
|
+
export declare function isGroupOptionProps(option: any): option is GroupOptionProps;
|
|
6
|
+
export declare function isFieldSelectMultipleProps(props: any): props is FieldSelectMultipleProps;
|
|
7
|
+
export declare function isFieldSelectSingleProps(props: any): props is FieldSelectSingleProps;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
+
export function isBaseOptionProps(option) {
|
|
3
|
+
return !('options' in option);
|
|
4
|
+
}
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
|
+
export function isAccordionOptionProps(option) {
|
|
7
|
+
return 'options' in option && option['type'] === 'collapse';
|
|
8
|
+
}
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
+
export function isNextListOptionProps(option) {
|
|
11
|
+
return 'options' in option && option['type'] === 'next-list';
|
|
12
|
+
}
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
export function isGroupOptionProps(option) {
|
|
15
|
+
return 'options' in option && option['type'] === undefined;
|
|
16
|
+
}
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
export function isFieldSelectMultipleProps(props) {
|
|
19
|
+
return 'selection' in props && props['selection'] === 'multiple';
|
|
20
|
+
}
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
|
+
export function isFieldSelectSingleProps(props) {
|
|
23
|
+
return ('selection' in props && props['selection'] === 'single') || props['selection'] === undefined;
|
|
24
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ItemProps, SelectionSingleValueType } from '@snack-uikit/list';
|
|
2
|
+
import { ItemWithId, OptionProps } from '../types';
|
|
3
|
+
export declare function createPlaceholderItem(value: SelectionSingleValueType): {
|
|
4
|
+
id: SelectionSingleValueType;
|
|
5
|
+
content: {
|
|
6
|
+
option: string;
|
|
7
|
+
};
|
|
8
|
+
placeholder: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare function updateItems({ options, value, selectedItem, }: {
|
|
11
|
+
options: OptionProps[];
|
|
12
|
+
value: SelectionSingleValueType;
|
|
13
|
+
selectedItem?: ItemWithId;
|
|
14
|
+
currentItems?: ItemProps[];
|
|
15
|
+
}): {
|
|
16
|
+
selectedItem: ItemWithId | undefined;
|
|
17
|
+
items: ItemProps[];
|
|
18
|
+
};
|
|
19
|
+
export declare function updateMultipleItems({ options, value, selectedItems, }: {
|
|
20
|
+
options: OptionProps[];
|
|
21
|
+
value?: SelectionSingleValueType[];
|
|
22
|
+
selectedItems?: ItemWithId[];
|
|
23
|
+
currentItems?: ItemProps[];
|
|
24
|
+
}): {
|
|
25
|
+
selectedItems: undefined;
|
|
26
|
+
items: (ItemProps & {
|
|
27
|
+
appearance?: import("@snack-uikit/tag/dist/types").Appearance | undefined;
|
|
28
|
+
})[];
|
|
29
|
+
} | {
|
|
30
|
+
selectedItems: ItemWithId[];
|
|
31
|
+
items: ItemProps[];
|
|
32
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { flattenItems } from '@snack-uikit/list';
|
|
2
|
+
import { transformOptionsToItems } from './options';
|
|
3
|
+
export function createPlaceholderItem(value) {
|
|
4
|
+
return { id: value, content: { option: String(value) }, placeholder: true };
|
|
5
|
+
}
|
|
6
|
+
export function updateItems({ options, value, selectedItem, }) {
|
|
7
|
+
const originalItems = transformOptionsToItems(options);
|
|
8
|
+
if (!value) {
|
|
9
|
+
return {
|
|
10
|
+
selectedItem: undefined,
|
|
11
|
+
items: originalItems,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
let newItems = originalItems;
|
|
15
|
+
let newSelectedItem = selectedItem;
|
|
16
|
+
const foundItem = flattenItems(originalItems).find(item => item.id === value);
|
|
17
|
+
if (!foundItem) {
|
|
18
|
+
if (selectedItem && (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.id) === value) {
|
|
19
|
+
newItems = [selectedItem, ...newItems];
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
newSelectedItem = createPlaceholderItem(value);
|
|
23
|
+
newItems = [newSelectedItem, ...newItems];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
newSelectedItem = foundItem;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
selectedItem: newSelectedItem,
|
|
31
|
+
items: newItems,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function updateMultipleItems({ options, value, selectedItems, }) {
|
|
35
|
+
const originalItems = transformOptionsToItems(options);
|
|
36
|
+
if (!value || !value.length) {
|
|
37
|
+
return {
|
|
38
|
+
selectedItems: undefined,
|
|
39
|
+
items: originalItems,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
let newItems = originalItems;
|
|
43
|
+
let newSelectedItems = selectedItems;
|
|
44
|
+
const flattenOriginalItems = flattenItems(originalItems);
|
|
45
|
+
const foundItems = flattenOriginalItems.filter(item => value.includes(item.id));
|
|
46
|
+
const nonFoundValues = value.filter(value => !flattenOriginalItems.find(item => item.id === value));
|
|
47
|
+
if (nonFoundValues.length) {
|
|
48
|
+
const nonFoundItems = nonFoundValues.map(value => (selectedItems === null || selectedItems === void 0 ? void 0 : selectedItems.find(selectedItem => selectedItem.id === value)) || createPlaceholderItem(value));
|
|
49
|
+
newSelectedItems = [...foundItems, ...nonFoundItems];
|
|
50
|
+
newItems = [...nonFoundItems, ...newItems];
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
newSelectedItems = foundItems;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
selectedItems: newSelectedItems.sort((a, b) => {
|
|
57
|
+
if (b.disabled && !a.disabled) {
|
|
58
|
+
return 1;
|
|
59
|
+
}
|
|
60
|
+
if (a.disabled && !b.disabled) {
|
|
61
|
+
return -1;
|
|
62
|
+
}
|
|
63
|
+
return 0;
|
|
64
|
+
}),
|
|
65
|
+
items: newItems,
|
|
66
|
+
};
|
|
67
|
+
}
|