@cloud-ru/uikit-product-fields-predefined 3.0.3 → 3.1.1
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 +20 -0
- package/README.md +28 -0
- package/dist/cjs/components/FieldCode/FieldCode.d.ts +48 -0
- package/dist/cjs/components/FieldCode/FieldCode.js +47 -0
- package/dist/cjs/components/FieldCode/components/Cell/Cell.d.ts +7 -0
- package/dist/cjs/components/FieldCode/components/Cell/Cell.js +27 -0
- package/dist/cjs/components/FieldCode/components/Cell/index.d.ts +1 -0
- package/dist/cjs/components/FieldCode/components/Cell/index.js +17 -0
- package/dist/cjs/components/FieldCode/components/Cell/styles.module.css +19 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/ResendCode.d.ts +8 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/ResendCode.js +29 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/index.d.ts +1 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/index.js +17 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/utils.d.ts +1 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/utils.js +8 -0
- package/dist/cjs/components/FieldCode/components/index.d.ts +2 -0
- package/dist/cjs/components/FieldCode/components/index.js +18 -0
- package/dist/cjs/components/FieldCode/constants.d.ts +1 -0
- package/dist/cjs/components/FieldCode/constants.js +4 -0
- package/dist/cjs/components/FieldCode/hooks/index.d.ts +5 -0
- package/dist/cjs/components/FieldCode/hooks/index.js +21 -0
- package/dist/cjs/components/FieldCode/hooks/useCodeInput.d.ts +22 -0
- package/dist/cjs/components/FieldCode/hooks/useCodeInput.js +98 -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/hooks/useFieldCodeValidate.d.ts +8 -0
- package/dist/cjs/components/FieldCode/hooks/useFieldCodeValidate.js +24 -0
- package/dist/cjs/components/FieldCode/hooks/useFieldHelpers.d.ts +12 -0
- package/dist/cjs/components/FieldCode/hooks/useFieldHelpers.js +30 -0
- package/dist/cjs/components/FieldCode/hooks/useFocusCell.d.ts +5 -0
- package/dist/cjs/components/FieldCode/hooks/useFocusCell.js +22 -0
- package/dist/cjs/components/FieldCode/index.d.ts +2 -0
- package/dist/cjs/components/FieldCode/index.js +20 -0
- package/dist/cjs/components/FieldCode/styles.module.css +41 -0
- package/dist/cjs/components/FieldCode/utils.d.ts +6 -0
- package/dist/cjs/components/FieldCode/utils.js +21 -0
- package/dist/cjs/components/index.d.ts +1 -0
- package/dist/cjs/components/index.js +1 -0
- package/dist/esm/components/FieldCode/FieldCode.d.ts +48 -0
- package/dist/esm/components/FieldCode/FieldCode.js +41 -0
- package/dist/esm/components/FieldCode/components/Cell/Cell.d.ts +7 -0
- package/dist/esm/components/FieldCode/components/Cell/Cell.js +21 -0
- package/dist/esm/components/FieldCode/components/Cell/index.d.ts +1 -0
- package/dist/esm/components/FieldCode/components/Cell/index.js +1 -0
- package/dist/esm/components/FieldCode/components/Cell/styles.module.css +19 -0
- package/dist/esm/components/FieldCode/components/ResendCode/ResendCode.d.ts +8 -0
- package/dist/esm/components/FieldCode/components/ResendCode/ResendCode.js +26 -0
- package/dist/esm/components/FieldCode/components/ResendCode/index.d.ts +1 -0
- package/dist/esm/components/FieldCode/components/ResendCode/index.js +1 -0
- package/dist/esm/components/FieldCode/components/ResendCode/utils.d.ts +1 -0
- package/dist/esm/components/FieldCode/components/ResendCode/utils.js +5 -0
- package/dist/esm/components/FieldCode/components/index.d.ts +2 -0
- package/dist/esm/components/FieldCode/components/index.js +2 -0
- package/dist/esm/components/FieldCode/constants.d.ts +1 -0
- package/dist/esm/components/FieldCode/constants.js +1 -0
- package/dist/esm/components/FieldCode/hooks/index.d.ts +5 -0
- package/dist/esm/components/FieldCode/hooks/index.js +5 -0
- package/dist/esm/components/FieldCode/hooks/useCodeInput.d.ts +22 -0
- package/dist/esm/components/FieldCode/hooks/useCodeInput.js +95 -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/hooks/useFieldCodeValidate.d.ts +8 -0
- package/dist/esm/components/FieldCode/hooks/useFieldCodeValidate.js +21 -0
- package/dist/esm/components/FieldCode/hooks/useFieldHelpers.d.ts +12 -0
- package/dist/esm/components/FieldCode/hooks/useFieldHelpers.js +27 -0
- package/dist/esm/components/FieldCode/hooks/useFocusCell.d.ts +5 -0
- package/dist/esm/components/FieldCode/hooks/useFocusCell.js +19 -0
- package/dist/esm/components/FieldCode/index.d.ts +2 -0
- package/dist/esm/components/FieldCode/index.js +2 -0
- package/dist/esm/components/FieldCode/styles.module.css +41 -0
- package/dist/esm/components/FieldCode/utils.d.ts +6 -0
- package/dist/esm/components/FieldCode/utils.js +13 -0
- package/dist/esm/components/index.d.ts +1 -0
- package/dist/esm/components/index.js +1 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +7 -4
- package/src/components/FieldCode/FieldCode.tsx +138 -0
- package/src/components/FieldCode/components/Cell/Cell.tsx +35 -0
- package/src/components/FieldCode/components/Cell/index.ts +1 -0
- package/src/components/FieldCode/components/Cell/styles.module.scss +24 -0
- package/src/components/FieldCode/components/ResendCode/ResendCode.tsx +36 -0
- package/src/components/FieldCode/components/ResendCode/index.ts +1 -0
- package/src/components/FieldCode/components/ResendCode/utils.ts +5 -0
- package/src/components/FieldCode/components/index.ts +2 -0
- package/src/components/FieldCode/constants.ts +1 -0
- package/src/components/FieldCode/hooks/index.ts +5 -0
- package/src/components/FieldCode/hooks/useCodeInput.ts +147 -0
- package/src/components/FieldCode/hooks/useFieldCodeOverflow.ts +54 -0
- package/src/components/FieldCode/hooks/useFieldCodeValidate.ts +35 -0
- package/src/components/FieldCode/hooks/useFieldHelpers.ts +44 -0
- package/src/components/FieldCode/hooks/useFocusCell.ts +29 -0
- package/src/components/FieldCode/index.ts +2 -0
- package/src/components/FieldCode/styles.module.scss +46 -0
- package/src/components/FieldCode/utils.ts +23 -0
- package/src/components/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,26 @@
|
|
|
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
|
+
## 3.1.1 (2026-06-10)
|
|
7
|
+
|
|
8
|
+
### Only dependencies have been changed
|
|
9
|
+
* [@cloud-ru/uikit-product-mobile-fields@2.2.0]($PUBLIC_PROJECT_URL/blob/master/packages/mobile-fields/CHANGELOG.md)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# 3.1.0 (2026-06-08)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **PDS-3568:** field code ([7d8374e](https://github.com/cloud-ru-tech/uikit-product/commit/7d8374e3ff9545c204ffd1a3d54624fa98baccc1))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
6
26
|
## 3.0.3 (2026-06-05)
|
|
7
27
|
|
|
8
28
|
### Only dependencies have been changed
|
package/README.md
CHANGED
|
@@ -314,6 +314,34 @@
|
|
|
314
314
|
| onChange | `(value: string, mask: InputMask<Record<string, unknown>>) => void` | - | |
|
|
315
315
|
| ref | `LegacyRef<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 {@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs} |
|
|
316
316
|
| key | `Key` | - | |
|
|
317
|
+
## useFieldCodeValidate
|
|
318
|
+
Возвращает функцию валидации значения кода (пусто / неполный код).
|
|
319
|
+
### Props
|
|
320
|
+
| name | type | default value | description |
|
|
321
|
+
|------|------|---------------|-------------|
|
|
322
|
+
| codeLength* | `number` | - | Ожидаемая длина кода (цифр) |
|
|
323
|
+
## FieldCode
|
|
324
|
+
### Props
|
|
325
|
+
| name | type | default value | description |
|
|
326
|
+
|------|------|---------------|-------------|
|
|
327
|
+
| codeLength* | `number` | - | Количество цифр в коде (ожидается целое ≥ 1) |
|
|
328
|
+
| layoutType* | enum LayoutType: `"mobile"`, `"tablet"`, `"desktop"`, `"desktopSmall"` | - | |
|
|
329
|
+
| className | `string` | - | CSS-класс компонента |
|
|
330
|
+
| cellClassName | `string` | - | CSS-класс ячейки кода |
|
|
331
|
+
| spacing | `number[]` | - | Позиции, после которых нужно вставить пробел (индексы символов, после которых будет пробел) |
|
|
332
|
+
| showEmptyChars | `boolean` | - | Подсветить пустые символы кода |
|
|
333
|
+
| resendCode | `ResendCodeProps` | - | Компонент отправки нового кода |
|
|
334
|
+
| invalidCode | `string` | - | Сообщение при неверном коде, если не передан свой `error` |
|
|
335
|
+
| stretchCells | `boolean` | - | Растягивать ячейки на всю доступную ширину; иначе фиксированная ширина по `size` |
|
|
336
|
+
| value | `string` | - | Значение кода |
|
|
337
|
+
| onChange | `(code: string) => void` | - | Колбек изменения значения |
|
|
338
|
+
| onComplete | `(code: string) => void` | - | Колбек достижения ввода всех символов кода |
|
|
339
|
+
| disabled | `boolean` | - | Деактивирован ли элемент Является ли поле деактивированным |
|
|
340
|
+
| label | `string` | - | Лейбл |
|
|
341
|
+
| size | enum Size: `"s"`, `"m"`, `"l"` | - | Размер |
|
|
342
|
+
| error | `string` | - | |
|
|
343
|
+
| ref | `LegacyRef<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 {@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs} |
|
|
344
|
+
| key | `Key` | - | |
|
|
317
345
|
|
|
318
346
|
|
|
319
347
|
[//]: DOCUMENTATION_SECTION_END
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { WithLayoutType } from '@cloud-ru/uikit-product-utils';
|
|
2
|
+
import { FieldDecoratorProps } from '@snack-uikit/fields';
|
|
3
|
+
import { type ResendCodeProps } from './components';
|
|
4
|
+
import { UseCodeInputParams } from './hooks';
|
|
5
|
+
export type FieldCodeRef = {
|
|
6
|
+
/** Перенести фокус на ячейку с индексом `index` */
|
|
7
|
+
moveFocus: (index: number) => void;
|
|
8
|
+
/** Убрать фокус со всех ячеек кода */
|
|
9
|
+
blurFields: () => void;
|
|
10
|
+
/** Сбросить значение кода */
|
|
11
|
+
resetCode: () => void;
|
|
12
|
+
};
|
|
13
|
+
/** Собственные пропсы `FieldCode` */
|
|
14
|
+
export type FieldCodeOwnProps = WithLayoutType<{
|
|
15
|
+
/** CSS-класс компонента */
|
|
16
|
+
className?: string;
|
|
17
|
+
/** CSS-класс ячейки кода */
|
|
18
|
+
cellClassName?: string;
|
|
19
|
+
/** Позиции, после которых нужно вставить пробел (индексы символов, после которых будет пробел) */
|
|
20
|
+
spacing?: number[];
|
|
21
|
+
/** Подсветить пустые символы кода */
|
|
22
|
+
showEmptyChars?: boolean;
|
|
23
|
+
/** Компонент отправки нового кода */
|
|
24
|
+
resendCode?: ResendCodeProps;
|
|
25
|
+
/** Сообщение при неверном коде, если не передан свой `error` */
|
|
26
|
+
invalidCode?: string;
|
|
27
|
+
/** Растягивать ячейки на всю доступную ширину; иначе фиксированная ширина по `size` */
|
|
28
|
+
stretchCells?: boolean;
|
|
29
|
+
}>;
|
|
30
|
+
export type FieldCodeProps = FieldCodeOwnProps & Omit<UseCodeInputParams, 'moveFocus'> & Pick<FieldDecoratorProps, 'size' | 'disabled' | 'label' | 'error' | 'data-test-id'>;
|
|
31
|
+
export declare const FieldCode: import("react").ForwardRefExoticComponent<{
|
|
32
|
+
/** CSS-класс компонента */
|
|
33
|
+
className?: string;
|
|
34
|
+
/** CSS-класс ячейки кода */
|
|
35
|
+
cellClassName?: string;
|
|
36
|
+
/** Позиции, после которых нужно вставить пробел (индексы символов, после которых будет пробел) */
|
|
37
|
+
spacing?: number[];
|
|
38
|
+
/** Подсветить пустые символы кода */
|
|
39
|
+
showEmptyChars?: boolean;
|
|
40
|
+
/** Компонент отправки нового кода */
|
|
41
|
+
resendCode?: ResendCodeProps;
|
|
42
|
+
/** Сообщение при неверном коде, если не передан свой `error` */
|
|
43
|
+
invalidCode?: string;
|
|
44
|
+
/** Растягивать ячейки на всю доступную ширину; иначе фиксированная ширина по `size` */
|
|
45
|
+
stretchCells?: boolean;
|
|
46
|
+
} & {
|
|
47
|
+
layoutType: import("@cloud-ru/uikit-product-utils/.").LayoutType;
|
|
48
|
+
} & Omit<UseCodeInputParams, "moveFocus"> & Pick<FieldDecoratorProps, "size" | "label" | "error" | "disabled" | "data-test-id"> & import("react").RefAttributes<FieldCodeRef>>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.FieldCode = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
9
|
+
const react_1 = require("react");
|
|
10
|
+
const fields_1 = require("@snack-uikit/fields");
|
|
11
|
+
const components_1 = require("./components");
|
|
12
|
+
const hooks_1 = require("./hooks");
|
|
13
|
+
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
14
|
+
const utils_1 = require("./utils");
|
|
15
|
+
exports.FieldCode = (0, react_1.forwardRef)(function FieldCode(props, ref) {
|
|
16
|
+
var _a;
|
|
17
|
+
const { codeLength, className, cellClassName, value, onChange, spacing, onComplete, size, disabled, label, error, invalidCode, showEmptyChars, resendCode, layoutType, stretchCells = false, 'data-test-id': dataTestId, } = props;
|
|
18
|
+
const isMobile = layoutType === 'mobile';
|
|
19
|
+
const { inputsRef, moveFocus, blurFields } = (0, hooks_1.useFocusCell)(codeLength);
|
|
20
|
+
const { code, cellHandlers, onChangeCode } = (0, hooks_1.useCodeInput)({ value, onChange, codeLength, moveFocus, onComplete });
|
|
21
|
+
const { resetCode } = (0, hooks_1.useFieldHelpers)({
|
|
22
|
+
onChangeCode,
|
|
23
|
+
isMobile,
|
|
24
|
+
moveFocus,
|
|
25
|
+
showEmptyChars,
|
|
26
|
+
code,
|
|
27
|
+
codeLength,
|
|
28
|
+
});
|
|
29
|
+
const { rootRef, codeContainerRef, hasOverflow } = (0, hooks_1.useFieldCodeOverflow)();
|
|
30
|
+
(0, react_1.useImperativeHandle)(ref, () => ({
|
|
31
|
+
moveFocus,
|
|
32
|
+
blurFields,
|
|
33
|
+
resetCode,
|
|
34
|
+
}), [moveFocus, blurFields, resetCode]);
|
|
35
|
+
const resolvedError = error !== null && error !== void 0 ? error : invalidCode;
|
|
36
|
+
const resolvedDecoratorProps = {
|
|
37
|
+
label,
|
|
38
|
+
disabled,
|
|
39
|
+
size,
|
|
40
|
+
error: resolvedError,
|
|
41
|
+
};
|
|
42
|
+
return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ ref: rootRef, className: (0, classnames_1.default)(styles_module_scss_1.default.fieldCode, hasOverflow && styles_module_scss_1.default.fieldCodeScrollable, className), "data-stretch-cells": stretchCells || undefined }, (dataTestId ? { 'data-test-id': dataTestId } : undefined), { children: [(0, jsx_runtime_1.jsx)(fields_1.FieldDecorator, Object.assign({ className: (0, classnames_1.default)(!hasOverflow && styles_module_scss_1.default.fieldDecorator) }, resolvedDecoratorProps, { children: (0, jsx_runtime_1.jsx)("div", { ref: codeContainerRef, className: styles_module_scss_1.default.codeContainer, "data-size": size, "data-stretch-cells": stretchCells || undefined, children: code.map((char, index) => ((0, jsx_runtime_1.jsx)(components_1.Cell, { ref: inputRef => {
|
|
43
|
+
if (inputRef) {
|
|
44
|
+
inputsRef.current[index] = inputRef;
|
|
45
|
+
}
|
|
46
|
+
}, className: (0, classnames_1.default)((spacing === null || spacing === void 0 ? void 0 : spacing.includes(index)) && styles_module_scss_1.default.cellSpacing, cellClassName), stretchCells: stretchCells, size: size, value: char, disabled: disabled, autoComplete: index === 0 ? 'one-time-code' : undefined, onKeyDown: e => cellHandlers.onKeyDown(e, index), onPaste: cellHandlers.onPaste, onChange: e => cellHandlers.onChange(e, index), validationState: (0, utils_1.getCellValidationState)(char, showEmptyChars, Boolean(resolvedError)) }, index))) }) })), resendCode ? (0, jsx_runtime_1.jsx)(components_1.ResendCode, Object.assign({}, resendCode, { size: (_a = resendCode.size) !== null && _a !== void 0 ? _a : size })) : null] })));
|
|
47
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FieldTextProps } from '@snack-uikit/fields';
|
|
2
|
+
export declare const Cell: import("react").ForwardRefExoticComponent<{
|
|
3
|
+
/** CSS-класс ячейки кода */
|
|
4
|
+
className?: string;
|
|
5
|
+
/** Растягивать ячейку на всю доступную ширину */
|
|
6
|
+
stretchCells?: boolean;
|
|
7
|
+
} & Pick<FieldTextProps, "size" | "onPaste" | "onChange" | "onKeyDown" | "value" | "disabled" | "autoComplete" | "validationState"> & import("react").RefAttributes<HTMLInputElement>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.Cell = void 0;
|
|
18
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
19
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
20
|
+
const react_1 = require("react");
|
|
21
|
+
const fields_1 = require("@snack-uikit/fields");
|
|
22
|
+
const constants_1 = require("../../constants");
|
|
23
|
+
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
24
|
+
exports.Cell = (0, react_1.forwardRef)((props, ref) => {
|
|
25
|
+
const { className, size, stretchCells, value } = props, fieldCellProps = __rest(props, ["className", "size", "stretchCells", "value"]);
|
|
26
|
+
return ((0, jsx_runtime_1.jsx)(fields_1.FieldText, Object.assign({ inputMode: 'numeric', ref: ref, className: (0, classnames_1.default)(styles_module_scss_1.default.cell, className), "data-size": size, "data-stretch-cells": stretchCells || undefined, showClearButton: false, value: value === constants_1.ZERO_WIDTH_SPACE ? '' : value, size: size }, fieldCellProps)));
|
|
27
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Cell';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Cell"), exports);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.cell{
|
|
2
|
+
flex-shrink:0;
|
|
3
|
+
}
|
|
4
|
+
.cell input{
|
|
5
|
+
text-align:center;
|
|
6
|
+
}
|
|
7
|
+
.cell[data-size=s]:not([data-stretch-cells]){
|
|
8
|
+
width:32px;
|
|
9
|
+
}
|
|
10
|
+
.cell[data-size=m]:not([data-stretch-cells]){
|
|
11
|
+
width:40px;
|
|
12
|
+
}
|
|
13
|
+
.cell[data-size=l]:not([data-stretch-cells]){
|
|
14
|
+
width:52px;
|
|
15
|
+
}
|
|
16
|
+
.cell[data-stretch-cells]{
|
|
17
|
+
flex:1 1 0;
|
|
18
|
+
min-width:0;
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ButtonFunctionProps } from '@snack-uikit/button';
|
|
2
|
+
export type ResendCodeProps = {
|
|
3
|
+
/** Колбек отправки нового кода */
|
|
4
|
+
onResend: () => void;
|
|
5
|
+
/** Количество секунд до следующего отправления кода */
|
|
6
|
+
secondsToNextResend: number;
|
|
7
|
+
} & Pick<ButtonFunctionProps, 'size' | 'disabled'>;
|
|
8
|
+
export declare function ResendCode(props: ResendCodeProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.ResendCode = ResendCode;
|
|
15
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
16
|
+
const uikit_product_icons_1 = require("@cloud-ru/uikit-product-icons");
|
|
17
|
+
const uikit_product_locale_1 = require("@cloud-ru/uikit-product-locale");
|
|
18
|
+
const button_1 = require("@snack-uikit/button");
|
|
19
|
+
const utils_1 = require("./utils");
|
|
20
|
+
function ResendCode(props) {
|
|
21
|
+
const { onResend, secondsToNextResend } = props, buttonProps = __rest(props, ["onResend", "secondsToNextResend"]);
|
|
22
|
+
const { t } = (0, uikit_product_locale_1.useLocale)('FieldsPredefined');
|
|
23
|
+
const isResendCodeWithVia = secondsToNextResend > 0;
|
|
24
|
+
return ((0, jsx_runtime_1.jsx)(button_1.ButtonFunction, Object.assign({ label: isResendCodeWithVia
|
|
25
|
+
? t('FieldCode.resendCodeButtons.resendCodeWithVia', {
|
|
26
|
+
timer: (0, utils_1.formatSecondsAsMmSs)(secondsToNextResend),
|
|
27
|
+
})
|
|
28
|
+
: t('FieldCode.resendCodeButtons.resendCode'), onClick: onResend, icon: (0, jsx_runtime_1.jsx)(uikit_product_icons_1.UpdateSVG, {}), iconPosition: 'before', disabled: isResendCodeWithVia !== null && isResendCodeWithVia !== void 0 ? isResendCodeWithVia : buttonProps.disabled }, buttonProps)));
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ResendCode';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./ResendCode"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function formatSecondsAsMmSs(totalSeconds: number): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatSecondsAsMmSs = formatSecondsAsMmSs;
|
|
4
|
+
function formatSecondsAsMmSs(totalSeconds) {
|
|
5
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
6
|
+
const seconds = totalSeconds % 60;
|
|
7
|
+
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
|
|
8
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Cell"), exports);
|
|
18
|
+
__exportStar(require("./ResendCode"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ZERO_WIDTH_SPACE = "\u200B";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./useCodeInput"), exports);
|
|
18
|
+
__exportStar(require("./useFieldCodeOverflow"), exports);
|
|
19
|
+
__exportStar(require("./useFieldCodeValidate"), exports);
|
|
20
|
+
__exportStar(require("./useFocusCell"), exports);
|
|
21
|
+
__exportStar(require("./useFieldHelpers"), exports);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ClipboardEvent, KeyboardEvent } from 'react';
|
|
2
|
+
export type UseCodeInputParams = {
|
|
3
|
+
/** Количество цифр в коде (ожидается целое ≥ 1) */
|
|
4
|
+
codeLength: number;
|
|
5
|
+
/** Значение кода */
|
|
6
|
+
value?: string;
|
|
7
|
+
/** Колбек изменения значения */
|
|
8
|
+
onChange?: (code: string) => void;
|
|
9
|
+
/** Функция фокуса */
|
|
10
|
+
moveFocus: (index: number) => void;
|
|
11
|
+
/** Колбек достижения ввода всех символов кода */
|
|
12
|
+
onComplete?: (code: string) => void;
|
|
13
|
+
};
|
|
14
|
+
export declare function useCodeInput(params: UseCodeInputParams): {
|
|
15
|
+
code: string[];
|
|
16
|
+
cellHandlers: {
|
|
17
|
+
onKeyDown: (e: KeyboardEvent<HTMLInputElement>, index: number) => void;
|
|
18
|
+
onPaste: (e: ClipboardEvent<HTMLInputElement>) => void;
|
|
19
|
+
onChange: (code: string, index: number) => void;
|
|
20
|
+
};
|
|
21
|
+
onChangeCode: (value: any, ...args: any[]) => any | void;
|
|
22
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useCodeInput = useCodeInput;
|
|
4
|
+
const reactuse_1 = require("@siberiacancode/reactuse");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const utils_1 = require("@snack-uikit/utils");
|
|
7
|
+
const constants_1 = require("../constants");
|
|
8
|
+
const utils_2 = require("../utils");
|
|
9
|
+
const buildCodeArray = (str, codeLength) => Array.from({ length: codeLength }, (_, idx) => str[idx] || constants_1.ZERO_WIDTH_SPACE);
|
|
10
|
+
function useCodeInput(params) {
|
|
11
|
+
const { value: valueProp, onChange: onChangeProp, codeLength, moveFocus, onComplete } = params;
|
|
12
|
+
const [value = '', onChange] = (0, utils_1.useValueControl)({
|
|
13
|
+
value: valueProp,
|
|
14
|
+
onChange: onChangeProp,
|
|
15
|
+
defaultValue: '',
|
|
16
|
+
});
|
|
17
|
+
const codeRef = (0, reactuse_1.useRefState)(buildCodeArray(value, codeLength));
|
|
18
|
+
const updateCodeByIndex = (0, react_1.useCallback)((index, newChar) => {
|
|
19
|
+
codeRef.current[index] = newChar;
|
|
20
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(codeRef.current.join(''));
|
|
21
|
+
}, [codeRef, onChange]);
|
|
22
|
+
const updateFullCode = (0, react_1.useCallback)((newCode) => {
|
|
23
|
+
codeRef.current = newCode.split('');
|
|
24
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newCode);
|
|
25
|
+
moveFocus(codeLength - 1);
|
|
26
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete(newCode);
|
|
27
|
+
}, [codeLength, codeRef, moveFocus, onChange, onComplete]);
|
|
28
|
+
const handleAfterCellUpdate = (0, react_1.useCallback)((index) => {
|
|
29
|
+
const normalizedCode = codeRef.current.join('');
|
|
30
|
+
const isLastInput = index === codeLength - 1;
|
|
31
|
+
const isAllInputsFilled = (0, utils_2.isStringCodeLength)(normalizedCode, codeLength);
|
|
32
|
+
if (!isLastInput) {
|
|
33
|
+
moveFocus(index + 1);
|
|
34
|
+
}
|
|
35
|
+
else if (isAllInputsFilled) {
|
|
36
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete(normalizedCode);
|
|
37
|
+
}
|
|
38
|
+
}, [codeLength, codeRef, moveFocus, onComplete]);
|
|
39
|
+
const deleteChar = (0, react_1.useCallback)((index) => {
|
|
40
|
+
if (codeRef.current[index] && !(0, utils_2.isZeroWidthSpace)(codeRef.current[index])) {
|
|
41
|
+
updateCodeByIndex(index, constants_1.ZERO_WIDTH_SPACE);
|
|
42
|
+
}
|
|
43
|
+
else if (index > 0) {
|
|
44
|
+
moveFocus(index - 1);
|
|
45
|
+
}
|
|
46
|
+
}, [codeRef, moveFocus, updateCodeByIndex]);
|
|
47
|
+
const onAutoCompleteInput = (0, react_1.useCallback)((code, index) => {
|
|
48
|
+
if ((0, utils_2.isStringCodeLength)(code, codeLength)) {
|
|
49
|
+
updateFullCode(code);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (!(0, utils_2.isNumberChar)(code)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
updateCodeByIndex(index, code);
|
|
56
|
+
handleAfterCellUpdate(index);
|
|
57
|
+
}, [codeLength, handleAfterCellUpdate, updateCodeByIndex, updateFullCode]);
|
|
58
|
+
const onKeyDown = (0, react_1.useCallback)((e, index) => {
|
|
59
|
+
switch (e.key) {
|
|
60
|
+
case 'ArrowLeft':
|
|
61
|
+
moveFocus(index - 1);
|
|
62
|
+
break;
|
|
63
|
+
case 'ArrowRight':
|
|
64
|
+
moveFocus(index + 1);
|
|
65
|
+
break;
|
|
66
|
+
case 'Backspace':
|
|
67
|
+
deleteChar(index);
|
|
68
|
+
break;
|
|
69
|
+
default:
|
|
70
|
+
if ((0, utils_2.isNumberChar)(e.key)) {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
updateCodeByIndex(index, e.key);
|
|
73
|
+
handleAfterCellUpdate(index);
|
|
74
|
+
}
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}, [deleteChar, handleAfterCellUpdate, moveFocus, updateCodeByIndex]);
|
|
78
|
+
const onPaste = (0, react_1.useCallback)((e) => {
|
|
79
|
+
var _a;
|
|
80
|
+
const codeInput = (_a = e === null || e === void 0 ? void 0 : e.clipboardData.getData('text')) !== null && _a !== void 0 ? _a : '';
|
|
81
|
+
if (!(0, utils_2.isStringCodeLength)(codeInput, codeLength)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
updateFullCode(codeInput);
|
|
85
|
+
}, [codeLength, updateFullCode]);
|
|
86
|
+
(0, react_1.useEffect)(() => {
|
|
87
|
+
codeRef.current = buildCodeArray(value, codeLength);
|
|
88
|
+
}, [codeLength, codeRef, value]);
|
|
89
|
+
return {
|
|
90
|
+
code: codeRef.current,
|
|
91
|
+
cellHandlers: {
|
|
92
|
+
onKeyDown,
|
|
93
|
+
onPaste,
|
|
94
|
+
onChange: onAutoCompleteInput,
|
|
95
|
+
},
|
|
96
|
+
onChangeCode: onChange,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Fallback на крайний случай: включает горизонтальный скролл, если ряд ячеек шире контейнера. */
|
|
2
|
+
export declare function useFieldCodeOverflow(): {
|
|
3
|
+
rootRef: import("react").RefObject<HTMLDivElement>;
|
|
4
|
+
codeContainerRef: import("react").RefObject<HTMLDivElement>;
|
|
5
|
+
hasOverflow: boolean;
|
|
6
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useFieldCodeOverflow = useFieldCodeOverflow;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const utils_1 = require("@snack-uikit/utils");
|
|
6
|
+
function hasCodeOverflow(root, codeContainer) {
|
|
7
|
+
return codeContainer.scrollWidth > root.clientWidth;
|
|
8
|
+
}
|
|
9
|
+
/** Fallback на крайний случай: включает горизонтальный скролл, если ряд ячеек шире контейнера. */
|
|
10
|
+
function useFieldCodeOverflow() {
|
|
11
|
+
const [hasOverflow, setHasOverflow] = (0, react_1.useState)(false);
|
|
12
|
+
const rootRef = (0, react_1.useRef)(null);
|
|
13
|
+
const codeContainerRef = (0, react_1.useRef)(null);
|
|
14
|
+
const measure = (0, react_1.useCallback)(() => {
|
|
15
|
+
const root = rootRef.current;
|
|
16
|
+
const codeContainer = codeContainerRef.current;
|
|
17
|
+
if (!root || !codeContainer) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
setHasOverflow(prev => {
|
|
21
|
+
const next = hasCodeOverflow(root, codeContainer);
|
|
22
|
+
return prev === next ? prev : next;
|
|
23
|
+
});
|
|
24
|
+
}, []);
|
|
25
|
+
(0, utils_1.useLayoutEffect)(() => {
|
|
26
|
+
const root = rootRef.current;
|
|
27
|
+
const codeContainer = codeContainerRef.current;
|
|
28
|
+
if (!root || !codeContainer) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
measure();
|
|
32
|
+
const resizeObserver = new ResizeObserver(measure);
|
|
33
|
+
resizeObserver.observe(root);
|
|
34
|
+
resizeObserver.observe(codeContainer);
|
|
35
|
+
const mutationObserver = new MutationObserver(measure);
|
|
36
|
+
mutationObserver.observe(codeContainer, { childList: true });
|
|
37
|
+
return () => {
|
|
38
|
+
resizeObserver.disconnect();
|
|
39
|
+
mutationObserver.disconnect();
|
|
40
|
+
};
|
|
41
|
+
}, [measure]);
|
|
42
|
+
return { rootRef, codeContainerRef, hasOverflow };
|
|
43
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type UseFieldCodeValidateParams = {
|
|
2
|
+
/** Ожидаемая длина кода (цифр) */
|
|
3
|
+
codeLength: number;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Возвращает функцию валидации значения кода (пусто / неполный код).
|
|
7
|
+
*/
|
|
8
|
+
export declare function useFieldCodeValidate(params: UseFieldCodeValidateParams): (value?: string | number) => string | undefined;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useFieldCodeValidate = useFieldCodeValidate;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const uikit_product_locale_1 = require("@cloud-ru/uikit-product-locale");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
/**
|
|
8
|
+
* Возвращает функцию валидации значения кода (пусто / неполный код).
|
|
9
|
+
*/
|
|
10
|
+
function useFieldCodeValidate(params) {
|
|
11
|
+
const { codeLength } = params;
|
|
12
|
+
const { t } = (0, uikit_product_locale_1.useLocale)('FieldsPredefined');
|
|
13
|
+
return (0, react_1.useCallback)((value) => {
|
|
14
|
+
const str = value != null ? String(value) : '';
|
|
15
|
+
const digits = str.split('').filter(utils_1.isNumberChar).join('');
|
|
16
|
+
if (digits.length === 0) {
|
|
17
|
+
return t('FieldCode.required');
|
|
18
|
+
}
|
|
19
|
+
if (digits.length < codeLength) {
|
|
20
|
+
return t('FieldCode.minLength', { count: codeLength });
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}, [codeLength, t]);
|
|
24
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type UseFieldHelpersParams = {
|
|
2
|
+
onChangeCode: (code: string) => void;
|
|
3
|
+
moveFocus: (index: number) => void;
|
|
4
|
+
isMobile?: boolean;
|
|
5
|
+
showEmptyChars?: boolean;
|
|
6
|
+
code: readonly string[];
|
|
7
|
+
codeLength: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function useFieldHelpers(params: UseFieldHelpersParams): {
|
|
10
|
+
resetCode: () => void;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useFieldHelpers = useFieldHelpers;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
function useFieldHelpers(params) {
|
|
7
|
+
const { onChangeCode, moveFocus, isMobile = false, showEmptyChars, code, codeLength } = params;
|
|
8
|
+
const resetCode = (0, react_1.useCallback)(() => {
|
|
9
|
+
onChangeCode('');
|
|
10
|
+
if (!isMobile) {
|
|
11
|
+
moveFocus(0);
|
|
12
|
+
}
|
|
13
|
+
}, [isMobile, moveFocus, onChangeCode]);
|
|
14
|
+
(0, react_1.useEffect)(() => {
|
|
15
|
+
if (!isMobile) {
|
|
16
|
+
moveFocus(0);
|
|
17
|
+
}
|
|
18
|
+
}, [isMobile, moveFocus]);
|
|
19
|
+
(0, react_1.useEffect)(() => {
|
|
20
|
+
if (isMobile || !showEmptyChars) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const emptyIndex = (0, utils_1.getFirstEmptyCellIndex)(code);
|
|
24
|
+
if (emptyIndex >= 0) {
|
|
25
|
+
moveFocus(emptyIndex);
|
|
26
|
+
}
|
|
27
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
28
|
+
}, [showEmptyChars, isMobile, moveFocus, codeLength]);
|
|
29
|
+
return { resetCode };
|
|
30
|
+
}
|