@cloud-ru/uikit-product-fields-predefined 2.4.8-preview-df188565.0 → 2.4.8-preview-04a474c4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +8 -1
  2. package/dist/cjs/components/FieldCode/FieldCode.d.ts +7 -16
  3. package/dist/cjs/components/FieldCode/FieldCode.js +4 -3
  4. package/dist/cjs/components/FieldCode/hooks/index.d.ts +1 -0
  5. package/dist/cjs/components/FieldCode/hooks/index.js +1 -0
  6. package/dist/cjs/components/FieldCode/hooks/useCodeInput.d.ts +1 -1
  7. package/dist/cjs/components/FieldCode/hooks/useFieldCodeValidate.d.ts +8 -0
  8. package/dist/cjs/components/FieldCode/hooks/useFieldCodeValidate.js +24 -0
  9. package/dist/cjs/components/FieldCode/index.d.ts +1 -0
  10. package/dist/cjs/components/FieldCode/index.js +3 -0
  11. package/dist/esm/components/FieldCode/FieldCode.d.ts +7 -16
  12. package/dist/esm/components/FieldCode/FieldCode.js +4 -3
  13. package/dist/esm/components/FieldCode/hooks/index.d.ts +1 -0
  14. package/dist/esm/components/FieldCode/hooks/index.js +1 -0
  15. package/dist/esm/components/FieldCode/hooks/useCodeInput.d.ts +1 -1
  16. package/dist/esm/components/FieldCode/hooks/useFieldCodeValidate.d.ts +8 -0
  17. package/dist/esm/components/FieldCode/hooks/useFieldCodeValidate.js +21 -0
  18. package/dist/esm/components/FieldCode/index.d.ts +1 -0
  19. package/dist/esm/components/FieldCode/index.js +1 -0
  20. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  21. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  22. package/package.json +2 -2
  23. package/src/components/FieldCode/FieldCode.tsx +13 -4
  24. package/src/components/FieldCode/hooks/index.ts +1 -0
  25. package/src/components/FieldCode/hooks/useCodeInput.ts +1 -1
  26. package/src/components/FieldCode/hooks/useFieldCodeValidate.ts +35 -0
  27. package/src/components/FieldCode/index.ts +1 -0
package/README.md CHANGED
@@ -351,17 +351,24 @@
351
351
  | onChange | `(value: string, mask: InputMask<Record<string, unknown>>) => void` | - | |
352
352
  | 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} |
353
353
  | key | `Key` | - | |
354
+ ## useFieldCodeValidate
355
+ Возвращает функцию валидации значения кода (пусто / неполный код).
356
+ ### Props
357
+ | name | type | default value | description |
358
+ |------|------|---------------|-------------|
359
+ | codeLength* | `number` | - | Ожидаемая длина кода (цифр) |
354
360
  ## FieldCode
355
361
  ### Props
356
362
  | name | type | default value | description |
357
363
  |------|------|---------------|-------------|
358
- | codeLength* | `number` | - | Количество цифр в коде |
364
+ | codeLength* | `number` | - | Количество цифр в коде (ожидается целое ≥ 1) |
359
365
  | className | `string` | - | CSS-класс компонента |
360
366
  | cellClassName | `string` | - | CSS-класс ячейки кода |
361
367
  | spacing | `number[]` | - | Позиции, после которых нужно вставить пробел (индексы символов, после которых будет пробел) |
362
368
  | showEmptyChars | `boolean` | - | Подсветить пустые символы кода |
363
369
  | resendCode | `ResendCodeProps` | - | Компонент отправки нового кода |
364
370
  | focusEffects | `readonly FieldCodeFocusEffect[]` | - | Сценарии автофокуса; по умолчанию — первая ячейка при монтировании и после сброса (см. `FieldCodeFocusEffect`) |
371
+ | invalidCode | `string` | - | Сообщение при неверном коде, если не передан свой `error` |
365
372
  | value | `string` | - | Значение кода |
366
373
  | onChange | `(code: string) => void` | - | Колбек изменения значения |
367
374
  | onComplete | `(code: string) => void` | - | Колбек достижения ввода всех символов кода |
@@ -10,7 +10,8 @@ export type FieldCodeRef = {
10
10
  /** Сбросить значение кода */
11
11
  resetCode: () => void;
12
12
  };
