@formwright/core 0.2.0 → 0.2.2
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/chunk-OWEG6VGP.js +3 -0
- package/dist/{chunk-O4DUMDBU.js.map → chunk-OWEG6VGP.js.map} +1 -1
- package/dist/index.cjs +163 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -11
- package/dist/index.d.ts +57 -11
- package/dist/index.js +163 -20
- package/dist/index.js.map +1 -1
- package/dist/reactive.cjs +1 -1
- package/dist/reactive.d.cts +1 -1
- package/dist/reactive.d.ts +1 -1
- package/dist/reactive.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-O4DUMDBU.js +0 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { signal, computed, effect, untrack, batch } from './chunk-
|
|
2
|
-
export { batch, computed, effect, isTracking, signal, untrack } from './chunk-
|
|
1
|
+
import { signal, computed, effect, untrack, batch } from './chunk-OWEG6VGP.js';
|
|
2
|
+
export { batch, computed, effect, isTracking, signal, untrack } from './chunk-OWEG6VGP.js';
|
|
3
3
|
import { parseSchema } from '@formwright/schema';
|
|
4
4
|
|
|
5
5
|
// src/conditions.ts
|
|
@@ -184,9 +184,11 @@ var FieldState = class {
|
|
|
184
184
|
revision;
|
|
185
185
|
validator;
|
|
186
186
|
rev = signal(0);
|
|
187
|
-
|
|
187
|
+
stepActive;
|
|
188
|
+
constructor(schema, initial, getValue, stepActive) {
|
|
188
189
|
this.id = schema.id;
|
|
189
190
|
this.schema = schema;
|
|
191
|
+
this.stepActive = stepActive;
|
|
190
192
|
this.value = signal(initial);
|
|
191
193
|
this.error = signal(null);
|
|
192
194
|
this.touched = signal(false);
|
|
@@ -214,12 +216,16 @@ var FieldState = class {
|
|
|
214
216
|
this.validator = this.schema.validation ? compileValidator(this.schema.validation) : null;
|
|
215
217
|
this.rev.update((n) => n + 1);
|
|
216
218
|
}
|
|
217
|
-
/** Run validation, store and return the error (or null). Hidden fields never error. */
|
|
218
|
-
validate() {
|
|
219
|
+
/** Run validation, store and return the error (or null). Hidden / inactive-step fields never error. */
|
|
220
|
+
validate(options) {
|
|
219
221
|
if (!this.visible.peek()) {
|
|
220
222
|
this.error.set(null);
|
|
221
223
|
return null;
|
|
222
224
|
}
|
|
225
|
+
if (!options?.allSteps && this.stepActive && !this.stepActive.peek()) {
|
|
226
|
+
this.error.set(null);
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
223
229
|
let result = null;
|
|
224
230
|
if (this.required.peek() && isEmpty2(this.value.peek())) {
|
|
225
231
|
result = requiredMessage(this.schema.validation);
|
|
@@ -256,18 +262,24 @@ function collectValues(nodes) {
|
|
|
256
262
|
}
|
|
257
263
|
return out;
|
|
258
264
|
}
|
|
259
|
-
function buildNodes(schemas, scope, initial) {
|
|
265
|
+
function buildNodes(schemas, scope, initial, stepActive) {
|
|
260
266
|
const nodes = [];
|
|
261
267
|
const byName = /* @__PURE__ */ new Map();
|
|
262
268
|
for (const schema of schemas) {
|
|
263
269
|
let node;
|
|
264
270
|
if (schema.type === "group") {
|
|
265
|
-
node = new GroupNode(schema, scope, asDict(initial[schema.id]));
|
|
271
|
+
node = new GroupNode(schema, scope, asDict(initial[schema.id]), stepActive);
|
|
272
|
+
} else if (schema.type === "step") {
|
|
273
|
+
if (!stepActive)
|
|
274
|
+
throw new Error('Field type "step" must be nested inside a "steps" container');
|
|
275
|
+
node = new StepNode(schema, scope, asDict(initial[schema.id]), stepActive);
|
|
266
276
|
} else if (schema.type === "collection") {
|
|
267
277
|
node = new CollectionNode(schema, scope, asArray(initial[schema.id]));
|
|
278
|
+
} else if (schema.type === "steps") {
|
|
279
|
+
node = new StepsNode(schema, scope, asDict(initial[schema.id]));
|
|
268
280
|
} else {
|
|
269
281
|
const init = initial[schema.id] ?? schema.defaultValue ?? defaultValueFor(schema.type);
|
|
270
|
-
node = new FieldState(schema, init, scope);
|
|
282
|
+
node = new FieldState(schema, init, scope, stepActive);
|
|
271
283
|
}
|
|
272
284
|
nodes.push(node);
|
|
273
285
|
byName.set(schema.id, node);
|
|
@@ -285,7 +297,9 @@ function resetNodes(nodes, initial) {
|
|
|
285
297
|
if (node.kind === "field") {
|
|
286
298
|
const init = initial[node.id] ?? node.schema.defaultValue ?? defaultValueFor(node.schema.type);
|
|
287
299
|
node.reset(init);
|
|
288
|
-
} else if (node.kind === "group") {
|
|
300
|
+
} else if (node.kind === "group" || node.kind === "step") {
|
|
301
|
+
node.reset(asDict(initial[node.id]));
|
|
302
|
+
} else if (node.kind === "steps") {
|
|
289
303
|
node.reset(asDict(initial[node.id]));
|
|
290
304
|
} else {
|
|
291
305
|
node.reset(asArray(initial[node.id]));
|
|
@@ -303,14 +317,14 @@ var GroupNode = class {
|
|
|
303
317
|
enabled;
|
|
304
318
|
/** The scope a child uses: resolve a name among siblings, else delegate upward. */
|
|
305
319
|
scope;
|
|
306
|
-
constructor(schema, parentScope, initial) {
|
|
320
|
+
constructor(schema, parentScope, initial, stepActive) {
|
|
307
321
|
this.id = schema.id;
|
|
308
322
|
this.schema = schema;
|
|
309
323
|
this.scope = (name) => {
|
|
310
324
|
const child = this.byName.get(name);
|
|
311
325
|
return child ? nodeValue(child) : parentScope(name);
|
|
312
326
|
};
|
|
313
|
-
const built = buildNodes(schema.fields ?? [], this.scope, initial);
|
|
327
|
+
const built = buildNodes(schema.fields ?? [], this.scope, initial, stepActive);
|
|
314
328
|
this.children = built.nodes;
|
|
315
329
|
this.byName = built.byName;
|
|
316
330
|
this.value = computed(() => collectValues(this.children));
|
|
@@ -373,6 +387,109 @@ var CollectionNode = class {
|
|
|
373
387
|
this.rows.set(this.seedRows(initial));
|
|
374
388
|
}
|
|
375
389
|
};
|
|
390
|
+
var StepNode = class {
|
|
391
|
+
kind = "step";
|
|
392
|
+
id;
|
|
393
|
+
schema;
|
|
394
|
+
children;
|
|
395
|
+
byName;
|
|
396
|
+
value;
|
|
397
|
+
visible;
|
|
398
|
+
enabled;
|
|
399
|
+
scope;
|
|
400
|
+
/** True when this step is the active step in its parent wizard. */
|
|
401
|
+
active;
|
|
402
|
+
constructor(schema, parentScope, initial, active) {
|
|
403
|
+
this.id = schema.id;
|
|
404
|
+
this.schema = schema;
|
|
405
|
+
this.active = active;
|
|
406
|
+
this.scope = (name) => {
|
|
407
|
+
const child = this.byName.get(name);
|
|
408
|
+
return child ? nodeValue(child) : parentScope(name);
|
|
409
|
+
};
|
|
410
|
+
const built = buildNodes(schema.fields ?? [], this.scope, initial, active);
|
|
411
|
+
this.children = built.nodes;
|
|
412
|
+
this.byName = built.byName;
|
|
413
|
+
this.value = computed(() => collectValues(this.children));
|
|
414
|
+
this.visible = computed(() => evaluateCondition(schema.visibleWhen, parentScope, true));
|
|
415
|
+
this.enabled = computed(() => evaluateCondition(schema.enabledWhen, parentScope, true));
|
|
416
|
+
}
|
|
417
|
+
reset(initial) {
|
|
418
|
+
resetNodes(this.children, initial);
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
var StepsNode = class {
|
|
422
|
+
kind = "steps";
|
|
423
|
+
id;
|
|
424
|
+
schema;
|
|
425
|
+
steps;
|
|
426
|
+
byName;
|
|
427
|
+
value;
|
|
428
|
+
visible;
|
|
429
|
+
enabled;
|
|
430
|
+
currentStep;
|
|
431
|
+
scope;
|
|
432
|
+
constructor(schema, parentScope, initial) {
|
|
433
|
+
this.id = schema.id;
|
|
434
|
+
this.schema = schema;
|
|
435
|
+
this.currentStep = signal(0);
|
|
436
|
+
this.byName = /* @__PURE__ */ new Map();
|
|
437
|
+
this.scope = (name) => {
|
|
438
|
+
const step = this.byName.get(name);
|
|
439
|
+
return step ? step.value.get() : parentScope(name);
|
|
440
|
+
};
|
|
441
|
+
const stepSchemas = schema.fields ?? [];
|
|
442
|
+
const steps = stepSchemas.map((stepSchema, index) => {
|
|
443
|
+
const active = computed(() => this.currentStep.get() === index);
|
|
444
|
+
const stepInitial = asDict(initial[stepSchema.id]);
|
|
445
|
+
const step = new StepNode(stepSchema, this.scope, stepInitial, active);
|
|
446
|
+
this.byName.set(stepSchema.id, step);
|
|
447
|
+
return step;
|
|
448
|
+
});
|
|
449
|
+
this.steps = steps;
|
|
450
|
+
this.value = computed(() => {
|
|
451
|
+
const out = {};
|
|
452
|
+
for (const step of this.steps) out[step.id] = step.value.get();
|
|
453
|
+
return out;
|
|
454
|
+
});
|
|
455
|
+
this.visible = computed(() => evaluateCondition(schema.visibleWhen, parentScope, true));
|
|
456
|
+
this.enabled = computed(() => evaluateCondition(schema.enabledWhen, parentScope, true));
|
|
457
|
+
}
|
|
458
|
+
/** Validate every leaf in the step at `index` (defaults to the current step). */
|
|
459
|
+
validateStep(index) {
|
|
460
|
+
const i = index ?? this.currentStep.peek();
|
|
461
|
+
const step = this.steps[i];
|
|
462
|
+
if (!step) return true;
|
|
463
|
+
let ok = true;
|
|
464
|
+
eachLeaf([step], (leaf) => {
|
|
465
|
+
if (leaf.validate() !== null) ok = false;
|
|
466
|
+
});
|
|
467
|
+
return ok;
|
|
468
|
+
}
|
|
469
|
+
/** Advance to the next step after optionally validating the current one. Returns false if blocked. */
|
|
470
|
+
next() {
|
|
471
|
+
const validate = this.schema.validateOnNext !== false;
|
|
472
|
+
if (validate && !this.validateStep()) return false;
|
|
473
|
+
const cur = this.currentStep.peek();
|
|
474
|
+
if (cur < this.steps.length - 1) {
|
|
475
|
+
this.currentStep.set(cur + 1);
|
|
476
|
+
return true;
|
|
477
|
+
}
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
/** Go back one step (no validation). */
|
|
481
|
+
prev() {
|
|
482
|
+
this.currentStep.update((i) => Math.max(0, i - 1));
|
|
483
|
+
}
|
|
484
|
+
/** Jump to a step by index (does not validate). */
|
|
485
|
+
goTo(index) {
|
|
486
|
+
if (index >= 0 && index < this.steps.length) this.currentStep.set(index);
|
|
487
|
+
}
|
|
488
|
+
reset(initial) {
|
|
489
|
+
this.currentStep.set(0);
|
|
490
|
+
for (const step of this.steps) step.reset(asDict(initial[step.id]));
|
|
491
|
+
}
|
|
492
|
+
};
|
|
376
493
|
function buildTree(schemas, initial) {
|
|
377
494
|
let byName;
|
|
378
495
|
const scope = (name) => {
|
|
@@ -386,8 +503,10 @@ function buildTree(schemas, initial) {
|
|
|
386
503
|
function eachLeaf(nodes, visit) {
|
|
387
504
|
for (const node of nodes) {
|
|
388
505
|
if (node.kind === "field") visit(node);
|
|
389
|
-
else if (node.kind === "group") eachLeaf(node.children, visit);
|
|
390
|
-
else
|
|
506
|
+
else if (node.kind === "group" || node.kind === "step") eachLeaf(node.children, visit);
|
|
507
|
+
else if (node.kind === "steps") {
|
|
508
|
+
for (const step of node.steps) eachLeaf(step.children, visit);
|
|
509
|
+
} else for (const row of node.items.peek()) eachLeaf(row.group.children, visit);
|
|
391
510
|
}
|
|
392
511
|
}
|
|
393
512
|
var defaultRenderer = null;
|
|
@@ -490,17 +609,22 @@ var Form = class {
|
|
|
490
609
|
}
|
|
491
610
|
// ---- lifecycle ----------------------------------------------------------
|
|
492
611
|
/** Validate every (visible) leaf field; returns true when the whole form is valid. */
|
|
493
|
-
validate() {
|
|
612
|
+
validate(options) {
|
|
613
|
+
const allSteps = options?.allSteps ?? false;
|
|
494
614
|
return untrack(() => {
|
|
495
615
|
let ok = true;
|
|
496
616
|
batch(() => {
|
|
497
617
|
eachLeaf(this.tree, (leaf) => {
|
|
498
|
-
if (leaf.validate() !== null) ok = false;
|
|
618
|
+
if (leaf.validate({ allSteps }) !== null) ok = false;
|
|
499
619
|
});
|
|
500
620
|
});
|
|
501
621
|
return ok;
|
|
502
622
|
});
|
|
503
623
|
}
|
|
624
|
+
/** Find the first `steps` container in the field tree (if any). */
|
|
625
|
+
findSteps() {
|
|
626
|
+
return findSteps(this.tree);
|
|
627
|
+
}
|
|
504
628
|
/**
|
|
505
629
|
* Run the submission pipeline: validate → transform → send → onSuccess/onError.
|
|
506
630
|
* Pass an inline `transform` to shape the final payload, e.g.
|
|
@@ -511,7 +635,7 @@ var Form = class {
|
|
|
511
635
|
* `const res = await form.submit(); res.ok ? res.data : res.error`.
|
|
512
636
|
*/
|
|
513
637
|
async submit(transform) {
|
|
514
|
-
if (!this.validate()) {
|
|
638
|
+
if (!this.validate({ allSteps: true })) {
|
|
515
639
|
const errors = this.collectErrors();
|
|
516
640
|
const error = new FormValidationError(errors);
|
|
517
641
|
this.runErrorHandler(error);
|
|
@@ -691,8 +815,10 @@ function collectLeaves(tree) {
|
|
|
691
815
|
for (const node of nodes) {
|
|
692
816
|
const path = prefix ? `${prefix}.${node.id}` : node.id;
|
|
693
817
|
if (node.kind === "field") out.set(path, node);
|
|
694
|
-
else if (node.kind === "group") walk(node.children, path);
|
|
695
|
-
else {
|
|
818
|
+
else if (node.kind === "group" || node.kind === "step") walk(node.children, path);
|
|
819
|
+
else if (node.kind === "steps") {
|
|
820
|
+
for (const step of node.steps) walk(step.children, `${path}.${step.id}`);
|
|
821
|
+
} else {
|
|
696
822
|
node.items.peek().forEach((row, i) => walk(row.group.children, `${path}.${i}`));
|
|
697
823
|
}
|
|
698
824
|
}
|
|
@@ -705,7 +831,9 @@ function resolveLeaf(tree, rootByName, path) {
|
|
|
705
831
|
let node = rootByName.get(parts[0]);
|
|
706
832
|
for (let i = 1; i < parts.length && node; i++) {
|
|
707
833
|
const part = parts[i];
|
|
708
|
-
if (node instanceof GroupNode) {
|
|
834
|
+
if (node instanceof GroupNode || node instanceof StepNode) {
|
|
835
|
+
node = node.byName.get(part);
|
|
836
|
+
} else if (node instanceof StepsNode) {
|
|
709
837
|
node = node.byName.get(part);
|
|
710
838
|
} else if (node instanceof CollectionNode) {
|
|
711
839
|
node = node.items.peek()[Number(part)]?.group;
|
|
@@ -715,7 +843,22 @@ function resolveLeaf(tree, rootByName, path) {
|
|
|
715
843
|
}
|
|
716
844
|
return node && node.kind === "field" ? node : void 0;
|
|
717
845
|
}
|
|
846
|
+
function findSteps(tree) {
|
|
847
|
+
for (const node of tree) {
|
|
848
|
+
if (node.kind === "steps") return node;
|
|
849
|
+
if (node.kind === "group" || node.kind === "step") {
|
|
850
|
+
const found = findSteps(node.children);
|
|
851
|
+
if (found) return found;
|
|
852
|
+
} else if (node.kind === "collection") {
|
|
853
|
+
for (const row of node.items.peek()) {
|
|
854
|
+
const found = findSteps(row.group.children);
|
|
855
|
+
if (found) return found;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
return void 0;
|
|
860
|
+
}
|
|
718
861
|
|
|
719
|
-
export { CollectionNode, FieldState, Form, FormValidationError, GroupNode, buildTree, compileValidator, defaultValueFor, eachLeaf, evaluateCondition, isPresentational, isProviderRef, referencedFields, resolve, resolveQuery, setDefaultRenderer };
|
|
862
|
+
export { CollectionNode, FieldState, Form, FormValidationError, GroupNode, StepNode, StepsNode, buildTree, compileValidator, defaultValueFor, eachLeaf, evaluateCondition, isPresentational, isProviderRef, referencedFields, resolve, resolveQuery, setDefaultRenderer };
|
|
720
863
|
//# sourceMappingURL=index.js.map
|
|
721
864
|
//# sourceMappingURL=index.js.map
|