@snack-uikit/fields 0.28.0 → 0.29.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 +9 -0
- package/dist/components/FieldColor/FieldColor.d.ts +1 -1
- package/dist/components/FieldColor/FieldColor.js +3 -3
- package/dist/components/FieldDate/FieldDate.js +11 -5
- package/dist/components/FieldSecure/FieldSecure.d.ts +1 -1
- package/dist/components/FieldSecure/FieldSecure.js +3 -3
- package/dist/components/FieldSelect/FieldSelectMultiple.d.ts +3 -1
- package/dist/components/FieldSelect/FieldSelectMultiple.js +7 -5
- package/dist/components/FieldSelect/FieldSelectSingle.d.ts +3 -1
- package/dist/components/FieldSelect/FieldSelectSingle.js +8 -6
- package/dist/components/FieldSelect/hooks.d.ts +1 -1
- package/dist/components/FieldSelect/hooks.js +3 -3
- package/dist/components/FieldSelect/types.d.ts +5 -1
- package/dist/components/FieldSlider/FieldSlider.d.ts +6 -2
- package/dist/components/FieldSlider/FieldSlider.js +13 -11
- package/dist/components/FieldStepper/FieldStepper.d.ts +5 -1
- package/dist/components/FieldStepper/FieldStepper.js +6 -4
- package/dist/components/FieldText/FieldText.d.ts +9 -2
- package/dist/components/FieldText/FieldText.js +46 -8
- package/dist/components/FieldText/helpers.d.ts +4 -0
- package/dist/components/FieldText/helpers.js +9 -0
- package/dist/components/FieldTextArea/FieldTextArea.d.ts +1 -1
- package/dist/components/FieldTextArea/FieldTextArea.js +3 -3
- package/dist/constants.d.ts +6 -0
- package/dist/constants.js +6 -0
- package/dist/helperComponents/ButtonField/ButtonField.d.ts +18 -0
- package/dist/helperComponents/ButtonField/ButtonField.js +10 -0
- package/dist/helperComponents/ButtonField/index.d.ts +1 -0
- package/dist/helperComponents/ButtonField/index.js +1 -0
- package/dist/helperComponents/ButtonField/styles.module.css +96 -0
- package/dist/helperComponents/ButtonFieldList/ButtonFieldList.d.ts +4 -0
- package/dist/helperComponents/ButtonFieldList/ButtonFieldList.js +27 -0
- package/dist/helperComponents/ButtonFieldList/helpers.d.ts +5 -0
- package/dist/helperComponents/ButtonFieldList/helpers.js +8 -0
- package/dist/helperComponents/ButtonFieldList/index.d.ts +1 -0
- package/dist/helperComponents/ButtonFieldList/index.js +1 -0
- package/dist/helperComponents/ButtonFieldList/styles.module.css +3 -0
- package/dist/helperComponents/FieldContainerPrivate/FieldContainerPrivate.d.ts +5 -4
- package/dist/helperComponents/FieldContainerPrivate/FieldContainerPrivate.js +2 -2
- package/dist/helperComponents/FieldContainerPrivate/styles.module.css +56 -5
- package/dist/helperComponents/index.d.ts +2 -0
- package/dist/helperComponents/index.js +2 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/styles.module.css +13 -0
- package/dist/hooks/useCopyButton.d.ts +3 -1
- package/dist/hooks/useCopyButton.js +4 -3
- package/dist/hooks/useHideButton.js +1 -0
- package/dist/hooks/usePostfix.d.ts +6 -0
- package/dist/hooks/usePostfix.js +11 -0
- package/dist/hooks/usePostfixButton.d.ts +11 -0
- package/dist/hooks/usePostfixButton.js +28 -0
- package/dist/hooks/usePrefix.d.ts +6 -0
- package/dist/hooks/usePrefix.js +11 -0
- package/dist/hooks/usePrefixButton.d.ts +11 -0
- package/dist/hooks/usePrefixButton.js +28 -0
- package/dist/types.d.ts +12 -1
- package/package.json +6 -5
- package/src/components/FieldColor/FieldColor.tsx +6 -3
- package/src/components/FieldDate/FieldDate.tsx +17 -10
- package/src/components/FieldSecure/FieldSecure.tsx +3 -3
- package/src/components/FieldSelect/FieldSelectMultiple.tsx +17 -4
- package/src/components/FieldSelect/FieldSelectSingle.tsx +17 -4
- package/src/components/FieldSelect/hooks.ts +3 -3
- package/src/components/FieldSelect/types.ts +10 -2
- package/src/components/FieldSlider/FieldSlider.tsx +30 -14
- package/src/components/FieldStepper/FieldStepper.tsx +40 -23
- package/src/components/FieldText/FieldText.tsx +78 -10
- package/src/components/FieldText/helpers.tsx +13 -0
- package/src/components/FieldTextArea/FieldTextArea.tsx +6 -3
- package/src/constants.ts +7 -0
- package/src/helperComponents/ButtonField/ButtonField.tsx +73 -0
- package/src/helperComponents/ButtonField/index.ts +1 -0
- package/src/helperComponents/ButtonField/styles.module.scss +57 -0
- package/src/helperComponents/ButtonFieldList/ButtonFieldList.tsx +36 -0
- package/src/helperComponents/ButtonFieldList/helpers.tsx +13 -0
- package/src/helperComponents/ButtonFieldList/index.ts +1 -0
- package/src/helperComponents/ButtonFieldList/styles.module.scss +5 -0
- package/src/helperComponents/FieldContainerPrivate/FieldContainerPrivate.tsx +6 -3
- package/src/helperComponents/FieldContainerPrivate/styles.module.scss +14 -8
- package/src/helperComponents/index.ts +2 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/styles.module.scss +17 -0
- package/src/hooks/useCopyButton.tsx +7 -2
- package/src/hooks/useHideButton.tsx +1 -0
- package/src/hooks/usePostfix.tsx +21 -0
- package/src/hooks/usePostfixButton.tsx +74 -0
- package/src/hooks/usePrefix.tsx +21 -0
- package/src/hooks/usePrefixButton.tsx +74 -0
- package/src/types.ts +16 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import styles from './styles.module.css';
|
|
4
|
+
export function usePostfix({ postfix, disabled }) {
|
|
5
|
+
return useMemo(() => ({
|
|
6
|
+
id: 'postfix',
|
|
7
|
+
active: false,
|
|
8
|
+
show: Boolean(postfix),
|
|
9
|
+
render: props => (_jsx("div", Object.assign({}, props, { className: styles.postfix, "data-test-id": 'field-postfix', "data-disabled": disabled || undefined, children: postfix }))),
|
|
10
|
+
}), [disabled, postfix]);
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
import { ButtonProps, Size } from '@snack-uikit/input-private';
|
|
3
|
+
import { ButtonFieldProps } from '../helperComponents';
|
|
4
|
+
import { Button } from '../types';
|
|
5
|
+
export declare function usePostfixButton({ button, size, postfixIcon, disabled, readonly, onFocus, onBlur, }: {
|
|
6
|
+
button?: Button;
|
|
7
|
+
size: Size;
|
|
8
|
+
postfixIcon?: ReactElement;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
readonly?: boolean;
|
|
11
|
+
} & Pick<ButtonFieldProps, 'onFocus' | 'onBlur'>): ButtonProps;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useRef } from 'react';
|
|
3
|
+
import { ButtonField, ButtonFieldList } from '../helperComponents';
|
|
4
|
+
export function usePostfixButton({ button, size, postfixIcon, disabled, readonly, onFocus, onBlur, }) {
|
|
5
|
+
const buttonListRef = useRef(null);
|
|
6
|
+
const postfixIconProps = useMemo(() => ({
|
|
7
|
+
id: 'postfixIcon',
|
|
8
|
+
active: false,
|
|
9
|
+
show: Boolean(postfixIcon && !button),
|
|
10
|
+
render: () => _jsx(_Fragment, { children: postfixIcon }),
|
|
11
|
+
}), [button, postfixIcon]);
|
|
12
|
+
const postfixButtonProps = useMemo(() => ({
|
|
13
|
+
id: 'postfixButton',
|
|
14
|
+
active: false,
|
|
15
|
+
show: Boolean(button && button.variant === 'after'),
|
|
16
|
+
render: renderProps => {
|
|
17
|
+
const buttonProps = Object.assign(Object.assign({}, renderProps), { variant: 'after', size, content: button === null || button === void 0 ? void 0 : button.content, disabled: disabled || readonly, onFocus,
|
|
18
|
+
onBlur });
|
|
19
|
+
if (button === null || button === void 0 ? void 0 : button.items) {
|
|
20
|
+
return (_jsx(ButtonFieldList, Object.assign({}, buttonProps, { ref: buttonListRef, onClick: () => {
|
|
21
|
+
setTimeout(() => { var _a; return (_a = buttonListRef.current) === null || _a === void 0 ? void 0 : _a.focus(); }, 0);
|
|
22
|
+
}, items: button.items, selection: button.selection, open: button.open, onOpenChange: button.onOpenChange })));
|
|
23
|
+
}
|
|
24
|
+
return _jsx(ButtonField, Object.assign({}, buttonProps));
|
|
25
|
+
},
|
|
26
|
+
}), [button, size, disabled, readonly, onFocus, onBlur]);
|
|
27
|
+
return button ? postfixButtonProps : postfixIconProps;
|
|
28
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import styles from './styles.module.css';
|
|
4
|
+
export function usePrefix({ prefix, disabled }) {
|
|
5
|
+
return useMemo(() => ({
|
|
6
|
+
id: 'prefix',
|
|
7
|
+
active: false,
|
|
8
|
+
show: Boolean(prefix),
|
|
9
|
+
render: props => (_jsx("div", Object.assign({}, props, { "data-test-id": 'field-prefix', className: styles.prefix, "data-disabled": disabled || undefined, children: prefix }))),
|
|
10
|
+
}), [disabled, prefix]);
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
import { ButtonProps, Size } from '@snack-uikit/input-private';
|
|
3
|
+
import { ButtonFieldProps } from '../helperComponents';
|
|
4
|
+
import { Button } from '../types';
|
|
5
|
+
export declare function usePrefixButton({ button, prefixIcon, size, disabled, readonly, onFocus, onBlur, }: {
|
|
6
|
+
button?: Button;
|
|
7
|
+
prefixIcon?: ReactElement;
|
|
8
|
+
size: Size;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
readonly?: boolean;
|
|
11
|
+
} & Pick<ButtonFieldProps, 'onFocus' | 'onBlur'>): ButtonProps;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useRef } from 'react';
|
|
3
|
+
import { ButtonField, ButtonFieldList } from '../helperComponents';
|
|
4
|
+
export function usePrefixButton({ button, prefixIcon, size, disabled, readonly, onFocus, onBlur, }) {
|
|
5
|
+
const buttonListRef = useRef(null);
|
|
6
|
+
const prefixIconProps = useMemo(() => ({
|
|
7
|
+
id: 'prefixIcon',
|
|
8
|
+
active: false,
|
|
9
|
+
show: Boolean(prefixIcon && !button),
|
|
10
|
+
render: () => _jsx(_Fragment, { children: prefixIcon }),
|
|
11
|
+
}), [button, prefixIcon]);
|
|
12
|
+
const prefixButtonProps = useMemo(() => ({
|
|
13
|
+
id: 'prefixButton',
|
|
14
|
+
active: false,
|
|
15
|
+
show: Boolean(button && button.variant === 'before'),
|
|
16
|
+
render: renderProps => {
|
|
17
|
+
const buttonProps = Object.assign(Object.assign({}, renderProps), { variant: 'before', size, content: button === null || button === void 0 ? void 0 : button.content, disabled: disabled || readonly, onFocus,
|
|
18
|
+
onBlur });
|
|
19
|
+
if (button === null || button === void 0 ? void 0 : button.items) {
|
|
20
|
+
return (_jsx(ButtonFieldList, Object.assign({}, buttonProps, { ref: buttonListRef, onClick: () => {
|
|
21
|
+
setTimeout(() => { var _a; return (_a = buttonListRef.current) === null || _a === void 0 ? void 0 : _a.focus(); }, 0);
|
|
22
|
+
}, items: button.items, selection: button.selection, open: button.open, onOpenChange: button.onOpenChange })));
|
|
23
|
+
}
|
|
24
|
+
return _jsx(ButtonField, Object.assign({}, buttonProps));
|
|
25
|
+
},
|
|
26
|
+
}), [button, size, disabled, readonly, onFocus, onBlur]);
|
|
27
|
+
return button ? prefixButtonProps : prefixIconProps;
|
|
28
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { DroplistProps, SelectionSingleState } from '@snack-uikit/list';
|
|
1
3
|
import { ValueOf } from '@snack-uikit/utils';
|
|
2
|
-
import { CONTAINER_VARIANT, VALIDATION_STATE } from './constants';
|
|
4
|
+
import { BUTTON_VARIANT, CONTAINER_VARIANT, VALIDATION_STATE } from './constants';
|
|
3
5
|
export type ValidationState = ValueOf<typeof VALIDATION_STATE>;
|
|
4
6
|
export type ContainerVariant = ValueOf<typeof CONTAINER_VARIANT>;
|
|
7
|
+
export type ButtonVariant = ValueOf<typeof BUTTON_VARIANT>;
|
|
5
8
|
export type AsyncValueRequest = Promise<{
|
|
6
9
|
success: boolean;
|
|
7
10
|
value?: string;
|
|
8
11
|
}>;
|
|
12
|
+
export type NativeDroplistProps = Pick<DroplistProps, 'items' | 'open' | 'onOpenChange'> & {
|
|
13
|
+
selection?: Omit<SelectionSingleState, 'mode'>;
|
|
14
|
+
};
|
|
15
|
+
export type Button = Omit<NativeDroplistProps, 'items'> & {
|
|
16
|
+
variant: ButtonVariant;
|
|
17
|
+
content?: ReactNode;
|
|
18
|
+
items?: DroplistProps['items'];
|
|
19
|
+
};
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
6
|
"title": "Fields",
|
|
7
|
-
"version": "0.
|
|
7
|
+
"version": "0.29.0",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"*.css",
|
|
10
10
|
"*.woff",
|
|
@@ -34,11 +34,12 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@snack-uikit/button": "0.17.5",
|
|
36
36
|
"@snack-uikit/calendar": "0.7.12",
|
|
37
|
-
"@snack-uikit/color-picker": "0.1.
|
|
37
|
+
"@snack-uikit/color-picker": "0.1.1",
|
|
38
|
+
"@snack-uikit/divider": "3.0.4",
|
|
38
39
|
"@snack-uikit/dropdown": "0.2.7",
|
|
39
40
|
"@snack-uikit/icons": "0.22.1",
|
|
40
|
-
"@snack-uikit/input-private": "
|
|
41
|
-
"@snack-uikit/list": "0.
|
|
41
|
+
"@snack-uikit/input-private": "4.0.0",
|
|
42
|
+
"@snack-uikit/list": "0.17.0",
|
|
42
43
|
"@snack-uikit/scroll": "0.6.2",
|
|
43
44
|
"@snack-uikit/skeleton": "0.3.5",
|
|
44
45
|
"@snack-uikit/slider": "0.1.18",
|
|
@@ -60,5 +61,5 @@
|
|
|
60
61
|
"peerDependencies": {
|
|
61
62
|
"@snack-uikit/locale": "*"
|
|
62
63
|
},
|
|
63
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "36a86f3bf30c115e8c6b49f6c8d7a2d2ffb86ff1"
|
|
64
65
|
}
|
|
@@ -111,9 +111,12 @@ export const FieldColor = forwardRef<HTMLInputElement, FieldColorProps>(
|
|
|
111
111
|
|
|
112
112
|
const clearButtonSettings = useClearButton({ clearButtonRef, showClearButton, size, onClear });
|
|
113
113
|
const copyButtonSettings = useCopyButton({ copyButtonRef, showCopyButton, size, valueToCopy: value });
|
|
114
|
-
const {
|
|
114
|
+
const { postfixButtons, inputTabIndex, onInputKeyDown } = useButtonNavigation({
|
|
115
115
|
inputRef: localRef,
|
|
116
|
-
|
|
116
|
+
postfixButtons: useMemo(
|
|
117
|
+
() => [clearButtonSettings, copyButtonSettings],
|
|
118
|
+
[clearButtonSettings, copyButtonSettings],
|
|
119
|
+
),
|
|
117
120
|
readonly,
|
|
118
121
|
submitKeys: ['Enter', 'Space', 'Tab'],
|
|
119
122
|
});
|
|
@@ -175,7 +178,7 @@ export const FieldColor = forwardRef<HTMLInputElement, FieldColorProps>(
|
|
|
175
178
|
variant={CONTAINER_VARIANT.SingleLine}
|
|
176
179
|
focused={showDropList}
|
|
177
180
|
inputRef={localRef}
|
|
178
|
-
postfix={
|
|
181
|
+
postfix={postfixButtons}
|
|
179
182
|
prefix={
|
|
180
183
|
<div
|
|
181
184
|
className={styles.colorPreview}
|
|
@@ -16,6 +16,7 @@ import { Calendar, CalendarProps } from '@snack-uikit/calendar';
|
|
|
16
16
|
import { Dropdown } from '@snack-uikit/dropdown';
|
|
17
17
|
import { CalendarSVG } from '@snack-uikit/icons';
|
|
18
18
|
import {
|
|
19
|
+
ButtonProps,
|
|
19
20
|
ICON_SIZE,
|
|
20
21
|
InputPrivate,
|
|
21
22
|
InputPrivateProps,
|
|
@@ -154,10 +155,21 @@ export const FieldDate = forwardRef<HTMLInputElement, FieldDateProps>(
|
|
|
154
155
|
|
|
155
156
|
const clearButtonSettings = useClearButton({ clearButtonRef, showClearButton, size, onClear: handleClear });
|
|
156
157
|
const copyButtonSettings = useCopyButton({ copyButtonRef, showCopyButton, size, valueToCopy: valueProp || '' });
|
|
158
|
+
const calendarIcon: ButtonProps = useMemo(
|
|
159
|
+
() => ({
|
|
160
|
+
active: false,
|
|
161
|
+
show: true,
|
|
162
|
+
id: 'calendarIcon',
|
|
163
|
+
render: props => (
|
|
164
|
+
<CalendarSVG {...props} size={calendarIconSize} className={styles.calendarIcon} data-size={size} />
|
|
165
|
+
),
|
|
166
|
+
}),
|
|
167
|
+
[calendarIconSize, size],
|
|
168
|
+
);
|
|
157
169
|
|
|
158
170
|
const memorizedButtons = useMemo(
|
|
159
|
-
() => [clearButtonSettings, copyButtonSettings],
|
|
160
|
-
[clearButtonSettings, copyButtonSettings],
|
|
171
|
+
() => [clearButtonSettings, copyButtonSettings, calendarIcon],
|
|
172
|
+
[clearButtonSettings, copyButtonSettings, calendarIcon],
|
|
161
173
|
);
|
|
162
174
|
|
|
163
175
|
const {
|
|
@@ -179,14 +191,14 @@ export const FieldDate = forwardRef<HTMLInputElement, FieldDateProps>(
|
|
|
179
191
|
const setInputFocusFromButtons = useCallback(() => setInputFocus(SlotKey.Year), [setInputFocus]);
|
|
180
192
|
|
|
181
193
|
const {
|
|
182
|
-
|
|
194
|
+
postfixButtons,
|
|
183
195
|
inputTabIndex,
|
|
184
196
|
onInputKeyDown: navigationInputKeyDownHandler,
|
|
185
197
|
setInitialTabIndices,
|
|
186
198
|
} = useButtonNavigation({
|
|
187
199
|
setInputFocus: setInputFocusFromButtons,
|
|
188
200
|
inputRef: localRef,
|
|
189
|
-
|
|
201
|
+
postfixButtons: memorizedButtons,
|
|
190
202
|
onButtonKeyDown: checkForLeavingFocus,
|
|
191
203
|
readonly,
|
|
192
204
|
submitKeys: ['Enter', 'Space', 'Tab'],
|
|
@@ -311,12 +323,7 @@ export const FieldDate = forwardRef<HTMLInputElement, FieldDateProps>(
|
|
|
311
323
|
variant={CONTAINER_VARIANT.SingleLine}
|
|
312
324
|
focused={showDropList}
|
|
313
325
|
inputRef={localRef}
|
|
314
|
-
postfix={
|
|
315
|
-
<>
|
|
316
|
-
{buttons}
|
|
317
|
-
<CalendarSVG size={calendarIconSize} className={styles.calendarIcon} data-size={size} />
|
|
318
|
-
</>
|
|
319
|
-
}
|
|
326
|
+
postfix={postfixButtons}
|
|
320
327
|
>
|
|
321
328
|
<InputPrivate
|
|
322
329
|
ref={mergeRefs(ref, localRef)}
|
|
@@ -177,9 +177,9 @@ export const FieldSecure = forwardRef<HTMLInputElement, FieldSecureProps>(
|
|
|
177
177
|
disabled: disabled || isLoading,
|
|
178
178
|
});
|
|
179
179
|
|
|
180
|
-
const {
|
|
180
|
+
const { postfixButtons, inputTabIndex, onInputKeyDown } = useButtonNavigation({
|
|
181
181
|
inputRef: localRef,
|
|
182
|
-
|
|
182
|
+
postfixButtons: useMemo(() => [copyButtonSettings, hideButtonSettings], [copyButtonSettings, hideButtonSettings]),
|
|
183
183
|
readonly,
|
|
184
184
|
submitKeys: ['Enter', 'Space', 'Tab'],
|
|
185
185
|
});
|
|
@@ -211,7 +211,7 @@ export const FieldSecure = forwardRef<HTMLInputElement, FieldSecureProps>(
|
|
|
211
211
|
variant={CONTAINER_VARIANT.SingleLine}
|
|
212
212
|
inputRef={localRef}
|
|
213
213
|
prefix={prefixIcon}
|
|
214
|
-
postfix={
|
|
214
|
+
postfix={postfixButtons}
|
|
215
215
|
>
|
|
216
216
|
<WithSkeleton skeleton={<Skeleton width='100%' borderRadius={2} />} loading={isLoading}>
|
|
217
217
|
<InputPrivate
|
|
@@ -8,7 +8,7 @@ import { Tag } from '@snack-uikit/tag';
|
|
|
8
8
|
import { extractSupportProps, isBrowser, useLayoutEffect } from '@snack-uikit/utils';
|
|
9
9
|
|
|
10
10
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
11
|
-
import { useValueControl } from '../../hooks';
|
|
11
|
+
import { usePostfix, usePrefix, useValueControl } from '../../hooks';
|
|
12
12
|
import { getValidationState } from '../../utils/getValidationState';
|
|
13
13
|
import { FieldDecorator } from '../FieldDecorator';
|
|
14
14
|
import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
|
|
@@ -43,6 +43,8 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
43
43
|
search,
|
|
44
44
|
autocomplete = false,
|
|
45
45
|
prefixIcon,
|
|
46
|
+
prefix,
|
|
47
|
+
postfix,
|
|
46
48
|
removeByBackspace = false,
|
|
47
49
|
addOptionByEnter = false,
|
|
48
50
|
untouchableScrollbars = false,
|
|
@@ -77,6 +79,9 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
77
79
|
resetSearchOnOptionSelection,
|
|
78
80
|
});
|
|
79
81
|
|
|
82
|
+
const prefixSettings = usePrefix({ prefix, disabled });
|
|
83
|
+
const postfixSettings = usePostfix({ postfix, disabled });
|
|
84
|
+
|
|
80
85
|
useLayoutEffect(() => {
|
|
81
86
|
setItems(({ selectedItems }) => updateMultipleItems({ options, value, selectedItems }));
|
|
82
87
|
}, [options, value]);
|
|
@@ -92,7 +97,7 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
92
97
|
|
|
93
98
|
const { ArrowIcon, arrowIconSize } = getArrowIcon({ size, open });
|
|
94
99
|
|
|
95
|
-
const {
|
|
100
|
+
const { postfixButtons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
|
|
96
101
|
readonly,
|
|
97
102
|
size,
|
|
98
103
|
showClearButton: showClearButton && !disabled && !readonly && Boolean(selectedItems?.find(item => !item.disabled)),
|
|
@@ -208,7 +213,14 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
208
213
|
variant='single-line-container'
|
|
209
214
|
inputRef={localRef}
|
|
210
215
|
size={size}
|
|
211
|
-
prefix={
|
|
216
|
+
prefix={
|
|
217
|
+
(prefixIcon || prefixSettings.show) && (
|
|
218
|
+
<>
|
|
219
|
+
{prefixIcon}
|
|
220
|
+
{prefixSettings.show && prefixSettings.render({ key: prefixSettings.id })}
|
|
221
|
+
</>
|
|
222
|
+
)
|
|
223
|
+
}
|
|
212
224
|
>
|
|
213
225
|
<>
|
|
214
226
|
<div className={styles.contentWrapper} ref={contentRef}>
|
|
@@ -256,7 +268,8 @@ export const FieldSelectMultiple = forwardRef<HTMLInputElement, FieldSelectMulti
|
|
|
256
268
|
</div>
|
|
257
269
|
|
|
258
270
|
<div className={styles.postfix}>
|
|
259
|
-
{
|
|
271
|
+
{postfixButtons}
|
|
272
|
+
{postfixSettings.show && postfixSettings.render({ key: postfixSettings.id })}
|
|
260
273
|
<ArrowIcon size={arrowIconSize} className={styles.arrowIcon} />
|
|
261
274
|
</div>
|
|
262
275
|
|
|
@@ -16,7 +16,7 @@ import { Droplist, ItemProps, SelectionSingleValueType } from '@snack-uikit/list
|
|
|
16
16
|
import { extractSupportProps, isBrowser, useLayoutEffect } from '@snack-uikit/utils';
|
|
17
17
|
|
|
18
18
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
19
|
-
import { useValueControl } from '../../hooks';
|
|
19
|
+
import { usePostfix, usePrefix, useValueControl } from '../../hooks';
|
|
20
20
|
import { getValidationState } from '../../utils/getValidationState';
|
|
21
21
|
import { FieldDecorator } from '../FieldDecorator';
|
|
22
22
|
import { extractFieldDecoratorProps } from '../FieldDecorator/utils';
|
|
@@ -51,6 +51,8 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
51
51
|
search,
|
|
52
52
|
autocomplete = false,
|
|
53
53
|
prefixIcon,
|
|
54
|
+
prefix,
|
|
55
|
+
postfix,
|
|
54
56
|
addOptionByEnter = false,
|
|
55
57
|
untouchableScrollbars = false,
|
|
56
58
|
open: openProp,
|
|
@@ -80,6 +82,9 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
80
82
|
|
|
81
83
|
const prevSelectedItem = useRef<ItemWithId | undefined>(selectedItem);
|
|
82
84
|
|
|
85
|
+
const prefixSettings = usePrefix({ prefix, disabled });
|
|
86
|
+
const postfixSettings = usePostfix({ postfix, disabled });
|
|
87
|
+
|
|
83
88
|
useLayoutEffect(() => {
|
|
84
89
|
setItems(({ selectedItem }) => updateItems({ options, value, selectedItem }));
|
|
85
90
|
}, [options, value]);
|
|
@@ -111,7 +116,7 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
111
116
|
|
|
112
117
|
const { ArrowIcon, arrowIconSize } = getArrowIcon({ size, open });
|
|
113
118
|
|
|
114
|
-
const {
|
|
119
|
+
const { postfixButtons, inputKeyDownNavigationHandler, buttonsRefs } = useButtons({
|
|
115
120
|
readonly,
|
|
116
121
|
size,
|
|
117
122
|
showClearButton: showClearButton && !disabled && !readonly && value !== undefined,
|
|
@@ -215,7 +220,14 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
215
220
|
variant={'single-line-container'}
|
|
216
221
|
inputRef={localRef}
|
|
217
222
|
size={size}
|
|
218
|
-
prefix={
|
|
223
|
+
prefix={
|
|
224
|
+
(prefixIcon || prefixSettings.show) && (
|
|
225
|
+
<>
|
|
226
|
+
{prefixIcon}
|
|
227
|
+
{prefixSettings.show && prefixSettings.render({ key: prefixSettings.id })}
|
|
228
|
+
</>
|
|
229
|
+
)
|
|
230
|
+
}
|
|
219
231
|
>
|
|
220
232
|
<InputPrivate
|
|
221
233
|
id={id}
|
|
@@ -236,7 +248,8 @@ export const FieldSelectSingle = forwardRef<HTMLInputElement, FieldSelectSingleP
|
|
|
236
248
|
/>
|
|
237
249
|
|
|
238
250
|
<div className={styles.postfix}>
|
|
239
|
-
{
|
|
251
|
+
{postfixButtons}
|
|
252
|
+
{postfixSettings.show && postfixSettings.render({ key: postfixSettings.id })}
|
|
240
253
|
<ArrowIcon size={arrowIconSize} className={styles.arrowIcon} />
|
|
241
254
|
</div>
|
|
242
255
|
</FieldContainerPrivate>
|
|
@@ -90,15 +90,15 @@ export function useButtons({
|
|
|
90
90
|
size,
|
|
91
91
|
valueToCopy,
|
|
92
92
|
});
|
|
93
|
-
const { onInputKeyDown: inputKeyDownNavigationHandler,
|
|
93
|
+
const { onInputKeyDown: inputKeyDownNavigationHandler, postfixButtons } = useButtonNavigation({
|
|
94
94
|
inputRef,
|
|
95
|
-
|
|
95
|
+
postfixButtons: useMemo(() => [clearButtonSettings, copyButtonSettings], [clearButtonSettings, copyButtonSettings]),
|
|
96
96
|
onButtonKeyDown: undefined,
|
|
97
97
|
readonly,
|
|
98
98
|
submitKeys: ['Enter', 'Space', 'Tab'],
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
-
return {
|
|
101
|
+
return { postfixButtons, inputKeyDownNavigationHandler, buttonsRefs };
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
export function useSearchInput({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactElement } from 'react';
|
|
1
|
+
import { ReactElement, ReactNode } from 'react';
|
|
2
2
|
|
|
3
3
|
import { InputPrivateProps } from '@snack-uikit/input-private';
|
|
4
4
|
import {
|
|
@@ -79,7 +79,15 @@ export type SearchState = {
|
|
|
79
79
|
onChange?(value: string): void;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
-
export type FieldSelectPrivateProps = InputProps &
|
|
82
|
+
export type FieldSelectPrivateProps = InputProps &
|
|
83
|
+
WrapperProps & {
|
|
84
|
+
options: OptionProps[];
|
|
85
|
+
loading?: boolean;
|
|
86
|
+
/** Произвольный префикс для поля */
|
|
87
|
+
prefix?: ReactNode;
|
|
88
|
+
/** Произвольный постфикс для поля */
|
|
89
|
+
postfix?: ReactNode;
|
|
90
|
+
};
|
|
83
91
|
|
|
84
92
|
type FiledSelectCommonProps = WithSupportProps<{
|
|
85
93
|
options: OptionProps[];
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
forwardRef,
|
|
5
5
|
KeyboardEvent,
|
|
6
6
|
ReactElement,
|
|
7
|
+
ReactNode,
|
|
7
8
|
useCallback,
|
|
8
9
|
useEffect,
|
|
9
10
|
useMemo,
|
|
@@ -17,7 +18,7 @@ import { extractSupportProps, useEventHandler, WithSupportProps } from '@snack-u
|
|
|
17
18
|
|
|
18
19
|
import { CONTAINER_VARIANT, VALIDATION_STATE } from '../../constants';
|
|
19
20
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
20
|
-
import { useValueControl } from '../../hooks';
|
|
21
|
+
import { usePostfix, usePrefix, useValueControl } from '../../hooks';
|
|
21
22
|
import { FieldDecorator, FieldDecoratorProps } from '../FieldDecorator';
|
|
22
23
|
import { generateAllowedValues, getClosestMark, getTextFieldValue, isMarkObject } from './helpers';
|
|
23
24
|
import styles from './styles.module.scss';
|
|
@@ -49,6 +50,10 @@ type FieldSliderOwnProps = {
|
|
|
49
50
|
textInputFormatter?: TextInputFormatter;
|
|
50
51
|
/** Отвязать текстовое поле от значений на линейке */
|
|
51
52
|
unbindInputFromMarks?: boolean;
|
|
53
|
+
/** Произвольный префикс для поля */
|
|
54
|
+
prefix?: ReactNode;
|
|
55
|
+
/** Произвольный постфикс для поля */
|
|
56
|
+
postfix?: ReactNode;
|
|
52
57
|
};
|
|
53
58
|
|
|
54
59
|
export type FieldSliderProps = WithSupportProps<FieldSliderOwnProps & SliderProps & WrapperProps>;
|
|
@@ -96,13 +101,29 @@ export const FieldSlider = forwardRef<HTMLInputElement, FieldSliderProps>(
|
|
|
96
101
|
hint,
|
|
97
102
|
showHintIcon,
|
|
98
103
|
size = SIZE.S,
|
|
99
|
-
postfixIcon,
|
|
100
104
|
textInputFormatter,
|
|
101
105
|
unbindInputFromMarks,
|
|
106
|
+
postfixIcon,
|
|
107
|
+
prefix,
|
|
108
|
+
postfix,
|
|
102
109
|
...rest
|
|
103
110
|
},
|
|
104
111
|
ref,
|
|
105
112
|
) => {
|
|
113
|
+
const [value = getDefaultValue(range, min, max, valueProp), onChange] = useValueControl<number | number[]>({
|
|
114
|
+
value: valueProp,
|
|
115
|
+
defaultValue: getDefaultValue(range, min, max, valueProp),
|
|
116
|
+
onChange: onChangeProp,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const [textFieldInputValue, setTextFieldInputValue] = useState<string>(
|
|
120
|
+
getTextFieldValue(value, textInputFormatter),
|
|
121
|
+
);
|
|
122
|
+
const localRef = useRef<HTMLInputElement>(null);
|
|
123
|
+
|
|
124
|
+
const prefixSettings = usePrefix({ prefix, disabled });
|
|
125
|
+
const postfixSettings = usePostfix({ postfix, disabled });
|
|
126
|
+
|
|
106
127
|
const getMarkValue = useCallback(
|
|
107
128
|
(key: keyof SliderProps['marks']) => {
|
|
108
129
|
const mark = marks[key];
|
|
@@ -121,17 +142,6 @@ export const FieldSlider = forwardRef<HTMLInputElement, FieldSliderProps>(
|
|
|
121
142
|
[getMarkValue, marks],
|
|
122
143
|
);
|
|
123
144
|
|
|
124
|
-
const [value = getDefaultValue(range, min, max, valueProp), onChange] = useValueControl<number | number[]>({
|
|
125
|
-
value: valueProp,
|
|
126
|
-
defaultValue: getDefaultValue(range, min, max, valueProp),
|
|
127
|
-
onChange: onChangeProp,
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const [textFieldInputValue, setTextFieldInputValue] = useState<string>(
|
|
131
|
-
getTextFieldValue(value, textInputFormatter),
|
|
132
|
-
);
|
|
133
|
-
const localRef = useRef<HTMLInputElement>(null);
|
|
134
|
-
|
|
135
145
|
const onTextFieldChange = (textFieldValue: string) => {
|
|
136
146
|
const numValue = parseInt(textFieldValue);
|
|
137
147
|
|
|
@@ -280,7 +290,13 @@ export const FieldSlider = forwardRef<HTMLInputElement, FieldSliderProps>(
|
|
|
280
290
|
readonly={readonly}
|
|
281
291
|
variant={CONTAINER_VARIANT.SingleLine}
|
|
282
292
|
inputRef={localRef}
|
|
283
|
-
|
|
293
|
+
prefix={prefixSettings.show && prefixSettings.render({ key: prefixSettings.id })}
|
|
294
|
+
postfix={
|
|
295
|
+
<>
|
|
296
|
+
{postfixSettings.show && postfixSettings.render({ key: postfixSettings.id })}
|
|
297
|
+
{postfixIcon}
|
|
298
|
+
</>
|
|
299
|
+
}
|
|
284
300
|
>
|
|
285
301
|
<InputPrivate
|
|
286
302
|
ref={mergeRefs(ref, localRef)}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
forwardRef,
|
|
6
6
|
KeyboardEventHandler,
|
|
7
7
|
MouseEvent,
|
|
8
|
+
ReactNode,
|
|
8
9
|
useEffect,
|
|
9
10
|
useRef,
|
|
10
11
|
useState,
|
|
@@ -19,7 +20,7 @@ import { extractSupportProps, WithSupportProps } from '@snack-uikit/utils';
|
|
|
19
20
|
|
|
20
21
|
import { CONTAINER_VARIANT, VALIDATION_STATE } from '../../constants';
|
|
21
22
|
import { FieldContainerPrivate } from '../../helperComponents';
|
|
22
|
-
import { useValueControl } from '../../hooks';
|
|
23
|
+
import { usePostfix, usePrefix, useValueControl } from '../../hooks';
|
|
23
24
|
import { getValidationState } from '../../utils/getValidationState';
|
|
24
25
|
import { FieldDecorator, FieldDecoratorProps } from '../FieldDecorator';
|
|
25
26
|
import styles from './styles.module.scss';
|
|
@@ -53,6 +54,10 @@ type FieldStepperOwnProps = {
|
|
|
53
54
|
step?: number;
|
|
54
55
|
/** Можно ли вводить c клавиатуры числа, выходящие за пределы min/max */
|
|
55
56
|
allowMoreThanLimits?: boolean;
|
|
57
|
+
/** Произвольный префикс для поля */
|
|
58
|
+
prefix?: ReactNode;
|
|
59
|
+
/** Произвольный постфикс для поля */
|
|
60
|
+
postfix?: ReactNode;
|
|
56
61
|
};
|
|
57
62
|
|
|
58
63
|
export type FieldStepperProps = WithSupportProps<FieldStepperOwnProps & InputProps & WrapperProps>;
|
|
@@ -97,6 +102,8 @@ export const FieldStepper = forwardRef<HTMLInputElement, FieldStepperProps>(
|
|
|
97
102
|
size = SIZE.S,
|
|
98
103
|
validationState = VALIDATION_STATE.Default,
|
|
99
104
|
error,
|
|
105
|
+
prefix,
|
|
106
|
+
postfix,
|
|
100
107
|
...rest
|
|
101
108
|
},
|
|
102
109
|
ref,
|
|
@@ -116,6 +123,9 @@ export const FieldStepper = forwardRef<HTMLInputElement, FieldStepperProps>(
|
|
|
116
123
|
const isMinusButtonDisabled = (typeof min === 'number' && value <= min) || readonly || disabled;
|
|
117
124
|
const isPlusButtonDisabled = (typeof max === 'number' && value >= max) || readonly || disabled;
|
|
118
125
|
|
|
126
|
+
const prefixSettings = usePrefix({ prefix, disabled });
|
|
127
|
+
const postfixSettings = usePostfix({ postfix, disabled });
|
|
128
|
+
|
|
119
129
|
const fieldValidationState = getValidationState({ validationState, error });
|
|
120
130
|
|
|
121
131
|
const adjustValue = (value: number) => {
|
|
@@ -240,30 +250,37 @@ export const FieldStepper = forwardRef<HTMLInputElement, FieldStepperProps>(
|
|
|
240
250
|
variant={CONTAINER_VARIANT.SingleLine}
|
|
241
251
|
inputRef={inputRef}
|
|
242
252
|
prefix={
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
253
|
+
<>
|
|
254
|
+
<ButtonFunction
|
|
255
|
+
tabIndex={-1}
|
|
256
|
+
ref={minusButtonRef}
|
|
257
|
+
size='xs'
|
|
258
|
+
className={styles.button}
|
|
259
|
+
icon={<MinusSVG />}
|
|
260
|
+
onClick={handleMinusButtonClick}
|
|
261
|
+
onKeyDown={handleMinusButtonKeyDown}
|
|
262
|
+
disabled={isMinusButtonDisabled}
|
|
263
|
+
data-test-id='field-stepper__minus-button'
|
|
264
|
+
/>
|
|
265
|
+
{prefixSettings.show && prefixSettings.render({ key: prefixSettings.id })}
|
|
266
|
+
</>
|
|
254
267
|
}
|
|
255
268
|
postfix={
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
269
|
+
<>
|
|
270
|
+
{postfixSettings.show && postfixSettings.render({ key: postfixSettings.id })}
|
|
271
|
+
|
|
272
|
+
<ButtonFunction
|
|
273
|
+
ref={plusButtonRef}
|
|
274
|
+
tabIndex={-1}
|
|
275
|
+
size='xs'
|
|
276
|
+
className={styles.button}
|
|
277
|
+
icon={<PlusSVG />}
|
|
278
|
+
onClick={handlePlusButtonClick}
|
|
279
|
+
onKeyDown={handlePlusButtonKeyDown}
|
|
280
|
+
disabled={isPlusButtonDisabled}
|
|
281
|
+
data-test-id='field-stepper__plus-button'
|
|
282
|
+
/>
|
|
283
|
+
</>
|
|
267
284
|
}
|
|
268
285
|
>
|
|
269
286
|
<InputPrivate
|