@reformer/core 1.1.0-beta.6 → 1.1.0-beta.8

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 (80) hide show
  1. package/dist/behaviors-BRaiR-UY.js +528 -0
  2. package/dist/behaviors.d.ts +6 -2
  3. package/dist/behaviors.js +18 -227
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.js +3380 -10
  6. package/dist/validators-DjXtDVoE.js +455 -0
  7. package/dist/validators.d.ts +6 -2
  8. package/dist/validators.js +29 -281
  9. package/package.json +1 -1
  10. package/dist/core/behavior/behavior-applicator.js +0 -92
  11. package/dist/core/behavior/behavior-context.js +0 -43
  12. package/dist/core/behavior/behavior-registry.js +0 -198
  13. package/dist/core/behavior/behaviors/compute-from.js +0 -84
  14. package/dist/core/behavior/behaviors/copy-from.js +0 -64
  15. package/dist/core/behavior/behaviors/enable-when.js +0 -81
  16. package/dist/core/behavior/behaviors/index.js +0 -11
  17. package/dist/core/behavior/behaviors/reset-when.js +0 -63
  18. package/dist/core/behavior/behaviors/revalidate-when.js +0 -51
  19. package/dist/core/behavior/behaviors/sync-fields.js +0 -66
  20. package/dist/core/behavior/behaviors/transform-value.js +0 -110
  21. package/dist/core/behavior/behaviors/watch-field.js +0 -56
  22. package/dist/core/behavior/compose-behavior.js +0 -166
  23. package/dist/core/behavior/create-field-path.js +0 -69
  24. package/dist/core/behavior/index.js +0 -17
  25. package/dist/core/behavior/types.js +0 -7
  26. package/dist/core/context/form-context-impl.js +0 -37
  27. package/dist/core/factories/index.js +0 -6
  28. package/dist/core/factories/node-factory.js +0 -281
  29. package/dist/core/nodes/array-node.js +0 -534
  30. package/dist/core/nodes/field-node.js +0 -510
  31. package/dist/core/nodes/form-node.js +0 -343
  32. package/dist/core/nodes/group-node/field-registry.js +0 -215
  33. package/dist/core/nodes/group-node/index.js +0 -11
  34. package/dist/core/nodes/group-node/proxy-builder.js +0 -161
  35. package/dist/core/nodes/group-node/state-manager.js +0 -265
  36. package/dist/core/nodes/group-node.js +0 -770
  37. package/dist/core/types/deep-schema.js +0 -11
  38. package/dist/core/types/field-path.js +0 -4
  39. package/dist/core/types/form-context.js +0 -25
  40. package/dist/core/types/group-node-proxy.js +0 -31
  41. package/dist/core/types/index.js +0 -4
  42. package/dist/core/types/validation-schema.js +0 -10
  43. package/dist/core/utils/create-form.js +0 -24
  44. package/dist/core/utils/debounce.js +0 -197
  45. package/dist/core/utils/error-handler.js +0 -226
  46. package/dist/core/utils/field-path-navigator.js +0 -374
  47. package/dist/core/utils/index.js +0 -14
  48. package/dist/core/utils/registry-helpers.js +0 -79
  49. package/dist/core/utils/registry-stack.js +0 -86
  50. package/dist/core/utils/resources.js +0 -69
  51. package/dist/core/utils/subscription-manager.js +0 -214
  52. package/dist/core/utils/type-guards.js +0 -169
  53. package/dist/core/validation/core/apply-when.js +0 -41
  54. package/dist/core/validation/core/apply.js +0 -38
  55. package/dist/core/validation/core/index.js +0 -8
  56. package/dist/core/validation/core/validate-async.js +0 -45
  57. package/dist/core/validation/core/validate-tree.js +0 -43
  58. package/dist/core/validation/core/validate.js +0 -38
  59. package/dist/core/validation/field-path.js +0 -147
  60. package/dist/core/validation/index.js +0 -33
  61. package/dist/core/validation/validate-form.js +0 -152
  62. package/dist/core/validation/validation-applicator.js +0 -217
  63. package/dist/core/validation/validation-context.js +0 -75
  64. package/dist/core/validation/validation-registry.js +0 -298
  65. package/dist/core/validation/validators/array-validators.js +0 -86
  66. package/dist/core/validation/validators/date.js +0 -117
  67. package/dist/core/validation/validators/email.js +0 -60
  68. package/dist/core/validation/validators/index.js +0 -14
  69. package/dist/core/validation/validators/max-length.js +0 -60
  70. package/dist/core/validation/validators/max.js +0 -60
  71. package/dist/core/validation/validators/min-length.js +0 -60
  72. package/dist/core/validation/validators/min.js +0 -60
  73. package/dist/core/validation/validators/number.js +0 -90
  74. package/dist/core/validation/validators/pattern.js +0 -62
  75. package/dist/core/validation/validators/phone.js +0 -58
  76. package/dist/core/validation/validators/required.js +0 -69
  77. package/dist/core/validation/validators/url.js +0 -55
  78. package/dist/create-field-path-nXfTtl55.js +0 -283
  79. package/dist/hooks/useFormControl.js +0 -298
  80. package/dist/validation-context-cWXmh_Ho.js +0 -156
