@reformer/core 1.1.0 → 2.0.0-beta.3
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/dist/behaviors-DzYL8kY_.js +499 -0
- package/dist/behaviors.d.ts +6 -2
- package/dist/behaviors.js +19 -227
- package/dist/core/behavior/behavior-context.d.ts +6 -2
- package/dist/core/behavior/create-field-path.d.ts +3 -16
- package/dist/core/nodes/group-node.d.ts +14 -193
- package/dist/core/types/form-context.d.ts +10 -4
- package/dist/core/utils/field-path.d.ts +48 -0
- package/dist/core/utils/index.d.ts +1 -0
- package/dist/core/validation/core/validate-tree.d.ts +10 -4
- package/dist/core/validation/field-path.d.ts +3 -39
- package/dist/core/validation/validation-context.d.ts +23 -0
- package/dist/hooks/types.d.ts +328 -0
- package/dist/hooks/useFormControl.d.ts +13 -37
- package/dist/hooks/useFormControlValue.d.ts +167 -0
- package/dist/hooks/useSignalSubscription.d.ts +17 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +2886 -8
- package/dist/{create-field-path-CdPF3lIK.js → registry-helpers-BRxAr6nG.js} +133 -347
- package/dist/validators-gXoHPdqM.js +418 -0
- package/dist/validators.d.ts +6 -2
- package/dist/validators.js +29 -296
- package/llms.txt +1283 -22
- package/package.json +8 -4
- package/dist/core/behavior/behavior-applicator.d.ts +0 -71
- package/dist/core/behavior/behavior-applicator.js +0 -92
- package/dist/core/behavior/behavior-context.js +0 -38
- package/dist/core/behavior/behavior-registry.js +0 -198
- package/dist/core/behavior/behaviors/compute-from.js +0 -84
- package/dist/core/behavior/behaviors/copy-from.js +0 -64
- package/dist/core/behavior/behaviors/enable-when.js +0 -81
- package/dist/core/behavior/behaviors/index.js +0 -11
- package/dist/core/behavior/behaviors/reset-when.js +0 -63
- package/dist/core/behavior/behaviors/revalidate-when.js +0 -51
- package/dist/core/behavior/behaviors/sync-fields.js +0 -66
- package/dist/core/behavior/behaviors/transform-value.js +0 -110
- package/dist/core/behavior/behaviors/watch-field.js +0 -56
- package/dist/core/behavior/compose-behavior.js +0 -166
- package/dist/core/behavior/create-field-path.js +0 -69
- package/dist/core/behavior/index.js +0 -17
- package/dist/core/behavior/types.js +0 -7
- package/dist/core/context/form-context-impl.js +0 -37
- package/dist/core/factories/index.js +0 -6
- package/dist/core/factories/node-factory.js +0 -281
- package/dist/core/nodes/array-node.js +0 -534
- package/dist/core/nodes/field-node.js +0 -510
- package/dist/core/nodes/form-node.js +0 -343
- package/dist/core/nodes/group-node/field-registry.d.ts +0 -191
- package/dist/core/nodes/group-node/field-registry.js +0 -215
- package/dist/core/nodes/group-node/index.d.ts +0 -11
- package/dist/core/nodes/group-node/index.js +0 -11
- package/dist/core/nodes/group-node/proxy-builder.d.ts +0 -71
- package/dist/core/nodes/group-node/proxy-builder.js +0 -161
- package/dist/core/nodes/group-node/state-manager.d.ts +0 -184
- package/dist/core/nodes/group-node/state-manager.js +0 -265
- package/dist/core/nodes/group-node.js +0 -770
- package/dist/core/types/deep-schema.js +0 -11
- package/dist/core/types/field-path.js +0 -4
- package/dist/core/types/form-context.js +0 -25
- package/dist/core/types/group-node-proxy.js +0 -31
- package/dist/core/types/index.js +0 -4
- package/dist/core/types/validation-schema.js +0 -10
- package/dist/core/utils/create-form.js +0 -24
- package/dist/core/utils/debounce.js +0 -197
- package/dist/core/utils/error-handler.js +0 -226
- package/dist/core/utils/field-path-navigator.js +0 -374
- package/dist/core/utils/index.js +0 -14
- package/dist/core/utils/registry-helpers.js +0 -79
- package/dist/core/utils/registry-stack.js +0 -86
- package/dist/core/utils/resources.js +0 -69
- package/dist/core/utils/subscription-manager.js +0 -214
- package/dist/core/utils/type-guards.js +0 -169
- package/dist/core/validation/core/apply-when.js +0 -41
- package/dist/core/validation/core/apply.js +0 -38
- package/dist/core/validation/core/index.js +0 -8
- package/dist/core/validation/core/validate-async.js +0 -45
- package/dist/core/validation/core/validate-tree.js +0 -37
- package/dist/core/validation/core/validate.js +0 -38
- package/dist/core/validation/field-path.js +0 -147
- package/dist/core/validation/index.js +0 -33
- package/dist/core/validation/validate-form.js +0 -152
- package/dist/core/validation/validation-applicator.js +0 -217
- package/dist/core/validation/validation-context.js +0 -75
- package/dist/core/validation/validation-registry.js +0 -298
- package/dist/core/validation/validators/array-validators.js +0 -86
- package/dist/core/validation/validators/date.js +0 -117
- package/dist/core/validation/validators/email.js +0 -60
- package/dist/core/validation/validators/index.js +0 -14
- package/dist/core/validation/validators/max-length.js +0 -60
- package/dist/core/validation/validators/max.js +0 -60
- package/dist/core/validation/validators/min-length.js +0 -60
- package/dist/core/validation/validators/min.js +0 -60
- package/dist/core/validation/validators/number.js +0 -90
- package/dist/core/validation/validators/pattern.js +0 -62
- package/dist/core/validation/validators/phone.js +0 -58
- package/dist/core/validation/validators/required.js +0 -69
- package/dist/core/validation/validators/url.js +0 -55
- package/dist/hooks/useFormControl.js +0 -298
- package/dist/node-factory-D7DOnSSN.js +0 -3200
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { FieldNode } from '../core/nodes/field-node';
|
|
2
|
+
import type { FormValue } from '../core/types';
|
|
3
|
+
/**
|
|
4
|
+
* React-хук для подписки только на значение поля.
|
|
5
|
+
*
|
|
6
|
+
* Оптимизированная версия {@link useFormControl}, которая подписывается
|
|
7
|
+
* только на сигнал `value`. Компонент не будет ре-рендериться при изменении
|
|
8
|
+
* `errors`, `touched`, `valid` и других свойств состояния.
|
|
9
|
+
*
|
|
10
|
+
* ## Когда использовать
|
|
11
|
+
*
|
|
12
|
+
* - **Условный рендеринг** на основе значения другого поля
|
|
13
|
+
* - **Вычисляемые значения** зависящие от значения поля
|
|
14
|
+
* - **Read-only отображение** значения без интерактивности
|
|
15
|
+
* - **Оптимизация производительности** когда не нужны другие свойства состояния
|
|
16
|
+
*
|
|
17
|
+
* ## Когда НЕ использовать
|
|
18
|
+
*
|
|
19
|
+
* Если компоненту нужны `errors`, `touched`, `disabled` или другие свойства -
|
|
20
|
+
* используйте {@link useFormControl}. Множественные подписки на один контрол
|
|
21
|
+
* через разные хуки менее эффективны, чем одна подписка через `useFormControl`.
|
|
22
|
+
*
|
|
23
|
+
* @typeParam T - Тип значения поля
|
|
24
|
+
* @param control - FieldNode для подписки на значение
|
|
25
|
+
* @returns Текущее значение поля
|
|
26
|
+
*
|
|
27
|
+
* @example Условный рендеринг секции
|
|
28
|
+
* ```tsx
|
|
29
|
+
* import { useFormControlValue } from '@reformer/core';
|
|
30
|
+
*
|
|
31
|
+
* interface FormFields {
|
|
32
|
+
* hasShipping: FieldNode<boolean>;
|
|
33
|
+
* shippingAddress: GroupNode<AddressFields>;
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* function ShippingSection({ form }: { form: FormFields }) {
|
|
37
|
+
* // Подписка только на значение checkbox
|
|
38
|
+
* const hasShipping = useFormControlValue(form.hasShipping);
|
|
39
|
+
*
|
|
40
|
+
* if (!hasShipping) {
|
|
41
|
+
* return null;
|
|
42
|
+
* }
|
|
43
|
+
*
|
|
44
|
+
* return (
|
|
45
|
+
* <div className="shipping-section">
|
|
46
|
+
* <h3>Shipping Address</h3>
|
|
47
|
+
* <AddressForm control={form.shippingAddress} />
|
|
48
|
+
* </div>
|
|
49
|
+
* );
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @example Динамические опции на основе другого поля
|
|
54
|
+
* ```tsx
|
|
55
|
+
* interface FormFields {
|
|
56
|
+
* country: FieldNode<string>;
|
|
57
|
+
* city: FieldNode<string>;
|
|
58
|
+
* }
|
|
59
|
+
*
|
|
60
|
+
* function CitySelect({ form }: { form: FormFields }) {
|
|
61
|
+
* const country = useFormControlValue(form.country);
|
|
62
|
+
* const { value, disabled } = useFormControl(form.city);
|
|
63
|
+
*
|
|
64
|
+
* // Получаем города для выбранной страны
|
|
65
|
+
* const cities = useMemo(() => getCitiesForCountry(country), [country]);
|
|
66
|
+
*
|
|
67
|
+
* // Сбрасываем город при смене страны
|
|
68
|
+
* useEffect(() => {
|
|
69
|
+
* form.city.setValue('');
|
|
70
|
+
* }, [country, form.city]);
|
|
71
|
+
*
|
|
72
|
+
* return (
|
|
73
|
+
* <select
|
|
74
|
+
* value={value}
|
|
75
|
+
* disabled={disabled || !country}
|
|
76
|
+
* onChange={e => form.city.setValue(e.target.value)}
|
|
77
|
+
* >
|
|
78
|
+
* <option value="">Select city...</option>
|
|
79
|
+
* {cities.map(city => (
|
|
80
|
+
* <option key={city.id} value={city.id}>{city.name}</option>
|
|
81
|
+
* ))}
|
|
82
|
+
* </select>
|
|
83
|
+
* );
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @example Отображение суммы в реальном времени
|
|
88
|
+
* ```tsx
|
|
89
|
+
* interface OrderItem {
|
|
90
|
+
* quantity: FieldNode<number>;
|
|
91
|
+
* price: FieldNode<number>;
|
|
92
|
+
* }
|
|
93
|
+
*
|
|
94
|
+
* function OrderTotal({ items }: { items: ArrayNode<OrderItem> }) {
|
|
95
|
+
* // Для каждого элемента получаем только значения
|
|
96
|
+
* const quantities = items.map(item => useFormControlValue(item.controls.quantity));
|
|
97
|
+
* const prices = items.map(item => useFormControlValue(item.controls.price));
|
|
98
|
+
*
|
|
99
|
+
* const total = quantities.reduce((sum, qty, i) => sum + qty * prices[i], 0);
|
|
100
|
+
*
|
|
101
|
+
* return (
|
|
102
|
+
* <div className="order-total">
|
|
103
|
+
* <strong>Total: ${total.toFixed(2)}</strong>
|
|
104
|
+
* </div>
|
|
105
|
+
* );
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @example Preview значения
|
|
110
|
+
* ```tsx
|
|
111
|
+
* interface MarkdownEditorProps {
|
|
112
|
+
* control: FieldNode<string>;
|
|
113
|
+
* }
|
|
114
|
+
*
|
|
115
|
+
* function MarkdownPreview({ control }: MarkdownEditorProps) {
|
|
116
|
+
* // Подписка только на значение для preview
|
|
117
|
+
* const markdown = useFormControlValue(control);
|
|
118
|
+
*
|
|
119
|
+
* const html = useMemo(() => marked(markdown), [markdown]);
|
|
120
|
+
*
|
|
121
|
+
* return (
|
|
122
|
+
* <div
|
|
123
|
+
* className="markdown-preview"
|
|
124
|
+
* dangerouslySetInnerHTML={{ __html: html }}
|
|
125
|
+
* />
|
|
126
|
+
* );
|
|
127
|
+
* }
|
|
128
|
+
*
|
|
129
|
+
* // Основной редактор использует useFormControl для полного состояния
|
|
130
|
+
* function MarkdownEditor({ control }: MarkdownEditorProps) {
|
|
131
|
+
* const { value, shouldShowError, errors } = useFormControl(control);
|
|
132
|
+
*
|
|
133
|
+
* return (
|
|
134
|
+
* <div className="editor-container">
|
|
135
|
+
* <textarea
|
|
136
|
+
* value={value}
|
|
137
|
+
* onChange={e => control.setValue(e.target.value)}
|
|
138
|
+
* />
|
|
139
|
+
* {shouldShowError && <span className="error">{errors[0]?.message}</span>}
|
|
140
|
+
*
|
|
141
|
+
* {/* Preview обновляется только при изменении value *}
|
|
142
|
+
* <MarkdownPreview control={control} />
|
|
143
|
+
* </div>
|
|
144
|
+
* );
|
|
145
|
+
* }
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* @example Счётчик символов
|
|
149
|
+
* ```tsx
|
|
150
|
+
* function CharacterCounter({ control, max }: { control: FieldNode<string>; max: number }) {
|
|
151
|
+
* const value = useFormControlValue(control);
|
|
152
|
+
* const remaining = max - value.length;
|
|
153
|
+
*
|
|
154
|
+
* return (
|
|
155
|
+
* <span className={remaining < 20 ? 'warning' : ''}>
|
|
156
|
+
* {remaining} characters remaining
|
|
157
|
+
* </span>
|
|
158
|
+
* );
|
|
159
|
+
* }
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* @see {@link useFormControl} - для полного состояния поля
|
|
163
|
+
* @see {@link FieldNode} - тип контрола поля
|
|
164
|
+
*
|
|
165
|
+
* @group React Hooks
|
|
166
|
+
*/
|
|
167
|
+
export declare function useFormControlValue<T extends FormValue>(control: FieldNode<T>): T;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type Signal } from '@preact/signals-core';
|
|
2
|
+
/** @internal */
|
|
3
|
+
export type SignalMap = Record<string, Signal<unknown>>;
|
|
4
|
+
/** @internal */
|
|
5
|
+
export type ExtractSignalValues<T extends SignalMap> = {
|
|
6
|
+
[K in keyof T]: T[K] extends Signal<infer V> ? V : never;
|
|
7
|
+
};
|
|
8
|
+
/** @internal */
|
|
9
|
+
export interface SignalConfig<K extends string> {
|
|
10
|
+
key: K;
|
|
11
|
+
useShallowArrayEqual?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Хук для подписки на набор сигналов с кешированием
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export declare function useSignalSubscription<TSignals extends SignalMap, TSnapshot extends ExtractSignalValues<TSignals>>(signals: TSignals, configs: SignalConfig<Extract<keyof TSignals, string>>[], buildSnapshot: (values: ExtractSignalValues<TSignals>) => TSnapshot): TSnapshot;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,10 @@ export { FieldNode } from './core/nodes/field-node';
|
|
|
6
6
|
export { GroupNode } from './core/nodes/group-node';
|
|
7
7
|
export { ArrayNode } from './core/nodes/array-node';
|
|
8
8
|
export type { SetValueOptions } from './core/nodes/form-node';
|
|
9
|
-
export { useFormControl
|
|
9
|
+
export { useFormControl } from './hooks/useFormControl';
|
|
10
|
+
export { useFormControlValue } from './hooks/useFormControlValue';
|
|
11
|
+
export type { FieldControlState, ArrayControlState } from './hooks/types';
|
|
10
12
|
export type { BehaviorSchemaFn } from './core/behavior/types';
|
|
13
|
+
export { validateForm } from './core/validation/validate-form';
|
|
14
|
+
export * as behaviors from './core/behavior';
|
|
15
|
+
export * as validators from './core/validation';
|