@snack-uikit/fields 0.14.2 → 0.15.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/CHANGELOG.md +16 -0
- package/README.md +15 -14
- package/dist/components/FieldDecorator/Header.js +1 -1
- package/dist/components/FieldDecorator/styles.module.css +7 -1
- package/dist/components/FieldSelect/FieldSelect.d.ts +1 -7
- package/dist/components/FieldSelect/FieldSelect.js +9 -21
- package/dist/components/FieldSelect/FieldSelectMultiple.d.ts +17 -0
- package/dist/components/FieldSelect/FieldSelectMultiple.js +118 -0
- package/dist/components/FieldSelect/FieldSelectSingle.d.ts +9 -28
- package/dist/components/FieldSelect/FieldSelectSingle.js +69 -55
- package/dist/components/FieldSelect/hooks.d.ts +30 -0
- package/dist/components/FieldSelect/hooks.js +72 -0
- package/dist/components/FieldSelect/index.d.ts +2 -1
- package/dist/components/FieldSelect/index.js +1 -1
- package/dist/components/FieldSelect/styles.module.css +129 -27
- package/dist/components/FieldSelect/types.d.ts +42 -37
- package/dist/components/FieldSelect/utils.d.ts +19 -0
- package/dist/components/FieldSelect/utils.js +112 -0
- package/dist/helperComponents/FieldContainerPrivate/styles.module.css +30 -6
- package/package.json +5 -3
- package/src/components/FieldDecorator/Header.tsx +6 -1
- package/src/components/FieldDecorator/styles.module.scss +38 -30
- package/src/components/FieldSelect/FieldSelect.tsx +13 -21
- package/src/components/FieldSelect/FieldSelectMultiple.tsx +255 -0
- package/src/components/FieldSelect/FieldSelectSingle.tsx +159 -99
- package/src/components/FieldSelect/hooks.ts +125 -0
- package/src/components/FieldSelect/index.ts +12 -1
- package/src/components/FieldSelect/styles.module.scss +71 -31
- package/src/components/FieldSelect/types.ts +55 -40
- package/src/components/FieldSelect/utils.ts +163 -0
- package/src/helperComponents/FieldContainerPrivate/FieldContainerPrivate.tsx +2 -0
- package/src/helperComponents/FieldContainerPrivate/styles.module.scss +32 -11
- package/dist/components/FieldSelect/FieldSelectBase.d.ts +0 -31
- package/dist/components/FieldSelect/FieldSelectBase.js +0 -51
- package/dist/components/FieldSelect/FieldSelectMulti.d.ts +0 -37
- package/dist/components/FieldSelect/FieldSelectMulti.js +0 -89
- package/dist/components/FieldSelect/constants.d.ts +0 -7
- package/dist/components/FieldSelect/constants.js +0 -6
- package/dist/components/FieldSelect/helpers/getArrowIcon.d.ts +0 -8
- package/dist/components/FieldSelect/helpers/getArrowIcon.js +0 -8
- package/dist/components/FieldSelect/helpers/getDisplayedValue.d.ts +0 -10
- package/dist/components/FieldSelect/helpers/getDisplayedValue.js +0 -12
- package/dist/components/FieldSelect/helpers/index.d.ts +0 -2
- package/dist/components/FieldSelect/helpers/index.js +0 -2
- package/dist/components/FieldSelect/hooks/index.d.ts +0 -3
- package/dist/components/FieldSelect/hooks/index.js +0 -3
- package/dist/components/FieldSelect/hooks/useFilteredOptions.d.ts +0 -7
- package/dist/components/FieldSelect/hooks/useFilteredOptions.js +0 -6
- package/dist/components/FieldSelect/hooks/useList.d.ts +0 -37
- package/dist/components/FieldSelect/hooks/useList.js +0 -52
- package/dist/components/FieldSelect/hooks/useListNavigation.d.ts +0 -26
- package/dist/components/FieldSelect/hooks/useListNavigation.js +0 -48
- package/src/components/FieldSelect/FieldSelectBase.tsx +0 -222
- package/src/components/FieldSelect/FieldSelectMulti.tsx +0 -163
- package/src/components/FieldSelect/constants.ts +0 -9
- package/src/components/FieldSelect/helpers/getArrowIcon.ts +0 -9
- package/src/components/FieldSelect/helpers/getDisplayedValue.ts +0 -25
- package/src/components/FieldSelect/helpers/index.ts +0 -2
- package/src/components/FieldSelect/hooks/index.ts +0 -3
- package/src/components/FieldSelect/hooks/useFilteredOptions.ts +0 -23
- package/src/components/FieldSelect/hooks/useList.ts +0 -87
- package/src/components/FieldSelect/hooks/useListNavigation.ts +0 -81
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
|
|
3
|
-
import { Option } from '../types';
|
|
4
|
-
|
|
5
|
-
export function useFilteredOptions({
|
|
6
|
-
searchable,
|
|
7
|
-
touched,
|
|
8
|
-
inputValue,
|
|
9
|
-
options,
|
|
10
|
-
}: {
|
|
11
|
-
searchable: boolean;
|
|
12
|
-
touched: boolean;
|
|
13
|
-
inputValue: string;
|
|
14
|
-
options: Option[];
|
|
15
|
-
}) {
|
|
16
|
-
return useMemo(
|
|
17
|
-
() =>
|
|
18
|
-
searchable && touched && inputValue
|
|
19
|
-
? options.filter(item => item.label.toLowerCase().includes(inputValue.toLowerCase().trim()))
|
|
20
|
-
: options,
|
|
21
|
-
[inputValue, options, searchable, touched],
|
|
22
|
-
);
|
|
23
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef } from 'react';
|
|
2
|
-
import { useUncontrolledProp } from 'uncontrollable';
|
|
3
|
-
|
|
4
|
-
import { FieldSelectProps } from '../FieldSelect';
|
|
5
|
-
import { Option } from '../types';
|
|
6
|
-
import { useFilteredOptions } from './useFilteredOptions';
|
|
7
|
-
import { useListNavigation } from './useListNavigation';
|
|
8
|
-
|
|
9
|
-
type UseListProps = Pick<
|
|
10
|
-
FieldSelectProps,
|
|
11
|
-
'readonly' | 'disabled' | 'open' | 'onOpenChange' | 'options' | 'showCopyButton'
|
|
12
|
-
> & {
|
|
13
|
-
searchable: NonNullable<FieldSelectProps['searchable']>;
|
|
14
|
-
showAdditionalButton: boolean;
|
|
15
|
-
showClearButton: boolean;
|
|
16
|
-
inputValue: string;
|
|
17
|
-
setInputValue(value: string): void;
|
|
18
|
-
isChecked(option: Option): boolean;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export function useList({
|
|
22
|
-
open,
|
|
23
|
-
onOpenChange,
|
|
24
|
-
readonly,
|
|
25
|
-
disabled,
|
|
26
|
-
searchable,
|
|
27
|
-
showAdditionalButton,
|
|
28
|
-
showCopyButton: showCopyButtonProp,
|
|
29
|
-
showClearButton: showClearButtonProp,
|
|
30
|
-
inputValue,
|
|
31
|
-
setInputValue,
|
|
32
|
-
options,
|
|
33
|
-
isChecked,
|
|
34
|
-
}: UseListProps) {
|
|
35
|
-
const touched = useRef(false);
|
|
36
|
-
const localRef = useRef<HTMLInputElement>(null);
|
|
37
|
-
const clearButtonRef = useRef<HTMLButtonElement>(null);
|
|
38
|
-
const copyButtonRef = useRef<HTMLButtonElement>(null);
|
|
39
|
-
const [isOpen, setIsOpen] = useUncontrolledProp(open, false, onOpenChange);
|
|
40
|
-
const showDropList = isOpen && !readonly && !disabled;
|
|
41
|
-
const showClearButton = showClearButtonProp && !readonly && (showAdditionalButton || inputValue.length > 0);
|
|
42
|
-
const showCopyButton = Boolean(showAdditionalButton && showCopyButtonProp && readonly);
|
|
43
|
-
|
|
44
|
-
const { extendedOptions, onInputKeyDown, onButtonKeyDown, onDroplistFocusLeave, firstDroplistItemRefCallback } =
|
|
45
|
-
useListNavigation({
|
|
46
|
-
inputRef: localRef,
|
|
47
|
-
options: useFilteredOptions({ searchable, options, touched: touched.current, inputValue }),
|
|
48
|
-
toggleListOpen: setIsOpen,
|
|
49
|
-
isChecked,
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const handleOpenChange = (value: boolean) => {
|
|
53
|
-
if (!value) {
|
|
54
|
-
touched.current = false;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
setIsOpen(value);
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const handleInputValueChange = (value: string) => {
|
|
61
|
-
touched.current = true;
|
|
62
|
-
setIsOpen(true);
|
|
63
|
-
setInputValue(value);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
if (open) {
|
|
68
|
-
localRef.current?.focus();
|
|
69
|
-
}
|
|
70
|
-
}, [localRef, open]);
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
isOpen: showDropList,
|
|
74
|
-
setIsOpen: handleOpenChange,
|
|
75
|
-
localRef,
|
|
76
|
-
clearButtonRef,
|
|
77
|
-
showClearButton,
|
|
78
|
-
copyButtonRef,
|
|
79
|
-
showCopyButton,
|
|
80
|
-
extendedOptions,
|
|
81
|
-
onInputKeyDown,
|
|
82
|
-
onButtonKeyDown,
|
|
83
|
-
onInputValueChange: handleInputValueChange,
|
|
84
|
-
firstDroplistItemRefCallback,
|
|
85
|
-
onDroplistFocusLeave,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { KeyboardEvent, KeyboardEventHandler, RefObject, useCallback, useMemo, useRef } from 'react';
|
|
2
|
-
|
|
3
|
-
import { moveCursorToEnd, runAfterRerender } from '@snack-uikit/input-private';
|
|
4
|
-
|
|
5
|
-
import { Option } from '../types';
|
|
6
|
-
|
|
7
|
-
type UseListNavigationProps = {
|
|
8
|
-
options: Option[];
|
|
9
|
-
toggleListOpen(value: boolean): void;
|
|
10
|
-
inputRef: RefObject<HTMLInputElement>;
|
|
11
|
-
isChecked(option: Option): boolean;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export function useListNavigation({ options, toggleListOpen, inputRef, isChecked }: UseListNavigationProps) {
|
|
15
|
-
const setInputFocus = useCallback(() => {
|
|
16
|
-
runAfterRerender(() => {
|
|
17
|
-
inputRef.current?.focus();
|
|
18
|
-
moveCursorToEnd(inputRef.current);
|
|
19
|
-
});
|
|
20
|
-
}, [inputRef]);
|
|
21
|
-
|
|
22
|
-
const firstDroplistItemRef = useRef<HTMLButtonElement | null>(null);
|
|
23
|
-
|
|
24
|
-
const firstDroplistItemRefCallback = useCallback(
|
|
25
|
-
(element: HTMLButtonElement | null) => {
|
|
26
|
-
firstDroplistItemRef.current = element;
|
|
27
|
-
},
|
|
28
|
-
[firstDroplistItemRef],
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
const setOptionFocus = useCallback(() => {
|
|
32
|
-
runAfterRerender(() => firstDroplistItemRef.current?.focus());
|
|
33
|
-
}, [firstDroplistItemRef]);
|
|
34
|
-
|
|
35
|
-
const leaveElement = (event: KeyboardEvent) => {
|
|
36
|
-
if (event.key === 'ArrowDown') {
|
|
37
|
-
event.preventDefault();
|
|
38
|
-
toggleListOpen(true);
|
|
39
|
-
setOptionFocus();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (event.key === 'Tab') {
|
|
43
|
-
toggleListOpen(false);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const handleInputKeyDown: KeyboardEventHandler<HTMLInputElement> = event => {
|
|
48
|
-
leaveElement(event);
|
|
49
|
-
|
|
50
|
-
if (event.key === 'Enter') {
|
|
51
|
-
toggleListOpen(true);
|
|
52
|
-
setOptionFocus();
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const onDroplistFocusLeave = useCallback(
|
|
57
|
-
(direction: string) => {
|
|
58
|
-
if (['top', 'common'].includes(direction)) {
|
|
59
|
-
setInputFocus();
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
[setInputFocus],
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const extendedOptions = useMemo(
|
|
66
|
-
() =>
|
|
67
|
-
options.map(option => ({
|
|
68
|
-
...option,
|
|
69
|
-
checked: isChecked(option),
|
|
70
|
-
})),
|
|
71
|
-
[isChecked, options],
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
onInputKeyDown: handleInputKeyDown,
|
|
76
|
-
onButtonKeyDown: leaveElement,
|
|
77
|
-
onDroplistFocusLeave,
|
|
78
|
-
extendedOptions,
|
|
79
|
-
firstDroplistItemRefCallback,
|
|
80
|
-
};
|
|
81
|
-
}
|