@reformer/core 11.0.0-beta.7 → 11.0.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 (56) hide show
  1. package/README.md +7 -3
  2. package/dist/behaviors.js +211 -174
  3. package/dist/create-model-BBRHhHwK.js +30 -0
  4. package/dist/form/behaviors/collections.d.ts +14 -1
  5. package/dist/form/behaviors/context.d.ts +18 -2
  6. package/dist/form/behaviors/index.d.ts +3 -1
  7. package/dist/form/behaviors/internals.d.ts +0 -1
  8. package/dist/form/behaviors/schema-operators.d.ts +76 -0
  9. package/dist/form/behaviors/types.d.ts +15 -3
  10. package/dist/form/create-core-form.d.ts +5 -3
  11. package/dist/form/create-form.d.ts +28 -53
  12. package/dist/form/form-bundle.d.ts +136 -0
  13. package/dist/form/index.d.ts +6 -1
  14. package/dist/form/nodes/field-node.d.ts +2 -2
  15. package/dist/form/nodes/group-node.d.ts +1 -1
  16. package/dist/form/nodes/model-array-node.d.ts +10 -5
  17. package/dist/form/schema-controller.d.ts +137 -0
  18. package/dist/form/schema-subtree.d.ts +28 -0
  19. package/dist/form/signal-node-registry.d.ts +22 -16
  20. package/dist/form/types/deep-schema.d.ts +2 -2
  21. package/dist/form/types/form-proxy.d.ts +1 -1
  22. package/dist/form/types/schema-node.d.ts +37 -12
  23. package/dist/form/validation/context.d.ts +6 -1
  24. package/dist/form/validation/index.d.ts +1 -1
  25. package/dist/form/validation/operators.d.ts +70 -8
  26. package/dist/form/validation/types.d.ts +2 -1
  27. package/dist/index.js +345 -254
  28. package/dist/model/index.d.ts +5 -0
  29. package/dist/model/model-nodes.d.ts +67 -4
  30. package/dist/model/model-signals-proxy.d.ts +8 -1
  31. package/dist/model/model-value-proxy.d.ts +76 -0
  32. package/dist/model/types.d.ts +7 -4
  33. package/dist/model-value-proxy-caTmAiUd.js +419 -0
  34. package/dist/model.js +19 -17
  35. package/dist/node-BeV_lV5i.js +100 -0
  36. package/dist/platforms/react/form-bundle-context.d.ts +27 -0
  37. package/dist/platforms/react/index.d.ts +1 -0
  38. package/dist/strategy-DgzELWno.js +204 -0
  39. package/dist/validation.js +7 -6
  40. package/docs/llms/03-api-signatures.md +4 -4
  41. package/docs/llms/09-formschema.md +5 -5
  42. package/docs/llms/10-arrays.md +23 -4
  43. package/docs/llms/16-ui-components.md +2 -2
  44. package/docs/llms/18-conditional-fields.md +1 -1
  45. package/docs/llms/21-array-operations.md +26 -0
  46. package/docs/llms/28-submit-and-reset.md +3 -3
  47. package/docs/llms/29-async-preload.md +4 -4
  48. package/docs/llms/33-validation-strategy.md +2 -2
  49. package/docs/llms/35-unified-contract.md +246 -0
  50. package/llms-index.json +1 -1
  51. package/llms.txt +1148 -122
  52. package/package.json +1 -1
  53. package/dist/create-model-B8U-COv-.js +0 -103
  54. package/dist/model-signals-proxy-2vqS243J.js +0 -250
  55. package/dist/node-DGEFMTQu.js +0 -18
  56. package/dist/strategy-BXS_gBfz.js +0 -170
package/README.md CHANGED
@@ -31,7 +31,7 @@ npm install @reformer/core@beta # Active development is underway, so you can try
31
31
  ## Quick Start
32
32
 
33
33
  ReFormer is built around the **M1 architecture**: a reactive `FormModel` owns the values, a layout
