@cloud-ru/uikit-product-fields-predefined 3.0.3-preview-7cd1981e.0 → 3.0.3-preview-30fdf48b.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/README.md +1 -1
- package/dist/cjs/components/FieldCode/FieldCode.d.ts +21 -5
- package/dist/cjs/components/FieldCode/FieldCode.js +4 -2
- package/dist/cjs/components/FieldCode/hooks/index.d.ts +1 -0
- package/dist/cjs/components/FieldCode/hooks/index.js +1 -0
- package/dist/cjs/components/FieldCode/hooks/useFieldCodeOverflow.d.ts +6 -0
- package/dist/cjs/components/FieldCode/hooks/useFieldCodeOverflow.js +43 -0
- package/dist/cjs/components/FieldCode/styles.module.css +5 -1
- package/dist/esm/components/FieldCode/FieldCode.d.ts +21 -5
- package/dist/esm/components/FieldCode/FieldCode.js +5 -3
- package/dist/esm/components/FieldCode/hooks/index.d.ts +1 -0
- package/dist/esm/components/FieldCode/hooks/index.js +1 -0
- package/dist/esm/components/FieldCode/hooks/useFieldCodeOverflow.d.ts +6 -0
- package/dist/esm/components/FieldCode/hooks/useFieldCodeOverflow.js +40 -0
- package/dist/esm/components/FieldCode/styles.module.css +5 -1
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/components/FieldCode/FieldCode.tsx +18 -9
- package/src/components/FieldCode/hooks/index.ts +1 -0
- package/src/components/FieldCode/hooks/useFieldCodeOverflow.ts +54 -0
- package/src/components/FieldCode/styles.module.scss +5 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloud-ru/uikit-product-fields-predefined",
|
|
3
3
|
"title": "Fields Predefined",
|
|
4
|
-
"version": "3.0.3-preview-
|
|
4
|
+
"version": "3.0.3-preview-30fdf48b.0",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"*.css",
|
|
7
7
|
"*.woff",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"react-hook-form": ">=7.51.0",
|
|
63
63
|
"yup": ">=0.32.0"
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "e099ff0e265dbde19b4985b2766c327517fd9836"
|
|
66
66
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import cn from 'classnames';
|
|
2
2
|
import { forwardRef, useImperativeHandle } from 'react';
|
|
3
3
|
|
|
4
|
+
import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
|
|
4
5
|
import { FieldDecorator, FieldDecoratorProps } from '@snack-uikit/fields';
|
|
5
6
|
|
|
6
7
|
import { Cell, ResendCode, type ResendCodeProps } from './components';
|
|
7
|
-
import { useCodeInput, UseCodeInputParams, useFieldHelpers, useFocusCell } from './hooks';
|
|
8
|
+
import { useCodeInput, UseCodeInputParams, useFieldCodeOverflow, useFieldHelpers, useFocusCell } from './hooks';
|
|
8
9
|
import styles from './styles.module.scss';
|
|
9
10
|
import { getCellValidationState } from './utils';
|
|
10
11
|
|
|
@@ -18,7 +19,7 @@ export type FieldCodeRef = {
|
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
/** Собственные пропсы `FieldCode` */
|
|
21
|
-
export type FieldCodeOwnProps = {
|
|
22
|
+
export type FieldCodeOwnProps = WithLayoutType<{
|
|
22
23
|
/** CSS-класс компонента */
|
|
23
24
|
className?: string;
|
|
24
25
|
/** CSS-класс ячейки кода */
|
|
@@ -29,13 +30,11 @@ export type FieldCodeOwnProps = {
|
|
|
29
30
|
showEmptyChars?: boolean;
|
|
30
31
|
/** Компонент отправки нового кода */
|
|
31
32
|
resendCode?: ResendCodeProps;
|
|
32
|
-
/** Отключить автофокус (при монтировании, сбросе и при ошибке валидации) */
|
|
33
|
-
isMobile: boolean;
|
|
34
33
|
/** Сообщение при неверном коде, если не передан свой `error` */
|
|
35
34
|
invalidCode?: string;
|
|
36
35
|
/** Растягивать ячейки на всю доступную ширину; иначе фиксированная ширина по `size` */
|
|
37
36
|
stretchCells?: boolean;
|
|
38
|
-
}
|
|
37
|
+
}>;
|
|
39
38
|
|
|
40
39
|
export type FieldCodeProps = FieldCodeOwnProps &
|
|
41
40
|
Omit<UseCodeInputParams, 'moveFocus'> &
|
|
@@ -57,11 +56,13 @@ export const FieldCode = forwardRef<FieldCodeRef, FieldCodeProps>(function Field
|
|
|
57
56
|
invalidCode,
|
|
58
57
|
showEmptyChars,
|
|
59
58
|
resendCode,
|
|
60
|
-
|
|
59
|
+
layoutType,
|
|
61
60
|
stretchCells = false,
|
|
62
61
|
'data-test-id': dataTestId,
|
|
63
62
|
} = props;
|
|
64
63
|
|
|
64
|
+
const isMobile = layoutType === 'mobile';
|
|
65
|
+
|
|
65
66
|
const { inputsRef, moveFocus, blurFields } = useFocusCell(codeLength);
|
|
66
67
|
const { code, cellHandlers, onChangeCode } = useCodeInput({ value, onChange, codeLength, moveFocus, onComplete });
|
|
67
68
|
const { resetCode } = useFieldHelpers({
|
|
@@ -73,6 +74,8 @@ export const FieldCode = forwardRef<FieldCodeRef, FieldCodeProps>(function Field
|
|
|
73
74
|
codeLength,
|
|
74
75
|
});
|
|
75
76
|
|
|
77
|
+
const { rootRef, codeContainerRef, hasOverflow } = useFieldCodeOverflow();
|
|
78
|
+
|
|
76
79
|
useImperativeHandle(
|
|
77
80
|
ref,
|
|
78
81
|
() => ({
|
|
@@ -94,12 +97,18 @@ export const FieldCode = forwardRef<FieldCodeRef, FieldCodeProps>(function Field
|
|
|
94
97
|
|
|
95
98
|
return (
|
|
96
99
|
<div
|
|
97
|
-
|
|
100
|
+
ref={rootRef}
|
|
101
|
+
className={cn(styles.fieldCode, hasOverflow && styles.fieldCodeScrollable, className)}
|
|
98
102
|
data-stretch-cells={stretchCells || undefined}
|
|
99
103
|
{...(dataTestId ? { 'data-test-id': dataTestId } : undefined)}
|
|
100
104
|
>
|
|
101
|
-
<FieldDecorator className={styles.fieldDecorator} {...resolvedDecoratorProps}>
|
|
102
|
-
<div
|
|
105
|
+
<FieldDecorator className={cn(!hasOverflow && styles.fieldDecorator)} {...resolvedDecoratorProps}>
|
|
106
|
+
<div
|
|
107
|
+
ref={codeContainerRef}
|
|
108
|
+
className={styles.codeContainer}
|
|
109
|
+
data-size={size}
|
|
110
|
+
data-stretch-cells={stretchCells || undefined}
|
|
111
|
+
>
|
|
103
112
|
{code.map((char, index) => (
|
|
104
113
|
<Cell
|
|
105
114
|
ref={inputRef => {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { useLayoutEffect } from '@snack-uikit/utils';
|
|
4
|
+
|
|
5
|
+
function hasCodeOverflow(root: HTMLElement, codeContainer: HTMLElement): boolean {
|
|
6
|
+
return codeContainer.scrollWidth > root.clientWidth;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Fallback на крайний случай: включает горизонтальный скролл, если ряд ячеек шире контейнера. */
|
|
10
|
+
export function useFieldCodeOverflow() {
|
|
11
|
+
const [hasOverflow, setHasOverflow] = useState(false);
|
|
12
|
+
|
|
13
|
+
const rootRef = useRef<HTMLDivElement>(null);
|
|
14
|
+
const codeContainerRef = useRef<HTMLDivElement>(null);
|
|
15
|
+
|
|
16
|
+
const measure = useCallback(() => {
|
|
17
|
+
const root = rootRef.current;
|
|
18
|
+
const codeContainer = codeContainerRef.current;
|
|
19
|
+
|
|
20
|
+
if (!root || !codeContainer) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
setHasOverflow(prev => {
|
|
25
|
+
const next = hasCodeOverflow(root, codeContainer);
|
|
26
|
+
return prev === next ? prev : next;
|
|
27
|
+
});
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
useLayoutEffect(() => {
|
|
31
|
+
const root = rootRef.current;
|
|
32
|
+
const codeContainer = codeContainerRef.current;
|
|
33
|
+
|
|
34
|
+
if (!root || !codeContainer) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
measure();
|
|
39
|
+
|
|
40
|
+
const resizeObserver = new ResizeObserver(measure);
|
|
41
|
+
resizeObserver.observe(root);
|
|
42
|
+
resizeObserver.observe(codeContainer);
|
|
43
|
+
|
|
44
|
+
const mutationObserver = new MutationObserver(measure);
|
|
45
|
+
mutationObserver.observe(codeContainer, { childList: true });
|
|
46
|
+
|
|
47
|
+
return () => {
|
|
48
|
+
resizeObserver.disconnect();
|
|
49
|
+
mutationObserver.disconnect();
|
|
50
|
+
};
|
|
51
|
+
}, [measure]);
|
|
52
|
+
|
|
53
|
+
return { rootRef, codeContainerRef, hasOverflow };
|
|
54
|
+
}
|
|
@@ -18,13 +18,17 @@ $container-gaps: (
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
.fieldCodeScrollable {
|
|
22
|
+
overflow-x: auto;
|
|
23
|
+
}
|
|
24
|
+
|
|
21
25
|
.fieldDecorator {
|
|
22
26
|
width: unset;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
.codeContainer {
|
|
26
30
|
display: flex;
|
|
27
|
-
justify-content: center;
|
|
31
|
+
justify-content: safe center;
|
|
28
32
|
|
|
29
33
|
@each $size, $gap in $container-gaps {
|
|
30
34
|
&[data-size='#{$size}'] {
|