@reformer/core 10.0.0-beta.2 → 10.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.
Files changed (67) hide show
  1. package/dist/{behaviors-node-DUrqAqp1.js → behaviors-node-DGEFMTQu.js} +1 -1
  2. package/dist/{behaviors-value-lCpqicfa.js → behaviors-value-C7dSEhCc.js} +43 -57
  3. package/dist/behaviors.js +108 -107
  4. package/dist/derived-registry-CluZCQ7U.js +16 -0
  5. package/dist/form/form-submitter.d.ts +0 -4
  6. package/dist/form/hooks/types.d.ts +3 -3
  7. package/dist/form/hooks/use-form-validation.d.ts +48 -0
  8. package/dist/form/index.d.ts +2 -3
  9. package/dist/form/nodes/array-node.d.ts +0 -84
  10. package/dist/form/nodes/form-node.d.ts +0 -14
  11. package/dist/form/nodes/group-node.d.ts +0 -4
  12. package/dist/form/status-machine.d.ts +0 -38
  13. package/dist/form/types/contracts.d.ts +0 -6
  14. package/dist/form/types/deep-schema.d.ts +0 -9
  15. package/dist/form/types/index.d.ts +4 -38
  16. package/dist/form/types/schema-node.d.ts +13 -16
  17. package/dist/form/types/validation-schema.d.ts +0 -25
  18. package/dist/form/unique-id.d.ts +3 -11
  19. package/dist/form/validation-schema.d.ts +16 -3
  20. package/dist/form/validation-strategy.d.ts +55 -0
  21. package/dist/form/validators.d.ts +8 -3
  22. package/dist/form-model-DYCzGGKF.js +286 -0
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +477 -648
  25. package/dist/runtime-token.d.ts +23 -0
  26. package/dist/state/form-model.d.ts +12 -1
  27. package/dist/state.js +17 -15
  28. package/dist/subscription-manager-705bls97.js +171 -0
  29. package/dist/validation.js +133 -81
  30. package/dist/validators.d.ts +0 -4
  31. package/dist/validators.js +88 -122
  32. package/docs/llms/01-api-reference.md +63 -0
  33. package/docs/llms/02-quick-start.md +143 -0
  34. package/docs/llms/03-api-signatures.md +273 -0
  35. package/docs/llms/04-common-patterns.md +202 -0
  36. package/docs/llms/05-common-mistakes.md +167 -0
  37. package/docs/llms/06-troubleshooting.md +11 -0
  38. package/docs/llms/07-complete-import.md +99 -0
  39. package/docs/llms/08-form-types.md +47 -0
  40. package/docs/llms/09-formschema.md +143 -0
  41. package/docs/llms/10-arrays.md +161 -0
  42. package/docs/llms/11-async-watchfield.md +53 -0
  43. package/docs/llms/12-array-cleanup.md +31 -0
  44. package/docs/llms/13-multi-step.md +91 -0
  45. package/docs/llms/14-extended-mistakes.md +98 -0
  46. package/docs/llms/15-project-structure.md +125 -0
  47. package/docs/llms/16-ui-components.md +189 -0
  48. package/docs/llms/17-nonexistent-api.md +93 -0
  49. package/docs/llms/18-conditional-fields.md +183 -0
  50. package/docs/llms/19-reading-values.md +59 -0
  51. package/docs/llms/20-compute-vs-watch.md +138 -0
  52. package/docs/llms/21-array-operations.md +113 -0
  53. package/docs/llms/22-cycle-detection.md +86 -0
  54. package/docs/llms/23-copy-from.md +141 -0
  55. package/docs/llms/24-sync-fields.md +114 -0
  56. package/docs/llms/25-reset-when.md +115 -0
  57. package/docs/llms/26-transform-value.md +136 -0
  58. package/docs/llms/27-revalidate-when.md +132 -0
  59. package/docs/llms/28-submit-and-reset.md +259 -0
  60. package/docs/llms/29-async-preload.md +193 -0
  61. package/docs/llms/30-type-safety-recipes.md +159 -0
  62. package/docs/llms/31-async-validator-debounce.md +135 -0
  63. package/docs/llms/32-async-options-loading.md +108 -0
  64. package/docs/llms/33-validation-strategy.md +193 -0
  65. package/llms.txt +435 -1580
  66. package/package.json +33 -10
  67. package/dist/form-model-C8Fi83k4.js +0 -439
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reformer/core",
3
- "version": "10.0.0-beta.2",
3
+ "version": "10.0.0-beta.4",
4
4
  "description": "Reactive form state management library for React with signals-based architecture",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -87,9 +87,33 @@