13
- export type FieldCodeProps = {
13
+ /** Собственные пропсы `FieldCode` */
14
+ export type FieldCodeOwnProps = {
14
15
  /** CSS-класс компонента */
15
16
  className?: string;
16
17
  /** CSS-класс ячейки кода */
@@ -23,20 +24,10 @@ export type FieldCodeProps = {
23
24
  resendCode?: ResendCodeProps;
24
25
  /** Сценарии автофокуса; по умолчанию — первая ячейка при монтировании и после сброса (см. `FieldCodeFocusEffect`) */
25
26
  focusEffects?: readonly FieldCodeFocusEffect[];
26
- } & Omit<UseCodeInputParams, 'moveFocus'> & Pick<FieldDecoratorProps, 'size' | 'disabled' | 'label' | 'error' | 'data-test-id'>;
27
- export declare const FieldCode: import("react").ForwardRefExoticComponent<{
28
- /** CSS-класс компонента */
29
- className?: string;
30
- /** CSS-класс ячейки кода */
31
- cellClassName?: string;
32
- /** Позиции, после которых нужно вставить пробел (индексы символов, после которых будет пробел) */
33
- spacing?: number[];
34
- /** Подсветить пустые символы кода */
35
- showEmptyChars?: boolean;
36
- /** Компонент отправки нового кода */
37
- resendCode?: ResendCodeProps;
38
- /** Сценарии автофокуса; по умолчанию — первая ячейка при монтировании и после сброса (см. `FieldCodeFocusEffect`) */
39
- focusEffects?: readonly FieldCodeFocusEffect[];
40
- } & Omit<UseCodeInputParams, "moveFocus"> & Pick<FieldDecoratorProps, "size" | "label" | "error" | "disabled" | "data-test-id"> & import("react").RefAttributes<FieldCodeRef>>;
27
+ /** Сообщение при неверном коде, если не передан свой `error` */
28
+ invalidCode?: string;
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<FieldCodeOwnProps & Omit<UseCodeInputParams, "moveFocus"> & Pick<FieldDecoratorProps, "size" | "label" | "error" | "disabled" | "data-test-id"> & import("react").RefAttributes<FieldCodeRef>>;
41
32
  export type { FieldCodeFocusEffect } from './constants';
42
33
  export { FIELD_CODE_DEFAULT_FOCUS_EFFECTS } from './constants';
@@ -15,7 +15,7 @@ const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
15
15
  const utils_1 = require("./utils");
16
16
  exports.FieldCode = (0, react_1.forwardRef)(function FieldCode(props, ref) {
17
17
  var _a;
18
- const { codeLength, className, cellClassName, value, onChange, spacing, onComplete, size, disabled, label, error, showEmptyChars, resendCode, focusEffects = constants_1.FIELD_CODE_DEFAULT_FOCUS_EFFECTS, 'data-test-id': dataTestId, } = props;
18
+ const { codeLength, className, cellClassName, value, onChange, spacing, onComplete, size, disabled, label, error, invalidCode, showEmptyChars, resendCode, focusEffects = constants_1.FIELD_CODE_DEFAULT_FOCUS_EFFECTS, 'data-test-id': dataTestId, } = props;
19
19
  const { inputsRef, moveFocus, blurFields } = (0, hooks_1.useFocusCell)(codeLength);
20
20
  const { code, cellHandlers, onChangeCode } = (0, hooks_1.useCodeInput)({ value, onChange, codeLength, moveFocus, onComplete });
21
21
  const { resetCode } = (0, hooks_1.useFieldHelpers)({
@@ -31,17 +31,18 @@ exports.FieldCode = (0, react_1.forwardRef)(function FieldCode(props, ref) {
31
31
  blurFields,
32
32
  resetCode,
33
33
  }), [moveFocus, blurFields, resetCode]);
34
+ const resolvedError = error !== null && error !== void 0 ? error : invalidCode;
34
35
  const resolvedDecoratorProps = {
35
36
  label,
36
37
  disabled,
37
38
  size,
38
- error,
39
+ error: resolvedError,
39
40
  };
40
41
  return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: (0, classnames_1.default)(styles_module_scss_1.default.fieldCode, className) }, (dataTestId ? { 'data-test-id': dataTestId } : undefined), { children: [(0, jsx_runtime_1.jsx)(fields_1.FieldDecorator, Object.assign({}, resolvedDecoratorProps, { children: (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.codeContainer, "data-size": size, children: code.map((char, index) => ((0, jsx_runtime_1.jsx)(components_1.Cell, { ref: inputRef => {
41
42
  if (inputRef) {
42
43
  inputsRef.current[index] = inputRef;
43
44
  }
44
- }, className: (0, classnames_1.default)((spacing === null || spacing === void 0 ? void 0 : spacing.includes(index)) && styles_module_scss_1.default.cellSpacing, cellClassName), 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(error)) }, index))) }) })), resendCode ? (0, jsx_runtime_1.jsx)(components_1.ResendCode, Object.assign({}, resendCode, { size: (_a = resendCode.size) !== null && _a !== void 0 ? _a : size })) : null] })));
45
+ }, className: (0, classnames_1.default)((spacing === null || spacing === void 0 ? void 0 : spacing.includes(index)) && styles_module_scss_1.default.cellSpacing, cellClassName), 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] })));
45
46
  });