34
- schema binds field config (component / props) to the model's signals, and `createForm({ model, schema })`
34
+ schema binds field config (component / props) to the model's signals, and `createFormFromModel({ model, schema })`
35
35
  wires them into a typed form. Validation is a **separate** ambient contract — `defineValidationSchema`,
36
36
  run on demand by `validateModel(model, schema)` — so the layout schema carries no validators.
37
37
 
@@ -39,7 +39,8 @@ run on demand by `validateModel(model, schema)` — so the layout schema carries
39
39
  import { useMemo } from 'react';
40
40
  import {
41
41
  createModel,
42
- createForm,
42
+ createFormFromModel,
43
+ createLegacyForm,
43
44
  useFormControl,
44
45
  type FieldNode,
45
46
  type ValidationError,
@@ -121,7 +122,10 @@ const behavior = defineFormBehavior<RegistrationForm>(({ model, form }) => {
121
122
 
122
123
  // 6. Registration form component
123
124
  function RegistrationFormExample() {
124
- const form = useMemo(() => createForm<RegistrationForm>({ model, schema, behavior }), []);
125
+ const form = useMemo(
126
+ () => createFormFromModel<RegistrationForm>({ model, schema, behavior }),
127
+ []
128
+ );
125
129
 
126
130
  const handleSubmit = async (e: React.FormEvent) => {
127
131
  e.preventDefault();
package/dist/behaviors.js CHANGED
@@ -1,60 +1,72 @@
1
- import { effect as j } from "@preact/signals-core";
2
- import { d as k, a as A, w as $, t as C, r as O, s as D, b as G } from "./behaviors-value-C7dSEhCc.js";
3
- import { d as T, i as I, m as x, u as P } from "./model-signals-proxy-2vqS243J.js";
4
- import { e as R } from "./node-DGEFMTQu.js";
5
- let h = null;
6
- function B(e) {
7
- if (!h)
1
+ import { effect as H } from "@preact/signals-core";
2
+ import { d as $, a as P, w as M, t as B, r as T, s as L, b as N } from "./behaviors-value-C7dSEhCc.js";
3
+ import { c as U, e as q } from "./node-BeV_lV5i.js";
4
+ import { j as z, i as J, c as E, u as S, h as b, m as _, g as K } from "./model-value-proxy-caTmAiUd.js";
5
+ import { g as v } from "./signal-node-registry-tiwel-TV.js";
6
+ let m = null;
7
+ function k(e) {
8
+ if (!m)
8
9
  throw new Error(
9
10
  `[@reformer/core/behaviors] "${e}" вызван вне defineFormBehavior(...) — операторы поведения можно вызывать только внутри схемы.`
10
11
  );
11
- return h;
12
+ return m;
12
13
  }
13
14
  function a(e) {
14
- B("onDispose").cleanups.push(e);
15
+ k("onDispose").cleanups.push(e);
15
16
  }
16
- function p() {
17
- const e = B("getScope");
18
- return { model: e.model, form: e.form };
17
+ function g(e) {
18
+ m?.cleanups.push(e);
19
+ }
20
+ function ie() {
21
+ const e = k("getScope");
22
+ return x(e);
19
23
  }
20
- function q(e) {
24
+ function F(e = "getController") {
25
+ return k(e).controller;
26
+ }
27
+ const x = (e) => ({
28
+ model: e.model,
29
+ form: e.form,
30
+ schema: e.controller.scopeOf(e.model)
31
+ });
32
+ function Q(e) {
21
33
  return {
22
- __run(t, n) {
23
- const o = { cleanups: [], model: t, form: n }, r = h;
24
- h = o;
34
+ __run(t, n, o = U()) {
35
+ const r = { cleanups: [], model: t, form: n, controller: o }, c = m;
36
+ m = r;
25
37
  try {
26
- e({ model: t, form: n });
38
+ e(x(r));
27
39
  } finally {
28
- h = r;
40
+ m = c;
29
41
  }
30
42
  return () => {
31
- for (const c of o.cleanups) c();
43
+ for (const s of r.cleanups) s();
32
44
  };
33
45
  }
34
46
  };
35
47
  }
36
- function m(e) {
37
- a(j(e));
48
+ function p(e) {
49
+ a(H(e));
38
50
  }
39
- function g(e) {
40
- k(e);
51
+ function O(e) {
52
+ $(e);
41
53
  }
42
- const _ = (e) => typeof e == "object" && e !== null && typeof e.peek == "function" && !I(e), b = (e) => _(e) || T(e), E = (e) => Array.isArray(e) ? e : [e];
43
- function S(e) {
54
+ const C = (e) => typeof e == "object" && e !== null && typeof e.peek == "function" && !J(e), y = (e) => C(e) || z(e), W = (e) => Array.isArray(e) ? e : [e];
55
+ function j(e) {
44
56
  const t = {};
45
57
  for (const n of Object.keys(e)) {
46
58
  const o = e[n];
47
- t[n] = b(o) ? o.value : S(o);
59
+ t[n] = y(o) ? o.value : j(o);
48
60
  }
49
61
  return t;
50
62
  }
51
- function V(e, t) {
63
+ function A(e, t) {
52
64
  for (const n of Object.keys(e)) {
53
65
  const o = e[n];
54
- b(o) ? o.value = t?.[n] : V(o, t?.[n] ?? {});
66
+ y(o) ? o.value = t?.[n] : A(o, t?.[n] ?? {});
55
67
  }
56
68
  }
57
- function W(e) {
69
+ function D(e) {
58
70
  return (t) => {
59
71
  try {
60
72
  t();
@@ -69,18 +81,10 @@ function W(e) {
69
81
  }
70
82
  };
71
83
  }
72
- function F(e, t) {
73
- return t.split(".").reduce((n, o) => n?.[o], e);
74
- }
75
- function z(e) {
76
- if (!e) return;
77
- const { form: t } = p();
78
- return t.getFieldByPath(e);
79
- }
80
- function Z(e, t, n) {
81
- x(e), a(() => P(e));
82
- const o = W(e);
83
- m(() => {
84
+ function ae(e, t, n) {
85
+ E(e), a(() => S(e));
86
+ const o = D(e);
87
+ p(() => {
84
88
  if (n?.when && !n.when()) return;
85
89
  const r = t();
86
90
  e.peek() !== r && o(() => {
@@ -88,96 +92,83 @@ function Z(e, t, n) {
88
92
  });
89
93
  });
90
94
  }
91
- function ee(e, t, n, o) {
92
- x(t), a(() => P(t));
93
- const r = W(t);
94
- m(() => {
95
- const c = e.map((s) => s.value);
95
+ function fe(e, t, n, o) {
96
+ E(t), a(() => S(t));
97
+ const r = D(t);
98
+ p(() => {
99
+ const c = e.map((i) => i.value);
96
100
  if (o?.when && !o.when(...c)) return;
97
- const i = n(...c);
98
- t.peek() !== i && r(() => {
99
- t.value = i;
101
+ const s = n(...c);
102
+ t.peek() !== s && r(() => {
103
+ t.value = s;
100
104
  });
101
105
  });
102
106
  }
103
- function ne(e, t, n) {
104
- if (b(e) && b(t)) {
105
- a(A(e, t, n));
107
+ function le(e, t, n) {
108
+ if (y(e) && y(t)) {
109
+ a(P(e, t, n));
106
110
  return;
107
111
  }
108
112
  const o = e, r = t;
109
- m(() => {
110
- const c = S(o);
111
- n?.when && !n.when() || g(() => V(r, c));
113
+ p(() => {
114
+ const c = j(o);
115
+ n?.when && !n.when() || O(() => A(r, c));
112
116
  });
113
117
  }
114
- function H(e, t, n) {
118
+ function X(e, t, n) {
115
119
  let o;
116
120
  const r = (c) => {
117
121
  o?.abort(), o = new AbortController();
118
- const { signal: i } = o;
119
- k(() => t(c, { signal: i }));
122
+ const { signal: s } = o;
123
+ $(() => t(c, { signal: s }));
120
124
  };
121
125
  if (!n?.debounce)
122
- a($(e, r, { immediate: n?.immediate }));
126
+ a(M(e, r, { immediate: n?.immediate }));
123
127
  else {
124
128
  let c;
125
- const i = $(
129
+ const s = M(
126
130
  e,
127
- (s) => {
128
- c && clearTimeout(c), c = setTimeout(() => r(s), n.debounce);
131
+ (i) => {
132
+ c && clearTimeout(c), c = setTimeout(() => r(i), n.debounce);
129
133
  },
130
134
  { immediate: n?.immediate }
131
135
  );
132
136
  a(() => {
133
- c && clearTimeout(c), i();
137
+ c && clearTimeout(c), s();
134
138
  });
135
139
  }
136
140
  a(() => o?.abort());
137
141
  }
138
- function L(e, t, n) {
139
- for (const o of E(e))
140
- _(o) ? a(R(o, t, n)) : N(o, t, n);
142
+ function Y(e, t, n) {
143
+ for (const o of W(e))
144
+ C(o) ? a(q(o, t, n)) : Z(o, t, n);
141
145
  }
142
- function te(e, t, n) {
143
- L(e, () => !t(), n);
146
+ function ue(e, t, n) {
147
+ Y(e, () => !t(), n);
144
148
  }
145
- function N(e, t, n) {
146
- const o = z(e.__path);
147
- o && m(() => {
149
+ function Z(e, t, n) {
150
+ const o = v(e);
151
+ o && p(() => {
148
152
  const r = t();
149
- g(() => {
153
+ O(() => {
150
154
  r ? o.enable() : (o.disable(), n?.resetOnDisable && o.reset());
151
155
  });
152
156
  });
153
157
  }
154
- function oe(e, t) {
155
- a(C(e, t));
158
+ function de(e, t) {
159
+ a(B(e, t));
156
160
  }
157
- function re(e, t, n) {
158
- a(O(e, t, n));
161
+ function me(e, t, n) {
162
+ a(T(e, t, n));
159
163
  }
160
- function ce(e, t, n) {
161
- a(D(e, t, n));
164
+ function pe(e, t, n) {
165
+ a(L(e, t, n));
162
166
  }
163
- function ie(e, t) {
164
- a(G(e, t));
165
- }
166
- function M(e) {
167
- return new Proxy(
168
- {},
169
- {
170
- get: (t, n) => {
171
- if (n === "$") return e;
172
- if (typeof n != "string") return;
173
- const o = e[n];
174
- if (o != null)
175
- return _(o) ? o.value : M(o);
176
- }
177
- }
178
- );
167
+ function he(e, t) {
168
+ a(N(e, t));
179
169
  }
180
- function J(e) {
170
+ const I = (e) => e.__path ?? "?", R = (e) => void F(e);
171
+ function ee(e) {
181
172
  return new Proxy(
182
173
  {},
183
174
  {
@@ -192,111 +183,157 @@ function J(e) {
192
183
  }
193
184
  );
194
185
  }
195
- function K(e, t) {
196
- const { model: n, form: o } = p(), r = e.__path;
197
- if (!r) return;
198
- const c = F(n, r);
199
- if (!c) return;
200
- const i = o.getFieldByPath(
201
- r
202
- ), s = i?.length, f = /* @__PURE__ */ new Map();
203
- m(() => {
204
- const d = s ? s.value : c.length, y = /* @__PURE__ */ new Set();
205
- for (let u = 0; u < d; u++) {
206
- const l = c.at(u);
207
- if (l != null && (y.add(l), !f.has(l))) {
208
- const w = i?.at?.(u) ?? J(r);
209
- f.set(l, t.__run(l, w));
186
+ function te(e, t) {
187
+ const n = F("applyEach"), o = b(e);
188
+ if (!o) return;
189
+ const r = _(o), c = v(o), s = typeof c?.at == "function" ? c : void 0, i = s?.length, f = /* @__PURE__ */ new Map();
190
+ p(() => {
191
+ const h = i ? i.value : r.length, d = /* @__PURE__ */ new Set();
192
+ for (let l = 0; l < h; l++) {
193
+ const u = r.at(l);
194
+ if (u != null && (d.add(u), !f.has(u))) {
195
+ const G = s?.at?.(l) ?? ee(I(o));
196
+ f.set(u, t.__run(u, G, n));
210
197
  }
211
198
  }
212
- for (const [u, l] of f)
213
- y.has(u) || (l(), f.delete(u));
199
+ for (const [l, u] of f)
200
+ d.has(l) || (u(), f.delete(l));
214
201
  }), a(() => {
215
- for (const d of f.values()) d();
202
+ for (const h of f.values()) h();
216
203
  f.clear();
217
204
  });
218
205
  }
219
- function v(e) {
206
+ function w(e) {
220
207
  if (e == null || typeof e != "object") return;
221
208
  const t = e;
222
209
  if (typeof t.at == "function" && typeof t.length == "number") {
223
210
  const n = t.length;
224
- for (let o = 0; o < n; o++) v(t.at(o));
211
+ for (let o = 0; o < n; o++) w(t.at(o));
225
212
  return;
226
213
  }
227
- for (const n of Object.keys(e)) v(e[n]);
214
+ for (const n of Object.keys(e)) w(e[n]);
228
215
  }
229
- function se(e, t) {
230
- const { model: n } = p(), o = e.__path;
231
- if (!o) return;
232
- const r = F(n, o);
233
- r && K(
234
- e,
235
- q(({ model: c }) => {
236
- H(t(c), (i) => {
237
- if (i)
238
- for (let s = 0; s < r.length; s++) {
239
- const f = r.at(s);
240
- if (f && f !== c) {
241
- const d = t(f);
242
- d.peek() && (d.value = !1);
216
+ function ye(e, t) {
217
+ R("exclusiveFlag");
218
+ const n = b(e);
219
+ if (!n) return;
220
+ const o = _(n);
221
+ te(
222
+ n,
223
+ Q(({ model: r }) => {
224
+ X(t(r), (c) => {
225
+ if (c)
226
+ for (let s = 0; s < o.length; s++) {
227
+ const i = o.at(s);
228
+ if (i && i !== r) {
229
+ const f = t(i);
230
+ f.peek() && (f.value = !1);
243
231
  }
244
232
  }
245
233
  });
246
234
  })
247
235
  );
248
236
  }
249
- function ae(e, t) {
250
- const { model: n } = p(), o = e.__path;
251
- if (!o) return;
252
- const r = F(n, o);
253
- if (!r) return;
254
- let c = !1, i = 0;
255
- m(() => {
256
- v(r), !c && (c = !0, g(() => {
257
- c = !1;
258
- const s = t(r.toArray());
259
- let f = !1;
260
- for (const { index: d, patch: y } of s) {
261
- const u = r.at(d);
262
- if (u)
263
- for (const [l, w] of Object.entries(y))
264
- u[l] !== w && (u[l] = w, f = !0);
237
+ function _e(e, t) {
238
+ R("aggregateInto");
239
+ const n = b(e);
240
+ if (!n) return;
241
+ const o = _(n);
242
+ let r = !1, c = 0;
243
+ p(() => {
244
+ w(o), !r && (r = !0, O(() => {
245
+ r = !1;
246
+ const s = t(o.toArray());
247
+ let i = !1;
248
+ for (const { index: f, patch: h } of s) {
249
+ const d = o.at(f);
250
+ if (d)
251
+ for (const [l, u] of Object.entries(h))
252
+ d[l] !== u && (d[l] = u, i = !0);
265
253
  }
266
- if (i = f ? i + 1 : 0, i > 50)
267
- throw i = 0, new Error(
268
- `[@reformer/core/behaviors] aggregateInto("${o}"): запись не сходится (>50 проходов) — derive должна быть идемпотентной на фикспоинте.`
254
+ if (c = i ? c + 1 : 0, c > 50)
255
+ throw c = 0, new Error(
256
+ `[@reformer/core/behaviors] aggregateInto("${I(n)}"): запись не сходится (>50 проходов) — derive должна быть идемпотентной на фикспоинте.`
269
257
  );
270
258
  }));
271
259
  });
272
260
  }
273
- function fe(e, t) {
274
- const { form: n } = p();
275
- for (const o of E(e)) {
276
- const r = o, c = r.__path;
277
- if (!c) continue;
278
- const i = n ? n.getFieldByPath(c) : void 0, s = i ? i.getProxy?.() ?? i : void 0;
279
- a(t.__run(M(r), s));
261
+ function ge(e, t) {
262
+ const n = F("apply");
263
+ for (const o of W(e)) {
264
+ const r = K(o);
265
+ if (!r) continue;
266
+ const c = _(r), s = v(r), i = s ? s.getProxy?.() ?? s : void 0;
267
+ a(t.__run(c, i, n));
280
268
  }
281
269
  }
270
+ function we(e, t) {
271
+ const { conditionRegistry: n } = e.__overrideMaps;
272
+ n.set(e.__selector, t), g(() => {
273
+ n.get(e.__selector) === t && n.delete(e.__selector);
274
+ });
275
+ }
276
+ function be(e, t, n) {
277
+ const { callbackRegistry: o } = e.__overrideMaps;
278
+ let r = o.get(e.__selector);
279
+ r || (r = /* @__PURE__ */ new Map(), o.set(e.__selector, r)), r.set(t, n);
280
+ const c = r;
281
+ g(() => {
282
+ c.get(t) === n && c.delete(t);
283
+ });
284
+ }
285
+ function ve(e, t) {
286
+ const { effectRegistry: n } = e.__overrideMaps;
287
+ n.push(t), g(() => {
288
+ const o = n.indexOf(t);
289
+ o !== -1 && n.splice(o, 1);
290
+ });
291
+ }
292
+ function V(e, t, n) {
293
+ const { lifecycleRegistry: o } = e.__overrideMaps;
294
+ o.set(e.__selector, {
295
+ ...o.get(e.__selector) ?? {},
296
+ [t]: n
297
+ }), g(() => {
298
+ const r = o.get(e.__selector);
299
+ if (r?.[t] !== n) return;
300
+ const c = { ...r };
301
+ delete c[t], Object.keys(c).length === 0 ? o.delete(e.__selector) : o.set(e.__selector, c);
302
+ });
303
+ }
304
+ function ke(e, t) {
305
+ t();
306
+ }
307
+ function Fe(e, t) {
308
+ V(e, "onMount", t);
309
+ }
310
+ function Oe(e, t) {
311
+ V(e, "onUnmount", t);
312
+ }
282
313
  export {
283
- ae as aggregateInto,
284
- fe as apply,
285
- K as applyEach,
286
- Z as compute,
287
- ee as computeFrom,
288
- ne as copyFrom,
289
- g as defer,
290
- q as defineFormBehavior,
291
- te as disableWhen,
292
- m as effect,
293
- L as enableWhen,
294
- se as exclusiveFlag,
295
- p as getScope,
296
- H as onChange,
314
+ _e as aggregateInto,
315
+ ge as apply,
316
+ te as applyEach,
317
+ ae as compute,
318
+ fe as computeFrom,
319
+ le as copyFrom,
320
+ O as defer,
321
+ Q as defineFormBehavior,
322
+ ue as disableWhen,
323
+ p as effect,
324
+ Y as enableWhen,
325
+ ye as exclusiveFlag,
326
+ ie as getScope,
327
+ we as hideWhen,
328
+ X as onChange,
329
+ be as onComponentEvent,
297
330
  a as onDispose,
298
- re as resetWhen,
299
- ie as revalidateWhen,
300
- ce as syncFields,
301
- oe as transformValue
331
+ ke as onInit,
332
+ Fe as onMount,
333
+ Oe as onUnmount,
334
+ ve as renderEffect,
335
+ me as resetWhen,
336
+ he as revalidateWhen,
337
+ pe as syncFields,
338
+ de as transformValue
302
339
  };
@@ -0,0 +1,30 @@
1
+ import { G as f, e as c, r as t, s } from "./model-value-proxy-caTmAiUd.js";
2
+ function n(o, e, a) {
3
+ if (o.kind === "leaf") {
4
+ e(o.signal);
5
+ return;
6
+ }
7
+ if (o.kind === "group") {
8
+ for (const r of o.children.values()) n(r, e, a);
9
+ return;
10
+ }
11
+ a && e(s(o));
12
+ for (const r of o.items.value) n(r, e, a);
13
+ }
14
+ function u(o, e) {
15
+ const a = t.get(o);
16
+ a && n(a, e, !1);
17
+ }
18
+ function i(o, e) {
19
+ const a = t.get(o);
20
+ a && n(a, e, !0);
21
+ }
22
+ function g(o) {
23
+ const e = new f(o, "");
24
+ return c(e);
25
+ }
26
+ export {
27
+ i as a,
28
+ g as c,
29
+ u as e
30
+ };
@@ -12,10 +12,14 @@ import { FormBehavior } from './types';
12
12
  * рендерится, а её сигналы зарегистрированы (`enableWhen` резолвит ноду). Без материализации доступ
13
13
  * к `form.*` бросит понятную ошибку (см. {@link unmaterializedRowForm}).
14
14
  *
15
+ * Работает на любой глубине: массив в корне, в группе и в строке другого массива — в схеме строки
16
+ * можно снова вызвать `applyEach`.
17
+ *
15
18
  * @example
16
19
  * applyEach(model.$.items, defineFormBehavior<Item>(({ model: row, form }) => {
17
20
  * compute(row.$.lineTotal, () => row.qty * row.price); // value-op — всегда
18
21
  * enableWhen(row.$.discount, () => row.qty > 10); // node-op — нужна материализация массива
22
+ * applyEach(row.$.phones, phoneBehavior); // массив внутри строки
19
23
  * }));
20
24
  */
21
25
  export declare function applyEach<TItem>(array: object, itemSchema: FormBehavior<TItem>): void;
@@ -46,5 +50,14 @@ export declare function aggregateInto<TItem>(array: object, derive: (rows: TItem
46
50
  index: number;
47
51
  patch: Partial<TItem>;
48
52
  }>): void;
49
- /** Применить под-схему к одному или нескольким полям-группам (переиспользование). */
53
+ /**
54
+ * Применить под-схему к одному или нескольким полям-группам (переиспользование).
55
+ *
56
+ * Под-схема получает scope группы: `model` — настоящая под-модель (`model.$.field`, чтение и
57
+ * запись значений, `get`/`set`/`patch`), `form` — нода группы. Цель — ручка группы
58
+ * (`model.$.address`); работает и в корневой схеме, и в схеме строки массива.
59
+ *
60
+ * @example
61
+ * apply([model.$.registrationAddress, model.$.residenceAddress], addressBehavior);
62
+ */
50
63
  export declare function apply<TField>(targets: object | object[], subSchema: FormBehavior<TField>): void;
@@ -1,18 +1,34 @@
1
1
  import { BehaviorCleanup } from '../../index';
2
+ import { SchemaController } from '../schema-controller';
2
3
  import { BehaviorScope, FormBehavior } from './types';
3
4
  /** Зарегистрировать произвольную отписку в активной схеме. */
4
5
  export declare function onDispose(cleanup: BehaviorCleanup): void;
5
- /** Текущий scope ({ model, form }) активной схемы (escape hatch для кросс-операторов). */
6
+ /**
7
+ * Зарегистрировать отписку, если оператор вызван внутри схемы поведения; вне схемы — ничего.
8
+ * Для операторов, которые работают и сами по себе (правила узлов схемы).
9
+ *
10
+ * @internal
11
+ */
12
+ export declare function onDisposeIfActive(cleanup: BehaviorCleanup): void;
13
+ /** Текущая область ({ model, form, schema }) активной схемы (escape hatch для кросс-операторов). */
6
14
  export declare function getScope<T>(): BehaviorScope<T>;
15
+ /**
16
+ * Схема-контроллер сборки, в которой идёт активная схема: под-схемы (`apply`, `applyEach`)
17
+ * получают через него область своей под-модели.
18
+ *
19
+ * @internal
20
+ */
21
+ export declare function getController(op?: string): SchemaController;
7
22
  /**
8
23
  * Описать поведение формы декларативно. Возвращает {@link FormBehavior} для `createForm({ behavior })`.
9
24
  *
10
25
  * @example
11
26
  * ```ts
12
- * export const myBehavior = defineFormBehavior<MyForm>(({ model, form }) => {
27
+ * export const myBehavior = defineFormBehavior<MyForm>(({ model, form, schema }) => {
13
28
  * compute(model.$.total, () => model.price * model.qty);
14
29
  * enableWhen([model.$.city], () => Boolean(model.country));
15
30
  * onChange(model.$.country, async (c) => form.city.updateComponentProps({ options: await load(c) }));
31
+ * hideWhen(schema.node('delivery'), () => model.country === '');
16
32
  * });
17
33
  * ```
18
34
  */
@@ -2,7 +2,7 @@
2
2
  * Декларативный контракт схемы поведения формы — `@reformer/core/behaviors`.
3
3
  *
4
4
  * Свободные операторы (`compute`/`copyFrom`/`enableWhen`/`onChange`/…) вызываются внутри
5
- * `defineFormBehavior(({ model, form }) => { … })` и САМИ регистрируют свои отписки в ambient-стоке —
5
+ * `defineFormBehavior(({ model, form, schema }) => { … })` и САМИ регистрируют свои отписки в ambient-стоке —
6
6
  * автор схемы не видит ни массива `cleanups`, ни `.push`, ни вызовов через точку. Жизненным циклом
7
7
  * владеет форма (`createForm({ behavior })`). Операторы — тонкие обёртки над примитивами слоя данных
8
8
  * ({@link module:model/behaviors-value}); пользовательские операторы пишутся так же и неотличимы от встроенных.
@@ -26,3 +26,5 @@ export type { Signal, ReadonlySignal, BehaviorCleanup } from './types';
26
26
  export { onDispose, getScope, defineFormBehavior, effect, defer } from './context';
27
27
  export { compute, computeFrom, copyFrom, onChange, enableWhen, disableWhen, transformValue, resetWhen, syncFields, revalidateWhen, } from './operators';
28
28
  export { applyEach, exclusiveFlag, aggregateInto, apply } from './collections';
29
+ export { hideWhen, onComponentEvent, renderEffect, onInit, onMount, onUnmount, } from './schema-operators';
30
+ export type { SchemaScope, SchemaNodeControl } from '../schema-controller';
@@ -32,4 +32,3 @@ export declare function writeGroup(g: GroupSignals, val: Record<string, unknown>
32
32
  * синхронные мутации цикла не порождают → не затрагиваются.
33
33
  */
34
34
  export declare function makeCycleGuard(target: Signal<unknown>): (write: () => void) => void;
35
- export declare function getByPath(root: unknown, path: string): any;