87
87
  "types": "./dist/validators/non-zero.d.ts",
88
88
  "import": "./dist/validators/non-zero.js"
89
89
  },
90
- "./validators/date": {
91
- "types": "./dist/validators/date.d.ts",
92
- "import": "./dist/validators/date.js"
90
+ "./validators/is-date": {
91
+ "types": "./dist/validators/is-date.d.ts",
92
+ "import": "./dist/validators/is-date.js"
93
+ },
94
+ "./validators/min-date": {
95
+ "types": "./dist/validators/min-date.d.ts",
96
+ "import": "./dist/validators/min-date.js"
97
+ },
98
+ "./validators/max-date": {
99
+ "types": "./dist/validators/max-date.d.ts",
100
+ "import": "./dist/validators/max-date.js"
101
+ },
102
+ "./validators/past-date": {
103
+ "types": "./dist/validators/past-date.d.ts",
104
+ "import": "./dist/validators/past-date.js"
105
+ },
106
+ "./validators/future-date": {
107
+ "types": "./dist/validators/future-date.d.ts",
108
+ "import": "./dist/validators/future-date.js"
109
+ },
110
+ "./validators/min-age": {
111
+ "types": "./dist/validators/min-age.d.ts",
112
+ "import": "./dist/validators/min-age.js"
113
+ },
114
+ "./validators/max-age": {
115
+ "types": "./dist/validators/max-age.d.ts",
116
+ "import": "./dist/validators/max-age.js"
93
117
  }
94
118
  },
95
119
  "sideEffects": false,
@@ -99,7 +123,8 @@
99
123
  "build:stackblitz": "vite build",
100
124
  "dev": "vite",
101
125
  "test": "node ../../scripts/run-vitest.mjs",
102
- "test:watch": "vitest watch"
126
+ "test:watch": "vitest watch",
127
+ "coverage": "vitest run --coverage"
103
128
  },
104
129
  "keywords": [
105
130
  "react",
@@ -134,7 +159,8 @@
134
159
  "dist",
135
160
  "README.md",
136
161
  "LICENSE",
137
- "llms.txt"
162
+ "llms.txt",
163
+ "docs/llms"
138
164
  ],