46
47
  var constants_2 = require("./constants");
47
48
  Object.defineProperty(exports, "FIELD_CODE_DEFAULT_FOCUS_EFFECTS", { enumerable: true, get: function () { return constants_2.FIELD_CODE_DEFAULT_FOCUS_EFFECTS; } });
@@ -1,3 +1,4 @@
1
1
  export * from './useCodeInput';
2
+ export * from './useFieldCodeValidate';
2
3
  export * from './useFocusCell';
3
4
  export * from './useFieldHelpers';
@@ -15,5 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./useCodeInput"), exports);
18
+ __exportStar(require("./useFieldCodeValidate"), exports);
18
19
  __exportStar(require("./useFocusCell"), exports);
19
20
  __exportStar(require("./useFieldHelpers"), exports);
@@ -1,6 +1,6 @@
1
1
  import { ClipboardEvent, KeyboardEvent } from 'react';
2
2
  export type UseCodeInputParams = {
3
- /** Количество цифр в коде */
3
+ /** Количество цифр в коде (ожидается целое ≥ 1) */
4
4
  codeLength: number;
5
5
  /** Значение кода */
6
6
  value?: string;
@@ -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
+ }
@@ -1 +1,2 @@
1
1
  export * from './FieldCode';
2
+ export { useFieldCodeValidate, type UseFieldCodeValidateParams } from './hooks/useFieldCodeValidate';
@@ -14,4 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.useFieldCodeValidate = void 0;
17
18
  __exportStar(require("./FieldCode"), exports);
19
+ var useFieldCodeValidate_1 = require("./hooks/useFieldCodeValidate");
20
+ Object.defineProperty(exports, "useFieldCodeValidate", { enumerable: true, get: function () { return useFieldCodeValidate_1.useFieldCodeValidate; } });
@@ -10,7 +10,8 @@ export type FieldCodeRef = {
10
10
  /** Сбросить значение кода */
11
11
  resetCode: () => void;
12
12
  };
13
- export type FieldCodeProps = {
13
+ /** Собственные пропсы `FieldCode` */
14
+ export type FieldCodeOwnProps = {
14
15
  /** CSS-класс компонента */
15
16
  className?: string;
16
17
  /** CSS-класс ячейки кода */
@@ -23,20 +24,10 @@ export type FieldCodeProps = {
23
24
  resendCode?: ResendCodeProps;
24
25
  /** Сценарии автофокуса; по умолчанию — первая ячейка при монтировании и после сброса (см. `FieldCodeFocusEffect`) */
25
26
  focusEffects?: readonly FieldCodeFocusEffect[];
26
- } & Omit<UseCodeInputParams, 'moveFocus'> & Pick<FieldDecoratorProps, 'size' | 'disabled' | 'label' | 'error' | 'data-test-id'>;
27
- export declare const FieldCode: import("react").ForwardRefExoticComponent<{
28
- /** CSS-класс компонента */
29
- className?: string;
30
- /** CSS-класс ячейки кода */
31
- cellClassName?: string;
32
- /** Позиции, после которых нужно вставить пробел (индексы символов, после которых будет пробел) */
33
- spacing?: number[];
34
- /** Подсветить пустые символы кода */
35
- showEmptyChars?: boolean;
36
- /** Компонент отправки нового кода */
37
- resendCode?: ResendCodeProps;
38
- /** Сценарии автофокуса; по умолчанию — первая ячейка при монтировании и после сброса (см. `FieldCodeFocusEffect`) */
39
- focusEffects?: readonly FieldCodeFocusEffect[];
40
- } & Omit<UseCodeInputParams, "moveFocus"> & Pick<FieldDecoratorProps, "size" | "label" | "error" | "disabled" | "data-test-id"> & import("react").RefAttributes<FieldCodeRef>>;
27
+ /** Сообщение при неверном коде, если не передан свой `error` */
28
+ invalidCode?: string;
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<FieldCodeOwnProps & Omit<UseCodeInputParams, "moveFocus"> & Pick<FieldDecoratorProps, "size" | "label" | "error" | "disabled" | "data-test-id"> & import("react").RefAttributes<FieldCodeRef>>;
41
32
  export type { FieldCodeFocusEffect } from './constants';
42
33
  export { FIELD_CODE_DEFAULT_FOCUS_EFFECTS } from './constants';
@@ -9,7 +9,7 @@ import styles from './styles.module.css';
9
9
  import { getCellValidationState } from './utils';
10
10
  export const FieldCode = forwardRef(function FieldCode(props, ref) {
11
11
  var _a;
12
- const { codeLength, className, cellClassName, value, onChange, spacing, onComplete, size, disabled, label, error, showEmptyChars, resendCode, focusEffects = FIELD_CODE_DEFAULT_FOCUS_EFFECTS, 'data-test-id': dataTestId, } = props;
12
+ const { codeLength, className, cellClassName, value, onChange, spacing, onComplete, size, disabled, label, error, invalidCode, showEmptyChars, resendCode, focusEffects = FIELD_CODE_DEFAULT_FOCUS_EFFECTS, 'data-test-id': dataTestId, } = props;
13
13
  const { inputsRef, moveFocus, blurFields } = useFocusCell(codeLength);
14
14
  const { code, cellHandlers, onChangeCode } = useCodeInput({ value, onChange, codeLength, moveFocus, onComplete });
15
15
  const { resetCode } = useFieldHelpers({
@@ -25,16 +25,17 @@ export const FieldCode = forwardRef(function FieldCode(props, ref) {
25
25
  blurFields,
26
26
  resetCode,
27
27
  }), [moveFocus, blurFields, resetCode]);
28
+ const resolvedError = error !== null && error !== void 0 ? error : invalidCode;
28
29
  const resolvedDecoratorProps = {
29
30
  label,
30
31
  disabled,
31
32
  size,
32
- error,
33
+ error: resolvedError,
33
34
  };
34
35
  return (_jsxs("div", Object.assign({ className: cn(styles.fieldCode, className) }, (dataTestId ? { 'data-test-id': dataTestId } : undefined), { children: [_jsx(FieldDecorator, Object.assign({}, resolvedDecoratorProps, { children: _jsx("div", { className: styles.codeContainer, "data-size": size, children: code.map((char, index) => (_jsx(Cell, { ref: inputRef => {
35
36
  if (inputRef) {
36
37
  inputsRef.current[index] = inputRef;
37
38
  }
38
- }, className: cn((spacing === null || spacing === void 0 ? void 0 : spacing.includes(index)) && styles.cellSpacing, cellClassName), 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: getCellValidationState(char, showEmptyChars, Boolean(error)) }, index))) }) })), resendCode ? _jsx(ResendCode, Object.assign({}, resendCode, { size: (_a = resendCode.size) !== null && _a !== void 0 ? _a : size })) : null] })));
39
+ }, className: cn((spacing === null || spacing === void 0 ? void 0 : spacing.includes(index)) && styles.cellSpacing, cellClassName), 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: getCellValidationState(char, showEmptyChars, Boolean(resolvedError)) }, index))) }) })), resendCode ? _jsx(ResendCode, Object.assign({}, resendCode, { size: (_a = resendCode.size) !== null && _a !== void 0 ? _a : size })) : null] })));
39
40
  });
