@reformer/core 11.0.0-beta.3 → 11.0.0-beta.4
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.d.ts +1 -1
- package/dist/behaviors.js +37 -37
- package/dist/create-model-Dxh9cfLp.js +97 -0
- package/dist/form/behaviors/collections.d.ts +50 -0
- package/dist/form/behaviors/context.d.ts +23 -0
- package/dist/form/behaviors/index.d.ts +28 -0
- package/dist/form/behaviors/internals.d.ts +26 -0
- package/dist/form/{behaviors-node.d.ts → behaviors/node.d.ts} +3 -3
- package/dist/form/behaviors/operators.d.ts +51 -0
- package/dist/form/behaviors/types.d.ts +17 -0
- package/dist/form/create-core-form.d.ts +3 -3
- package/dist/form/create-form.d.ts +1 -1
- package/dist/form/index.d.ts +10 -16
- package/dist/form/nodes/model-array-node.d.ts +1 -1
- package/dist/form/types/contracts.d.ts +9 -6
- package/dist/form/types/validation-schema.d.ts +1 -1
- package/dist/form/{validation-config.d.ts → validation/config.d.ts} +3 -3
- package/dist/form/validation/context.d.ts +27 -0
- package/dist/form/{error-handler.d.ts → validation/error-handler.d.ts} +1 -1
- package/dist/form/validation/index.d.ts +23 -28
- package/dist/form/validation/operators.d.ts +42 -0
- package/dist/form/validation/run.d.ts +45 -0
- package/dist/form/{validation-strategy.d.ts → validation/strategy.d.ts} +2 -2
- package/dist/form/validation/types.d.ts +28 -0
- package/dist/form/{validation/validators → validators}/date-utils.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/email.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/file-type.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/file-utils.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/future-date.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/index.d.ts +6 -4
- package/dist/form/{validation/validators → validators}/integer.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/is-date.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/is-number.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/max-age.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/max-date.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/max-file-size.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/max-files.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/max-length.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/max-total-file-size.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/max.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/min-age.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/min-date.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/min-file-size.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/min-files.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/min-length.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/min.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/multiple-of.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/non-negative.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/non-zero.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/past-date.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/pattern.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/phone.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/required.d.ts +1 -1
- package/dist/form/{validation/validators → validators}/url.d.ts +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.js +246 -71
- package/dist/{state/form-model.d.ts → model/create-model.d.ts} +0 -14
- package/dist/{state → model}/index.d.ts +10 -11
- package/dist/model/model-nodes.d.ts +60 -0
- package/dist/model/model-signals-proxy.d.ts +32 -0
- package/dist/model/model-value-proxy.d.ts +3 -0
- package/dist/{state → model}/safe-effect.d.ts +1 -1
- package/dist/model-signals-proxy-mV3WGdlO.js +233 -0
- package/dist/model.d.ts +2 -0
- package/dist/model.js +21 -0
- package/dist/{form → platforms/react}/hooks/types.d.ts +1 -1
- package/dist/{form → platforms/react}/hooks/use-form-bundle.d.ts +1 -1
- package/dist/{form → platforms/react}/hooks/use-form-validation.d.ts +3 -3
- package/dist/{form → platforms/react}/hooks/useArrayLength.d.ts +1 -1
- package/dist/{form → platforms/react}/hooks/useFormControl.d.ts +3 -3
- package/dist/{form → platforms/react}/hooks/useFormControlValue.d.ts +2 -2
- package/dist/platforms/react/index.d.ts +23 -0
- package/dist/signals.d.ts +1 -1
- package/dist/strategy-DA3JwxsR.js +170 -0
- package/dist/validation.d.ts +1 -1
- package/dist/validation.js +10 -165
- package/dist/validators/email.d.ts +1 -1
- package/dist/validators/future-date.d.ts +1 -1
- package/dist/validators/integer.d.ts +1 -1
- package/dist/validators/is-date.d.ts +1 -1
- package/dist/validators/is-number.d.ts +1 -1
- package/dist/validators/max-age.d.ts +1 -1
- package/dist/validators/max-date.d.ts +1 -1
- package/dist/validators/max-length.d.ts +1 -1
- package/dist/validators/max.d.ts +1 -1
- package/dist/validators/min-age.d.ts +1 -1
- package/dist/validators/min-date.d.ts +1 -1
- package/dist/validators/min-length.d.ts +1 -1
- package/dist/validators/min.d.ts +1 -1
- package/dist/validators/multiple-of.d.ts +1 -1
- package/dist/validators/non-negative.d.ts +1 -1
- package/dist/validators/non-zero.d.ts +1 -1
- package/dist/validators/past-date.d.ts +1 -1
- package/dist/validators/pattern.d.ts +1 -1
- package/dist/validators/phone.d.ts +1 -1
- package/dist/validators/required.d.ts +1 -1
- package/dist/validators/url.d.ts +1 -1
- package/dist/validators.d.ts +1 -1
- package/llms.txt +64 -43
- package/package.json +4 -4
- package/dist/form/behaviors.d.ts +0 -133
- package/dist/form/validation-schema.d.ts +0 -106
- package/dist/form/validators.d.ts +0 -11
- package/dist/form-model-DhW2HZOB.js +0 -323
- package/dist/state.d.ts +0 -2
- package/dist/state.js +0 -21
- package/dist/subscription-manager-705bls97.js +0 -171
- /package/dist/{state → form/nodes}/subscription-manager.d.ts +0 -0
- /package/dist/{state → model}/behaviors-value.d.ts +0 -0
- /package/dist/{state → model}/derived-registry.d.ts +0 -0
- /package/dist/{state → model}/types.d.ts +0 -0
- /package/dist/{behaviors-node-DGEFMTQu.js → node-DGEFMTQu.js} +0 -0
- /package/dist/{form → platforms/react}/hooks/useSignalSubscription.d.ts +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { PathAwareSignal } from './types';
|
|
2
|
+
import { ModelNode, GroupNode } from './model-nodes';
|
|
3
|
+
/**
|
|
4
|
+
* Узел дерева `$`: лист → сам {@link PathAwareSignal}, группа/массив → контейнерный узел —
|
|
5
|
+
* {@link ReadonlySignal} агрегированного значения ПЛЮС доступ к детям по имени/индексу.
|
|
6
|
+
*
|
|
7
|
+
* Порядок разрешения ключа: служебные `__path`/`__kind` → ребёнок → свойство сигнала. Дети идут
|
|
8
|
+
* раньше свойств сигнала — тот же приоритет, что у {@link makeFormModel} (поле формы затеняет метод
|
|
9
|
+
* API). Поэтому имена `value`/`peek`/`subscribe`/`valueOf`/`toString`/`toJSON`/`brand` де-факто
|
|
10
|
+
* зарезервированы: одноимённое поле формы затенит свойство сигнала (`subscribe` при этом продолжает
|
|
11
|
+
* работать — он замкнут на агрегат, а не читает `.value` через прокси).
|
|
12
|
+
*
|
|
13
|
+
* `has`/`ownKeys` намеренно НЕ показывают свойства сигнала — ровно как `__path`, доступный через
|
|
14
|
+
* `get`, но невидимый для `in`/`Object.keys`. Так `Object.keys(model.$.<group>)` остаётся списком
|
|
15
|
+
* полей, а потребители, перечисляющие модель, не видят служебных ключей.
|
|
16
|
+
*/
|
|
17
|
+
export declare function signalsProxy(node: ModelNode): any;
|
|
18
|
+
/**
|
|
19
|
+
* Узел дерева `model.$` — контейнер (группа/массив), а не лист?
|
|
20
|
+
*
|
|
21
|
+
* Контейнерный узел структурно совместим с `ReadonlySignal` (`peek`/`value`/`subscribe`), поэтому
|
|
22
|
+
* duck-typing «есть `peek` ⇒ это лист» на нём даёт ложное срабатывание. Этот guard — надёжный
|
|
23
|
+
* способ различить: обходчикам дерева нужно спускаться в контейнер, а не читать его целиком.
|
|
24
|
+
*
|
|
25
|
+
* @group Model
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const isLeaf = (v: unknown) => isSignalLike(v) && !isModelContainerSignal(v);
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function isModelContainerSignal(value: unknown): boolean;
|
|
32
|
+
export declare function resolveSignalAt(root: GroupNode, path: string): PathAwareSignal<unknown> | undefined;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { batch as m, signal as y, computed as b } from "@preact/signals-core";
|
|
2
|
+
const c = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
function R(t) {
|
|
4
|
+
c.set(t, (c.get(t) ?? 0) + 1);
|
|
5
|
+
}
|
|
6
|
+
function S(t) {
|
|
7
|
+
const e = c.get(t);
|
|
8
|
+
e !== void 0 && (e <= 1 ? c.delete(t) : c.set(t, e - 1));
|
|
9
|
+
}
|
|
10
|
+
function A(t) {
|
|
11
|
+
return c.has(t);
|
|
12
|
+
}
|
|
13
|
+
const f = (t) => !(t === null || typeof t != "object" || Array.isArray(t) || t instanceof Date || typeof Blob < "u" && t instanceof Blob || typeof File < "u" && t instanceof File), o = (t, e) => t === "" ? String(e) : `${t}.${e}`, w = (t) => /^\d+$/.test(t), l = (t) => {
|
|
14
|
+
if (Array.isArray(t)) return t.map(l);
|
|
15
|
+
if (f(t)) {
|
|
16
|
+
const e = {};
|
|
17
|
+
for (const i of Object.keys(t)) e[i] = l(t[i]);
|
|
18
|
+
return e;
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
}, h = (t, e) => {
|
|
22
|
+
if (t === e) return !0;
|
|
23
|
+
if (Array.isArray(t) && Array.isArray(e))
|
|
24
|
+
return t.length !== e.length ? !1 : t.every((i, r) => h(i, e[r]));
|
|
25
|
+
if (f(t) && f(e)) {
|
|
26
|
+
const i = Object.keys(t), r = Object.keys(e);
|
|
27
|
+
return i.length !== r.length ? !1 : i.every((s) => h(t[s], e[s]));
|
|
28
|
+
}
|
|
29
|
+
return !1;
|
|
30
|
+
};
|
|
31
|
+
class _ {
|
|
32
|
+
constructor(e, i) {
|
|
33
|
+
this.path = i;
|
|
34
|
+
const r = y(e);
|
|
35
|
+
r.__path = i, this.signal = r, this.initial = l(e);
|
|
36
|
+
}
|
|
37
|
+
kind = "leaf";
|
|
38
|
+
signal;
|
|
39
|
+
initial;
|
|
40
|
+
rebase(e) {
|
|
41
|
+
this.path = e, this.signal.__path = e;
|
|
42
|
+
}
|
|
43
|
+
/** Реактивное чтение (внутри effect/computed создаёт зависимость). */
|
|
44
|
+
read() {
|
|
45
|
+
return this.signal.value;
|
|
46
|
+
}
|
|
47
|
+
/** Нереактивный снимок. */
|
|
48
|
+
peek() {
|
|
49
|
+
return this.signal.peek();
|
|
50
|
+
}
|
|
51
|
+
set(e) {
|
|
52
|
+
this.signal.value = e;
|
|
53
|
+
}
|
|
54
|
+
resetToInitial() {
|
|
55
|
+
this.signal.value = l(this.initial);
|
|
56
|
+
}
|
|
57
|
+
captureInitial() {
|
|
58
|
+
this.initial = l(this.signal.peek());
|
|
59
|
+
}
|
|
60
|
+
dirty() {
|
|
61
|
+
return !h(this.signal.peek(), this.initial);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
class j {
|
|
65
|
+
constructor(e, i) {
|
|
66
|
+
this.path = i;
|
|
67
|
+
for (const r of Object.keys(e))
|
|
68
|
+
this.children.set(r, u(e[r], o(i, r)));
|
|
69
|
+
}
|
|
70
|
+
kind = "group";
|
|
71
|
+
children = /* @__PURE__ */ new Map();
|
|
72
|
+
rebase(e) {
|
|
73
|
+
this.path = e;
|
|
74
|
+
for (const [i, r] of this.children) r.rebase(o(e, i));
|
|
75
|
+
}
|
|
76
|
+
/** Реактивное чтение поддерева (внутри effect/computed подписывает на все листья группы). */
|
|
77
|
+
read() {
|
|
78
|
+
const e = {};
|
|
79
|
+
for (const [i, r] of this.children) e[i] = r.read();
|
|
80
|
+
return e;
|
|
81
|
+
}
|
|
82
|
+
peek() {
|
|
83
|
+
const e = {};
|
|
84
|
+
for (const [i, r] of this.children) e[i] = r.peek();
|
|
85
|
+
return e;
|
|
86
|
+
}
|
|
87
|
+
set(e) {
|
|
88
|
+
if (e == null || typeof e != "object") return;
|
|
89
|
+
const i = e;
|
|
90
|
+
m(() => {
|
|
91
|
+
for (const [r, s] of this.children)
|
|
92
|
+
r in i && (s.kind === "leaf" && A(s.signal) || s.set(i[r]));
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
resetToInitial() {
|
|
96
|
+
m(() => {
|
|
97
|
+
for (const e of this.children.values()) e.resetToInitial();
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
captureInitial() {
|
|
101
|
+
for (const e of this.children.values()) e.captureInitial();
|
|
102
|
+
}
|
|
103
|
+
dirty() {
|
|
104
|
+
for (const e of this.children.values()) if (e.dirty()) return !0;
|
|
105
|
+
return !1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
class x {
|
|
109
|
+
constructor(e, i) {
|
|
110
|
+
this.path = i, this.items = y(e.map((r, s) => u(r, o(i, s)))), this.initial = l(e);
|
|
111
|
+
}
|
|
112
|
+
kind = "array";
|
|
113
|
+
items;
|
|
114
|
+
initial;
|
|
115
|
+
rebase(e) {
|
|
116
|
+
this.path = e, this.items.peek().forEach((i, r) => i.rebase(o(e, r)));
|
|
117
|
+
}
|
|
118
|
+
reindex() {
|
|
119
|
+
this.items.peek().forEach((e, i) => e.rebase(o(this.path, i)));
|
|
120
|
+
}
|
|
121
|
+
push(e) {
|
|
122
|
+
const i = this.items.peek();
|
|
123
|
+
this.items.value = [...i, u(e, o(this.path, i.length))];
|
|
124
|
+
}
|
|
125
|
+
insertAt(e, i) {
|
|
126
|
+
const r = [...this.items.peek()];
|
|
127
|
+
r.splice(e, 0, u(i, o(this.path, e))), this.items.value = r, this.reindex();
|
|
128
|
+
}
|
|
129
|
+
removeAt(e) {
|
|
130
|
+
const i = [...this.items.peek()];
|
|
131
|
+
i.splice(e, 1), this.items.value = i, this.reindex();
|
|
132
|
+
}
|
|
133
|
+
move(e, i) {
|
|
134
|
+
const r = [...this.items.peek()], [s] = r.splice(e, 1);
|
|
135
|
+
s && r.splice(i, 0, s), this.items.value = r, this.reindex();
|
|
136
|
+
}
|
|
137
|
+
swap(e, i) {
|
|
138
|
+
const r = [...this.items.peek()];
|
|
139
|
+
e < 0 || i < 0 || e >= r.length || i >= r.length || e === i || ([r[e], r[i]] = [r[i], r[e]], this.items.value = r, this.reindex());
|
|
140
|
+
}
|
|
141
|
+
clear() {
|
|
142
|
+
this.items.value = [];
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Реактивное чтение массива. Читаем `items.value` (а не `.peek()`) — внутри effect/computed это
|
|
146
|
+
* подписка на СОСТАВ массива, поэтому push/removeAt/move ретригерят наравне с правкой элемента.
|
|
147
|
+
*/
|
|
148
|
+
read() {
|
|
149
|
+
return this.items.value.map((e) => e.read());
|
|
150
|
+
}
|
|
151
|
+
peek() {
|
|
152
|
+
return this.items.peek().map((e) => e.peek());
|
|
153
|
+
}
|
|
154
|
+
set(e) {
|
|
155
|
+
const i = Array.isArray(e) ? e : [];
|
|
156
|
+
this.items.value = i.map((r, s) => u(r, o(this.path, s)));
|
|
157
|
+
}
|
|
158
|
+
resetToInitial() {
|
|
159
|
+
this.set(l(this.initial));
|
|
160
|
+
}
|
|
161
|
+
captureInitial() {
|
|
162
|
+
this.initial = l(this.peek());
|
|
163
|
+
}
|
|
164
|
+
dirty() {
|
|
165
|
+
return !h(this.peek(), this.initial);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function u(t, e) {
|
|
169
|
+
return Array.isArray(t) ? new x(t, e) : f(t) ? new j(t, e) : new _(t, e);
|
|
170
|
+
}
|
|
171
|
+
const k = /* @__PURE__ */ new WeakMap();
|
|
172
|
+
function I(t) {
|
|
173
|
+
const e = b(() => t.read());
|
|
174
|
+
return {
|
|
175
|
+
get value() {
|
|
176
|
+
return e.value;
|
|
177
|
+
},
|
|
178
|
+
peek: () => e.peek(),
|
|
179
|
+
subscribe: (i) => e.subscribe(i),
|
|
180
|
+
valueOf: () => e.value,
|
|
181
|
+
toString: () => String(e.value),
|
|
182
|
+
toJSON: () => e.value,
|
|
183
|
+
brand: e.brand
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function O(t) {
|
|
187
|
+
if (t.kind === "leaf") return t.signal;
|
|
188
|
+
const e = k.get(t);
|
|
189
|
+
if (e) return e;
|
|
190
|
+
const i = I(t), r = t.kind === "group", s = (a) => r ? t.children.get(a) : w(a) ? t.items.value[Number(a)] : void 0, d = r ? {} : {
|
|
191
|
+
get length() {
|
|
192
|
+
return t.items.value.length;
|
|
193
|
+
}
|
|
194
|
+
}, p = new Proxy(d, {
|
|
195
|
+
get: (a, n, v) => {
|
|
196
|
+
if (n === "__path") return t.path;
|
|
197
|
+
if (n === "__kind") return t.kind;
|
|
198
|
+
if (typeof n != "string") return Reflect.get(i, n, i);
|
|
199
|
+
const g = s(n);
|
|
200
|
+
return g ? O(g) : !r && Reflect.has(a, n) ? Reflect.get(a, n, v) : Reflect.get(i, n, i);
|
|
201
|
+
},
|
|
202
|
+
has: (a, n) => typeof n == "string" && (s(n) !== void 0 || !r && Reflect.has(a, n)),
|
|
203
|
+
ownKeys: () => r ? [...t.children.keys()] : Reflect.ownKeys(d),
|
|
204
|
+
getOwnPropertyDescriptor: (a, n) => typeof n == "string" && s(n) ? { enumerable: !0, configurable: !0 } : r ? void 0 : Reflect.getOwnPropertyDescriptor(a, n)
|
|
205
|
+
});
|
|
206
|
+
return k.set(t, p), p;
|
|
207
|
+
}
|
|
208
|
+
function D(t) {
|
|
209
|
+
if (t == null || typeof t != "object") return !1;
|
|
210
|
+
const e = t.__kind;
|
|
211
|
+
return e === "group" || e === "array";
|
|
212
|
+
}
|
|
213
|
+
function P(t, e) {
|
|
214
|
+
if (!e) return;
|
|
215
|
+
let i = t;
|
|
216
|
+
for (const r of e.split(".")) {
|
|
217
|
+
if (!i) return;
|
|
218
|
+
if (i.kind === "group") i = i.children.get(r);
|
|
219
|
+
else if (i.kind === "array") i = i.items.peek()[Number(r)];
|
|
220
|
+
else return;
|
|
221
|
+
}
|
|
222
|
+
return i && i.kind === "leaf" ? i.signal : void 0;
|
|
223
|
+
}
|
|
224
|
+
export {
|
|
225
|
+
j as G,
|
|
226
|
+
A as a,
|
|
227
|
+
w as b,
|
|
228
|
+
D as i,
|
|
229
|
+
R as m,
|
|
230
|
+
P as r,
|
|
231
|
+
O as s,
|
|
232
|
+
S as u
|
|
233
|
+
};
|
package/dist/model.d.ts
ADDED
package/dist/model.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { c as s, e as r } from "./create-model-Dxh9cfLp.js";
|
|
2
|
+
import { a as i, i as t, m as c, u as l } from "./model-signals-proxy-mV3WGdlO.js";
|
|
3
|
+
import { c as n, a as f, r as m, b as u, d as p, e as b, f as h, s as k, t as v, w as D } from "./behaviors-value-C7dSEhCc.js";
|
|
4
|
+
export {
|
|
5
|
+
n as computeFrom,
|
|
6
|
+
f as copyFrom,
|
|
7
|
+
s as createModel,
|
|
8
|
+
r as eachLeafSignal,
|
|
9
|
+
i as isDerived,
|
|
10
|
+
t as isModelContainerSignal,
|
|
11
|
+
c as markDerived,
|
|
12
|
+
m as resetWhen,
|
|
13
|
+
u as revalidateWhen,
|
|
14
|
+
p as runOutsideEffect,
|
|
15
|
+
b as safeCallback,
|
|
16
|
+
h as safeDebouncedCallback,
|
|
17
|
+
k as syncFields,
|
|
18
|
+
v as transformValue,
|
|
19
|
+
l as unmarkDerived,
|
|
20
|
+
D as watchField
|
|
21
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FormValidationController } from '
|
|
1
|
+
import { FormValidationController } from '../../../form/validation/strategy';
|
|
2
2
|
/** Минимум, который хук ожидает от бандла: опциональный контроллер живой валидации. */
|
|
3
3
|
export interface FormBundleLike {
|
|
4
4
|
validation?: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { FormModel } from '
|
|
2
|
-
import { ValidationSchema } from '
|
|
3
|
-
import { ValidationStrategyKind } from '
|
|
1
|
+
import { FormModel } from '../../../index';
|
|
2
|
+
import { ValidationSchema } from '../../../form/validation';
|
|
3
|
+
import { ValidationStrategyKind } from '../../../form/validation/strategy';
|
|
4
4
|
export interface UseFormValidationArgs<T> {
|
|
5
5
|
/** Модель данных формы. */
|
|
6
6
|
model: FormModel<T>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { FieldNode } from '
|
|
2
|
-
import { ArrayNode } from '
|
|
3
|
-
import { FormValue } from '
|
|
1
|
+
import { FieldNode } from '../../../form/nodes/field-node';
|
|
2
|
+
import { ArrayNode } from '../../../form/nodes/array-node';
|
|
3
|
+
import { FormValue } from '../../../form/types/index';
|
|
4
4
|
import { FieldControlState, ArrayControlState } from './types';
|
|
5
5
|
/**
|
|
6
6
|
* React-хук для подписки на состояние {@link ArrayNode}.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FieldNode } from '
|
|
2
|
-
import { FormValue } from '
|
|
1
|
+
import { FieldNode } from '../../../form/nodes/field-node';
|
|
2
|
+
import { FormValue } from '../../../form/types/index';
|
|
3
3
|
/**
|
|
4
4
|
* React-хук для подписки только на значение поля.
|
|
5
5
|
*
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Модуль `platforms/react` — биндинги ядра к React.
|
|
3
|
+
*
|
|
4
|
+
* Единственное место в пакете, где есть runtime-зависимость от `react` и
|
|
5
|
+
* `use-sync-external-store`: слои `model` и `form` от React свободны (в `form/types/` остаются
|
|
6
|
+
* только type-only `ComponentType`/`ElementType` — они стираются при компиляции). Хуки читают
|
|
7
|
+
* сигналы нод формы через `useSyncExternalStore` и отдают плоские снапшоты
|
|
8
|
+
* ({@link FieldControlState}/{@link ArrayControlState}) в рендер.
|
|
9
|
+
*
|
|
10
|
+
* Barrel заведён как точка для будущего сабпата `@reformer/core/react`; сейчас его состав
|
|
11
|
+
* реэкспортируется зонтиком `@reformer/core` — ровно теми же именами, что и до выноса.
|
|
12
|
+
*
|
|
13
|
+
* @group Platforms
|
|
14
|
+
* @module platforms/react
|
|
15
|
+
*/
|
|
16
|
+
export { useFormControl } from './hooks/useFormControl';
|
|
17
|
+
export { useFormControlValue } from './hooks/useFormControlValue';
|
|
18
|
+
export { useArrayLength } from './hooks/useArrayLength';
|
|
19
|
+
export { useFormValidation } from './hooks/use-form-validation';
|
|
20
|
+
export type { UseFormValidationArgs, UseFormValidationResult } from './hooks/use-form-validation';
|
|
21
|
+
export { useFormBundle } from './hooks/use-form-bundle';
|
|
22
|
+
export type { FormBundleLike } from './hooks/use-form-bundle';
|
|
23
|
+
export type { FieldControlState, ArrayControlState } from './hooks/types';
|
package/dist/signals.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* пакетов — это критично для проверок вида `value instanceof Signal` над сигналами,
|
|
8
8
|
* созданными внутри @reformer/core.
|
|
9
9
|
*
|
|
10
|
-
* @module
|
|
10
|
+
* @module signals
|
|
11
11
|
*/
|
|
12
12
|
export { signal, computed, effect, batch, untracked, Signal } from '@preact/signals-core';
|
|
13
13
|
export type { ReadonlySignal } from '@preact/signals-core';
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { signal as A, effect as M } from "@preact/signals-core";
|
|
2
|
+
import { e as W } from "./create-model-Dxh9cfLp.js";
|
|
3
|
+
import { g as v } from "./signal-node-registry-tiwel-TV.js";
|
|
4
|
+
let g = null;
|
|
5
|
+
function E(e, n) {
|
|
6
|
+
const t = g;
|
|
7
|
+
g = e;
|
|
8
|
+
try {
|
|
9
|
+
return n();
|
|
10
|
+
} finally {
|
|
11
|
+
g = t;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function u(e) {
|
|
15
|
+
if (!g)
|
|
16
|
+
throw new Error(
|
|
17
|
+
`[@reformer/core/validation] "${e}" вызван вне схемы валидации — операторы валидации можно вызывать только внутри прогона validateModel(...) (напрямую или через apply/each).`
|
|
18
|
+
);
|
|
19
|
+
return g;
|
|
20
|
+
}
|
|
21
|
+
function m(e, n) {
|
|
22
|
+
let t = e.errors.get(n);
|
|
23
|
+
return t || e.errors.set(n, t = []), t;
|
|
24
|
+
}
|
|
25
|
+
const b = (e) => e.whenStack.every((n) => n());
|
|
26
|
+
function D(e, n) {
|
|
27
|
+
const t = u("validate"), r = m(t, e);
|
|
28
|
+
if (!b(t)) return;
|
|
29
|
+
const o = e.peek();
|
|
30
|
+
for (const a of n) {
|
|
31
|
+
const i = a(o, t.model, t.model);
|
|
32
|
+
i && r.push(i);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function N(e, n) {
|
|
36
|
+
const t = u("validateAsync"), r = m(t, e);
|
|
37
|
+
if (!b(t)) return;
|
|
38
|
+
const o = e.peek(), a = t.signal;
|
|
39
|
+
for (const i of n)
|
|
40
|
+
t.pending.push(
|
|
41
|
+
i(o, { signal: a }).then(
|
|
42
|
+
(s) => {
|
|
43
|
+
s && !a.aborted && r.push(s);
|
|
44
|
+
},
|
|
45
|
+
() => {
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
function R(e, n) {
|
|
51
|
+
const t = u("validateWhen");
|
|
52
|
+
t.whenStack.push(e);
|
|
53
|
+
try {
|
|
54
|
+
n();
|
|
55
|
+
} finally {
|
|
56
|
+
t.whenStack.pop();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function _(e, n) {
|
|
60
|
+
const t = u("cross"), r = m(t, e);
|
|
61
|
+
if (!b(t)) return;
|
|
62
|
+
const o = n(t.model.get());
|
|
63
|
+
o && r.push(o);
|
|
64
|
+
}
|
|
65
|
+
function $(e, n) {
|
|
66
|
+
u("each");
|
|
67
|
+
const t = e.length;
|
|
68
|
+
for (let r = 0; r < t; r++) n(e.at(r));
|
|
69
|
+
}
|
|
70
|
+
function j(...e) {
|
|
71
|
+
const t = u("apply").model;
|
|
72
|
+
for (const r of e) r({ model: t });
|
|
73
|
+
}
|
|
74
|
+
function z(e) {
|
|
75
|
+
return e;
|
|
76
|
+
}
|
|
77
|
+
const x = /* @__PURE__ */ new WeakMap();
|
|
78
|
+
function L(e, n) {
|
|
79
|
+
let t = x.get(e);
|
|
80
|
+
t || x.set(e, t = /* @__PURE__ */ new WeakMap());
|
|
81
|
+
let r = t.get(n);
|
|
82
|
+
return r || t.set(n, r = { fields: /* @__PURE__ */ new Set(), ac: null }), r;
|
|
83
|
+
}
|
|
84
|
+
const P = (e) => {
|
|
85
|
+
for (const n of e.values()) for (const t of n) if (t.severity !== "warning") return !0;
|
|
86
|
+
return !1;
|
|
87
|
+
};
|
|
88
|
+
function T(e) {
|
|
89
|
+
return e.aborted ? Promise.resolve() : new Promise((n) => {
|
|
90
|
+
e.addEventListener("abort", () => n(), { once: !0 });
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
async function C(e, n, t) {
|
|
94
|
+
const r = L(e, n);
|
|
95
|
+
r.ac?.abort();
|
|
96
|
+
const o = new AbortController();
|
|
97
|
+
r.ac = o;
|
|
98
|
+
const a = {
|
|
99
|
+
model: e,
|
|
100
|
+
errors: /* @__PURE__ */ new Map(),
|
|
101
|
+
pending: [],
|
|
102
|
+
whenStack: [],
|
|
103
|
+
signal: o.signal
|
|
104
|
+
};
|
|
105
|
+
if (E(a, () => n({ model: e })), a.pending.length && await Promise.race([Promise.all(a.pending), T(o.signal)]), o.signal.aborted) return !1;
|
|
106
|
+
const i = new Set(a.errors.keys());
|
|
107
|
+
for (const s of r.fields) i.has(s) || v(s)?.setErrors([]);
|
|
108
|
+
for (const s of i) v(s)?.setErrors(a.errors.get(s) ?? []);
|
|
109
|
+
if (t?.touch) for (const s of i) v(s)?.markAsTouched();
|
|
110
|
+
return r.fields = i, !P(a.errors);
|
|
111
|
+
}
|
|
112
|
+
function G(e, n, t = {}) {
|
|
113
|
+
const { strategy: r = "submit", debounce: o = 0, liveAfterSubmit: a = "change" } = t, i = A(!1);
|
|
114
|
+
let s = 0, y = !1, f, c;
|
|
115
|
+
const w = async (l) => {
|
|
116
|
+
s++, i.value = !0;
|
|
117
|
+
try {
|
|
118
|
+
return await C(e, n, { touch: l });
|
|
119
|
+
} finally {
|
|
120
|
+
--s === 0 && (i.value = !1);
|
|
121
|
+
}
|
|
122
|
+
}, p = () => {
|
|
123
|
+
w(!1);
|
|
124
|
+
}, F = () => {
|
|
125
|
+
if (!o) {
|
|
126
|
+
p();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
c && clearTimeout(c), c = setTimeout(p, o);
|
|
130
|
+
}, k = (l, d) => {
|
|
131
|
+
let S = !0;
|
|
132
|
+
return M(() => {
|
|
133
|
+
if (W(e, l), S) {
|
|
134
|
+
S = !1;
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
r === "afterFirstSubmit" && !y || d();
|
|
138
|
+
});
|
|
139
|
+
}, h = {
|
|
140
|
+
async validate() {
|
|
141
|
+
return y = !0, w(!0);
|
|
142
|
+
},
|
|
143
|
+
start() {
|
|
144
|
+
if (f) return () => h.dispose();
|
|
145
|
+
const l = r === "afterFirstSubmit" ? a : r;
|
|
146
|
+
return l === "change" ? f = k((d) => void d.value, F) : l === "blur" && (f = k((d) => void v(d)?.touched.value, p)), () => h.dispose();
|
|
147
|
+
},
|
|
148
|
+
dispose() {
|
|
149
|
+
c && (clearTimeout(c), c = void 0), f?.(), f = void 0;
|
|
150
|
+
},
|
|
151
|
+
get isValidating() {
|
|
152
|
+
return i.value;
|
|
153
|
+
},
|
|
154
|
+
get validating() {
|
|
155
|
+
return i;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
return h;
|
|
159
|
+
}
|
|
160
|
+
export {
|
|
161
|
+
N as a,
|
|
162
|
+
R as b,
|
|
163
|
+
_ as c,
|
|
164
|
+
j as d,
|
|
165
|
+
$ as e,
|
|
166
|
+
z as f,
|
|
167
|
+
C as g,
|
|
168
|
+
G as h,
|
|
169
|
+
D as v
|
|
170
|
+
};
|
package/dist/validation.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './form/validation
|
|
1
|
+
export * from './form/validation/index'
|
|
2
2
|
export {}
|