139
165
  "peerDependencies": {
140
166
  "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
@@ -149,11 +175,8 @@
149
175
  "@types/node": "^24.10.1",
150
176
  "tsx": "^4.19.2",
151
177
  "@types/react": "^19.2.7",
152
- "@types/react-dom": "^19.2.3",
153
- "@vitejs/plugin-react": "^5.1.0",
154
- "@vitest/utils": "^4.0.8",
178
+ "@vitest/coverage-v8": "~4.0.15",
155
179
  "react": "^19.2.1",
156
- "react-dom": "^19.2.1",
157
180
  "typescript": "^5.9.3",
158
181
  "vite": "^7.2.2",
159
182
  "vite-plugin-dts": "^4.5.4",
@@ -1,439 +0,0 @@
1
- import { signal as v } from "@preact/signals-core";
2
- import { i as w } from "./behaviors-value-lCpqicfa.js";
3
- class P {
4
- /**
5
- * Хранилище подписок
6
- * Ключ: уникальный идентификатор подписки
7
- * Значение: функция отписки (dispose)
8
- */
9
- subscriptions = /* @__PURE__ */ new Map();
10
- /**
11
- * Добавляет подписку
12
- *
13
- * Если подписка с таким ключом уже существует, отписывается от неё
14
- * и заменяет новой. Это предотвращает утечки памяти при повторной
15
- * регистрации подписки с тем же ключом.
16
- *
17
- * @param key Уникальный ключ подписки
18
- * @param dispose Функция отписки (обычно возвращаемая из effect())
19
- * @returns Функция для отписки от этой конкретной подписки
20
- *
21
- * @example
22
- * ```typescript
23
- * const manager = new SubscriptionManager();
24
- *
25
- * // Добавление подписки
26
- * const unsubscribe = manager.add('mySubscription', () => {
27
- * console.log('Disposing subscription');
28
- * });
29
- *
30
- * // Отписка через возвращаемую функцию
31
- * unsubscribe();
32
- *
33
- * // Или через manager.remove()
34
- * manager.add('anotherSub', disposeFn);
35
- * manager.remove('anotherSub');
36
- * ```
37
- */
38
- add(t, e) {
39
- return this.subscriptions.has(t) && (process.env.NODE_ENV !== "production" && console.warn(`[SubscriptionManager] Subscription "${t}" already exists, replacing`), this.subscriptions.get(t)?.()), this.subscriptions.set(t, e), () => this.remove(t);
40
- }
41
- /**
42
- * Удаляет подписку по ключу
43
- *
44
- * Вызывает функцию отписки и удаляет подписку из хранилища.
45
- * Если подписка с таким ключом не найдена, ничего не делает.
46
- *
47
- * @param key Ключ подписки
48
- * @returns true, если подписка была удалена, false если не найдена
49
- *
50
- * @example
51
- * ```typescript
52
- * const manager = new SubscriptionManager();
53
- * manager.add('mySub', disposeFn);
54
- *
55
- * // Удаление подписки
56
- * const removed = manager.remove('mySub'); // true
57
- *
58
- * // Попытка удалить несуществующую подписку
59
- * const removed2 = manager.remove('nonExistent'); // false
60
- * ```
61
- */
62
- remove(t) {
63
- const e = this.subscriptions.get(t);
64
- return e ? (e(), this.subscriptions.delete(t), !0) : !1;
65
- }
66
- /**
67
- * Очищает все подписки
68
- *
69
- * Вызывает функции отписки для всех активных подписок
70
- * и очищает хранилище. Обычно используется при dispose узла формы.
71
- *
72
- * @example
73
- * ```typescript
74
- * class FieldNode {
75
- * private subscriptions = new SubscriptionManager();
76
- *
77
- * dispose() {
78
- * // Отписываемся от всех effect
79
- * this.subscriptions.clear();
80
- * }
81
- * }
82
- * ```
83
- */
84
- clear() {
85
- this.subscriptions.forEach((t) => {
86
- t();
87
- }), this.subscriptions.clear();
88
- }
89
- /**
90
- * Возвращает количество активных подписок
91
- *
92
- * Полезно для отладки утечек памяти. Если количество подписок
93
- * растет без ограничений, это может указывать на то, что
94
- * компоненты не отписываются должным образом.
95
- *
96
- * @returns Количество активных подписок
97
- *
98
- * @example
99
- * ```typescript
100
- * const manager = new SubscriptionManager();
101
- * console.log(manager.size()); // 0
102
- *
103
- * manager.add('sub1', disposeFn1);
104
- * manager.add('sub2', disposeFn2);
105
- * console.log(manager.size()); // 2
106
- *
107
- * manager.clear();
108
- * console.log(manager.size()); // 0
109
- * ```
110
- */
111
- size() {
112
- return this.subscriptions.size;
113
- }
114
- /**
115
- * Проверяет, есть ли подписка с данным ключом
116
- *
117
- * @param key Ключ подписки
118
- * @returns true, если подписка существует
119
- *
120
- * @example
121
- * ```typescript
122
- * const manager = new SubscriptionManager();
123
- * manager.add('mySub', disposeFn);
124
- *
125
- * console.log(manager.has('mySub')); // true
126
- * console.log(manager.has('nonExistent')); // false
127
- * ```
128
- */
129
- has(t) {
130
- return this.subscriptions.has(t);
131
- }
132
- /**
133
- * Возвращает список всех ключей активных подписок
134
- *
135
- * Полезно для отладки: можно увидеть, какие подписки активны.
136
- *
137
- * @returns Массив ключей всех активных подписок
138
- *
139
- * @example
140
- * ```typescript
141
- * const manager = new SubscriptionManager();
142
- * manager.add('watch-value', disposeFn1);
143
- * manager.add('watch-errors', disposeFn2);
144
- *
145
- * console.log(manager.getKeys()); // ['watch-value', 'watch-errors']
146
- * ```
147
- */
148
- getKeys() {
149
- return Array.from(this.subscriptions.keys());
150
- }
151
- /**
152
- * Отписывается от всех подписок (алиас для clear())
153
- *
154
- * Используется при dispose() узла формы для совместимости с ожидаемым API.
155
- *
156
- * @example
157
- * ```typescript
158
- * class FieldNode {
159
- * private subscriptions = new SubscriptionManager();
160
- *
161
- * dispose() {
162
- * this.subscriptions.dispose();
163
- * }
164
- * }
165
- * ```
166
- */
167
- dispose() {
168
- this.clear();
169
- }
170
- }
171
- const u = (i) => !(i === null || typeof i != "object" || Array.isArray(i) || i instanceof Date || typeof Blob < "u" && i instanceof Blob || typeof File < "u" && i instanceof File), a = (i, t) => i === "" ? String(t) : `${i}.${t}`, p = (i) => /^\d+$/.test(i), o = (i) => {
172
- if (Array.isArray(i)) return i.map(o);
173
- if (u(i)) {
174
- const t = {};
175
- for (const e of Object.keys(i)) t[e] = o(i[e]);
176
- return t;
177
- }
178
- return i;
179
- }, f = (i, t) => {
180
- if (i === t) return !0;
181
- if (Array.isArray(i) && Array.isArray(t))
182
- return i.length !== t.length ? !1 : i.every((e, s) => f(e, t[s]));
183
- if (u(i) && u(t)) {
184
- const e = Object.keys(i), s = Object.keys(t);
185
- return e.length !== s.length ? !1 : e.every((r) => f(i[r], t[r]));
186
- }
187
- return !1;
188
- };
189
- class _ {
190
- constructor(t, e) {
191
- this.path = e;
192
- const s = v(t);
193
- s.__path = e, this.signal = s, this.initial = o(t);
194
- }
195
- kind = "leaf";
196
- signal;
197
- initial;
198
- rebase(t) {
199
- this.path = t, this.signal.__path = t;
200
- }
201
- /** Реактивное чтение (внутри effect/computed создаёт зависимость). */
202
- read() {
203
- return this.signal.value;
204
- }
205
- /** Нереактивный снимок. */
206
- peek() {
207
- return this.signal.peek();
208
- }
209
- set(t) {
210
- this.signal.value = t;
211
- }
212
- resetToInitial() {
213
- this.signal.value = o(this.initial);
214
- }
215
- captureInitial() {
216
- this.initial = o(this.signal.peek());
217
- }
218
- dirty() {
219
- return !f(this.signal.peek(), this.initial);
220
- }
221
- }
222
- class b {
223
- constructor(t, e) {
224
- this.path = e;
225
- for (const s of Object.keys(t))
226
- this.children.set(s, c(t[s], a(e, s)));
227
- }
228
- kind = "group";
229
- children = /* @__PURE__ */ new Map();
230
- rebase(t) {
231
- this.path = t;
232
- for (const [e, s] of this.children) s.rebase(a(t, e));
233
- }
234
- peek() {
235
- const t = {};
236
- for (const [e, s] of this.children) t[e] = s.peek();
237
- return t;
238
- }
239
- set(t) {
240
- if (t == null || typeof t != "object") return;
241
- const e = t;
242
- for (const [s, r] of this.children)
243
- s in e && (r.kind === "leaf" && w(r.signal) || r.set(e[s]));
244
- }
245
- resetToInitial() {
246
- for (const t of this.children.values()) t.resetToInitial();
247
- }
248
- captureInitial() {
249
- for (const t of this.children.values()) t.captureInitial();
250
- }
251
- dirty() {
252
- for (const t of this.children.values()) if (t.dirty()) return !0;
253
- return !1;
254
- }
255
- }
256
- class k {
257
- constructor(t, e) {
258
- this.path = e, this.items = v(t.map((s, r) => c(s, a(e, r)))), this.initial = o(t);
259
- }
260
- kind = "array";
261
- items;
262
- initial;
263
- rebase(t) {
264
- this.path = t, this.items.peek().forEach((e, s) => e.rebase(a(t, s)));
265
- }
266
- reindex() {
267
- this.items.peek().forEach((t, e) => t.rebase(a(this.path, e)));
268
- }
269
- push(t) {
270
- const e = this.items.peek();
271
- this.items.value = [...e, c(t, a(this.path, e.length))];
272
- }
273
- insertAt(t, e) {
274
- const s = [...this.items.peek()];
275
- s.splice(t, 0, c(e, a(this.path, t))), this.items.value = s, this.reindex();
276
- }
277
- removeAt(t) {
278
- const e = [...this.items.peek()];
279
- e.splice(t, 1), this.items.value = e, this.reindex();
280
- }
281
- move(t, e) {
282
- const s = [...this.items.peek()], [r] = s.splice(t, 1);
283
- r && s.splice(e, 0, r), this.items.value = s, this.reindex();
284
- }
285
- swap(t, e) {
286
- const s = [...this.items.peek()];
287
- t < 0 || e < 0 || t >= s.length || e >= s.length || t === e || ([s[t], s[e]] = [s[e], s[t]], this.items.value = s, this.reindex());
288
- }
289
- clear() {
290
- this.items.value = [];
291
- }
292
- peek() {
293
- return this.items.peek().map((t) => t.peek());
294
- }
295
- set(t) {
296
- const e = Array.isArray(t) ? t : [];
297
- this.items.value = e.map((s, r) => c(s, a(this.path, r)));
298
- }
299
- resetToInitial() {
300
- this.set(o(this.initial));
301
- }
302
- captureInitial() {
303
- this.initial = o(this.peek());
304
- }
305
- dirty() {
306
- return !f(this.peek(), this.initial);
307
- }
308
- }
309
- function c(i, t) {
310
- return Array.isArray(i) ? new k(i, t) : u(i) ? new b(i, t) : new _(i, t);
311
- }
312
- function l(i) {
313
- if (i)
314
- return i.kind === "group" ? A(i) : i.kind === "array" ? x(i) : i.read();
315
- }
316
- function x(i) {
317
- const t = {
318
- get length() {
319
- return i.items.value.length;
320
- },
321
- push: (e) => i.push(e),
322
- insertAt: (e, s) => i.insertAt(e, s),
323
- removeAt: (e) => i.removeAt(e),
324
- move: (e, s) => i.move(e, s),
325
- swap: (e, s) => i.swap(e, s),
326
- clear: () => i.clear(),
327
- at: (e) => l(i.items.value[e]),
328
- map: (e) => i.items.value.map((s, r) => e(l(s), r)),
329
- forEach: (e) => i.items.value.forEach((s, r) => e(l(s), r)),
330
- toArray: () => i.peek(),
331
- [Symbol.iterator]: function* () {
332
- const e = i.items.value;
333
- for (let s = 0; s < e.length; s++) yield l(e[s]);
334
- }
335
- };
336
- return new Proxy(t, {
337
- get: (e, s, r) => s === "__path" ? i.path : typeof s == "string" && p(s) ? l(i.items.value[Number(s)]) : Reflect.get(e, s, r),
338
- has: (e, s) => typeof s == "string" && p(s) ? Number(s) < i.items.value.length : Reflect.has(e, s)
339
- });
340
- }
341
- function d(i) {
342
- if (i.kind === "leaf") return i.signal;
343
- if (i.kind === "group")
344
- return new Proxy(
345
- {},
346
- {
347
- get: (e, s) => {
348
- if (s === "__path") return i.path;
349
- if (typeof s != "string") return;
350
- const r = i.children.get(s);
351
- return r ? d(r) : void 0;
352
- },
353
- has: (e, s) => typeof s == "string" && i.children.has(s),
354
- ownKeys: () => [...i.children.keys()],
355
- getOwnPropertyDescriptor: (e, s) => typeof s == "string" && i.children.has(s) ? { enumerable: !0, configurable: !0 } : void 0
356
- }
357
- );
358
- const t = i;
359
- return new Proxy(
360
- {
361
- get length() {
362
- return t.items.value.length;
363
- }
364
- },
365
- {
366
- get: (e, s, r) => {
367
- if (s === "__path") return t.path;
368
- if (typeof s == "string" && p(s)) {
369
- const n = t.items.value[Number(s)];
370
- return n ? d(n) : void 0;
371
- }
372
- return Reflect.get(e, s, r);
373
- }
374
- }
375
- );
376
- }
377
- function I(i, t) {
378
- if (!t) return;
379
- let e = i;
380
- for (const s of t.split(".")) {
381
- if (!e) return;
382
- if (e.kind === "group") e = e.children.get(s);
383
- else if (e.kind === "array") e = e.items.peek()[Number(s)];
384
- else return;
385
- }
386
- return e && e.kind === "leaf" ? e.signal : void 0;
387
- }
388
- const g = /* @__PURE__ */ new Set([
389
- "$",
390
- "get",
391
- "set",
392
- "patch",
393
- "isDirty",
394
- "reset",
395
- "captureInitial",
396
- "signalAt"
397
- ]), y = /* @__PURE__ */ new WeakMap();
398
- function A(i) {
399
- const t = y.get(i);
400
- if (t) return t;
401
- const e = {
402
- $: d(i),
403
- get: () => i.peek(),
404
- set: (r) => i.set(r),
405
- patch: (r) => i.set(r),
406
- isDirty: () => i.dirty(),
407
- reset: () => i.resetToInitial(),
408
- captureInitial: () => i.captureInitial(),
409
- signalAt: (r) => I(i, r)
410
- }, s = new Proxy(
411
- {},
412
- {
413
- get: (r, n) => {
414
- if (n === "__path") return i.path;
415
- if (typeof n != "string") return;
416
- const h = i.children.get(n);
417
- if (h) return l(h);
418
- if (g.has(n)) return e[n];
419
- },
420
- set: (r, n, h) => {
421
- if (typeof n != "string") return !1;
422
- const m = i.children.get(n);
423
- return m ? (m.set(h), !0) : !1;
424
- },
425
- has: (r, n) => typeof n == "string" && (i.children.has(n) || g.has(n)),
426
- ownKeys: () => [...i.children.keys()],
427
- getOwnPropertyDescriptor: (r, n) => typeof n == "string" && i.children.has(n) ? { enumerable: !0, configurable: !0 } : void 0
428
- }
429
- );
430
- return y.set(i, s), s;
431
- }
432
- function S(i) {
433
- const t = new b(i, "");
434
- return A(t);
435
- }
436
- export {
437
- P as S,
438
- S as c
439
- };