@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.
Files changed (62) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +15 -14
  3. package/dist/components/FieldDecorator/Header.js +1 -1
  4. package/dist/components/FieldDecorator/styles.module.css +7 -1
  5. package/dist/components/FieldSelect/FieldSelect.d.ts +1 -7
  6. package/dist/components/FieldSelect/FieldSelect.js +9 -21
  7. package/dist/components/FieldSelect/FieldSelectMultiple.d.ts +17 -0
  8. package/dist/components/FieldSelect/FieldSelectMultiple.js +118 -0
  9. package/dist/components/FieldSelect/FieldSelectSingle.d.ts +9 -28
  10. package/dist/components/FieldSelect/FieldSelectSingle.js +69 -55
  11. package/dist/components/FieldSelect/hooks.d.ts +30 -0
  12. package/dist/components/FieldSelect/hooks.js +72 -0
  13. package/dist/components/FieldSelect/index.d.ts +2 -1
  14. package/dist/components/FieldSelect/index.js +1 -1
  15. package/dist/components/FieldSelect/styles.module.css +129 -27
  16. package/dist/components/FieldSelect/types.d.ts +42 -37
  17. package/dist/components/FieldSelect/utils.d.ts +19 -0
  18. package/dist/components/FieldSelect/utils.js +112 -0
  19. package/dist/helperComponents/FieldContainerPrivate/styles.module.css +30 -6
  20. package/package.json +5 -3
  21. package/src/components/FieldDecorator/Header.tsx +6 -1
  22. package/src/components/FieldDecorator/styles.module.scss +38 -30
  23. package/src/components/FieldSelect/FieldSelect.tsx +13 -21
  24. package/src/components/FieldSelect/FieldSelectMultiple.tsx +255 -0
  25. package/src/components/FieldSelect/FieldSelectSingle.tsx +159 -99
  26. package/src/components/FieldSelect/hooks.ts +125 -0
  27. package/src/components/FieldSelect/index.ts +12 -1
  28. package/src/components/FieldSelect/styles.module.scss +71 -31
  29. package/src/components/FieldSelect/types.ts +55 -40
  30. package/src/components/FieldSelect/utils.ts +163 -0
  31. package/src/helperComponents/FieldContainerPrivate/FieldContainerPrivate.tsx +2 -0
  32. package/src/helperComponents/FieldContainerPrivate/styles.module.scss +32 -11
  33. package/dist/components/FieldSelect/FieldSelectBase.d.ts +0 -31
  34. package/dist/components/FieldSelect/FieldSelectBase.js +0 -51
  35. package/dist/components/FieldSelect/FieldSelectMulti.d.ts +0 -37
  36. package/dist/components/FieldSelect/FieldSelectMulti.js +0 -89
  37. package/dist/components/FieldSelect/constants.d.ts +0 -7
  38. package/dist/components/FieldSelect/constants.js +0 -6
  39. package/dist/components/FieldSelect/helpers/getArrowIcon.d.ts +0 -8
  40. package/dist/components/FieldSelect/helpers/getArrowIcon.js +0 -8
  41. package/dist/components/FieldSelect/helpers/getDisplayedValue.d.ts +0 -10
  42. package/dist/components/FieldSelect/helpers/getDisplayedValue.js +0 -12
  43. package/dist/components/FieldSelect/helpers/index.d.ts +0 -2
  44. package/dist/components/FieldSelect/helpers/index.js +0 -2
  45. package/dist/components/FieldSelect/hooks/index.d.ts +0 -3
  46. package/dist/components/FieldSelect/hooks/index.js +0 -3
  47. package/dist/components/FieldSelect/hooks/useFilteredOptions.d.ts +0 -7
  48. package/dist/components/FieldSelect/hooks/useFilteredOptions.js +0 -6
  49. package/dist/components/FieldSelect/hooks/useList.d.ts +0 -37
  50. package/dist/components/FieldSelect/hooks/useList.js +0 -52
  51. package/dist/components/FieldSelect/hooks/useListNavigation.d.ts +0 -26
  52. package/dist/components/FieldSelect/hooks/useListNavigation.js +0 -48
  53. package/src/components/FieldSelect/FieldSelectBase.tsx +0 -222
  54. package/src/components/FieldSelect/FieldSelectMulti.tsx +0 -163
  55. package/src/components/FieldSelect/constants.ts +0 -9
  56. package/src/components/FieldSelect/helpers/getArrowIcon.ts +0 -9
  57. package/src/components/FieldSelect/helpers/getDisplayedValue.ts +0 -25
  58. package/src/components/FieldSelect/helpers/index.ts +0 -2
  59. package/src/components/FieldSelect/hooks/index.ts +0 -3
  60. package/src/components/FieldSelect/hooks/useFilteredOptions.ts +0 -23
  61. package/src/components/FieldSelect/hooks/useList.ts +0 -87
  62. 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
- }