@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,166 +0,0 @@
1
- /**
2
- * Композиция behavior схем
3
- *
4
- * Предоставляет функции для переиспользования behavior схем:
5
- * - toBehaviorFieldPath: преобразование FieldPath во вложенный путь
6
- * - apply: применение схемы к полям
7
- * - applyWhen: условное применение схемы
8
- *
9
- * Аналог toFieldPath и applyWhen из validation API.
10
- */
11
- import { createFieldPath } from './create-field-path';
12
- import { watchField } from './behaviors/watch-field';
13
- // ============================================================================
14
- // toBehaviorFieldPath - Преобразование FieldPath во вложенный путь
15
- // ============================================================================
16
- /**
17
- * Преобразовать FieldPath во вложенный путь для композиции behavior схем
18
- *
19
- * Аналог toFieldPath из validation API.
20
- *
21
- * @param fieldPath - Поле для преобразования
22
- * @returns Вложенный FieldPath
23
- *
24
- * @example
25
- * ```typescript
26
- * // address-behavior.ts
27
- * export const addressBehavior = (path: FieldPath<Address>) => {
28
- * watchField(path.country, async (country, ctx) => {
29
- * const regions = await fetchRegions(country);
30
- * ctx.updateComponentProps(path.region, { options: regions });
31
- * });
32
- * };
33
- *
34
- * // user-behavior.ts
35
- * export const userBehavior = (path: FieldPath<User>) => {
36
- * // Композиция: применяем addressBehavior к вложенному полю
37
- * addressBehavior(toBehaviorFieldPath(path.address));
38
- * };
39
- * ```
40
- */
41
- export function toBehaviorFieldPath(fieldPath) {
42
- if (!fieldPath) {
43
- return createFieldPath();
44
- }
45
- const basePath = fieldPath.__path;
46
- return createNestedBehaviorFieldPath(basePath);
47
- }
48
- /**
49
- * Создать вложенный FieldPath с базовым префиксом
50
- * @private
51
- */
52
- function createNestedBehaviorFieldPath(basePath) {
53
- return new Proxy({}, {
54
- get(_target, prop) {
55
- if (typeof prop === 'symbol')
56
- return undefined;
57
- const fullPath = basePath ? `${basePath}.${prop}` : prop;
58
- return {
59
- __path: fullPath,
60
- __key: prop,
61
- };
62
- },
63
- });
64
- }
65
- // ============================================================================
66
- // apply - Применение behavior схемы к полям
67
- // ============================================================================
68
- /**
69
- * Применить behavior схему к вложенному полю или полям
70
- *
71
- * Поддерживает:
72
- * - Одно поле или массив полей
73
- * - Одну схему или массив схем
74
- * - Все комбинации (поле + схема, поле + схемы, поля + схема, поля + схемы)
75
- *
76
- * @param fields - Одно поле или массив полей
77
- * @param behaviors - Одна схема или массив схем
78
- *
79
- * @example
80
- * ```typescript
81
- * // Одна схема к одному полю
82
- * apply(path.registrationAddress, addressBehavior);
83
- *
84
- * // Одна схема к нескольким полям
85
- * apply([path.registrationAddress, path.residenceAddress], addressBehavior);
86
- *
87
- * // Несколько схем к одному полю
88
- * apply(path.properties, [propertyBehavior, arrayBehavior]);
89
- *
90
- * // Несколько схем к нескольким полям
91
- * apply(
92
- * [path.registrationAddress, path.residenceAddress],
93
- * [addressBehavior, validationBehavior]
94
- * );
95
- * ```
96
- */
97
- export function apply(fields, behaviors) {
98
- // Нормализуем inputs в массивы
99
- const fieldArray = (Array.isArray(fields) ? fields : [fields]).filter(Boolean);
100
- const behaviorArray = Array.isArray(behaviors) ? behaviors : [behaviors];
101
- // Применяем все схемы ко всем полям
102
- for (const field of fieldArray) {
103
- const nestedPath = toBehaviorFieldPath(field);
104
- for (const behavior of behaviorArray) {
105
- behavior(nestedPath);
106
- }
107
- }
108
- }
109
- // ============================================================================
110
- // applyWhen - Условное применение behavior схемы
111
- // ============================================================================
112
- /**
113
- * Условное применение behavior схем (аналог applyWhen из validation API)
114
- *
115
- * ⚠️ ВАЖНО: Эта функция НЕ создаёт новые behaviors при каждом изменении условия!
116
- * Вместо этого behaviors регистрируются ОДИН РАЗ при первом вызове и затем
117
- * просто не выполняются, если условие не выполнено.
118
- *
119
- * Это отличается от старой реализации, которая создавала утечку памяти,
120
- * регистрируя behaviors при каждом изменении conditionField.
121
- *
122
- * @param conditionField - Поле для проверки условия
123
- * @param condition - Функция проверки условия
124
- * @param callback - Callback для применения behavior схем
125
- *
126
- * @example
127
- * ```typescript
128
- * // Применить addressBehavior только когда sameAsRegistration === false
129
- * applyWhen(
130
- * path.sameAsRegistration,
131
- * (value) => value === false,
132
- * (path) => {
133
- * apply(path.residenceAddress, addressBehavior);
134
- * }
135
- * );
136
- *
137
- * // Или с прямым использованием path
138
- * applyWhen(
139
- * path.hasProperty,
140
- * (value) => value === true,
141
- * (path) => {
142
- * apply(path.properties, propertyBehavior);
143
- * // Можно применить несколько схем
144
- * apply([path.properties, path.items], arrayBehavior);
145
- * }
146
- * );
147
- * ```
148
- */
149
- export function applyWhen(conditionField, condition, callback) {
150
- if (!conditionField)
151
- return;
152
- // ИСПРАВЛЕНО: Регистрируем behaviors только ОДИН РАЗ
153
- // вне watchField callback, чтобы избежать утечки памяти
154
- let hasRegistered = false;
155
- watchField(conditionField, (value, _ctx) => {
156
- // Регистрируем behaviors только при первом срабатывании
157
- // когда условие выполнено
158
- if (!hasRegistered && condition(value)) {
159
- const fieldPath = createFieldPath();
160
- callback(fieldPath);
161
- hasRegistered = true;
162
- }
163
- // TODO: В будущем можно добавить поддержку деактивации behaviors
164
- // при изменении условия, но это требует изменений в BehaviorRegistry
165
- }, { immediate: true });
166
- }
@@ -1,69 +0,0 @@
1
- /**
2
- * Создание типизированного FieldPath для Behavior Schema
3
- * Аналогично createFieldPath из validators
4
- */
5
- /**
6
- * Создать типизированный путь к полям формы
7
- * Используется для декларативного описания behavior схем
8
- *
9
- * @example
10
- * ```typescript
11
- * const schema: BehaviorSchemaFn<MyForm> = (path) => {
12
- * // path.email, path.address.city и т.д. - типизированы
13
- * copyFrom(path.residenceAddress, path.registrationAddress, {
14
- * when: (form) => form.sameAsRegistration
15
- * });
16
- * };
17
- * ```
18
- */
19
- export function createFieldPath() {
20
- return createFieldPathProxy('');
21
- }
22
- /**
23
- * Создать Proxy для вложенного доступа к полям
24
- * @private
25
- */
26
- function createFieldPathProxy(currentPath) {
27
- return new Proxy(
28
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
- {}, {
30
- get(__target, prop) {
31
- // Поддержка обоих вариантов для обратной совместимости
32
- if (prop === '__path' || prop === '__fieldPath') {
33
- return currentPath || prop;
34
- }
35
- if (prop === '__key') {
36
- const parts = currentPath.split('.');
37
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
- return (parts[parts.length - 1] || prop);
39
- }
40
- const newPath = currentPath ? `${currentPath}.${prop}` : prop;
41
- // Создаем объект FieldPathNode с вложенным Proxy
42
- const node = {
43
- __path: newPath,
44
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
- __key: prop,
46
- __formType: undefined,
47
- __fieldType: undefined,
48
- };
49
- // Возвращаем Proxy, который поддерживает дальнейшую вложенность
50
- return new Proxy(node, {
51
- get(_target, nestedProp) {
52
- // Поддержка обоих вариантов для обратной совместимости
53
- if (nestedProp === '__path' || nestedProp === '__fieldPath') {
54
- return newPath;
55
- }
56
- if (nestedProp === '__key') {
57
- return prop;
58
- }
59
- if (nestedProp === '__formType' || nestedProp === '__fieldType') {
60
- return undefined;
61
- }
62
- // Для вложенных свойств создаем новый Proxy
63
- const nestedPath = `${newPath}.${nestedProp}`;
64
- return createFieldPathProxy(nestedPath);
65
- },
66
- });
67
- },
68
- });
69
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Behavior Schema API - Декларативное описание реактивного поведения форм
3
- *
4
- * @group Behaviors
5
- * @module behaviors
6
- */
7
- // Функции для декларативного описания поведения
8
- // Behaviors
9
- export * from './behaviors';
10
- // Композиция behavior схем (аналог toFieldPath из validation API)
11
- export { apply, applyWhen, toBehaviorFieldPath } from './compose-behavior';
12
- // Вспомогательные классы и функции
13
- // Примечание: BehaviorRegistry (глобальный singleton) был удален в пользу
14
- // локальных экземпляров BehaviorRegistry в каждом GroupNode
15
- export { BehaviorRegistry } from './behavior-registry';
16
- export { BehaviorContextImpl } from './behavior-context';
17
- export { createFieldPath } from './create-field-path';
@@ -1,7 +0,0 @@
1
- /**
2
- * Типы и интерфейсы для Behavior Schema API
3
- *
4
- * @group Behaviors
5
- * @category Behavior Types
6
- */
7
- export {};
@@ -1,37 +0,0 @@
1
- /**
2
- * Реализация единого FormContext
3
- *
4
- * Используется как базовая реализация для behavior и validation контекстов
5
- */
6
- /**
7
- * Базовая реализация FormContext
8
- *
9
- * Предоставляет:
10
- * - `form` - типизированный Proxy-доступ к форме
11
- * - `setFieldValue` - безопасная установка значения (emitEvent: false)
12
- */
13
- export class FormContextImpl {
14
- /**
15
- * Форма с типизированным Proxy-доступом к полям
16
- */
17
- form;
18
- _groupNode;
19
- constructor(groupNode) {
20
- this._groupNode = groupNode;
21
- // Используем _proxyInstance если доступен, иначе fallback
22
- this.form = (groupNode
23
- ._proxyInstance || groupNode.getProxy());
24
- }
25
- /**
26
- * Безопасно установить значение поля по строковому пути
27
- *
28
- * Автоматически использует emitEvent: false для предотвращения циклов
29
- */
30
- setFieldValue(path, value) {
31
- const node = this._groupNode.getFieldByPath(path);
32
- if (node) {
33
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
- node.setValue(value, { emitEvent: false });
35
- }
36
- }
37
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * Фабрики для создания узлов формы
3
- *
4
- * Централизованное место для всех фабрик и builder-паттернов.
5
- */
6
- export { NodeFactory } from './node-factory';
@@ -1,281 +0,0 @@
1
- /**
2
- * NodeFactory - фабрика для создания узлов формы
3
- *
4
- * Инкапсулирует логику определения типа конфига и создания соответствующего узла.
5
- * Используется в GroupNode и ArrayNode для создания дочерних узлов.
6
- *
7
- * Паттерн Factory Method упрощает создание узлов и делает код более читаемым:
8
- * - Вместо if-else в GroupNode/ArrayNode
9
- * - Единая точка для создания узлов
10
- * - Легко добавлять новые типы узлов
11
- *
12
- * @example
13
- * ```typescript
14
- * const factory = new NodeFactory();
15
- *
16
- * // Создание FieldNode
17
- * const field = factory.createNode({ value: '', component: Input });
18
- *
19
- * // Создание GroupNode
20
- * const group = factory.createNode({
21
- * email: { value: '', component: Input },
22
- * password: { value: '', component: Input }
23
- * });
24
- *
25
- * // Создание ArrayNode
26
- * const array = factory.createNode({
27
- * schema: { title: { value: '', component: Input } },
28
- * initialItems: []
29
- * });
30
- * ```
31
- */
32
- import { FieldNode } from '../nodes/field-node';
33
- import { GroupNode } from '../nodes/group-node';
34
- import { ArrayNode } from '../nodes/array-node';
35
- /**
36
- * Фабрика для создания узлов формы
37
- *
38
- * Определяет тип конфига и создает соответствующий узел (FieldNode, GroupNode, ArrayNode)
39
- */
40
- export class NodeFactory {
41
- /**
42
- * Создает узел формы на основе конфигурации
43
- *
44
- * ✅ ОБНОВЛЕНО: Теперь поддерживает массивы напрямую
45
- *
46
- * Автоматически определяет тип узла:
47
- * - FieldNode: имеет value и component
48
- * - ArrayNode: массив [schema, ...items] или { schema, initialItems }
49
- * - GroupNode: объект без value, component, schema
50
- *
51
- * @param config Конфигурация узла
52
- * @returns Экземпляр FieldNode, GroupNode или ArrayNode
53
- * @throws Error если конфиг не соответствует ни одному типу
54
- *
55
- * @example
56
- * ```typescript
57
- * const factory = new NodeFactory();
58
- *
59
- * // FieldNode
60
- * const field = factory.createNode({
61
- * value: 'test@mail.com',
62
- * component: Input,
63
- * validators: [required, email]
64
- * });
65
- *
66
- * // GroupNode
67
- * const group = factory.createNode({
68
- * email: { value: '', component: Input },
69
- * password: { value: '', component: Input }
70
- * });
71
- *
72
- * // ArrayNode (объект)
73
- * const array = factory.createNode({
74
- * schema: { title: { value: '', component: Input } },
75
- * initialItems: [{ title: 'Item 1' }]
76
- * });
77
- *
78
- * // ArrayNode (массив) - новый формат
79
- * const array2 = factory.createNode([
80
- * { title: { value: '', component: Input } }, // schema
81
- * { title: 'Item 1' }, // initial item 1
82
- * { title: 'Item 2' } // initial item 2
83
- * ]);
84
- * ```
85
- */
86
- createNode(config) {
87
- // 0. ✅ НОВОЕ: Проверка массива (приоритет: специфический формат)
88
- if (Array.isArray(config) && config.length >= 1) {
89
- return this.createArrayNodeFromArray(config);
90
- }
91
- // 1. Проверка FieldConfig (приоритет: самый специфичный тип)
92
- if (this.isFieldConfig(config)) {
93
- return new FieldNode(config);
94
- }
95
- // 2. Проверка ArrayConfig
96
- if (this.isArrayConfig(config)) {
97
- const arrayConfig = config;
98
- return new ArrayNode(arrayConfig.schema, arrayConfig.initialItems);
99
- }
100
- // 3. Проверка GroupConfig (самый общий тип)
101
- if (this.isGroupConfig(config)) {
102
- return new GroupNode(config);
103
- }
104
- // Неизвестный конфиг
105
- throw new Error(`NodeFactory: Unknown node config. Expected FieldConfig, GroupConfig, or ArrayConfig, but got: ${JSON.stringify(config)}`);
106
- }
107
- /**
108
- * Создать ArrayNode из массива [schema, ...initialItems]
109
- *
110
- * ✅ НОВОЕ: Извлечено из GroupNode для централизации логики
111
- *
112
- * Формат: [itemSchema, ...initialItems]
113
- * - Первый элемент - схема элемента массива
114
- * - Остальные элементы - начальные значения
115
- *
116
- * @param config Массив с схемой и начальными элементами
117
- * @returns ArrayNode
118
- *
119
- * @example
120
- * ```typescript
121
- * const factory = new NodeFactory();
122
- *
123
- * // Массив с начальными элементами
124
- * const array = factory.createArrayNodeFromArray([
125
- * { title: { value: '', component: Input } }, // schema
126
- * { title: 'Item 1' }, // initial value
127
- * { title: 'Item 2' } // initial value
128
- * ]);
129
- * ```
130
- * @private
131
- */
132
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
133
- createArrayNodeFromArray(config) {
134
- const [itemSchema, ...restItems] = config;
135
- // Обработка начальных элементов:
136
- // Если элемент - схема группы, извлечь значения
137
- const initialItems = [];
138
- // ИСПРАВЛЕНИЕ: Первый элемент является и схемой, и первым элементом данных
139
- // Если первый элемент имеет значения (GroupConfig с value), добавляем его как первый item
140
- if (this.isGroupConfig(itemSchema)) {
141
- initialItems.push(this.extractValues(itemSchema));
142
- }
143
- // Добавляем остальные элементы
144
- for (const item of restItems) {
145
- if (this.isGroupConfig(item)) {
146
- initialItems.push(this.extractValues(item));
147
- }
148
- else {
149
- initialItems.push(item);
150
- }
151
- }
152
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
153
- return new ArrayNode(itemSchema, initialItems);
154
- }
155
- /**
156
- * Извлечь значения из схемы (рекурсивно)
157
- *
158
- * ✅ НОВОЕ: Извлечено из GroupNode для централизации логики
159
- *
160
- * Преобразует схему формы в объект со значениями:
161
- * - `{ name: { value: 'John', component: Input } } → { name: 'John' }`
162
- * - Поддерживает вложенные группы
163
- * - Поддерживает массивы
164
- *
165
- * @param schema Схема формы
166
- * @returns Объект со значениями полей
167
- *
168
- * @example
169
- * ```typescript
170
- * const factory = new NodeFactory();
171
- *
172
- * const schema = {
173
- * name: { value: 'John', component: Input },
174
- * age: { value: 30, component: Input },
175
- * address: {
176
- * city: { value: 'Moscow', component: Input }
177
- * }
178
- * };
179
- *
180
- * factory.extractValues(schema);
181
- * // { name: 'John', age: 30, address: { city: 'Moscow' } }
182
- * ```
183
- */
184
- extractValues(schema) {
185
- // 1. FieldConfig - вернуть value
186
- if (this.isFieldConfig(schema)) {
187
- return schema.value;
188
- }
189
- // 2. Массив - рекурсивно обработать элементы
190
- if (Array.isArray(schema)) {
191
- return schema.map((item) => this.extractValues(item));
192
- }
193
- // 3. GroupConfig - рекурсивно извлечь значения всех полей
194
- if (this.isGroupConfig(schema)) {
195
- const result = {};
196
- for (const [key, config] of Object.entries(schema)) {
197
- result[key] = this.extractValues(config);
198
- }
199
- return result;
200
- }
201
- // 4. Примитивное значение - вернуть как есть
202
- return schema;
203
- }
204
- /**
205
- * Проверяет, является ли конфиг конфигурацией поля (FieldConfig)
206
- *
207
- * FieldConfig имеет обязательные свойства:
208
- * - value: начальное значение поля
209
- * - component: React-компонент для отображения
210
- *
211
- * @param config Проверяемая конфигурация
212
- * @returns true если config является FieldConfig
213
- *
214
- * @example
215
- * ```typescript
216
- * const factory = new NodeFactory();
217
- *
218
- * factory.isFieldConfig({ value: '', component: Input }); // true
219
- * factory.isFieldConfig({ email: { value: '' } }); // false
220
- * factory.isFieldConfig(null); // false
221
- * ```
222
- */
223
- isFieldConfig(config) {
224
- return (config != null && typeof config === 'object' && 'value' in config && 'component' in config);
225
- }
226
- /**
227
- * Проверяет, является ли конфиг конфигурацией массива (ArrayConfig)
228
- *
229
- * ArrayConfig имеет обязательное свойство:
230
- * - schema: схема для элементов массива
231
- *
232
- * И НЕ имеет:
233
- * - value (отличие от FieldConfig)
234
- *
235
- * @param config Проверяемая конфигурация
236
- * @returns true если config является ArrayConfig
237
- *
238
- * @example
239
- * ```typescript
240
- * const factory = new NodeFactory();
241
- *
242
- * factory.isArrayConfig({ schema: {}, initialItems: [] }); // true
243
- * factory.isArrayConfig({ value: '', component: Input }); // false
244
- * factory.isArrayConfig({ email: { value: '' } }); // false
245
- * ```
246
- */
247
- isArrayConfig(config) {
248
- return (config != null && typeof config === 'object' && 'schema' in config && !('value' in config));
249
- }
250
- /**
251
- * Проверяет, является ли конфиг конфигурацией группы (GroupConfig)
252
- *
253
- * GroupConfig - это объект, который:
254
- * - НЕ является FieldConfig (нет value/component)
255
- * - НЕ является ArrayConfig (нет schema)
256
- * - Содержит вложенные конфиги полей/групп/массивов
257
- *
258
- * @param config Проверяемая конфигурация
259
- * @returns true если config является GroupConfig
260
- *
261
- * @example
262
- * ```typescript
263
- * const factory = new NodeFactory();
264
- *
265
- * factory.isGroupConfig({
266
- * email: { value: '', component: Input },
267
- * password: { value: '', component: Input }
268
- * }); // true
269
- *
270
- * factory.isGroupConfig({ value: '', component: Input }); // false
271
- * factory.isGroupConfig({ schema: {} }); // false
272
- * factory.isGroupConfig(null); // false
273
- * ```
274
- */
275
- isGroupConfig(config) {
276
- return (config != null &&
277
- typeof config === 'object' &&
278
- !this.isFieldConfig(config) &&
279
- !this.isArrayConfig(config));
280
- }
281
- }