@snack-uikit/fields 0.26.0 → 0.27.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 +18 -0
- package/README.md +11 -10
- package/dist/components/FieldDate/hooks/useDateField.js +2 -1
- package/dist/components/FieldSelect/FieldSelectMultiple.d.ts +1 -0
- package/dist/components/FieldSelect/FieldSelectMultiple.js +6 -5
- package/dist/components/FieldSelect/FieldSelectSingle.d.ts +3 -2
- package/dist/components/FieldSelect/FieldSelectSingle.js +4 -8
- package/dist/components/FieldSelect/hooks.d.ts +2 -1
- package/dist/components/FieldSelect/hooks.js +3 -3
- package/dist/components/FieldSelect/types.d.ts +3 -1
- package/dist/helperComponents/TextArea/TextArea.js +2 -2
- package/package.json +15 -15
- package/src/components/FieldDate/hooks/useDateField.ts +3 -1
- package/src/components/FieldSelect/FieldSelectMultiple.tsx +5 -3
- package/src/components/FieldSelect/FieldSelectSingle.tsx +3 -6
- package/src/components/FieldSelect/hooks.ts +11 -11
- package/src/components/FieldSelect/types.ts +4 -1
- package/src/helperComponents/TextArea/TextArea.tsx +1 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 0.27.0 (2024-09-23)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **DPS-12873:** selectedOptionFormatter with predefined value ([7a8d335](https://github.com/cloud-ru-tech/snack-uikit/commit/7a8d33574a6205a56aa742aaa052d07d30f99eb0))
|
|
12
|
+
* **PDS-480:** remove direct usage of browser api elements ([1231ff7](https://github.com/cloud-ru-tech/snack-uikit/commit/1231ff7ab7a1b210b579a7b694633ef23bffcf44))
|
|
13
|
+
* **PDS-480:** replace useLayoutEffect -> useIsomorphicLayoutEffect for ssr ([21aa9ad](https://github.com/cloud-ru-tech/snack-uikit/commit/21aa9ad9f113e465766339d396924357ccb1d432))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* **PDS-000:** add resetSearchOnOptionSelection property ([1fe3640](https://github.com/cloud-ru-tech/snack-uikit/commit/1fe3640b23a3da35c6b949c2bdc0796073b51425))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
6
24
|
# 0.26.0 (2024-09-17)
|
|
7
25
|
|
|
8
26
|
|
package/README.md
CHANGED
|
@@ -368,31 +368,32 @@ FieldStepper в основном предназначен для работы с
|
|
|
368
368
|
| value | `ItemId \| ItemId[]` | - | Controlled состояние |
|
|
369
369
|
| onChange | `OnChangeHandler<any>` | - | Controlled обработчик измения состояния |
|
|
370
370
|
| defaultValue | `ItemId \| ItemId[]` | - | Начальное состояние |
|
|
371
|
-
|
|
|
372
|
-
|
|
|
373
|
-
| searchable | `boolean` | - | |
|
|
371
|
+
| open | `boolean` | - | |
|
|
372
|
+
| onOpenChange | `(open: boolean) => void` | - | |
|
|
374
373
|
| showCopyButton | `boolean` | - | Отображение кнопки Копировать для поля (актуально только для `readonly = true`) |
|
|
375
374
|
| showClearButton | `boolean` | true | Отображение кнопки очистки поля |
|
|
376
375
|
| prefixIcon | `ReactElement<any, string \| JSXElementConstructor<any>>` | - | Иконка-префикс для поля |
|
|
377
|
-
| footer | `ReactNode` | - | |
|
|
378
376
|
| widthStrategy | enum PopoverWidthStrategy: `"auto"`, `"gte"`, `"eq"` | - | |
|
|
377
|
+
| pinTop | `OptionProps[]` | - | |
|
|
378
|
+
| pinBottom | `OptionProps[]` | - | |
|
|
379
|
+
| footer | `ReactNode` | - | |
|
|
379
380
|
| search | `SearchState` | - | |
|
|
380
|
-
| autocomplete | `boolean` | - | |
|
|
381
|
-
| addOptionByEnter | `boolean` | - | |
|
|
382
|
-
| open | `boolean` | - | |
|
|
383
|
-
| enableFuzzySearch | `boolean` | - | Включить нечеткий поиск |
|
|
384
|
-
| onOpenChange | `(open: boolean) => void` | - | |
|
|
385
|
-
| selectedOptionFormatter | `SelectedOptionFormatter` | - | |
|
|
386
381
|
| untouchableScrollbars | `boolean` | - | Отключает возможность взаимодействовать со скролбарами мышью. |
|
|
387
382
|
| dataFiltered | `boolean` | - | |
|
|
388
383
|
| dataError | `boolean` | - | |
|
|
389
384
|
| noDataState | `EmptyStateProps` | - | Экран при отстутствии данных |
|
|
390
385
|
| noResultsState | `EmptyStateProps` | - | Экран при отстутствии результатов поиска или фильтров |
|
|
391
386
|
| errorDataState | `EmptyStateProps` | - | Экран при ошибке запроса |
|
|
387
|
+
| searchable | `boolean` | - | |
|
|
388
|
+
| autocomplete | `boolean` | - | |
|
|
389
|
+
| addOptionByEnter | `boolean` | - | |
|
|
390
|
+
| enableFuzzySearch | `boolean` | - | Включить нечеткий поиск |
|
|
391
|
+
| selectedOptionFormatter | `SelectedOptionFormatter` | - | |
|
|
392
392
|
| selection | "single" \| "multiple" | - | |
|
|
393
393
|
| 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 |
|
|
394
394
|
| key | `Key` | - | |
|
|
395
395
|
| removeByBackspace | `boolean` | - | |
|
|
396
|
+
| resetSearchOnOptionSelection | `boolean` | - | Поведение строки поиска при выборе опции из списка |
|
|
396
397
|
## FieldStepper
|
|
397
398
|
### Props
|
|
398
399
|
| name | type | default value | description |
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback, useMemo, useRef } from 'react';
|
|
2
|
+
import { isBrowser } from '@snack-uikit/utils';
|
|
2
3
|
import { DEFAULT_LOCALE, MASK, SlotKey, SLOTS, SLOTS_PLACEHOLDER } from '../constants';
|
|
3
4
|
import { getNextSlotKey, getPrevSlotKey, getSlotKey } from '../utils';
|
|
4
5
|
import { useDateFieldHelpers } from './useDateFieldHelpers';
|
|
@@ -12,7 +13,7 @@ export function useDateField({ inputRef, onChange, readonly, locale = DEFAULT_LO
|
|
|
12
13
|
if (!inputRef.current || readonly) {
|
|
13
14
|
return;
|
|
14
15
|
}
|
|
15
|
-
if (document.activeElement !== inputRef.current) {
|
|
16
|
+
if (isBrowser() && document.activeElement !== inputRef.current) {
|
|
16
17
|
focusSlotRef.current = focusSlot || SlotKey.Day;
|
|
17
18
|
inputRef.current.focus();
|
|
18
19
|
return;
|
|
@@ -22,6 +22,7 @@ export declare const FieldSelectMultiple: import("react").ForwardRefExoticCompon
|
|
|
22
22
|
addOptionByEnter?: boolean;
|
|
23
23
|
open?: boolean;
|
|
24
24
|
enableFuzzySearch?: boolean;
|
|
25
|
+
resetSearchOnOptionSelection?: boolean;
|
|
25
26
|
onOpenChange?(open: boolean): void;
|
|
26
27
|
selectedOptionFormatter?: SelectedOptionFormatter;
|
|
27
28
|
} & Pick<import("@snack-uikit/list").DroplistProps, "untouchableScrollbars" | "dataError" | "dataFiltered" | "noDataState" | "noResultsState" | "errorDataState">, "showCopyButton"> & import("react").RefAttributes<HTMLInputElement>>;
|
|
@@ -12,11 +12,11 @@ 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, useRef, useState } from 'react';
|
|
16
16
|
import { InputPrivate } from '@snack-uikit/input-private';
|
|
17
17
|
import { Droplist } from '@snack-uikit/list';
|
|
18
18
|
import { Tag } from '@snack-uikit/tag';
|
|
19
|
-
import { extractSupportProps } from '@snack-uikit/utils';
|
|
19
|
+
import { extractSupportProps, isBrowser, useLayoutEffect } from '@snack-uikit/utils';
|
|
20
20
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
21
21
|
import { useValueControl } from '../../hooks';
|
|
22
22
|
import { getValidationState } from '../../utils/getValidationState';
|
|
@@ -32,7 +32,7 @@ const defaultSelectedOptionFormatter = item =>
|
|
|
32
32
|
(item === null || item === void 0 ? void 0 : item.content.option) || '';
|
|
33
33
|
export const FieldSelectMultiple = forwardRef((props, ref) => {
|
|
34
34
|
var _a;
|
|
35
|
-
const { 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, untouchableScrollbars = false, open: openProp, enableFuzzySearch = true, onOpenChange, selectedOptionFormatter = defaultSelectedOptionFormatter } = props, rest = __rest(props, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "disabled", "readonly", "searchable", "showClearButton", "onKeyDown", "validationState", "search", "autocomplete", "prefixIcon", "removeByBackspace", "addOptionByEnter", "untouchableScrollbars", "open", "enableFuzzySearch", "onOpenChange", "selectedOptionFormatter"]);
|
|
35
|
+
const { 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, untouchableScrollbars = false, open: openProp, enableFuzzySearch = true, resetSearchOnOptionSelection = true, onOpenChange, selectedOptionFormatter = defaultSelectedOptionFormatter } = props, rest = __rest(props, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "disabled", "readonly", "searchable", "showClearButton", "onKeyDown", "validationState", "search", "autocomplete", "prefixIcon", "removeByBackspace", "addOptionByEnter", "untouchableScrollbars", "open", "enableFuzzySearch", "resetSearchOnOptionSelection", "onOpenChange", "selectedOptionFormatter"]);
|
|
36
36
|
const localRef = useRef(null);
|
|
37
37
|
const inputPlugRef = useRef(null);
|
|
38
38
|
const contentRef = useRef(null);
|
|
@@ -43,7 +43,8 @@ export const FieldSelectMultiple = forwardRef((props, ref) => {
|
|
|
43
43
|
onChange: onChangeProp,
|
|
44
44
|
});
|
|
45
45
|
const [{ selectedItems, items = [] }, setItems] = useState(() => updateMultipleItems({ options, value, currentItems: [], selectedItems: undefined }));
|
|
46
|
-
const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: '', selectedOptionFormatter
|
|
46
|
+
const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: '', selectedOptionFormatter,
|
|
47
|
+
resetSearchOnOptionSelection }));
|
|
47
48
|
useLayoutEffect(() => {
|
|
48
49
|
setItems(({ selectedItems }) => updateMultipleItems({ options, value, selectedItems }));
|
|
49
50
|
}, [options, value]);
|
|
@@ -92,7 +93,7 @@ export const FieldSelectMultiple = forwardRef((props, ref) => {
|
|
|
92
93
|
commonHandleOnKeyDown(onKeyDown)(e);
|
|
93
94
|
};
|
|
94
95
|
const handleOpenChange = (open) => {
|
|
95
|
-
if (!readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
96
|
+
if (isBrowser() && !readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
96
97
|
setOpen(open);
|
|
97
98
|
if (!open) {
|
|
98
99
|
if (inputPlugRef.current) {
|
|
@@ -2,7 +2,7 @@ import { SelectedOptionFormatter } from './types';
|
|
|
2
2
|
export declare const FieldSelectSingle: import("react").ForwardRefExoticComponent<import("./types").InputProps & import("./types").WrapperProps & {
|
|
3
3
|
options: import("./types").OptionProps[];
|
|
4
4
|
loading?: boolean;
|
|
5
|
-
} & Omit<import("@snack-uikit/list").SelectionSingleState, "mode"> & {
|
|
5
|
+
} & Omit<import("@snack-uikit/list").SelectionSingleState, "mode"> & Omit<{
|
|
6
6
|
'data-test-id'?: string;
|
|
7
7
|
} & import("react").AriaAttributes & {
|
|
8
8
|
options: import("./types").OptionProps[];
|
|
@@ -20,6 +20,7 @@ export declare const FieldSelectSingle: import("react").ForwardRefExoticComponen
|
|
|
20
20
|
addOptionByEnter?: boolean;
|
|
21
21
|
open?: boolean;
|
|
22
22
|
enableFuzzySearch?: boolean;
|
|
23
|
+
resetSearchOnOptionSelection?: boolean;
|
|
23
24
|
onOpenChange?(open: boolean): void;
|
|
24
25
|
selectedOptionFormatter?: SelectedOptionFormatter;
|
|
25
|
-
} & Pick<import("@snack-uikit/list").DroplistProps, "untouchableScrollbars" | "dataError" | "dataFiltered" | "noDataState" | "noResultsState" | "errorDataState"> & import("react").RefAttributes<HTMLInputElement>>;
|
|
26
|
+
} & Pick<import("@snack-uikit/list").DroplistProps, "untouchableScrollbars" | "dataError" | "dataFiltered" | "noDataState" | "noResultsState" | "errorDataState">, "resetSearchOnOptionSelection"> & import("react").RefAttributes<HTMLInputElement>>;
|
|
@@ -12,10 +12,10 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
import cn from 'classnames';
|
|
14
14
|
import mergeRefs from 'merge-refs';
|
|
15
|
-
import { forwardRef, useCallback, useEffect,
|
|
15
|
+
import { forwardRef, useCallback, useEffect, useRef, useState, } from 'react';
|
|
16
16
|
import { InputPrivate } from '@snack-uikit/input-private';
|
|
17
17
|
import { Droplist } from '@snack-uikit/list';
|
|
18
|
-
import { extractSupportProps } from '@snack-uikit/utils';
|
|
18
|
+
import { extractSupportProps, isBrowser, useLayoutEffect } from '@snack-uikit/utils';
|
|
19
19
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
20
20
|
import { useValueControl } from '../../hooks';
|
|
21
21
|
import { getValidationState } from '../../utils/getValidationState';
|
|
@@ -29,7 +29,6 @@ const defaultSelectedOptionFormatter = item =>
|
|
|
29
29
|
// @ts-expect-error
|
|
30
30
|
(item === null || item === void 0 ? void 0 : item.content.option) || '';
|
|
31
31
|
export const FieldSelectSingle = forwardRef((props, ref) => {
|
|
32
|
-
var _a;
|
|
33
32
|
const { 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, untouchableScrollbars = false, open: openProp, onOpenChange, selectedOptionFormatter = defaultSelectedOptionFormatter, enableFuzzySearch = true } = props, rest = __rest(props, ["id", "name", "placeholder", "size", "options", "value", "defaultValue", "onChange", "disabled", "readonly", "searchable", "showCopyButton", "showClearButton", "onKeyDown", "required", "validationState", "search", "autocomplete", "prefixIcon", "addOptionByEnter", "untouchableScrollbars", "open", "onOpenChange", "selectedOptionFormatter", "enableFuzzySearch"]);
|
|
34
33
|
const localRef = useRef(null);
|
|
35
34
|
const [open = false, setOpen] = useValueControl({ value: openProp, onChange: onOpenChange });
|
|
@@ -39,10 +38,7 @@ export const FieldSelectSingle = forwardRef((props, ref) => {
|
|
|
39
38
|
onChange: onChangeProp,
|
|
40
39
|
});
|
|
41
40
|
const [{ selectedItem, items = [] }, setItems] = useState(() => updateItems({ options, value, currentItems: [], selectedItem: undefined }));
|
|
42
|
-
const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), {
|
|
43
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
44
|
-
// @ts-expect-error
|
|
45
|
-
defaultValue: (_a = selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.content.option) !== null && _a !== void 0 ? _a : '', selectedOptionFormatter }));
|
|
41
|
+
const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput(Object.assign(Object.assign({}, search), { defaultValue: selectedOptionFormatter(selectedItem), selectedOptionFormatter }));
|
|
46
42
|
const prevSelectedItem = useRef(selectedItem);
|
|
47
43
|
useLayoutEffect(() => {
|
|
48
44
|
setItems(({ selectedItem }) => updateItems({ options, value, selectedItem }));
|
|
@@ -111,7 +107,7 @@ export const FieldSelectSingle = forwardRef((props, ref) => {
|
|
|
111
107
|
commonHandleOnKeyDown(onKeyDown)(e);
|
|
112
108
|
};
|
|
113
109
|
const handleOpenChange = (open) => {
|
|
114
|
-
if (!readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
110
|
+
if (isBrowser() && !readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
115
111
|
setOpen(open);
|
|
116
112
|
if (!open) {
|
|
117
113
|
updateInputValue(selectedItem);
|
|
@@ -22,8 +22,9 @@ export declare function useButtons({ readonly, showClearButton, showCopyButton,
|
|
|
22
22
|
inputKeyDownNavigationHandler: KeyboardEventHandler<HTMLInputElement>;
|
|
23
23
|
buttonsRefs: (Element | null)[];
|
|
24
24
|
};
|
|
25
|
-
export declare function useSearchInput({ value, onChange, defaultValue, selectedOptionFormatter, }: SearchState & {
|
|
25
|
+
export declare function useSearchInput({ value, onChange, defaultValue, selectedOptionFormatter, resetSearchOnOptionSelection, }: SearchState & {
|
|
26
26
|
selectedOptionFormatter: SelectedOptionFormatter;
|
|
27
|
+
resetSearchOnOptionSelection?: boolean;
|
|
27
28
|
}): {
|
|
28
29
|
inputValue: string;
|
|
29
30
|
setInputValue: (value: any, ...args: any[]) => ReturnType<Handler> | void;
|
|
@@ -51,16 +51,16 @@ export function useButtons({ readonly, showClearButton, showCopyButton, size, on
|
|
|
51
51
|
});
|
|
52
52
|
return { buttons, inputKeyDownNavigationHandler, buttonsRefs };
|
|
53
53
|
}
|
|
54
|
-
export function useSearchInput({ value, onChange, defaultValue, selectedOptionFormatter, }) {
|
|
54
|
+
export function useSearchInput({ value, onChange, defaultValue, selectedOptionFormatter, resetSearchOnOptionSelection = true, }) {
|
|
55
55
|
const [inputValue = '', setInputValue] = useValueControl({ value, onChange, defaultValue });
|
|
56
56
|
const prevInputValue = useRef(inputValue);
|
|
57
57
|
const updateInputValue = useCallback((selectedItem) => {
|
|
58
58
|
const newInputValue = selectedOptionFormatter(selectedItem);
|
|
59
|
-
if (inputValue !== newInputValue || prevInputValue.current !== newInputValue) {
|
|
59
|
+
if (resetSearchOnOptionSelection && (inputValue !== newInputValue || prevInputValue.current !== newInputValue)) {
|
|
60
60
|
setInputValue(newInputValue);
|
|
61
61
|
prevInputValue.current = newInputValue;
|
|
62
62
|
}
|
|
63
|
-
}, [inputValue, selectedOptionFormatter, setInputValue]);
|
|
63
|
+
}, [inputValue, resetSearchOnOptionSelection, selectedOptionFormatter, setInputValue]);
|
|
64
64
|
return { inputValue, setInputValue, prevInputValue, onInputValueChange: setInputValue, updateInputValue };
|
|
65
65
|
}
|
|
66
66
|
export function useHandleDeleteItem(setValue) {
|
|
@@ -62,10 +62,12 @@ type FiledSelectCommonProps = WithSupportProps<{
|
|
|
62
62
|
open?: boolean;
|
|
63
63
|
/** Включить нечеткий поиск */
|
|
64
64
|
enableFuzzySearch?: boolean;
|
|
65
|
+
/** Поведение строки поиска при выборе опции из списка */
|
|
66
|
+
resetSearchOnOptionSelection?: boolean;
|
|
65
67
|
onOpenChange?(open: boolean): void;
|
|
66
68
|
selectedOptionFormatter?: SelectedOptionFormatter;
|
|
67
69
|
}> & Pick<DroplistProps, 'dataError' | 'noDataState' | 'noResultsState' | 'errorDataState' | 'dataFiltered' | 'untouchableScrollbars'>;
|
|
68
|
-
export type FieldSelectSingleProps = FieldSelectPrivateProps & Omit<SelectionSingleState, 'mode'> & WrapperProps & FiledSelectCommonProps
|
|
70
|
+
export type FieldSelectSingleProps = FieldSelectPrivateProps & Omit<SelectionSingleState, 'mode'> & WrapperProps & Omit<FiledSelectCommonProps, 'resetSearchOnOptionSelection'>;
|
|
69
71
|
export type FieldSelectMultipleProps = FieldSelectPrivateProps & {
|
|
70
72
|
removeByBackspace?: boolean;
|
|
71
73
|
} & Omit<SelectionMultipleState, 'mode'> & Omit<FiledSelectCommonProps, 'showCopyButton'>;
|
|
@@ -11,9 +11,9 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
};
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
13
|
import cn from 'classnames';
|
|
14
|
-
import { forwardRef,
|
|
14
|
+
import { forwardRef, useState, } from 'react';
|
|
15
15
|
import TextareaAutosize from 'react-textarea-autosize';
|
|
16
|
-
import { extractSupportProps } from '@snack-uikit/utils';
|
|
16
|
+
import { extractSupportProps, useLayoutEffect } from '@snack-uikit/utils';
|
|
17
17
|
import styles from './styles.module.css';
|
|
18
18
|
export const TextArea = forwardRef((_a, ref) => {
|
|
19
19
|
var { name, value = '', onChange, placeholder, id, className, disabled = false, readonly = false, autoComplete = false, maxLength, onFocus, onBlur, onKeyDown, tabIndex, minRows = 3 } = _a, rest = __rest(_a, ["name", "value", "onChange", "placeholder", "id", "className", "disabled", "readonly", "autoComplete", "maxLength", "onFocus", "onBlur", "onKeyDown", "tabIndex", "minRows"]);
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "Fields",
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.27.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -32,19 +32,19 @@
|
|
|
32
32
|
"license": "Apache-2.0",
|
|
33
33
|
"scripts": {},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@snack-uikit/button": "0.17.
|
|
36
|
-
"@snack-uikit/calendar": "0.7.
|
|
37
|
-
"@snack-uikit/dropdown": "0.2.
|
|
38
|
-
"@snack-uikit/icons": "0.22.
|
|
39
|
-
"@snack-uikit/input-private": "3.2.
|
|
40
|
-
"@snack-uikit/list": "0.16.
|
|
41
|
-
"@snack-uikit/scroll": "0.6.
|
|
42
|
-
"@snack-uikit/skeleton": "0.3.
|
|
43
|
-
"@snack-uikit/slider": "0.1.
|
|
44
|
-
"@snack-uikit/tag": "0.9.
|
|
45
|
-
"@snack-uikit/tooltip": "0.13.
|
|
46
|
-
"@snack-uikit/truncate-string": "0.4.
|
|
47
|
-
"@snack-uikit/utils": "3.
|
|
35
|
+
"@snack-uikit/button": "0.17.5",
|
|
36
|
+
"@snack-uikit/calendar": "0.7.11",
|
|
37
|
+
"@snack-uikit/dropdown": "0.2.6",
|
|
38
|
+
"@snack-uikit/icons": "0.22.1",
|
|
39
|
+
"@snack-uikit/input-private": "3.2.1",
|
|
40
|
+
"@snack-uikit/list": "0.16.2",
|
|
41
|
+
"@snack-uikit/scroll": "0.6.1",
|
|
42
|
+
"@snack-uikit/skeleton": "0.3.5",
|
|
43
|
+
"@snack-uikit/slider": "0.1.17",
|
|
44
|
+
"@snack-uikit/tag": "0.9.9",
|
|
45
|
+
"@snack-uikit/tooltip": "0.13.9",
|
|
46
|
+
"@snack-uikit/truncate-string": "0.4.22",
|
|
47
|
+
"@snack-uikit/utils": "3.4.0",
|
|
48
48
|
"classnames": "2.3.2",
|
|
49
49
|
"copy-to-clipboard": "3.3.3",
|
|
50
50
|
"fuzzy-search": "3.2.1",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"@snack-uikit/locale": "*"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "f9212fe04b0dbba9bedea1bb3a034ab612287841"
|
|
63
63
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ChangeEvent, FocusEventHandler, KeyboardEvent, RefObject, useCallback, useMemo, useRef } from 'react';
|
|
2
2
|
|
|
3
|
+
import { isBrowser } from '@snack-uikit/utils';
|
|
4
|
+
|
|
3
5
|
import { DEFAULT_LOCALE, MASK, SlotKey, SLOTS, SLOTS_PLACEHOLDER } from '../constants';
|
|
4
6
|
import { getNextSlotKey, getPrevSlotKey, getSlotKey } from '../utils';
|
|
5
7
|
import { useDateFieldHelpers } from './useDateFieldHelpers';
|
|
@@ -32,7 +34,7 @@ export function useDateField({ inputRef, onChange, readonly, locale = DEFAULT_LO
|
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
if (document.activeElement !== inputRef.current) {
|
|
37
|
+
if (isBrowser() && document.activeElement !== inputRef.current) {
|
|
36
38
|
focusSlotRef.current = focusSlot || SlotKey.Day;
|
|
37
39
|
inputRef.current.focus();
|
|
38
40
|
return;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import cn from 'classnames';
|
|
2
2
|
import mergeRefs from 'merge-refs';
|
|
3
|
-
import { FocusEvent, forwardRef, KeyboardEvent, KeyboardEventHandler,
|
|
3
|
+
import { FocusEvent, forwardRef, KeyboardEvent, KeyboardEventHandler, useRef, useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { InputPrivate } from '@snack-uikit/input-private';
|
|
6
6
|
import { BaseItemProps, Droplist, ItemProps, SelectionSingleValueType } from '@snack-uikit/list';
|
|
7
7
|
import { Tag } from '@snack-uikit/tag';
|
|
8
|
-
import { extractSupportProps } from '@snack-uikit/utils';
|
|
8
|
+
import { extractSupportProps, isBrowser, useLayoutEffect } from '@snack-uikit/utils';
|
|
9
9
|
|
|
10
10
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
11
11
|
import { useValueControl } from '../../hooks';
|
|
@@ -48,6 +48,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
48
48
|
untouchableScrollbars = false,
|
|
49
49
|
open: openProp,
|
|
50
50
|
enableFuzzySearch = true,
|
|
51
|
+
resetSearchOnOptionSelection = true,
|
|
51
52
|
onOpenChange,
|
|
52
53
|
selectedOptionFormatter = defaultSelectedOptionFormatter,
|
|
53
54
|
...rest
|
|
@@ -73,6 +74,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
73
74
|
...search,
|
|
74
75
|
defaultValue: '',
|
|
75
76
|
selectedOptionFormatter,
|
|
77
|
+
resetSearchOnOptionSelection,
|
|
76
78
|
});
|
|
77
79
|
|
|
78
80
|
useLayoutEffect(() => {
|
|
@@ -133,7 +135,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
133
135
|
};
|
|
134
136
|
|
|
135
137
|
const handleOpenChange = (open: boolean) => {
|
|
136
|
-
if (!readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
138
|
+
if (isBrowser() && !readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
137
139
|
setOpen(open);
|
|
138
140
|
|
|
139
141
|
if (!open) {
|
|
@@ -7,14 +7,13 @@ import {
|
|
|
7
7
|
KeyboardEventHandler,
|
|
8
8
|
useCallback,
|
|
9
9
|
useEffect,
|
|
10
|
-
useLayoutEffect,
|
|
11
10
|
useRef,
|
|
12
11
|
useState,
|
|
13
12
|
} from 'react';
|
|
14
13
|
|
|
15
14
|
import { InputPrivate } from '@snack-uikit/input-private';
|
|
16
15
|
import { Droplist, ItemProps, SelectionSingleValueType } from '@snack-uikit/list';
|
|
17
|
-
import { extractSupportProps } from '@snack-uikit/utils';
|
|
16
|
+
import { extractSupportProps, isBrowser, useLayoutEffect } from '@snack-uikit/utils';
|
|
18
17
|
|
|
19
18
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
20
19
|
import { useValueControl } from '../../hooks';
|
|
@@ -75,9 +74,7 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
75
74
|
|
|
76
75
|
const { inputValue, setInputValue, prevInputValue, updateInputValue } = useSearchInput({
|
|
77
76
|
...search,
|
|
78
|
-
|
|
79
|
-
// @ts-expect-error
|
|
80
|
-
defaultValue: selectedItem?.content.option ?? '',
|
|
77
|
+
defaultValue: selectedOptionFormatter(selectedItem),
|
|
81
78
|
selectedOptionFormatter,
|
|
82
79
|
});
|
|
83
80
|
|
|
@@ -168,7 +165,7 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
168
165
|
};
|
|
169
166
|
|
|
170
167
|
const handleOpenChange = (open: boolean) => {
|
|
171
|
-
if (!readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
168
|
+
if (isBrowser() && !readonly && !disabled && !buttonsRefs.includes(document.activeElement)) {
|
|
172
169
|
setOpen(open);
|
|
173
170
|
|
|
174
171
|
if (!open) {
|
|
@@ -106,7 +106,8 @@ export function useSearchInput({
|
|
|
106
106
|
onChange,
|
|
107
107
|
defaultValue,
|
|
108
108
|
selectedOptionFormatter,
|
|
109
|
-
|
|
109
|
+
resetSearchOnOptionSelection = true,
|
|
110
|
+
}: SearchState & { selectedOptionFormatter: SelectedOptionFormatter; resetSearchOnOptionSelection?: boolean }) {
|
|
110
111
|
const [inputValue = '', setInputValue] = useValueControl<string>({ value, onChange, defaultValue });
|
|
111
112
|
|
|
112
113
|
const prevInputValue = useRef<string>(inputValue);
|
|
@@ -115,13 +116,13 @@ export function useSearchInput({
|
|
|
115
116
|
(selectedItem?: ItemWithId) => {
|
|
116
117
|
const newInputValue = selectedOptionFormatter(selectedItem);
|
|
117
118
|
|
|
118
|
-
if (inputValue !== newInputValue || prevInputValue.current !== newInputValue) {
|
|
119
|
+
if (resetSearchOnOptionSelection && (inputValue !== newInputValue || prevInputValue.current !== newInputValue)) {
|
|
119
120
|
setInputValue(newInputValue);
|
|
120
121
|
|
|
121
122
|
prevInputValue.current = newInputValue;
|
|
122
123
|
}
|
|
123
124
|
},
|
|
124
|
-
[inputValue, selectedOptionFormatter, setInputValue],
|
|
125
|
+
[inputValue, resetSearchOnOptionSelection, selectedOptionFormatter, setInputValue],
|
|
125
126
|
);
|
|
126
127
|
|
|
127
128
|
return { inputValue, setInputValue, prevInputValue, onInputValueChange: setInputValue, updateInputValue };
|
|
@@ -144,14 +145,13 @@ export function useHandleDeleteItem(setValue: Handler) {
|
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
if (isBaseOptionProps(item)) {
|
|
147
|
-
setValue(
|
|
148
|
-
(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
),
|
|
148
|
+
setValue((value: SelectionSingleValueType[]) =>
|
|
149
|
+
value?.filter(
|
|
150
|
+
v =>
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
152
|
+
// @ts-expect-error
|
|
153
|
+
v !== item.id,
|
|
154
|
+
),
|
|
155
155
|
);
|
|
156
156
|
}
|
|
157
157
|
},
|
|
@@ -119,6 +119,9 @@ type FiledSelectCommonProps = WithSupportProps<{
|
|
|
119
119
|
/** Включить нечеткий поиск */
|
|
120
120
|
enableFuzzySearch?: boolean;
|
|
121
121
|
|
|
122
|
+
/** Поведение строки поиска при выборе опции из списка */
|
|
123
|
+
resetSearchOnOptionSelection?: boolean;
|
|
124
|
+
|
|
122
125
|
onOpenChange?(open: boolean): void;
|
|
123
126
|
|
|
124
127
|
selectedOptionFormatter?: SelectedOptionFormatter;
|
|
@@ -131,7 +134,7 @@ type FiledSelectCommonProps = WithSupportProps<{
|
|
|
131
134
|
export type FieldSelectSingleProps = FieldSelectPrivateProps &
|
|
132
135
|
Omit<SelectionSingleState, 'mode'> &
|
|
133
136
|
WrapperProps &
|
|
134
|
-
FiledSelectCommonProps
|
|
137
|
+
Omit<FiledSelectCommonProps, 'resetSearchOnOptionSelection'>;
|
|
135
138
|
|
|
136
139
|
export type FieldSelectMultipleProps = FieldSelectPrivateProps & {
|
|
137
140
|
removeByBackspace?: boolean;
|
|
@@ -7,12 +7,11 @@ import {
|
|
|
7
7
|
KeyboardEventHandler,
|
|
8
8
|
MouseEventHandler,
|
|
9
9
|
RefAttributes,
|
|
10
|
-
useLayoutEffect,
|
|
11
10
|
useState,
|
|
12
11
|
} from 'react';
|
|
13
12
|
import TextareaAutosize from 'react-textarea-autosize';
|
|
14
13
|
|
|
15
|
-
import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
|
|
14
|
+
import { extractSupportProps, useLayoutEffect, WithSupportProps } from '@snack-uikit/utils';
|
|
16
15
|
|
|
17
16
|
import styles from './styles.module.scss';
|
|
18
17
|
|