@@ -1,84 +0,0 @@
1
- /**
2
- * Вычисляемые поля
3
- *
4
- * @group Behaviors
5
- * @category Behavior Rules
6
- * @module behaviors/computeFrom
7
- */
8
- import { effect } from '@preact/signals-core';
9
- import { getCurrentBehaviorRegistry } from '../../utils/registry-helpers';
10
- /**
11
- * Автоматически вычисляет значение поля на основе других полей
12
- *
13
- * @group Behaviors
14
- * @category Behavior Rules
15
- *
16
- * @param sources - Массив полей-зависимостей
17
- * @param target - Поле для записи результата
18
- * @param computeFn - Функция вычисления (принимает объект с именами полей)
19
- * @param options - Опции
20
- *
21
- * @example
22
- * ```typescript
23
- * const schema: BehaviorSchemaFn<MyForm> = (path) => {
24
- * // Автоматический расчет минимального взноса
25
- * computeFrom(
26
- * [path.propertyValue],
27
- * path.initialPayment,
28
- * (values) => values.propertyValue ? values.propertyValue * 0.2 : null,
29
- * { debounce: 300 }
30
- * );
31
- *
32
- * // Общая стоимость = цена * количество
33
- * computeFrom(
34
- * [path.price, path.quantity],
35
- * path.total,
36
- * (values) => values.price * values.quantity
37
- * );
38
- * };
39
- * ```
40
- */
41
- export function computeFrom(
42
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
- sources, target, computeFn, options) {
44
- const { debounce, condition } = options || {};
45
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
- const handler = (form, _context, withDebounce) => {
47
- const targetNode = form.getFieldByPath(target.__path);
48
- if (!targetNode)
49
- return null;
50
- // Разрешаем source узлы
51
- const sourceNodes = sources
52
- .map((field) => form.getFieldByPath(field.__path))
53
- .filter((node) => node !== undefined);
54
- if (sourceNodes.length === 0)
55
- return null;
56
- return effect(() => {
57
- // Читаем значения всех source полей
58
- const sourceValues = sourceNodes.map((node) => node.value.value);
59
- withDebounce(() => {
60
- // Проверка условия
61
- if (condition) {
62
- const formValue = form.getValue();
63
- if (!condition(formValue))
64
- return;
65
- }
66
- // Создаем объект с именами полей для computeFn
67
- // computeFn ожидает объект вида { fieldName: value, ... }
68
- const sourceValuesObject = {};
69
- sources.forEach((source, index) => {
70
- // Извлекаем имя поля из пути (последний сегмент)
71
- const fieldName = source.__path.split('.').pop() || source.__path;
72
- sourceValuesObject[fieldName] = sourceValues[index];
73
- });
74
- // Вычисляем новое значение
75
- const computedValue = computeFn(sourceValuesObject);
76
- // Устанавливаем значение без триггера событий
77
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
- targetNode.setValue(computedValue, { emitEvent: false });
79
- });
80
- });
81
- };
82
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
- getCurrentBehaviorRegistry().register(handler, { debounce });
84
- }
@@ -1,64 +0,0 @@
1
- /**
2
- * Копирование значений между полями
3
- *
4
- * @group Behaviors
5
- * @category Behavior Rules
6
- * @module behaviors/copyFrom
7
- */
8
- import { watchField } from './watch-field';
9
- /**
10
- * Копирует значения из одного поля/группы в другое при выполнении условия
11
- *
12
- * @group Behaviors
13
- * @category Behavior Rules
14
- *
15
- * @param source - Откуда копировать
16
- * @param target - Куда копировать
17
- * @param options - Опции копирования
18
- *
19
- * @example
20
- * ```typescript
21
- * const schema: BehaviorSchemaFn<MyForm> = (path) => {
22
- * // Копировать адрес регистрации в адрес проживания
23
- * copyFrom(path.registrationAddress, path.residenceAddress, {
24
- * when: (form) => form.sameAsRegistration === true,
25
- * fields: 'all'
26
- * });
27
- * };
28
- * ```
29
- */
30
- export function copyFrom(source, target, options) {
31
- const { when, fields = 'all', transform, debounce } = options || {};
32
- watchField(source, (sourceValue, ctx) => {
33
- // Проверка условия
34
- if (when) {
35
- const formValue = ctx.form.getValue();
36
- if (!when(formValue))
37
- return;
38
- }
39
- // Трансформация значения
40
- const value = transform ? transform(sourceValue) : sourceValue;
41
- // Получаем target node
42
- const targetNode = ctx.form.getFieldByPath(target.__path);
43
- if (!targetNode)
44
- return;
45
- // Копирование
46
- if (fields === 'all' || !fields) {
47
- targetNode.setValue(value, { emitEvent: false });
48
- }
49
- else {
50
- // Частичное копирование для групп
51
- const patch = {};
52
- fields.forEach((key) => {
53
- if (sourceValue && typeof sourceValue === 'object') {
54
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
- patch[key] = sourceValue[key];
56
- }
57
- });
58
- if ('patchValue' in targetNode) {
59
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
- targetNode.patchValue(patch);
61
- }
62
- }
63
- }, { debounce });
64
- }
@@ -1,81 +0,0 @@
1
- /**
2
- * Условное включение/отключение полей
3
- *
4
- * @group Behaviors
5
- * @category Behavior Rules
6
- * @module behaviors/enableWhen
7
- */
8
- import { effect } from '@preact/signals-core';
9
- import { getCurrentBehaviorRegistry } from '../../utils/registry-helpers';
10
- /**
11
- * Условное включение поля на основе значений других полей
12
- *
13
- * @group Behaviors
14
- * @category Behavior Rules
15
- *
16
- * @param field - Поле для включения/выключения
17
- * @param condition - Функция условия (true = enable, false = disable)
18
- * @param options - Опции
19
- *
20
- * @example
21
- * ```typescript
22
- * const schema: BehaviorSchemaFn<MyForm> = (path) => {
23
- * // Включить поле только для ипотеки
24
- * enableWhen(path.propertyValue, (form) => form.loanType === 'mortgage', {
25
- * resetOnDisable: true
26
- * });
27
- * };
28
- * ```
29
- */
30
- export function enableWhen(
31
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
- field, condition, options) {
33
- const { debounce, resetOnDisable = false } = options || {};
34
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
- const handler = (form, _context, withDebounce) => {
36
- const targetNode = form.getFieldByPath(field.__path);
37
- if (!targetNode)
38
- return null;
39
- return effect(() => {
40
- const formValue = form.value.value;
41
- withDebounce(() => {
42
- const shouldEnable = condition(formValue);
43
- if (shouldEnable) {
44
- targetNode.enable();
45
- }
46
- else {
47
- targetNode.disable();
48
- if (resetOnDisable) {
49
- targetNode.reset();
50
- }
51
- }
52
- });
53
- });
54
- };
55
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
- getCurrentBehaviorRegistry().register(handler, { debounce });
57
- }
58
- /**
59
- * Условное выключение поля (инверсия enableWhen)
60
- *
61
- * @group Behaviors
62
- * @category Behavior Rules
63
- *
64
- * @param field - Поле для выключения
65
- * @param condition - Функция условия (true = disable, false = enable)
66
- * @param options - Опции
67
- *
68
- * @example
69
- * ```typescript
70
- * const schema: BehaviorSchemaFn<MyForm> = (path) => {
71
- * // Выключить поле для потребительского кредита
72
- * disableWhen(path.propertyValue, (form) => form.loanType === 'consumer');
73
- * };
74
- * ```
75
- */
76
- export function disableWhen(
77
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
- field, condition, options) {
79
- // Инвертируем условие
80
- enableWhen(field, (form) => !condition(form), options);
81
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * Behavior rules
3
- */
4
- export { copyFrom } from './copy-from';
5
- export { enableWhen, disableWhen } from './enable-when';
6
- export { computeFrom } from './compute-from';
7
- export { watchField } from './watch-field';
8
- export { revalidateWhen } from './revalidate-when';
9
- export { syncFields } from './sync-fields';
10
- export { resetWhen } from './reset-when';
11
- export { transformValue, createTransformer, transformers, } from './transform-value';
@@ -1,63 +0,0 @@
1
- /**
2
- * Условный сброс полей
3
- *
4
- * @group Behaviors
5
- * @category Behavior Rules
6
- * @module behaviors/resetWhen
7
- */
8
- import { effect } from '@preact/signals-core';
9
- import { getCurrentBehaviorRegistry } from '../../utils/registry-helpers';
10
- /**
11
- * Условный сброс поля при выполнении условия
12
- *
13
- * @group Behaviors
14
- * @category Behavior Rules
15
- *
16
- * @param field - Поле для сброса
17
- * @param condition - Функция условия (true = reset)
18
- * @param options - Опции
19
- *
20
- * @example
21
- * ```typescript
22
- * const schema: BehaviorSchemaFn<MyForm> = (path) => {
23
- * // Сбросить поле при изменении типа кредита
24
- * resetWhen(path.propertyValue, (form) => form.loanType !== 'mortgage');
25
- *
26
- * // Сбросить с кастомным значением
27
- * resetWhen(path.initialPayment, (form) => !form.propertyValue, {
28
- * resetValue: 0
29
- * });
30
- *
31
- * // Сбросить только если поле было изменено пользователем
32
- * resetWhen(path.carPrice, (form) => form.loanType !== 'car', {
33
- * onlyIfDirty: true
34
- * });
35
- * };
36
- * ```
37
- */
38
- export function resetWhen(field, condition, options) {
39
- const { debounce, resetValue = null, onlyIfDirty = false } = options || {};
40
- const handler = (form, _context, withDebounce) => {
41
- const targetNode = form.getFieldByPath(field.__path);
42
- if (!targetNode)
43
- return null;
44
- return effect(() => {
45
- const formValue = form.value.value;
46
- withDebounce(() => {
47
- const shouldReset = condition(formValue);
48
- if (shouldReset) {
49
- // Проверяем onlyIfDirty опцию
50
- if (onlyIfDirty && !targetNode.dirty.value) {
51
- return;
52
- }
53
- // Сбрасываем значение
54
- targetNode.setValue(resetValue);
55
- // Сбрасываем флаги dirty и touched
56
- targetNode.markAsPristine();
57
- targetNode.markAsUntouched();
58
- }
59
- });
60
- });
61
- };
62
- getCurrentBehaviorRegistry().register(handler, { debounce });
63
- }
@@ -1,51 +0,0 @@
1
- /**
2
- * Перевалидация полей при изменениях
3
- *
4
- * @group Behaviors
5
- * @category Behavior Rules
6
- * @module behaviors/revalidateWhen
7
- */
8
- import { effect } from '@preact/signals-core';
9
- import { getCurrentBehaviorRegistry } from '../../utils/registry-helpers';
10
- /**
11
- * Перевалидирует поле при изменении других полей
12
- *
13
- * @group Behaviors
14
- * @category Behavior Rules
15
- *
16
- * @param target - Поле для перевалидации
17
- * @param triggers - Поля-триггеры
18
- * @param options - Опции
19
- *
20
- * @example
21
- * ```typescript
22
- * const schema: BehaviorSchemaFn<MyForm> = (path) => {
23
- * // Перевалидировать initialPayment при изменении propertyValue
24
- * revalidateWhen(path.initialPayment, [path.propertyValue], {
25
- * debounce: 300
26
- * });
27
- * };
28
- * ```
29
- */
30
- export function revalidateWhen(target, triggers, options) {
31
- const { debounce } = options || {};
32
- const handler = (form, _context, withDebounce) => {
33
- const targetNode = form.getFieldByPath(target.__path);
34
- if (!targetNode)
35
- return null;
36
- const sourceNodes = triggers
37
- .map((field) => form.getFieldByPath(field.__path))
38
- .filter((node) => node !== undefined);
39
- if (sourceNodes.length === 0)
40
- return null;
41
- return effect(() => {
42
- // Отслеживаем изменения source полей
43
- sourceNodes.forEach((node) => node.value.value);
44
- withDebounce(() => {
45
- // Перезапускаем валидацию target поля
46
- targetNode.validate();
47
- });
48
- });
49
- };
50
- getCurrentBehaviorRegistry().register(handler, { debounce });
51
- }
@@ -1,66 +0,0 @@
1
- /**
2
- * Двусторонняя синхронизация полей
3
- *
4
- * @group Behaviors
5
- * @category Behavior Rules
6
- * @module behaviors/syncFields
7
- */
8
- import { effect } from '@preact/signals-core';
9
- import { getCurrentBehaviorRegistry } from '../../utils/registry-helpers';
10
- /**
11
- * Двусторонняя синхронизация двух полей
12
- *
13
- * @group Behaviors
14
- * @category Behavior Rules
15
- *
16
- * @param field1 - Первое поле
17
- * @param field2 - Второе поле
18
- * @param options - Опции
19
- *
20
- * @example
21
- * ```typescript
22
- * const schema: BehaviorSchemaFn<MyForm> = (path) => {
23
- * // Синхронизировать два поля
24
- * syncFields(path.email, path.emailCopy);
25
- * };
26
- * ```
27
- */
28
- export function syncFields(field1, field2, options) {
29
- const { debounce, transform } = options || {};
30
- const handler = (form, _context, withDebounce) => {
31
- const sourceNode = form.getFieldByPath(field1.__path);
32
- const targetNode = form.getFieldByPath(field2.__path);
33
- if (!sourceNode || !targetNode)
34
- return null;
35
- // Флаг для предотвращения циклических обновлений
36
- let isUpdating = false;
37
- const dispose1 = effect(() => {
38
- const sourceValue = sourceNode.value.value;
39
- if (isUpdating)
40
- return;
41
- withDebounce(() => {
42
- isUpdating = true;
43
- const finalValue = transform ? transform(sourceValue) : sourceValue;
44
- targetNode.setValue(finalValue, { emitEvent: false });
45
- isUpdating = false;
46
- });
47
- });
48
- const dispose2 = effect(() => {
49
- const targetValue = targetNode.value.value;
50
- if (isUpdating)
51
- return;
52
- withDebounce(() => {
53
- isUpdating = true;
54
- // Обратная синхронизация (без трансформации)
55
- sourceNode.setValue(targetValue, { emitEvent: false });
56
- isUpdating = false;
57
- });
58
- });
59
- // Возвращаем комбинированный cleanup
60
- return () => {
61
- dispose1();
62
- dispose2();
63
- };
64
- };
65
- getCurrentBehaviorRegistry().register(handler, { debounce });
66
- }
@@ -1,110 +0,0 @@
1
- /**
2
- * Трансформация значений полей
3
- *
4
- * @group Behaviors
5
- * @category Behavior Rules
6
- * @module behaviors/transformValue
7
- */
8
- import { watchField } from './watch-field';
9
- /**
10
- * Трансформация значения поля при изменении
11
- * Позволяет автоматически форматировать или преобразовывать значения
12
- *
13
- * @group Behaviors
14
- * @category Behavior Rules
15
- *
16
- * @param field - Поле для трансформации
17
- * @param transformer - Функция трансформации
18
- * @param options - Опции
19
- *
20
- * @example
21
- * ```typescript
22
- * const schema: BehaviorSchemaFn<MyForm> = (path) => {
23
- * // Автоматически переводить текст в верхний регистр
24
- * transformValue(path.code, (value) => value?.toUpperCase());
25
- *
26
- * // Форматировать номер телефона
27
- * transformValue(path.phone, (value) => {
28
- * if (!value) return value;
29
- * const digits = value.replace(/\D/g, '');
30
- * if (digits.length === 11) {
31
- * return `+7 (${digits.slice(1, 4)}) ${digits.slice(4, 7)}-${digits.slice(7, 9)}-${digits.slice(9)}`;
32
- * }
33
- * return value;
34
- * });
35
- *
36
- * // Удалять пробелы из email
37
- * transformValue(path.email, (value) => value?.trim().toLowerCase());
38
- *
39
- * // Округлять числа
40
- * transformValue(path.amount, (value) => {
41
- * return typeof value === 'number' ? Math.round(value) : value;
42
- * });
43
- * };
44
- * ```
45
- */
46
- export function transformValue(field, transformer, options) {
47
- const { onUserChangeOnly = false, emitEvent = true, debounce } = options || {};
48
- watchField(field, (currentValue, ctx) => {
49
- const targetNode = ctx.form.getFieldByPath(field.__path);
50
- if (!targetNode)
51
- return;
52
- // Если нужно трансформировать только при изменении пользователем
53
- if (onUserChangeOnly && !targetNode.touched.value) {
54
- return;
55
- }
56
- const transformedValue = transformer(currentValue);
57
- // Применяем трансформацию только если значение изменилось
58
- if (transformedValue !== currentValue) {
59
- targetNode.setValue(transformedValue, { emitEvent });
60
- }
61
- }, { debounce });
62
- }
63
- /**
64
- * Хелпер для создания переиспользуемых трансформаций
65
- *
66
- * @group Behaviors
67
- * @category Behavior Rules
68
- *
69
- * @example
70
- * ```typescript
71
- * // Создаем переиспользуемые трансформеры
72
- * const toUpperCase = createTransformer<string>((value) => value?.toUpperCase());
73
- * const toLowerCase = createTransformer<string>((value) => value?.toLowerCase());
74
- * const trim = createTransformer<string>((value) => value?.trim());
75
- *
76
- * // Используем в форме
77
- * const schema: BehaviorSchemaFn<MyForm> = (path) => {
78
- * toUpperCase(path.code);
79
- * toLowerCase(path.email);
80
- * trim(path.username);
81
- * };
82
- * ```
83
- */
84
- export function createTransformer(transformer, defaultOptions) {
85
- return (field, options) => {
86
- transformValue(field, transformer, { ...defaultOptions, ...options });
87
- };
88
- }
89
- /**
90
- * Готовые трансформеры для частых случаев
91
- *
92
- * @group Behaviors
93
- * @category Behavior Rules
94
- */
95
- export const transformers = {
96
- /** Перевести в верхний регистр */
97
- toUpperCase: createTransformer((value) => value?.toUpperCase()),
98
- /** Перевести в нижний регистр */
99
- toLowerCase: createTransformer((value) => value?.toLowerCase()),
100
- /** Удалить пробелы с краев */
101
- trim: createTransformer((value) => value?.trim()),
102
- /** Удалить все пробелы */
103
- removeSpaces: createTransformer((value) => value?.replace(/\s/g, '')),
104
- /** Оставить только цифры */
105
- digitsOnly: createTransformer((value) => value?.replace(/\D/g, '')),
106
- /** Округлить число */
107
- round: createTransformer((value) => typeof value === 'number' ? Math.round(value) : value),
108
- /** Округлить до 2 знаков после запятой */
109
- roundTo2: createTransformer((value) => typeof value === 'number' ? Math.round(value * 100) / 100 : value),
110
- };
@@ -1,56 +0,0 @@
1
- /**
2
- * Отслеживание изменений поля
3
- *
4
- * @group Behaviors
5
- * @category Behavior Rules
6
- * @module behaviors/watchField
7
- */
8
- import { effect } from '@preact/signals-core';
9
- import { getCurrentBehaviorRegistry } from '../../utils/registry-helpers';
10
- /**
11
- * Выполняет callback при изменении поля
12
- *
13
- * @group Behaviors
14
- * @category Behavior Rules
15
- *
16
- * @param field - Поле для отслеживания
17
- * @param callback - Функция обратного вызова
18
- * @param options - Опции
19
- *
20
- * @example
21
- * ```typescript
22
- * const schema: BehaviorSchemaFn<MyForm> = (path) => {
23
- * // Динамическая загрузка городов при изменении страны
24
- * watchField(path.registrationAddress.country, async (country, ctx) => {
25
- * if (country) {
26
- * const cities = await fetchCities(country);
27
- * ctx.updateComponentProps(path.registrationAddress.city, {
28
- * options: cities
29
- * });
30
- * }
31
- * });
32
- * };
33
- * ```
34
- */
35
- export function watchField(field, callback, options) {
36
- const { debounce, immediate = false } = options || {};
37
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
- const handler = (form, context, withDebounce) => {
39
- const node = form.getFieldByPath(field.__path);
40
- if (!node)
41
- return null;
42
- // Вызвать сразу если immediate: true
43
- if (immediate) {
44
- const value = node.value.value;
45
- callback(value, context);
46
- }
47
- return effect(() => {
48
- const value = node.value.value;
49
- withDebounce(() => {
50
- callback(value, context);
51
- });
52
- });
53
- };
54
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
- getCurrentBehaviorRegistry().register(handler, { debounce });
56
- }