@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 +9 -0
- package/README.md +0 -11
- package/dist/components/FieldSelect/FieldSelectMultiple.d.ts +1 -6
- package/dist/components/FieldSelect/FieldSelectMultiple.js +26 -51
- package/dist/components/FieldSelect/FieldSelectSingle.d.ts +1 -4
- package/dist/components/FieldSelect/FieldSelectSingle.js +20 -45
- package/dist/components/FieldSelect/hooks.d.ts +2 -2
- package/dist/components/FieldSelect/hooks.js +11 -11
- package/dist/components/FieldSelect/types.d.ts +2 -8
- package/dist/components/FieldSelect/utils.d.ts +4 -5
- package/dist/components/FieldSelect/utils.js +49 -41
- package/dist/hooks/useValueControl.js +1 -1
- package/package.json +5 -5
- package/src/components/FieldSelect/FieldSelectMultiple.tsx +58 -73
- package/src/components/FieldSelect/FieldSelectSingle.tsx +39 -54
- package/src/components/FieldSelect/hooks.ts +13 -17
- package/src/components/FieldSelect/types.ts +3 -16
- package/src/components/FieldSelect/utils.ts +65 -60
- package/src/hooks/useValueControl.ts +1 -1
- package/dist/components/FieldDecorator/utils.d.ts +0 -15
- package/dist/components/FieldDecorator/utils.js +0 -16
- package/src/components/FieldDecorator/utils.ts +0 -31
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import cn from 'classnames';
|
|
2
2
|
import mergeRefs from 'merge-refs';
|
|
3
|
-
import { FocusEvent, forwardRef, KeyboardEvent, KeyboardEventHandler, useMemo, useRef } from 'react';
|
|
3
|
+
import { FocusEvent, forwardRef, KeyboardEvent, KeyboardEventHandler, useMemo, useRef, useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { InputPrivate } from '@snack-uikit/input-private';
|
|
6
|
-
import {
|
|
6
|
+
import { Droplist, SelectionSingleValueType, useFuzzySearch } from '@snack-uikit/list';
|
|
7
7
|
import { Tag } from '@snack-uikit/tag';
|
|
8
8
|
import { extractSupportProps } from '@snack-uikit/utils';
|
|
9
9
|
|
|
10
10
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
11
11
|
import { useValueControl } from '../../hooks';
|
|
12
12
|
import { FieldDecorator } from '../FieldDecorator';
|
|
13
|
-
import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
|
|
14
13
|
import { useButtons, useHandleDeleteItem, useHandleOnKeyDown, useSearchInput } from './hooks';
|
|
15
14
|
import styles from './styles.module.scss';
|
|
16
15
|
import { FieldSelectMultipleProps } from './types';
|
|
17
|
-
import {
|
|
16
|
+
import { extractSelectedMultipleOptions, getArrowIcon, transformOptionsToItems } from './utils';
|
|
18
17
|
|
|
19
18
|
const BASE_MIN_WIDTH = 4;
|
|
20
19
|
|
|
@@ -29,19 +28,24 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
29
28
|
value: valueProp,
|
|
30
29
|
defaultValue,
|
|
31
30
|
onChange: onChangeProp,
|
|
31
|
+
loading,
|
|
32
32
|
disabled = false,
|
|
33
33
|
readonly = false,
|
|
34
34
|
searchable = true,
|
|
35
35
|
showClearButton = true,
|
|
36
36
|
onKeyDown: onInputKeyDownProp,
|
|
37
|
+
label,
|
|
38
|
+
labelTooltip,
|
|
39
|
+
labelTooltipPlacement,
|
|
40
|
+
required = false,
|
|
41
|
+
hint,
|
|
42
|
+
showHintIcon,
|
|
37
43
|
validationState = 'default',
|
|
44
|
+
footer,
|
|
38
45
|
search,
|
|
39
46
|
autocomplete = false,
|
|
40
47
|
prefixIcon,
|
|
41
|
-
|
|
42
|
-
addOptionByEnter = false,
|
|
43
|
-
open: openProp,
|
|
44
|
-
onOpenChange,
|
|
48
|
+
error,
|
|
45
49
|
...rest
|
|
46
50
|
},
|
|
47
51
|
ref,
|
|
@@ -50,7 +54,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
50
54
|
const inputPlugRef = useRef<HTMLSpanElement>(null);
|
|
51
55
|
const contentRef = useRef<HTMLDivElement>(null);
|
|
52
56
|
|
|
53
|
-
const [open
|
|
57
|
+
const [open, setOpen] = useState<boolean>(false);
|
|
54
58
|
const items = useMemo(() => transformOptionsToItems(options), [options]);
|
|
55
59
|
const [value, setValue] = useValueControl<SelectionSingleValueType[]>({
|
|
56
60
|
value: valueProp,
|
|
@@ -58,37 +62,27 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
58
62
|
onChange: onChangeProp,
|
|
59
63
|
});
|
|
60
64
|
|
|
61
|
-
const
|
|
62
|
-
const
|
|
65
|
+
const selectedOption = useMemo(() => {
|
|
66
|
+
const notSortSelectedOption = extractSelectedMultipleOptions(options, value);
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
notSortSelectedOption
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (b.disabled && !a.disabled) {
|
|
70
|
-
return 1;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (a.disabled && !b.disabled) {
|
|
74
|
-
return -1;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return 0;
|
|
78
|
-
})
|
|
79
|
-
: undefined;
|
|
68
|
+
if (notSortSelectedOption) {
|
|
69
|
+
return notSortSelectedOption.sort((a, b) => {
|
|
70
|
+
if (b.disabled && !a.disabled) {
|
|
71
|
+
return 1;
|
|
72
|
+
}
|
|
80
73
|
|
|
81
|
-
|
|
74
|
+
if (a.disabled && !b.disabled) {
|
|
75
|
+
return -1;
|
|
76
|
+
}
|
|
82
77
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}, [items, value]);
|
|
78
|
+
return 0;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}, [options, value]);
|
|
88
82
|
|
|
89
83
|
const { inputValue, onInputValueChange, prevInputValue } = useSearchInput({
|
|
90
84
|
...search,
|
|
91
|
-
defaultValue: '',
|
|
85
|
+
defaultValue: String(selectedOption ?? ''),
|
|
92
86
|
});
|
|
93
87
|
|
|
94
88
|
const onClear = () => {
|
|
@@ -104,7 +98,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
104
98
|
const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
|
|
105
99
|
readonly,
|
|
106
100
|
size,
|
|
107
|
-
showClearButton: showClearButton &&
|
|
101
|
+
showClearButton: showClearButton && Boolean(value),
|
|
108
102
|
showCopyButton: false,
|
|
109
103
|
inputRef: localRef,
|
|
110
104
|
onClear,
|
|
@@ -118,23 +112,12 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
118
112
|
|
|
119
113
|
const handleItemDelete = useHandleDeleteItem(setValue);
|
|
120
114
|
const handleOnKeyDown = (onKeyDown?: KeyboardEventHandler<HTMLElement>) => (e: KeyboardEvent<HTMLInputElement>) => {
|
|
121
|
-
if (
|
|
122
|
-
if (
|
|
123
|
-
handleItemDelete(
|
|
115
|
+
if (e.code === 'Backspace' && inputValue === '') {
|
|
116
|
+
if (selectedOption?.length && !selectedOption.slice(-1)[0].disabled) {
|
|
117
|
+
handleItemDelete(selectedOption.pop())();
|
|
124
118
|
}
|
|
125
119
|
}
|
|
126
120
|
|
|
127
|
-
if (e.code === 'Enter') {
|
|
128
|
-
e.stopPropagation();
|
|
129
|
-
e.preventDefault();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (addOptionByEnter && e.code === 'Enter' && inputValue !== '') {
|
|
133
|
-
setValue((value: SelectionSingleValueType[]) => (value ?? []).concat(inputValue));
|
|
134
|
-
onInputValueChange('');
|
|
135
|
-
prevInputValue.current = '';
|
|
136
|
-
}
|
|
137
|
-
|
|
138
121
|
if (!open && prevInputValue.current !== inputValue) {
|
|
139
122
|
setOpen(true);
|
|
140
123
|
}
|
|
@@ -145,19 +128,11 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
145
128
|
const handleOpenChange = (open: boolean) => {
|
|
146
129
|
if (!readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
147
130
|
setOpen(open);
|
|
148
|
-
|
|
149
131
|
if (!open) {
|
|
150
|
-
|
|
151
|
-
prevInputValue.current = '';
|
|
152
|
-
if (inputPlugRef.current) {
|
|
153
|
-
inputPlugRef.current.style.width = BASE_MIN_WIDTH + 'px';
|
|
154
|
-
}
|
|
132
|
+
prevInputValue.current = inputValue;
|
|
155
133
|
}
|
|
156
|
-
|
|
157
134
|
if (open) {
|
|
158
|
-
|
|
159
|
-
inputPlugRef.current.style.width = 'unset';
|
|
160
|
-
}
|
|
135
|
+
prevInputValue.current = '';
|
|
161
136
|
}
|
|
162
137
|
}
|
|
163
138
|
};
|
|
@@ -170,33 +145,43 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
170
145
|
rest?.onBlur?.(e);
|
|
171
146
|
};
|
|
172
147
|
|
|
173
|
-
const fuzzySearch = useFuzzySearch(
|
|
174
|
-
const result =
|
|
175
|
-
autocomplete || !searchable || prevInputValue.current === inputValue
|
|
176
|
-
? itemsWithPlaceholder
|
|
177
|
-
: fuzzySearch(inputValue);
|
|
148
|
+
const fuzzySearch = useFuzzySearch(items);
|
|
149
|
+
const result = autocomplete ? items : fuzzySearch(prevInputValue.current !== inputValue ? inputValue : '');
|
|
178
150
|
|
|
179
151
|
return (
|
|
180
152
|
<FieldDecorator
|
|
181
153
|
{...extractSupportProps(rest)}
|
|
182
|
-
{
|
|
154
|
+
error={error}
|
|
155
|
+
required={required}
|
|
156
|
+
readonly={readonly}
|
|
157
|
+
label={label}
|
|
158
|
+
labelTooltip={labelTooltip}
|
|
159
|
+
labelTooltipPlacement={labelTooltipPlacement}
|
|
183
160
|
labelFor={id}
|
|
161
|
+
hint={hint}
|
|
162
|
+
disabled={disabled}
|
|
163
|
+
showHintIcon={showHintIcon}
|
|
184
164
|
size={size}
|
|
185
165
|
validationState={validationState}
|
|
186
166
|
>
|
|
187
167
|
<Droplist
|
|
188
|
-
|
|
168
|
+
trigger='clickAndFocusVisible'
|
|
169
|
+
placement='bottom'
|
|
170
|
+
data-test-id='field-select__list'
|
|
189
171
|
items={result}
|
|
190
172
|
triggerElemRef={localRef}
|
|
173
|
+
scroll
|
|
174
|
+
marker
|
|
175
|
+
footer={footer}
|
|
191
176
|
selection={{
|
|
192
177
|
mode: 'multiple',
|
|
193
178
|
value: value,
|
|
194
179
|
onChange: setValue,
|
|
195
180
|
}}
|
|
196
|
-
dataFiltered={rest.dataFiltered ?? Boolean(inputValue.length)}
|
|
197
181
|
size={size}
|
|
198
182
|
open={!disabled && !readonly && open}
|
|
199
183
|
onOpenChange={handleOpenChange}
|
|
184
|
+
loading={loading}
|
|
200
185
|
>
|
|
201
186
|
{({ onKeyDown }) => (
|
|
202
187
|
<FieldContainerPrivate
|
|
@@ -212,14 +197,14 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
212
197
|
>
|
|
213
198
|
<>
|
|
214
199
|
<div className={styles.contentWrapper} ref={contentRef}>
|
|
215
|
-
{
|
|
216
|
-
|
|
200
|
+
{selectedOption &&
|
|
201
|
+
selectedOption.map(option => (
|
|
217
202
|
<Tag
|
|
218
203
|
size={size === 'l' ? 's' : 'xs'}
|
|
219
204
|
tabIndex={-1}
|
|
220
|
-
label={String(option.
|
|
221
|
-
key={option.
|
|
222
|
-
onDelete={!option.disabled && !disabled
|
|
205
|
+
label={String(option.option)}
|
|
206
|
+
key={option.value}
|
|
207
|
+
onDelete={!option.disabled && !disabled ? handleItemDelete(option) : undefined}
|
|
223
208
|
/>
|
|
224
209
|
))}
|
|
225
210
|
|
|
@@ -239,7 +224,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
239
224
|
name={name}
|
|
240
225
|
type='text'
|
|
241
226
|
disabled={disabled}
|
|
242
|
-
placeholder={!
|
|
227
|
+
placeholder={!selectedOption ? placeholder : undefined}
|
|
243
228
|
ref={mergeRefs(ref, localRef)}
|
|
244
229
|
onChange={searchable ? onInputValueChange : undefined}
|
|
245
230
|
value={searchable ? inputValue : ''}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import mergeRefs from 'merge-refs';
|
|
2
|
-
import {
|
|
2
|
+
import { forwardRef, KeyboardEvent, KeyboardEventHandler, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
|
|
4
4
|
import { InputPrivate } from '@snack-uikit/input-private';
|
|
5
|
-
import { Droplist,
|
|
5
|
+
import { Droplist, SelectionSingleValueType, useFuzzySearch } from '@snack-uikit/list';
|
|
6
6
|
import { extractSupportProps } from '@snack-uikit/utils';
|
|
7
7
|
|
|
8
8
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
9
9
|
import { useValueControl } from '../../hooks';
|
|
10
10
|
import { FieldDecorator } from '../FieldDecorator';
|
|
11
|
-
import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
|
|
12
11
|
import { useButtons, useHandleOnKeyDown, useSearchInput } from './hooks';
|
|
13
12
|
import styles from './styles.module.scss';
|
|
14
13
|
import { FieldSelectSingleProps } from './types';
|
|
15
|
-
import {
|
|
14
|
+
import { extractSelectedOptions, getArrowIcon, transformOptionsToItems } from './utils';
|
|
16
15
|
|
|
17
16
|
export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleProps>(
|
|
18
17
|
(
|
|
@@ -25,26 +24,31 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
25
24
|
value: valueProp,
|
|
26
25
|
defaultValue,
|
|
27
26
|
onChange: onChangeProp,
|
|
27
|
+
loading,
|
|
28
28
|
disabled = false,
|
|
29
29
|
readonly = false,
|
|
30
30
|
searchable = true,
|
|
31
31
|
showCopyButton = true,
|
|
32
32
|
showClearButton = true,
|
|
33
33
|
onKeyDown: onInputKeyDownProp,
|
|
34
|
+
label,
|
|
35
|
+
labelTooltip,
|
|
36
|
+
labelTooltipPlacement,
|
|
34
37
|
required = false,
|
|
38
|
+
hint,
|
|
39
|
+
showHintIcon,
|
|
35
40
|
validationState = 'default',
|
|
41
|
+
footer,
|
|
36
42
|
search,
|
|
37
43
|
autocomplete = false,
|
|
38
44
|
prefixIcon,
|
|
39
|
-
|
|
40
|
-
open: openProp,
|
|
41
|
-
onOpenChange,
|
|
45
|
+
error,
|
|
42
46
|
...rest
|
|
43
47
|
},
|
|
44
48
|
ref,
|
|
45
49
|
) => {
|
|
46
50
|
const localRef = useRef<HTMLInputElement>(null);
|
|
47
|
-
const [open
|
|
51
|
+
const [open, setOpen] = useState<boolean>(false);
|
|
48
52
|
const [value, setValue] = useValueControl<SelectionSingleValueType>({
|
|
49
53
|
value: valueProp,
|
|
50
54
|
defaultValue,
|
|
@@ -52,34 +56,22 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
52
56
|
});
|
|
53
57
|
|
|
54
58
|
const items = useMemo(() => transformOptionsToItems(options), [options]);
|
|
55
|
-
const
|
|
56
|
-
const [fonded, placeholder] = findSelectedOption(items, value);
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
selected: fonded ?? placeholder,
|
|
60
|
-
itemsWithPlaceholder: ((placeholder ? [placeholder] : []) as ItemProps[]).concat(items),
|
|
61
|
-
};
|
|
62
|
-
}, [items, value]);
|
|
59
|
+
const selectedOption = useMemo(() => extractSelectedOptions(options, value), [options, value]);
|
|
63
60
|
|
|
64
61
|
const { inputValue, onInputValueChange, prevInputValue } = useSearchInput({
|
|
65
62
|
...search,
|
|
66
|
-
defaultValue:
|
|
63
|
+
defaultValue: String(selectedOption ?? ''),
|
|
67
64
|
});
|
|
68
65
|
|
|
69
66
|
useEffect(() => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
prevInputValue.current = selected?.content.option;
|
|
73
|
-
}
|
|
74
|
-
}, [onInputValueChange, selected?.content.option, prevInputValue]);
|
|
67
|
+
!open && onInputValueChange(String(selectedOption?.option ?? ''));
|
|
68
|
+
}, [onInputValueChange, open, selectedOption]);
|
|
75
69
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
onInputValueChange(selected?.content.option ?? '');
|
|
79
|
-
}
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
onInputValueChange(String(selectedOption?.option ?? ''));
|
|
80
72
|
|
|
81
|
-
|
|
82
|
-
};
|
|
73
|
+
prevInputValue.current = String(selectedOption?.option ?? '');
|
|
74
|
+
}, [prevInputValue, onInputValueChange, selectedOption]);
|
|
83
75
|
|
|
84
76
|
const onClear = () => {
|
|
85
77
|
setValue('');
|
|
@@ -94,11 +86,11 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
94
86
|
const { buttons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
|
|
95
87
|
readonly,
|
|
96
88
|
size,
|
|
97
|
-
showClearButton: showClearButton &&
|
|
89
|
+
showClearButton: showClearButton && Boolean(value),
|
|
98
90
|
showCopyButton,
|
|
99
91
|
inputRef: localRef,
|
|
100
92
|
onClear,
|
|
101
|
-
valueToCopy:
|
|
93
|
+
valueToCopy: String(selectedOption?.option ?? ''),
|
|
102
94
|
});
|
|
103
95
|
|
|
104
96
|
const commonHandleOnKeyDown = useHandleOnKeyDown({
|
|
@@ -112,15 +104,6 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
112
104
|
setOpen(true);
|
|
113
105
|
}
|
|
114
106
|
|
|
115
|
-
if (e.code === 'Enter') {
|
|
116
|
-
e.stopPropagation();
|
|
117
|
-
e.preventDefault();
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (addOptionByEnter && e.code === 'Enter' && inputValue !== '') {
|
|
121
|
-
setValue(inputValue);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
107
|
commonHandleOnKeyDown(onKeyDown)(e);
|
|
125
108
|
};
|
|
126
109
|
|
|
@@ -136,34 +119,37 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
136
119
|
const handleOpenChange = (open: boolean) => {
|
|
137
120
|
if (!readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
138
121
|
setOpen(open);
|
|
139
|
-
|
|
140
|
-
if (!open) {
|
|
141
|
-
onInputValueChange(selected?.content.option ?? '');
|
|
142
|
-
prevInputValue.current = selected?.content.option ?? '';
|
|
143
|
-
}
|
|
144
122
|
}
|
|
145
123
|
};
|
|
146
124
|
|
|
147
|
-
const fuzzySearch = useFuzzySearch(
|
|
148
|
-
const result =
|
|
149
|
-
autocomplete || !searchable || prevInputValue.current === inputValue
|
|
150
|
-
? itemsWithPlaceholder
|
|
151
|
-
: fuzzySearch(inputValue);
|
|
125
|
+
const fuzzySearch = useFuzzySearch(items);
|
|
126
|
+
const result = autocomplete ? items : fuzzySearch(prevInputValue.current !== inputValue ? inputValue : '');
|
|
152
127
|
|
|
153
128
|
return (
|
|
154
129
|
<FieldDecorator
|
|
155
130
|
{...extractSupportProps(rest)}
|
|
156
|
-
{
|
|
157
|
-
validationState={validationState}
|
|
131
|
+
error={error}
|
|
158
132
|
required={required}
|
|
159
133
|
readonly={readonly}
|
|
134
|
+
label={label}
|
|
135
|
+
labelTooltip={labelTooltip}
|
|
136
|
+
labelTooltipPlacement={labelTooltipPlacement}
|
|
160
137
|
labelFor={id}
|
|
138
|
+
hint={hint}
|
|
161
139
|
disabled={disabled}
|
|
140
|
+
showHintIcon={showHintIcon}
|
|
162
141
|
size={size}
|
|
142
|
+
validationState={validationState}
|
|
163
143
|
>
|
|
164
144
|
<Droplist
|
|
165
|
-
|
|
145
|
+
trigger='clickAndFocusVisible'
|
|
146
|
+
placement='bottom'
|
|
147
|
+
data-test-id='field-select__list'
|
|
166
148
|
items={result}
|
|
149
|
+
triggerElemRef={localRef}
|
|
150
|
+
scroll
|
|
151
|
+
marker
|
|
152
|
+
footer={footer}
|
|
167
153
|
selection={{
|
|
168
154
|
mode: 'single',
|
|
169
155
|
value: value,
|
|
@@ -172,7 +158,7 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
172
158
|
size={size}
|
|
173
159
|
open={open}
|
|
174
160
|
onOpenChange={handleOpenChange}
|
|
175
|
-
|
|
161
|
+
loading={loading}
|
|
176
162
|
>
|
|
177
163
|
{({ onKeyDown }) => (
|
|
178
164
|
<FieldContainerPrivate
|
|
@@ -198,7 +184,6 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
198
184
|
readonly={!searchable || readonly}
|
|
199
185
|
data-test-id='field-select__input'
|
|
200
186
|
onKeyDown={handleOnKeyDown(onKeyDown)}
|
|
201
|
-
onBlur={handleBlur}
|
|
202
187
|
/>
|
|
203
188
|
|
|
204
189
|
<div className={styles.postfix}>
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { KeyboardEvent, KeyboardEventHandler, RefObject, useCallback, useMemo, useRef } from 'react';
|
|
2
|
-
import { Handler } from 'uncontrollable';
|
|
2
|
+
import { Handler, useUncontrolledProp } from 'uncontrollable';
|
|
3
3
|
|
|
4
4
|
import { useButtonNavigation, useClearButton } from '@snack-uikit/input-private';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
isAccordionItemProps,
|
|
8
|
-
isNextListItemProps,
|
|
9
|
-
SelectionSingleValueType,
|
|
10
|
-
} from '@snack-uikit/list';
|
|
5
|
+
import { SelectionSingleValueType } from '@snack-uikit/list';
|
|
6
|
+
import { extractChildIds } from '@snack-uikit/list/dist/utils';
|
|
11
7
|
|
|
12
|
-
import { useCopyButton
|
|
13
|
-
import {
|
|
14
|
-
import { isBaseOptionProps } from './utils';
|
|
8
|
+
import { useCopyButton } from '../../hooks';
|
|
9
|
+
import { OptionProps, SearchState } from './types';
|
|
10
|
+
import { isAccordionOptionProps, isBaseOptionProps, isNextListOptionProps, transformOptionsToItems } from './utils';
|
|
15
11
|
|
|
16
12
|
type UseHandleOnKeyDownProps = {
|
|
17
13
|
inputKeyDownNavigationHandler: KeyboardEventHandler<HTMLInputElement>;
|
|
@@ -99,7 +95,7 @@ export function useButtons({
|
|
|
99
95
|
}
|
|
100
96
|
|
|
101
97
|
export function useSearchInput({ value, onChange, defaultValue }: SearchState) {
|
|
102
|
-
const [inputValue
|
|
98
|
+
const [inputValue, onInputValueChange] = useUncontrolledProp<string>(value, defaultValue ?? '', onChange);
|
|
103
99
|
|
|
104
100
|
const prevInputValue = useRef<string>(inputValue);
|
|
105
101
|
|
|
@@ -108,20 +104,20 @@ export function useSearchInput({ value, onChange, defaultValue }: SearchState) {
|
|
|
108
104
|
|
|
109
105
|
export function useHandleDeleteItem(setValue: Handler) {
|
|
110
106
|
return useCallback(
|
|
111
|
-
(
|
|
112
|
-
if (!
|
|
107
|
+
(option?: OptionProps) => () => {
|
|
108
|
+
if (!option) {
|
|
113
109
|
return;
|
|
114
110
|
}
|
|
115
111
|
|
|
116
|
-
if (
|
|
117
|
-
const removeIds = extractChildIds({ items:
|
|
112
|
+
if (isAccordionOptionProps(option) || isNextListOptionProps(option)) {
|
|
113
|
+
const removeIds = extractChildIds({ items: transformOptionsToItems(option.options) }).concat(option.value);
|
|
118
114
|
|
|
119
115
|
setValue((value: SelectionSingleValueType[]) => value?.filter(v => !removeIds.includes(v ?? '')));
|
|
120
116
|
return;
|
|
121
117
|
}
|
|
122
118
|
|
|
123
|
-
if (isBaseOptionProps(
|
|
124
|
-
setValue((value: SelectionSingleValueType[]) => value?.filter(v => v !==
|
|
119
|
+
if (isBaseOptionProps(option)) {
|
|
120
|
+
setValue((value: SelectionSingleValueType[]) => value?.filter(v => v !== option.value));
|
|
125
121
|
}
|
|
126
122
|
},
|
|
127
123
|
[setValue],
|
|
@@ -78,30 +78,17 @@ type FiledSelectCommonProps = WithSupportProps<{
|
|
|
78
78
|
search?: SearchState;
|
|
79
79
|
|
|
80
80
|
autocomplete?: boolean;
|
|
81
|
-
|
|
82
|
-
addOptionByEnter?: boolean;
|
|
83
|
-
|
|
84
|
-
open?: boolean;
|
|
85
|
-
onOpenChange?(open: boolean): void;
|
|
86
|
-
}> &
|
|
87
|
-
Pick<
|
|
88
|
-
ListProps,
|
|
89
|
-
'dataError' | 'noDataState' | 'noResultsState' | 'errorDataState' | 'pinTop' | 'pinBottom' | 'dataFiltered'
|
|
90
|
-
>;
|
|
81
|
+
}>;
|
|
91
82
|
|
|
92
83
|
export type FieldSelectSingleProps = FieldSelectPrivateProps &
|
|
93
84
|
Omit<SelectionSingleState, 'mode'> &
|
|
94
85
|
WrapperProps &
|
|
95
86
|
FiledSelectCommonProps;
|
|
96
87
|
|
|
97
|
-
export type FieldSelectMultipleProps = FieldSelectPrivateProps &
|
|
98
|
-
|
|
99
|
-
'mode'
|
|
100
|
-
> &
|
|
88
|
+
export type FieldSelectMultipleProps = FieldSelectPrivateProps &
|
|
89
|
+
Omit<SelectionMultipleState, 'mode'> &
|
|
101
90
|
Omit<FiledSelectCommonProps, 'showCopyButton'>;
|
|
102
91
|
|
|
103
92
|
export type FieldSelectProps =
|
|
104
93
|
| (FieldSelectSingleProps & { selection?: 'single' })
|
|
105
94
|
| (FieldSelectMultipleProps & { selection: 'multiple' });
|
|
106
|
-
|
|
107
|
-
export type ItemWithId = BaseItemProps | AccordionItemProps | NextListItemProps;
|