@snack-uikit/fields 0.16.0 → 0.16.1-preview-cde51e4b.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/README.md +1 -0
- package/dist/components/FieldSelect/FieldSelectMultiple.d.ts +2 -0
- package/dist/components/FieldSelect/FieldSelectMultiple.js +6 -6
- package/dist/components/FieldSelect/FieldSelectSingle.js +18 -17
- package/dist/components/FieldSelect/types.d.ts +3 -1
- package/dist/hooks/useValueControl.js +1 -1
- package/package.json +2 -2
- package/src/components/FieldSelect/FieldSelectMultiple.tsx +7 -5
- package/src/components/FieldSelect/FieldSelectSingle.tsx +15 -12
- package/src/components/FieldSelect/types.ts +4 -2
- package/src/hooks/useValueControl.ts +1 -1
package/README.md
CHANGED
|
@@ -340,6 +340,7 @@ const [isOpen, setIsOpen] = useState(false);
|
|
|
340
340
|
| selection | "single" \| "multiple" | - | |
|
|
341
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 |
|
|
342
342
|
| key | `Key` | - | |
|
|
343
|
+
| removeByBackspace | `boolean` | - | |
|
|
343
344
|
## FieldStepper
|
|
344
345
|
### Props
|
|
345
346
|
| name | type | default value | description |
|
|
@@ -2,6 +2,8 @@
|
|
|
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;
|
|
5
7
|
} & Omit<import("@snack-uikit/list").SelectionMultipleState, "mode"> & Omit<{
|
|
6
8
|
'data-test-id'?: string | undefined;
|
|
7
9
|
} & import("react").AriaAttributes & {
|
|
@@ -25,7 +25,7 @@ import styles from './styles.module.css';
|
|
|
25
25
|
import { extractSelectedMultipleOptions, getArrowIcon, transformOptionsToItems } from './utils';
|
|
26
26
|
const BASE_MIN_WIDTH = 4;
|
|
27
27
|
export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
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"]);
|
|
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, removeByBackspace = false } = _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", "removeByBackspace"]);
|
|
29
29
|
const localRef = useRef(null);
|
|
30
30
|
const inputPlugRef = useRef(null);
|
|
31
31
|
const contentRef = useRef(null);
|
|
@@ -50,7 +50,7 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
52
|
}, [options, value]);
|
|
53
|
-
const { inputValue, onInputValueChange, prevInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue:
|
|
53
|
+
const { inputValue, onInputValueChange, prevInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: '' }));
|
|
54
54
|
const onClear = () => {
|
|
55
55
|
var _a;
|
|
56
56
|
setValue(undefined);
|
|
@@ -62,7 +62,7 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
|
62
62
|
const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
|
|
63
63
|
readonly,
|
|
64
64
|
size,
|
|
65
|
-
showClearButton: showClearButton && Boolean(value),
|
|
65
|
+
showClearButton: showClearButton && !disabled && !readonly && Boolean(value),
|
|
66
66
|
showCopyButton: false,
|
|
67
67
|
inputRef: localRef,
|
|
68
68
|
onClear,
|
|
@@ -74,7 +74,7 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
|
74
74
|
});
|
|
75
75
|
const handleItemDelete = useHandleDeleteItem(setValue);
|
|
76
76
|
const handleOnKeyDown = (onKeyDown) => (e) => {
|
|
77
|
-
if (e.code === 'Backspace' && inputValue === '') {
|
|
77
|
+
if (removeByBackspace && e.code === 'Backspace' && inputValue === '') {
|
|
78
78
|
if ((selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.length) && !selectedOption.slice(-1)[0].disabled) {
|
|
79
79
|
handleItemDelete(selectedOption.pop())();
|
|
80
80
|
}
|
|
@@ -103,7 +103,7 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
|
103
103
|
(_a = rest === null || rest === void 0 ? void 0 : rest.onBlur) === null || _a === void 0 ? void 0 : _a.call(rest, e);
|
|
104
104
|
};
|
|
105
105
|
const fuzzySearch = useFuzzySearch(items);
|
|
106
|
-
const result = autocomplete
|
|
106
|
+
const result = autocomplete || !searchable || prevInputValue.current !== inputValue ? items : fuzzySearch(inputValue);
|
|
107
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: {
|
|
108
108
|
mode: 'multiple',
|
|
109
109
|
value: value,
|
|
@@ -111,7 +111,7 @@ export const FieldSelectMultiple = forwardRef((_a, ref) => {
|
|
|
111
111
|
}, size: size, open: !disabled && !readonly && open, onOpenChange: handleOpenChange, loading: loading, children: ({ onKeyDown }) => {
|
|
112
112
|
var _a, _b, _c, _d;
|
|
113
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: {
|
|
114
|
+
selectedOption.map(option => (_jsx(Tag, { size: size === 'l' ? 's' : 'xs', tabIndex: -1, label: String(option.option), onDelete: !option.disabled && !disabled && !readonly ? handleItemDelete(option) : undefined }, option.value))), _jsx("div", { className: styles.inputWrapper, style: {
|
|
115
115
|
minWidth: value
|
|
116
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)
|
|
117
117
|
: '100%',
|
|
@@ -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,
|
|
14
|
+
import { forwardRef, 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';
|
|
@@ -22,7 +22,7 @@ import { useButtons, useHandleOnKeyDown, useSearchInput } from './hooks';
|
|
|
22
22
|
import styles from './styles.module.css';
|
|
23
23
|
import { extractSelectedOptions, getArrowIcon, transformOptionsToItems } from './utils';
|
|
24
24
|
export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
25
|
-
var _b;
|
|
25
|
+
var _b, _c;
|
|
26
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"]);
|
|
27
27
|
const localRef = useRef(null);
|
|
28
28
|
const [open, setOpen] = useState(false);
|
|
@@ -33,16 +33,14 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
|
33
33
|
});
|
|
34
34
|
const items = useMemo(() => transformOptionsToItems(options), [options]);
|
|
35
35
|
const selectedOption = useMemo(() => extractSelectedOptions(options, value), [options, value]);
|
|
36
|
-
const { inputValue, onInputValueChange, prevInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: String(selectedOption !== null &&
|
|
37
|
-
|
|
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]);
|
|
41
|
-
useEffect(() => {
|
|
36
|
+
const { inputValue, onInputValueChange, prevInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: String((_b = selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.option) !== null && _b !== void 0 ? _b : '') }));
|
|
37
|
+
const handleBlur = (e) => {
|
|
42
38
|
var _a, _b;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
if (!open && (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.option) !== inputValue) {
|
|
40
|
+
onInputValueChange((_a = selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.option) !== null && _a !== void 0 ? _a : '');
|
|
41
|
+
}
|
|
42
|
+
(_b = rest === null || rest === void 0 ? void 0 : rest.onBlur) === null || _b === void 0 ? void 0 : _b.call(rest, e);
|
|
43
|
+
};
|
|
46
44
|
const onClear = () => {
|
|
47
45
|
var _a;
|
|
48
46
|
setValue('');
|
|
@@ -54,11 +52,11 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
|
54
52
|
const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
|
|
55
53
|
readonly,
|
|
56
54
|
size,
|
|
57
|
-
showClearButton: showClearButton && Boolean(value),
|
|
55
|
+
showClearButton: showClearButton && !disabled && !readonly && Boolean(value),
|
|
58
56
|
showCopyButton,
|
|
59
57
|
inputRef: localRef,
|
|
60
58
|
onClear,
|
|
61
|
-
valueToCopy: String((
|
|
59
|
+
valueToCopy: String((_c = selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.option) !== null && _c !== void 0 ? _c : ''),
|
|
62
60
|
});
|
|
63
61
|
const commonHandleOnKeyDown = useHandleOnKeyDown({
|
|
64
62
|
inputKeyDownNavigationHandler,
|
|
@@ -72,9 +70,12 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
|
72
70
|
commonHandleOnKeyDown(onKeyDown)(e);
|
|
73
71
|
};
|
|
74
72
|
const handleSelectionChange = (newValue) => {
|
|
75
|
-
var _a;
|
|
73
|
+
var _a, _b, _c;
|
|
76
74
|
setValue(newValue);
|
|
77
|
-
(_a =
|
|
75
|
+
const selectedValue = (_b = (_a = extractSelectedOptions(options, newValue)) === null || _a === void 0 ? void 0 : _a.option) !== null && _b !== void 0 ? _b : '';
|
|
76
|
+
onInputValueChange(selectedValue);
|
|
77
|
+
prevInputValue.current = selectedValue;
|
|
78
|
+
(_c = localRef.current) === null || _c === void 0 ? void 0 : _c.focus();
|
|
78
79
|
if (newValue) {
|
|
79
80
|
setOpen(false);
|
|
80
81
|
}
|
|
@@ -85,10 +86,10 @@ export const FieldSelectSingle = forwardRef((_a, ref) => {
|
|
|
85
86
|
}
|
|
86
87
|
};
|
|
87
88
|
const fuzzySearch = useFuzzySearch(items);
|
|
88
|
-
const result = autocomplete
|
|
89
|
+
const result = autocomplete || !searchable || prevInputValue.current === inputValue ? items : fuzzySearch(inputValue);
|
|
89
90
|
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: {
|
|
90
91
|
mode: 'single',
|
|
91
92
|
value: value,
|
|
92
93
|
onChange: handleSelectionChange,
|
|
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 })] })] })) }) })));
|
|
94
|
+
}, 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), onBlur: handleBlur }), _jsxs("div", { className: styles.postfix, children: [buttons, _jsx(ArrowIcon, { size: arrowIconSize, className: styles.arrowIcon })] })] })) }) })));
|
|
94
95
|
});
|
|
@@ -50,7 +50,9 @@ type FiledSelectCommonProps = WithSupportProps<{
|
|
|
50
50
|
autocomplete?: boolean;
|
|
51
51
|
}>;
|
|
52
52
|
export type FieldSelectSingleProps = FieldSelectPrivateProps & Omit<SelectionSingleState, 'mode'> & WrapperProps & FiledSelectCommonProps;
|
|
53
|
-
export type FieldSelectMultipleProps = FieldSelectPrivateProps &
|
|
53
|
+
export type FieldSelectMultipleProps = FieldSelectPrivateProps & {
|
|
54
|
+
removeByBackspace?: boolean;
|
|
55
|
+
} & Omit<SelectionMultipleState, 'mode'> & Omit<FiledSelectCommonProps, 'showCopyButton'>;
|
|
54
56
|
export type FieldSelectProps = (FieldSelectSingleProps & {
|
|
55
57
|
selection?: 'single';
|
|
56
58
|
}) | (FieldSelectMultipleProps & {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useUncontrolledProp } from 'uncontrollable';
|
|
2
2
|
export function useValueControl({ value, onChange, defaultValue }) {
|
|
3
|
-
return useUncontrolledProp(value,
|
|
3
|
+
return useUncontrolledProp(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.0",
|
|
7
|
+
"version": "0.16.1-preview-cde51e4b.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"@snack-uikit/locale": "*"
|
|
58
58
|
},
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "c292f662f2a75b1c9dd814f64b9ac9887f040726"
|
|
60
60
|
}
|
|
@@ -46,6 +46,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
46
46
|
autocomplete = false,
|
|
47
47
|
prefixIcon,
|
|
48
48
|
error,
|
|
49
|
+
removeByBackspace = false,
|
|
49
50
|
...rest
|
|
50
51
|
},
|
|
51
52
|
ref,
|
|
@@ -82,7 +83,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
82
83
|
|
|
83
84
|
const { inputValue, onInputValueChange, prevInputValue } = useSearchInput({
|
|
84
85
|
...search,
|
|
85
|
-
defaultValue:
|
|
86
|
+
defaultValue: '',
|
|
86
87
|
});
|
|
87
88
|
|
|
88
89
|
const onClear = () => {
|
|
@@ -98,7 +99,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
98
99
|
const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
|
|
99
100
|
readonly,
|
|
100
101
|
size,
|
|
101
|
-
showClearButton: showClearButton && Boolean(value),
|
|
102
|
+
showClearButton: showClearButton && !disabled && !readonly && Boolean(value),
|
|
102
103
|
showCopyButton: false,
|
|
103
104
|
inputRef: localRef,
|
|
104
105
|
onClear,
|
|
@@ -112,7 +113,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
112
113
|
|
|
113
114
|
const handleItemDelete = useHandleDeleteItem(setValue);
|
|
114
115
|
const handleOnKeyDown = (onKeyDown?: KeyboardEventHandler<HTMLElement>) => (e: KeyboardEvent<HTMLInputElement>) => {
|
|
115
|
-
if (e.code === 'Backspace' && inputValue === '') {
|
|
116
|
+
if (removeByBackspace && e.code === 'Backspace' && inputValue === '') {
|
|
116
117
|
if (selectedOption?.length && !selectedOption.slice(-1)[0].disabled) {
|
|
117
118
|
handleItemDelete(selectedOption.pop())();
|
|
118
119
|
}
|
|
@@ -146,7 +147,8 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
146
147
|
};
|
|
147
148
|
|
|
148
149
|
const fuzzySearch = useFuzzySearch(items);
|
|
149
|
-
const result =
|
|
150
|
+
const result =
|
|
151
|
+
autocomplete || !searchable || prevInputValue.current !== inputValue ? items : fuzzySearch(inputValue);
|
|
150
152
|
|
|
151
153
|
return (
|
|
152
154
|
<FieldDecorator
|
|
@@ -204,7 +206,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
204
206
|
tabIndex={-1}
|
|
205
207
|
label={String(option.option)}
|
|
206
208
|
key={option.value}
|
|
207
|
-
onDelete={!option.disabled && !disabled ? handleItemDelete(option) : undefined}
|
|
209
|
+
onDelete={!option.disabled && !disabled && !readonly ? handleItemDelete(option) : undefined}
|
|
208
210
|
/>
|
|
209
211
|
))}
|
|
210
212
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import mergeRefs from 'merge-refs';
|
|
2
|
-
import { forwardRef, KeyboardEvent, KeyboardEventHandler,
|
|
2
|
+
import { FocusEvent, forwardRef, KeyboardEvent, KeyboardEventHandler, useMemo, useRef, useState } from 'react';
|
|
3
3
|
|
|
4
4
|
import { InputPrivate } from '@snack-uikit/input-private';
|
|
5
5
|
import { Droplist, SelectionSingleValueType, useFuzzySearch } from '@snack-uikit/list';
|
|
@@ -60,18 +60,16 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
60
60
|
|
|
61
61
|
const { inputValue, onInputValueChange, prevInputValue } = useSearchInput({
|
|
62
62
|
...search,
|
|
63
|
-
defaultValue: String(selectedOption ?? ''),
|
|
63
|
+
defaultValue: String(selectedOption?.option ?? ''),
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
!open &&
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
useEffect(() => {
|
|
71
|
-
onInputValueChange(String(selectedOption?.option ?? ''));
|
|
66
|
+
const handleBlur = (e: FocusEvent<HTMLInputElement>) => {
|
|
67
|
+
if (!open && selectedOption?.option !== inputValue) {
|
|
68
|
+
onInputValueChange(selectedOption?.option ?? '');
|
|
69
|
+
}
|
|
72
70
|
|
|
73
|
-
|
|
74
|
-
}
|
|
71
|
+
rest?.onBlur?.(e);
|
|
72
|
+
};
|
|
75
73
|
|
|
76
74
|
const onClear = () => {
|
|
77
75
|
setValue('');
|
|
@@ -86,7 +84,7 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
86
84
|
const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
|
|
87
85
|
readonly,
|
|
88
86
|
size,
|
|
89
|
-
showClearButton: showClearButton && Boolean(value),
|
|
87
|
+
showClearButton: showClearButton && !disabled && !readonly && Boolean(value),
|
|
90
88
|
showCopyButton,
|
|
91
89
|
inputRef: localRef,
|
|
92
90
|
onClear,
|
|
@@ -109,6 +107,9 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
109
107
|
|
|
110
108
|
const handleSelectionChange = (newValue?: SelectionSingleValueType) => {
|
|
111
109
|
setValue(newValue);
|
|
110
|
+
const selectedValue = extractSelectedOptions(options, newValue)?.option ?? '';
|
|
111
|
+
onInputValueChange(selectedValue);
|
|
112
|
+
prevInputValue.current = selectedValue;
|
|
112
113
|
localRef.current?.focus();
|
|
113
114
|
|
|
114
115
|
if (newValue) {
|
|
@@ -123,7 +124,8 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
123
124
|
};
|
|
124
125
|
|
|
125
126
|
const fuzzySearch = useFuzzySearch(items);
|
|
126
|
-
const result =
|
|
127
|
+
const result =
|
|
128
|
+
autocomplete || !searchable || prevInputValue.current === inputValue ? items : fuzzySearch(inputValue);
|
|
127
129
|
|
|
128
130
|
return (
|
|
129
131
|
<FieldDecorator
|
|
@@ -184,6 +186,7 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
184
186
|
readonly={!searchable || readonly}
|
|
185
187
|
data-test-id='field-select__input'
|
|
186
188
|
onKeyDown={handleOnKeyDown(onKeyDown)}
|
|
189
|
+
onBlur={handleBlur}
|
|
187
190
|
/>
|
|
188
191
|
|
|
189
192
|
<div className={styles.postfix}>
|
|
@@ -85,8 +85,10 @@ export type FieldSelectSingleProps = FieldSelectPrivateProps &
|
|
|
85
85
|
WrapperProps &
|
|
86
86
|
FiledSelectCommonProps;
|
|
87
87
|
|
|
88
|
-
export type FieldSelectMultipleProps = FieldSelectPrivateProps &
|
|
89
|
-
|
|
88
|
+
export type FieldSelectMultipleProps = FieldSelectPrivateProps & { removeByBackspace?: boolean } & Omit<
|
|
89
|
+
SelectionMultipleState,
|
|
90
|
+
'mode'
|
|
91
|
+
> &
|
|
90
92
|
Omit<FiledSelectCommonProps, 'showCopyButton'>;
|
|
91
93
|
|
|
92
94
|
export type FieldSelectProps =
|
|
@@ -7,7 +7,7 @@ type UseValueControl<TValue> = {
|
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export function useValueControl<TValue>({ value, onChange, defaultValue }: UseValueControl<TValue>) {
|
|
10
|
-
return useUncontrolledProp<TValue>(value,
|
|
10
|
+
return useUncontrolledProp<TValue>(value, defaultValue, (newValue: TValue) => {
|
|
11
11
|
const newState = typeof newValue === 'function' ? newValue(value) : newValue;
|
|
12
12
|
|
|
13
13
|
onChange?.(newState);
|