40
41
  export { FIELD_CODE_DEFAULT_FOCUS_EFFECTS } from './constants';
@@ -1,3 +1,4 @@
1
1
  export * from './useCodeInput';
2
+ export * from './useFieldCodeValidate';
2
3
  export * from './useFocusCell';
3
4
  export * from './useFieldHelpers';
@@ -1,3 +1,4 @@
1
1
  export * from './useCodeInput';
2
+ export * from './useFieldCodeValidate';
2
3
  export * from './useFocusCell';
3
4
  export * from './useFieldHelpers';
@@ -1,6 +1,6 @@
1
1
  import { ClipboardEvent, KeyboardEvent } from 'react';
2
2
  export type UseCodeInputParams = {
3
- /** Количество цифр в коде */
3
+ /** Количество цифр в коде (ожидается целое ≥ 1) */
4
4
  codeLength: number;
5
5
  /** Значение кода */
6
6
  value?: string;
@@ -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,21 @@
1
+ import { useCallback } from 'react';
2
+ import { useLocale } from '@cloud-ru/uikit-product-locale';
3
+ import { isNumberChar } from '../utils';
4
+ /**
5
+ * Возвращает функцию валидации значения кода (пусто / неполный код).
6
+ */
7
+ export function useFieldCodeValidate(params) {
8
+ const { codeLength } = params;
9
+ const { t } = useLocale('FieldsPredefined');
10
+ return useCallback((value) => {
11
+ const str = value != null ? String(value) : '';
12
+ const digits = str.split('').filter(isNumberChar).join('');
13
+ if (digits.length === 0) {
14
+ return t('FieldCode.required');
15
+ }
16
+ if (digits.length < codeLength) {
17
+ return t('FieldCode.minLength', { count: codeLength });
18
+ }
19
+ return undefined;
20
+ }, [codeLength, t]);
21
+ }
@@ -1 +1,2 @@
1
1
  export * from './FieldCode';
2
+ export { useFieldCodeValidate, type UseFieldCodeValidateParams } from './hooks/useFieldCodeValidate';
@@ -1 +1,2 @@
1
1
  export * from './FieldCode';
2
+ export { useFieldCodeValidate } from './hooks/useFieldCodeValidate';