@json-render/core 0.4.4 → 0.5.1
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/README.md +126 -0
- package/dist/index.d.mts +366 -166
- package/dist/index.d.ts +366 -166
- package/dist/index.js +467 -56
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +459 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
ActionBindingSchema: () => ActionBindingSchema,
|
|
23
24
|
ActionConfirmSchema: () => ActionConfirmSchema,
|
|
24
25
|
ActionOnErrorSchema: () => ActionOnErrorSchema,
|
|
25
26
|
ActionOnSuccessSchema: () => ActionOnSuccessSchema,
|
|
@@ -33,8 +34,11 @@ __export(index_exports, {
|
|
|
33
34
|
ValidationConfigSchema: () => ValidationConfigSchema,
|
|
34
35
|
VisibilityConditionSchema: () => VisibilityConditionSchema,
|
|
35
36
|
action: () => action,
|
|
37
|
+
actionBinding: () => actionBinding,
|
|
36
38
|
addByPath: () => addByPath,
|
|
37
39
|
applySpecStreamPatch: () => applySpecStreamPatch,
|
|
40
|
+
autoFixSpec: () => autoFixSpec,
|
|
41
|
+
buildUserPrompt: () => buildUserPrompt,
|
|
38
42
|
builtInValidationFunctions: () => builtInValidationFunctions,
|
|
39
43
|
check: () => check,
|
|
40
44
|
compileSpecStream: () => compileSpecStream,
|
|
@@ -46,6 +50,7 @@ __export(index_exports, {
|
|
|
46
50
|
evaluateVisibility: () => evaluateVisibility,
|
|
47
51
|
executeAction: () => executeAction,
|
|
48
52
|
findFormValue: () => findFormValue,
|
|
53
|
+
formatSpecIssues: () => formatSpecIssues,
|
|
49
54
|
generateCatalogPrompt: () => generateCatalogPrompt,
|
|
50
55
|
generateSystemPrompt: () => generateSystemPrompt,
|
|
51
56
|
getByPath: () => getByPath,
|
|
@@ -54,9 +59,12 @@ __export(index_exports, {
|
|
|
54
59
|
removeByPath: () => removeByPath,
|
|
55
60
|
resolveAction: () => resolveAction,
|
|
56
61
|
resolveDynamicValue: () => resolveDynamicValue,
|
|
62
|
+
resolveElementProps: () => resolveElementProps,
|
|
63
|
+
resolvePropValue: () => resolvePropValue,
|
|
57
64
|
runValidation: () => runValidation,
|
|
58
65
|
runValidationCheck: () => runValidationCheck,
|
|
59
66
|
setByPath: () => setByPath,
|
|
67
|
+
validateSpec: () => validateSpec,
|
|
60
68
|
visibility: () => visibility
|
|
61
69
|
});
|
|
62
70
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -82,12 +90,12 @@ var DynamicBooleanSchema = import_zod.z.union([
|
|
|
82
90
|
import_zod.z.boolean(),
|
|
83
91
|
import_zod.z.object({ path: import_zod.z.string() })
|
|
84
92
|
]);
|
|
85
|
-
function resolveDynamicValue(value,
|
|
93
|
+
function resolveDynamicValue(value, stateModel) {
|
|
86
94
|
if (value === null || value === void 0) {
|
|
87
95
|
return void 0;
|
|
88
96
|
}
|
|
89
97
|
if (typeof value === "object" && "path" in value) {
|
|
90
|
-
return getByPath(
|
|
98
|
+
return getByPath(stateModel, value.path);
|
|
91
99
|
}
|
|
92
100
|
return value;
|
|
93
101
|
}
|
|
@@ -415,7 +423,7 @@ var VisibilityConditionSchema = import_zod2.z.union([
|
|
|
415
423
|
LogicExpressionSchema
|
|
416
424
|
]);
|
|
417
425
|
function evaluateLogicExpression(expr, ctx) {
|
|
418
|
-
const {
|
|
426
|
+
const { stateModel } = ctx;
|
|
419
427
|
if ("and" in expr) {
|
|
420
428
|
return expr.and.every((subExpr) => evaluateLogicExpression(subExpr, ctx));
|
|
421
429
|
}
|
|
@@ -426,30 +434,30 @@ function evaluateLogicExpression(expr, ctx) {
|
|
|
426
434
|
return !evaluateLogicExpression(expr.not, ctx);
|
|
427
435
|
}
|
|
428
436
|
if ("path" in expr) {
|
|
429
|
-
const value = resolveDynamicValue({ path: expr.path },
|
|
437
|
+
const value = resolveDynamicValue({ path: expr.path }, stateModel);
|
|
430
438
|
return Boolean(value);
|
|
431
439
|
}
|
|
432
440
|
if ("eq" in expr) {
|
|
433
441
|
const [left, right] = expr.eq;
|
|
434
|
-
const leftValue = resolveDynamicValue(left,
|
|
435
|
-
const rightValue = resolveDynamicValue(right,
|
|
442
|
+
const leftValue = resolveDynamicValue(left, stateModel);
|
|
443
|
+
const rightValue = resolveDynamicValue(right, stateModel);
|
|
436
444
|
return leftValue === rightValue;
|
|
437
445
|
}
|
|
438
446
|
if ("neq" in expr) {
|
|
439
447
|
const [left, right] = expr.neq;
|
|
440
|
-
const leftValue = resolveDynamicValue(left,
|
|
441
|
-
const rightValue = resolveDynamicValue(right,
|
|
448
|
+
const leftValue = resolveDynamicValue(left, stateModel);
|
|
449
|
+
const rightValue = resolveDynamicValue(right, stateModel);
|
|
442
450
|
return leftValue !== rightValue;
|
|
443
451
|
}
|
|
444
452
|
if ("gt" in expr) {
|
|
445
453
|
const [left, right] = expr.gt;
|
|
446
454
|
const leftValue = resolveDynamicValue(
|
|
447
455
|
left,
|
|
448
|
-
|
|
456
|
+
stateModel
|
|
449
457
|
);
|
|
450
458
|
const rightValue = resolveDynamicValue(
|
|
451
459
|
right,
|
|
452
|
-
|
|
460
|
+
stateModel
|
|
453
461
|
);
|
|
454
462
|
if (typeof leftValue === "number" && typeof rightValue === "number") {
|
|
455
463
|
return leftValue > rightValue;
|
|
@@ -460,11 +468,11 @@ function evaluateLogicExpression(expr, ctx) {
|
|
|
460
468
|
const [left, right] = expr.gte;
|
|
461
469
|
const leftValue = resolveDynamicValue(
|
|
462
470
|
left,
|
|
463
|
-
|
|
471
|
+
stateModel
|
|
464
472
|
);
|
|
465
473
|
const rightValue = resolveDynamicValue(
|
|
466
474
|
right,
|
|
467
|
-
|
|
475
|
+
stateModel
|
|
468
476
|
);
|
|
469
477
|
if (typeof leftValue === "number" && typeof rightValue === "number") {
|
|
470
478
|
return leftValue >= rightValue;
|
|
@@ -475,11 +483,11 @@ function evaluateLogicExpression(expr, ctx) {
|
|
|
475
483
|
const [left, right] = expr.lt;
|
|
476
484
|
const leftValue = resolveDynamicValue(
|
|
477
485
|
left,
|
|
478
|
-
|
|
486
|
+
stateModel
|
|
479
487
|
);
|
|
480
488
|
const rightValue = resolveDynamicValue(
|
|
481
489
|
right,
|
|
482
|
-
|
|
490
|
+
stateModel
|
|
483
491
|
);
|
|
484
492
|
if (typeof leftValue === "number" && typeof rightValue === "number") {
|
|
485
493
|
return leftValue < rightValue;
|
|
@@ -490,11 +498,11 @@ function evaluateLogicExpression(expr, ctx) {
|
|
|
490
498
|
const [left, right] = expr.lte;
|
|
491
499
|
const leftValue = resolveDynamicValue(
|
|
492
500
|
left,
|
|
493
|
-
|
|
501
|
+
stateModel
|
|
494
502
|
);
|
|
495
503
|
const rightValue = resolveDynamicValue(
|
|
496
504
|
right,
|
|
497
|
-
|
|
505
|
+
stateModel
|
|
498
506
|
);
|
|
499
507
|
if (typeof leftValue === "number" && typeof rightValue === "number") {
|
|
500
508
|
return leftValue <= rightValue;
|
|
@@ -511,7 +519,7 @@ function evaluateVisibility(condition, ctx) {
|
|
|
511
519
|
return condition;
|
|
512
520
|
}
|
|
513
521
|
if ("path" in condition && !("and" in condition) && !("or" in condition)) {
|
|
514
|
-
const value = resolveDynamicValue({ path: condition.path }, ctx.
|
|
522
|
+
const value = resolveDynamicValue({ path: condition.path }, ctx.stateModel);
|
|
515
523
|
return Boolean(value);
|
|
516
524
|
}
|
|
517
525
|
if ("auth" in condition) {
|
|
@@ -565,6 +573,44 @@ var visibility = {
|
|
|
565
573
|
lte: (left, right) => ({ lte: [left, right] })
|
|
566
574
|
};
|
|
567
575
|
|
|
576
|
+
// src/props.ts
|
|
577
|
+
function isPathExpression(value) {
|
|
578
|
+
return typeof value === "object" && value !== null && "$path" in value && typeof value.$path === "string";
|
|
579
|
+
}
|
|
580
|
+
function isCondExpression(value) {
|
|
581
|
+
return typeof value === "object" && value !== null && "$cond" in value && "$then" in value && "$else" in value;
|
|
582
|
+
}
|
|
583
|
+
function resolvePropValue(value, ctx) {
|
|
584
|
+
if (value === null || value === void 0) {
|
|
585
|
+
return value;
|
|
586
|
+
}
|
|
587
|
+
if (isPathExpression(value)) {
|
|
588
|
+
return getByPath(ctx.stateModel, value.$path);
|
|
589
|
+
}
|
|
590
|
+
if (isCondExpression(value)) {
|
|
591
|
+
const result = evaluateVisibility(value.$cond, ctx);
|
|
592
|
+
return resolvePropValue(result ? value.$then : value.$else, ctx);
|
|
593
|
+
}
|
|
594
|
+
if (Array.isArray(value)) {
|
|
595
|
+
return value.map((item) => resolvePropValue(item, ctx));
|
|
596
|
+
}
|
|
597
|
+
if (typeof value === "object") {
|
|
598
|
+
const resolved = {};
|
|
599
|
+
for (const [key, val] of Object.entries(value)) {
|
|
600
|
+
resolved[key] = resolvePropValue(val, ctx);
|
|
601
|
+
}
|
|
602
|
+
return resolved;
|
|
603
|
+
}
|
|
604
|
+
return value;
|
|
605
|
+
}
|
|
606
|
+
function resolveElementProps(props, ctx) {
|
|
607
|
+
const resolved = {};
|
|
608
|
+
for (const [key, value] of Object.entries(props)) {
|
|
609
|
+
resolved[key] = resolvePropValue(value, ctx);
|
|
610
|
+
}
|
|
611
|
+
return resolved;
|
|
612
|
+
}
|
|
613
|
+
|
|
568
614
|
// src/actions.ts
|
|
569
615
|
var import_zod3 = require("zod");
|
|
570
616
|
var ActionConfirmSchema = import_zod3.z.object({
|
|
@@ -583,44 +629,45 @@ var ActionOnErrorSchema = import_zod3.z.union([
|
|
|
583
629
|
import_zod3.z.object({ set: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()) }),
|
|
584
630
|
import_zod3.z.object({ action: import_zod3.z.string() })
|
|
585
631
|
]);
|
|
586
|
-
var
|
|
587
|
-
|
|
632
|
+
var ActionBindingSchema = import_zod3.z.object({
|
|
633
|
+
action: import_zod3.z.string(),
|
|
588
634
|
params: import_zod3.z.record(import_zod3.z.string(), DynamicValueSchema).optional(),
|
|
589
635
|
confirm: ActionConfirmSchema.optional(),
|
|
590
636
|
onSuccess: ActionOnSuccessSchema.optional(),
|
|
591
637
|
onError: ActionOnErrorSchema.optional()
|
|
592
638
|
});
|
|
593
|
-
|
|
639
|
+
var ActionSchema = ActionBindingSchema;
|
|
640
|
+
function resolveAction(binding, stateModel) {
|
|
594
641
|
const resolvedParams = {};
|
|
595
|
-
if (
|
|
596
|
-
for (const [key, value] of Object.entries(
|
|
597
|
-
resolvedParams[key] = resolveDynamicValue(value,
|
|
642
|
+
if (binding.params) {
|
|
643
|
+
for (const [key, value] of Object.entries(binding.params)) {
|
|
644
|
+
resolvedParams[key] = resolveDynamicValue(value, stateModel);
|
|
598
645
|
}
|
|
599
646
|
}
|
|
600
|
-
let confirm =
|
|
647
|
+
let confirm = binding.confirm;
|
|
601
648
|
if (confirm) {
|
|
602
649
|
confirm = {
|
|
603
650
|
...confirm,
|
|
604
|
-
message: interpolateString(confirm.message,
|
|
605
|
-
title: interpolateString(confirm.title,
|
|
651
|
+
message: interpolateString(confirm.message, stateModel),
|
|
652
|
+
title: interpolateString(confirm.title, stateModel)
|
|
606
653
|
};
|
|
607
654
|
}
|
|
608
655
|
return {
|
|
609
|
-
|
|
656
|
+
action: binding.action,
|
|
610
657
|
params: resolvedParams,
|
|
611
658
|
confirm,
|
|
612
|
-
onSuccess:
|
|
613
|
-
onError:
|
|
659
|
+
onSuccess: binding.onSuccess,
|
|
660
|
+
onError: binding.onError
|
|
614
661
|
};
|
|
615
662
|
}
|
|
616
|
-
function interpolateString(template,
|
|
663
|
+
function interpolateString(template, stateModel) {
|
|
617
664
|
return template.replace(/\$\{([^}]+)\}/g, (_, path) => {
|
|
618
|
-
const value = resolveDynamicValue({ path },
|
|
665
|
+
const value = resolveDynamicValue({ path }, stateModel);
|
|
619
666
|
return String(value ?? "");
|
|
620
667
|
});
|
|
621
668
|
}
|
|
622
669
|
async function executeAction(ctx) {
|
|
623
|
-
const { action: action2, handler,
|
|
670
|
+
const { action: action2, handler, setState, navigate, executeAction: executeAction2 } = ctx;
|
|
624
671
|
try {
|
|
625
672
|
await handler(action2.params);
|
|
626
673
|
if (action2.onSuccess) {
|
|
@@ -628,7 +675,7 @@ async function executeAction(ctx) {
|
|
|
628
675
|
navigate(action2.onSuccess.navigate);
|
|
629
676
|
} else if ("set" in action2.onSuccess) {
|
|
630
677
|
for (const [path, value] of Object.entries(action2.onSuccess.set)) {
|
|
631
|
-
|
|
678
|
+
setState(path, value);
|
|
632
679
|
}
|
|
633
680
|
} else if ("action" in action2.onSuccess && executeAction2) {
|
|
634
681
|
await executeAction2(action2.onSuccess.action);
|
|
@@ -639,7 +686,7 @@ async function executeAction(ctx) {
|
|
|
639
686
|
if ("set" in action2.onError) {
|
|
640
687
|
for (const [path, value] of Object.entries(action2.onError.set)) {
|
|
641
688
|
const resolvedValue = typeof value === "string" && value === "$error.message" ? error.message : value;
|
|
642
|
-
|
|
689
|
+
setState(path, resolvedValue);
|
|
643
690
|
}
|
|
644
691
|
} else if ("action" in action2.onError && executeAction2) {
|
|
645
692
|
await executeAction2(action2.onError.action);
|
|
@@ -649,25 +696,26 @@ async function executeAction(ctx) {
|
|
|
649
696
|
}
|
|
650
697
|
}
|
|
651
698
|
}
|
|
652
|
-
var
|
|
653
|
-
/** Create a simple action */
|
|
654
|
-
simple: (
|
|
655
|
-
|
|
699
|
+
var actionBinding = {
|
|
700
|
+
/** Create a simple action binding */
|
|
701
|
+
simple: (actionName, params) => ({
|
|
702
|
+
action: actionName,
|
|
656
703
|
params
|
|
657
704
|
}),
|
|
658
|
-
/** Create an action with confirmation */
|
|
659
|
-
withConfirm: (
|
|
660
|
-
|
|
705
|
+
/** Create an action binding with confirmation */
|
|
706
|
+
withConfirm: (actionName, confirm, params) => ({
|
|
707
|
+
action: actionName,
|
|
661
708
|
params,
|
|
662
709
|
confirm
|
|
663
710
|
}),
|
|
664
|
-
/** Create an action with success handler */
|
|
665
|
-
withSuccess: (
|
|
666
|
-
|
|
711
|
+
/** Create an action binding with success handler */
|
|
712
|
+
withSuccess: (actionName, onSuccess, params) => ({
|
|
713
|
+
action: actionName,
|
|
667
714
|
params,
|
|
668
715
|
onSuccess
|
|
669
716
|
})
|
|
670
717
|
};
|
|
718
|
+
var action = actionBinding;
|
|
671
719
|
|
|
672
720
|
// src/validation.ts
|
|
673
721
|
var import_zod4 = require("zod");
|
|
@@ -776,11 +824,11 @@ var builtInValidationFunctions = {
|
|
|
776
824
|
}
|
|
777
825
|
};
|
|
778
826
|
function runValidationCheck(check2, ctx) {
|
|
779
|
-
const { value,
|
|
827
|
+
const { value, stateModel, customFunctions } = ctx;
|
|
780
828
|
const resolvedArgs = {};
|
|
781
829
|
if (check2.args) {
|
|
782
830
|
for (const [key, argValue] of Object.entries(check2.args)) {
|
|
783
|
-
resolvedArgs[key] = resolveDynamicValue(argValue,
|
|
831
|
+
resolvedArgs[key] = resolveDynamicValue(argValue, stateModel);
|
|
784
832
|
}
|
|
785
833
|
}
|
|
786
834
|
const fn = builtInValidationFunctions[check2.fn] ?? customFunctions?.[check2.fn];
|
|
@@ -805,7 +853,7 @@ function runValidation(config, ctx) {
|
|
|
805
853
|
const errors = [];
|
|
806
854
|
if (config.enabled) {
|
|
807
855
|
const enabled = evaluateLogicExpression(config.enabled, {
|
|
808
|
-
|
|
856
|
+
stateModel: ctx.stateModel,
|
|
809
857
|
authState: ctx.authState
|
|
810
858
|
});
|
|
811
859
|
if (!enabled) {
|
|
@@ -872,6 +920,155 @@ var check = {
|
|
|
872
920
|
})
|
|
873
921
|
};
|
|
874
922
|
|
|
923
|
+
// src/spec-validator.ts
|
|
924
|
+
function validateSpec(spec, options = {}) {
|
|
925
|
+
const { checkOrphans = false } = options;
|
|
926
|
+
const issues = [];
|
|
927
|
+
if (!spec.root) {
|
|
928
|
+
issues.push({
|
|
929
|
+
severity: "error",
|
|
930
|
+
message: "Spec has no root element defined.",
|
|
931
|
+
code: "missing_root"
|
|
932
|
+
});
|
|
933
|
+
return { valid: false, issues };
|
|
934
|
+
}
|
|
935
|
+
if (!spec.elements[spec.root]) {
|
|
936
|
+
issues.push({
|
|
937
|
+
severity: "error",
|
|
938
|
+
message: `Root element "${spec.root}" not found in elements map.`,
|
|
939
|
+
code: "root_not_found"
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
if (Object.keys(spec.elements).length === 0) {
|
|
943
|
+
issues.push({
|
|
944
|
+
severity: "error",
|
|
945
|
+
message: "Spec has no elements.",
|
|
946
|
+
code: "empty_spec"
|
|
947
|
+
});
|
|
948
|
+
return { valid: false, issues };
|
|
949
|
+
}
|
|
950
|
+
for (const [key, element] of Object.entries(spec.elements)) {
|
|
951
|
+
if (element.children) {
|
|
952
|
+
for (const childKey of element.children) {
|
|
953
|
+
if (!spec.elements[childKey]) {
|
|
954
|
+
issues.push({
|
|
955
|
+
severity: "error",
|
|
956
|
+
message: `Element "${key}" references child "${childKey}" which does not exist in the elements map.`,
|
|
957
|
+
elementKey: key,
|
|
958
|
+
code: "missing_child"
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
const props = element.props;
|
|
964
|
+
if (props && "visible" in props && props.visible !== void 0) {
|
|
965
|
+
issues.push({
|
|
966
|
+
severity: "error",
|
|
967
|
+
message: `Element "${key}" has "visible" inside "props". It should be a top-level field on the element (sibling of type/props/children).`,
|
|
968
|
+
elementKey: key,
|
|
969
|
+
code: "visible_in_props"
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
if (props && "on" in props && props.on !== void 0) {
|
|
973
|
+
issues.push({
|
|
974
|
+
severity: "error",
|
|
975
|
+
message: `Element "${key}" has "on" inside "props". It should be a top-level field on the element (sibling of type/props/children).`,
|
|
976
|
+
elementKey: key,
|
|
977
|
+
code: "on_in_props"
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
if (props && "repeat" in props && props.repeat !== void 0) {
|
|
981
|
+
issues.push({
|
|
982
|
+
severity: "error",
|
|
983
|
+
message: `Element "${key}" has "repeat" inside "props". It should be a top-level field on the element (sibling of type/props/children).`,
|
|
984
|
+
elementKey: key,
|
|
985
|
+
code: "repeat_in_props"
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
if (checkOrphans) {
|
|
990
|
+
const reachable = /* @__PURE__ */ new Set();
|
|
991
|
+
const walk = (key) => {
|
|
992
|
+
if (reachable.has(key)) return;
|
|
993
|
+
reachable.add(key);
|
|
994
|
+
const el = spec.elements[key];
|
|
995
|
+
if (el?.children) {
|
|
996
|
+
for (const childKey of el.children) {
|
|
997
|
+
if (spec.elements[childKey]) {
|
|
998
|
+
walk(childKey);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
if (spec.elements[spec.root]) {
|
|
1004
|
+
walk(spec.root);
|
|
1005
|
+
}
|
|
1006
|
+
for (const key of Object.keys(spec.elements)) {
|
|
1007
|
+
if (!reachable.has(key)) {
|
|
1008
|
+
issues.push({
|
|
1009
|
+
severity: "warning",
|
|
1010
|
+
message: `Element "${key}" is not reachable from root "${spec.root}".`,
|
|
1011
|
+
elementKey: key,
|
|
1012
|
+
code: "orphaned_element"
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
1018
|
+
return { valid: !hasErrors, issues };
|
|
1019
|
+
}
|
|
1020
|
+
function autoFixSpec(spec) {
|
|
1021
|
+
const fixes = [];
|
|
1022
|
+
const fixedElements = {};
|
|
1023
|
+
for (const [key, element] of Object.entries(spec.elements)) {
|
|
1024
|
+
const props = element.props;
|
|
1025
|
+
let fixed = element;
|
|
1026
|
+
if (props && "visible" in props && props.visible !== void 0) {
|
|
1027
|
+
const { visible, ...restProps } = fixed.props;
|
|
1028
|
+
fixed = {
|
|
1029
|
+
...fixed,
|
|
1030
|
+
props: restProps,
|
|
1031
|
+
visible
|
|
1032
|
+
};
|
|
1033
|
+
fixes.push(`Moved "visible" from props to element level on "${key}".`);
|
|
1034
|
+
}
|
|
1035
|
+
let currentProps = fixed.props;
|
|
1036
|
+
if (currentProps && "on" in currentProps && currentProps.on !== void 0) {
|
|
1037
|
+
const { on, ...restProps } = currentProps;
|
|
1038
|
+
fixed = {
|
|
1039
|
+
...fixed,
|
|
1040
|
+
props: restProps,
|
|
1041
|
+
on
|
|
1042
|
+
};
|
|
1043
|
+
fixes.push(`Moved "on" from props to element level on "${key}".`);
|
|
1044
|
+
}
|
|
1045
|
+
currentProps = fixed.props;
|
|
1046
|
+
if (currentProps && "repeat" in currentProps && currentProps.repeat !== void 0) {
|
|
1047
|
+
const { repeat, ...restProps } = currentProps;
|
|
1048
|
+
fixed = {
|
|
1049
|
+
...fixed,
|
|
1050
|
+
props: restProps,
|
|
1051
|
+
repeat
|
|
1052
|
+
};
|
|
1053
|
+
fixes.push(`Moved "repeat" from props to element level on "${key}".`);
|
|
1054
|
+
}
|
|
1055
|
+
fixedElements[key] = fixed;
|
|
1056
|
+
}
|
|
1057
|
+
return {
|
|
1058
|
+
spec: { root: spec.root, elements: fixedElements },
|
|
1059
|
+
fixes
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
function formatSpecIssues(issues) {
|
|
1063
|
+
const errors = issues.filter((i) => i.severity === "error");
|
|
1064
|
+
if (errors.length === 0) return "";
|
|
1065
|
+
const lines = ["The generated UI spec has the following errors:"];
|
|
1066
|
+
for (const issue of errors) {
|
|
1067
|
+
lines.push(`- ${issue.message}`);
|
|
1068
|
+
}
|
|
1069
|
+
return lines.join("\n");
|
|
1070
|
+
}
|
|
1071
|
+
|
|
875
1072
|
// src/schema.ts
|
|
876
1073
|
var import_zod5 = require("zod");
|
|
877
1074
|
function createBuilder() {
|
|
@@ -896,6 +1093,7 @@ function defineSchema(builder, options) {
|
|
|
896
1093
|
return {
|
|
897
1094
|
definition,
|
|
898
1095
|
promptTemplate: options?.promptTemplate,
|
|
1096
|
+
defaultRules: options?.defaultRules,
|
|
899
1097
|
createCatalog(catalog) {
|
|
900
1098
|
return createCatalogFromSchema(this, catalog);
|
|
901
1099
|
}
|
|
@@ -1051,15 +1249,95 @@ function generatePrompt(catalog, options) {
|
|
|
1051
1249
|
"Output JSONL (one JSON object per line) with patches to build a UI tree."
|
|
1052
1250
|
);
|
|
1053
1251
|
lines.push(
|
|
1054
|
-
"Each line is a JSON patch operation. Start with
|
|
1252
|
+
"Each line is a JSON patch operation. Start with /root, then stream /elements and /state patches interleaved so the UI fills in progressively as it streams."
|
|
1055
1253
|
);
|
|
1056
1254
|
lines.push("");
|
|
1057
1255
|
lines.push("Example output (each line is a separate JSON object):");
|
|
1058
1256
|
lines.push("");
|
|
1059
|
-
lines.push(`{"op":"add","path":"/root","value":"
|
|
1060
|
-
{"op":"add","path":"/elements/
|
|
1061
|
-
{"op":"add","path":"/elements/
|
|
1062
|
-
{"op":"add","path":"/elements/
|
|
1257
|
+
lines.push(`{"op":"add","path":"/root","value":"blog"}
|
|
1258
|
+
{"op":"add","path":"/elements/blog","value":{"type":"Stack","props":{"direction":"vertical","gap":"md"},"children":["heading","posts-grid"]}}
|
|
1259
|
+
{"op":"add","path":"/elements/heading","value":{"type":"Heading","props":{"text":"Blog","level":"h1"},"children":[]}}
|
|
1260
|
+
{"op":"add","path":"/elements/posts-grid","value":{"type":"Grid","props":{"columns":2,"gap":"md"},"repeat":{"path":"/posts","key":"id"},"children":["post-card"]}}
|
|
1261
|
+
{"op":"add","path":"/elements/post-card","value":{"type":"Card","props":{"title":{"$path":"$item/title"}},"children":["post-meta"]}}
|
|
1262
|
+
{"op":"add","path":"/elements/post-meta","value":{"type":"Text","props":{"text":{"$path":"$item/author"},"variant":"muted"},"children":[]}}
|
|
1263
|
+
{"op":"add","path":"/state/posts","value":[]}
|
|
1264
|
+
{"op":"add","path":"/state/posts/0","value":{"id":"1","title":"Getting Started","author":"Jane","date":"Jan 15"}}
|
|
1265
|
+
{"op":"add","path":"/state/posts/1","value":{"id":"2","title":"Advanced Tips","author":"Bob","date":"Feb 3"}}
|
|
1266
|
+
|
|
1267
|
+
Note: state patches appear right after the elements that use them, so the UI fills in as it streams.`);
|
|
1268
|
+
lines.push("");
|
|
1269
|
+
lines.push("INITIAL STATE:");
|
|
1270
|
+
lines.push(
|
|
1271
|
+
"Specs include a /state field to seed the state model. Components with statePath read from and write to this state, and $path expressions read from it."
|
|
1272
|
+
);
|
|
1273
|
+
lines.push(
|
|
1274
|
+
"CRITICAL: You MUST include state patches whenever your UI displays data via $path expressions, uses repeat to iterate over arrays, or uses statePath bindings. Without state, $path references resolve to nothing and repeat lists render zero items."
|
|
1275
|
+
);
|
|
1276
|
+
lines.push(
|
|
1277
|
+
"Output state patches right after the elements that reference them, so the UI fills in progressively as it streams."
|
|
1278
|
+
);
|
|
1279
|
+
lines.push(
|
|
1280
|
+
"Stream state progressively - output one patch per array item instead of one giant blob:"
|
|
1281
|
+
);
|
|
1282
|
+
lines.push(
|
|
1283
|
+
' For arrays: {"op":"add","path":"/state/posts/0","value":{"id":"1","title":"First Post",...}} then /state/posts/1, /state/posts/2, etc.'
|
|
1284
|
+
);
|
|
1285
|
+
lines.push(
|
|
1286
|
+
' For scalars: {"op":"add","path":"/state/newTodoText","value":""}'
|
|
1287
|
+
);
|
|
1288
|
+
lines.push(
|
|
1289
|
+
' Initialize the array first if needed: {"op":"add","path":"/state/posts","value":[]}'
|
|
1290
|
+
);
|
|
1291
|
+
lines.push(
|
|
1292
|
+
'When content comes from the state model, use { "$path": "/some/path" } dynamic props to display it instead of hardcoding the same value in both state and props. The state model is the single source of truth.'
|
|
1293
|
+
);
|
|
1294
|
+
lines.push(
|
|
1295
|
+
"Include realistic sample data in state. For blogs: 3-4 posts with titles, excerpts, authors, dates. For product lists: 3-5 items with names, prices, descriptions. Never leave arrays empty."
|
|
1296
|
+
);
|
|
1297
|
+
lines.push("");
|
|
1298
|
+
lines.push("DYNAMIC LISTS (repeat field):");
|
|
1299
|
+
lines.push(
|
|
1300
|
+
'Any element can have a top-level "repeat" field to render its children once per item in a state array: { "repeat": { "path": "/arrayPath", "key": "id" } }.'
|
|
1301
|
+
);
|
|
1302
|
+
lines.push(
|
|
1303
|
+
'The element itself renders once (as the container), and its children are expanded once per array item. "path" is the state array path. "key" is an optional field name on each item for stable React keys.'
|
|
1304
|
+
);
|
|
1305
|
+
lines.push(
|
|
1306
|
+
'Example: { "type": "Column", "props": { "gap": 8 }, "repeat": { "path": "/todos", "key": "id" }, "children": ["todo-item"] }'
|
|
1307
|
+
);
|
|
1308
|
+
lines.push(
|
|
1309
|
+
'Inside children of a repeated element, use "$item/field" for per-item paths: statePath:"$item/completed", { "$path": "$item/title" }. Use "$index" for the current array index.'
|
|
1310
|
+
);
|
|
1311
|
+
lines.push(
|
|
1312
|
+
"ALWAYS use the repeat field for lists backed by state arrays. NEVER hardcode individual elements for each array item."
|
|
1313
|
+
);
|
|
1314
|
+
lines.push(
|
|
1315
|
+
'IMPORTANT: "repeat" is a top-level field on the element (sibling of type/props/children), NOT inside props.'
|
|
1316
|
+
);
|
|
1317
|
+
lines.push("");
|
|
1318
|
+
lines.push("ARRAY STATE ACTIONS:");
|
|
1319
|
+
lines.push(
|
|
1320
|
+
'Use action "pushState" to append items to arrays. Params: { path: "/arrayPath", value: { ...item }, clearPath: "/inputPath" }.'
|
|
1321
|
+
);
|
|
1322
|
+
lines.push(
|
|
1323
|
+
'Values inside pushState can contain { "path": "/statePath" } references to read current state (e.g. the text from an input field).'
|
|
1324
|
+
);
|
|
1325
|
+
lines.push(
|
|
1326
|
+
'Use "$id" inside a pushState value to auto-generate a unique ID.'
|
|
1327
|
+
);
|
|
1328
|
+
lines.push(
|
|
1329
|
+
'Example: on: { "press": { "action": "pushState", "params": { "path": "/todos", "value": { "id": "$id", "title": { "path": "/newTodoText" }, "completed": false }, "clearPath": "/newTodoText" } } }'
|
|
1330
|
+
);
|
|
1331
|
+
lines.push(
|
|
1332
|
+
`Use action "removeState" to remove items from arrays by index. Params: { path: "/arrayPath", index: N }. Inside a repeated element's children, use "$index" for the current item index.`
|
|
1333
|
+
);
|
|
1334
|
+
lines.push(
|
|
1335
|
+
"For lists where users can add/remove items (todos, carts, etc.), use pushState and removeState instead of hardcoding with setState."
|
|
1336
|
+
);
|
|
1337
|
+
lines.push("");
|
|
1338
|
+
lines.push(
|
|
1339
|
+
'IMPORTANT: State paths use RFC 6901 JSON Pointer syntax (e.g. "/todos/0/title"). Do NOT use JavaScript-style dot notation (e.g. "/todos.length" is WRONG). To generate unique IDs for new items, use "$id" instead of trying to read array length.'
|
|
1340
|
+
);
|
|
1063
1341
|
lines.push("");
|
|
1064
1342
|
const components = catalog.data.components;
|
|
1065
1343
|
if (components) {
|
|
@@ -1069,8 +1347,9 @@ function generatePrompt(catalog, options) {
|
|
|
1069
1347
|
const propsStr = def.props ? formatZodType(def.props) : "{}";
|
|
1070
1348
|
const hasChildren = def.slots && def.slots.length > 0;
|
|
1071
1349
|
const childrenStr = hasChildren ? " [accepts children]" : "";
|
|
1350
|
+
const eventsStr = def.events && def.events.length > 0 ? ` [events: ${def.events.join(", ")}]` : "";
|
|
1072
1351
|
const descStr = def.description ? ` - ${def.description}` : "";
|
|
1073
|
-
lines.push(`- ${name}: ${propsStr}${descStr}${childrenStr}`);
|
|
1352
|
+
lines.push(`- ${name}: ${propsStr}${descStr}${childrenStr}${eventsStr}`);
|
|
1074
1353
|
}
|
|
1075
1354
|
lines.push("");
|
|
1076
1355
|
}
|
|
@@ -1083,16 +1362,90 @@ function generatePrompt(catalog, options) {
|
|
|
1083
1362
|
}
|
|
1084
1363
|
lines.push("");
|
|
1085
1364
|
}
|
|
1365
|
+
lines.push("EVENTS (the `on` field):");
|
|
1366
|
+
lines.push(
|
|
1367
|
+
"Elements can have an optional `on` field to bind events to actions. The `on` field is a top-level field on the element (sibling of type/props/children), NOT inside props."
|
|
1368
|
+
);
|
|
1369
|
+
lines.push(
|
|
1370
|
+
'Each key in `on` is an event name (from the component\'s supported events), and the value is an action binding: `{ "action": "<actionName>", "params": { ... } }`.'
|
|
1371
|
+
);
|
|
1372
|
+
lines.push("");
|
|
1373
|
+
lines.push("Example:");
|
|
1374
|
+
lines.push(
|
|
1375
|
+
' {"type":"Button","props":{"label":"Save"},"on":{"press":{"action":"setState","params":{"path":"/saved","value":true}}},"children":[]}'
|
|
1376
|
+
);
|
|
1377
|
+
lines.push("");
|
|
1378
|
+
lines.push(
|
|
1379
|
+
'Action params can use dynamic path references to read from state: { "path": "/statePath" }.'
|
|
1380
|
+
);
|
|
1381
|
+
lines.push(
|
|
1382
|
+
"IMPORTANT: Do NOT put action/actionParams inside props. Always use the `on` field for event bindings."
|
|
1383
|
+
);
|
|
1384
|
+
lines.push("");
|
|
1385
|
+
lines.push("VISIBILITY CONDITIONS:");
|
|
1386
|
+
lines.push(
|
|
1387
|
+
"Elements can have an optional `visible` field to conditionally show/hide based on data state. IMPORTANT: `visible` is a top-level field on the element object (sibling of type/props/children), NOT inside props."
|
|
1388
|
+
);
|
|
1389
|
+
lines.push(
|
|
1390
|
+
'Correct: {"type":"Column","props":{"gap":8},"visible":{"eq":[{"path":"/tab"},"home"]},"children":[...]}'
|
|
1391
|
+
);
|
|
1392
|
+
lines.push(
|
|
1393
|
+
'- `{ "eq": [{ "path": "/statePath" }, "value"] }` - visible when state at path equals value'
|
|
1394
|
+
);
|
|
1395
|
+
lines.push(
|
|
1396
|
+
'- `{ "neq": [{ "path": "/statePath" }, "value"] }` - visible when state at path does not equal value'
|
|
1397
|
+
);
|
|
1398
|
+
lines.push('- `{ "path": "/statePath" }` - visible when path is truthy');
|
|
1399
|
+
lines.push(
|
|
1400
|
+
'- `{ "and": [...] }`, `{ "or": [...] }`, `{ "not": {...} }` - combine conditions'
|
|
1401
|
+
);
|
|
1402
|
+
lines.push("- `true` / `false` - always visible/hidden");
|
|
1403
|
+
lines.push("");
|
|
1404
|
+
lines.push(
|
|
1405
|
+
"Use the Pressable component with on.press bound to setState to update state and drive visibility."
|
|
1406
|
+
);
|
|
1407
|
+
lines.push(
|
|
1408
|
+
'Example: A Pressable with on: { "press": { "action": "setState", "params": { "path": "/activeTab", "value": "home" } } } sets state, then a container with visible: { "eq": [{ "path": "/activeTab" }, "home"] } shows only when that tab is active.'
|
|
1409
|
+
);
|
|
1410
|
+
lines.push("");
|
|
1411
|
+
lines.push("DYNAMIC PROPS:");
|
|
1412
|
+
lines.push(
|
|
1413
|
+
"Any prop value can be a dynamic expression that resolves based on state. Two forms are supported:"
|
|
1414
|
+
);
|
|
1415
|
+
lines.push("");
|
|
1416
|
+
lines.push(
|
|
1417
|
+
'1. State binding: `{ "$path": "/statePath" }` - resolves to the value at that state path.'
|
|
1418
|
+
);
|
|
1419
|
+
lines.push(
|
|
1420
|
+
' Example: `"color": { "$path": "/theme/primary" }` reads the color from state.'
|
|
1421
|
+
);
|
|
1422
|
+
lines.push("");
|
|
1423
|
+
lines.push(
|
|
1424
|
+
'2. Conditional: `{ "$cond": <condition>, "$then": <value>, "$else": <value> }` - evaluates the condition (same syntax as visibility conditions) and picks the matching value.'
|
|
1425
|
+
);
|
|
1426
|
+
lines.push(
|
|
1427
|
+
' Example: `"color": { "$cond": { "eq": [{ "path": "/activeTab" }, "home"] }, "$then": "#007AFF", "$else": "#8E8E93" }`'
|
|
1428
|
+
);
|
|
1429
|
+
lines.push(
|
|
1430
|
+
' Example: `"name": { "$cond": { "eq": [{ "path": "/activeTab" }, "home"] }, "$then": "home", "$else": "home-outline" }`'
|
|
1431
|
+
);
|
|
1432
|
+
lines.push("");
|
|
1433
|
+
lines.push(
|
|
1434
|
+
"Use dynamic props instead of duplicating elements with opposing visible conditions when only prop values differ."
|
|
1435
|
+
);
|
|
1436
|
+
lines.push("");
|
|
1086
1437
|
lines.push("RULES:");
|
|
1087
1438
|
const baseRules = [
|
|
1088
1439
|
"Output ONLY JSONL patches - one JSON object per line, no markdown, no code fences",
|
|
1089
|
-
'First
|
|
1440
|
+
'First set root: {"op":"add","path":"/root","value":"<root-key>"}',
|
|
1090
1441
|
'Then add each element: {"op":"add","path":"/elements/<key>","value":{...}}',
|
|
1442
|
+
"Output /state patches right after the elements that use them, one per array item for progressive loading. REQUIRED whenever using $path, repeat, or statePath.",
|
|
1091
1443
|
"ONLY use components listed above",
|
|
1092
1444
|
"Each element value needs: type, props, children (array of child keys)",
|
|
1093
1445
|
"Use unique keys for the element map entries (e.g., 'header', 'metric-1', 'chart-revenue')"
|
|
1094
1446
|
];
|
|
1095
|
-
const
|
|
1447
|
+
const schemaRules = catalog.schema.defaultRules ?? [];
|
|
1448
|
+
const allRules = [...baseRules, ...schemaRules, ...customRules];
|
|
1096
1449
|
allRules.forEach((rule, i) => {
|
|
1097
1450
|
lines.push(`${i + 1}. ${rule}`);
|
|
1098
1451
|
});
|
|
@@ -1230,6 +1583,56 @@ function defineCatalog(schema, catalog) {
|
|
|
1230
1583
|
return schema.createCatalog(catalog);
|
|
1231
1584
|
}
|
|
1232
1585
|
|
|
1586
|
+
// src/prompt.ts
|
|
1587
|
+
function isNonEmptySpec(spec) {
|
|
1588
|
+
if (!spec || typeof spec !== "object") return false;
|
|
1589
|
+
const s = spec;
|
|
1590
|
+
return typeof s.root === "string" && typeof s.elements === "object" && s.elements !== null && Object.keys(s.elements).length > 0;
|
|
1591
|
+
}
|
|
1592
|
+
var PATCH_INSTRUCTIONS = `IMPORTANT: The current UI is already loaded. Output ONLY the patches needed to make the requested change:
|
|
1593
|
+
- To add a new element: {"op":"add","path":"/elements/new-key","value":{...}}
|
|
1594
|
+
- To modify an existing element: {"op":"replace","path":"/elements/existing-key","value":{...}}
|
|
1595
|
+
- To remove an element: {"op":"remove","path":"/elements/old-key"}
|
|
1596
|
+
- To update the root: {"op":"replace","path":"/root","value":"new-root-key"}
|
|
1597
|
+
- To add children: update the parent element with new children array
|
|
1598
|
+
|
|
1599
|
+
DO NOT output patches for elements that don't need to change. Only output what's necessary for the requested modification.`;
|
|
1600
|
+
function buildUserPrompt(options) {
|
|
1601
|
+
const { prompt, currentSpec, state, maxPromptLength } = options;
|
|
1602
|
+
let userText = String(prompt || "");
|
|
1603
|
+
if (maxPromptLength !== void 0 && maxPromptLength > 0) {
|
|
1604
|
+
userText = userText.slice(0, maxPromptLength);
|
|
1605
|
+
}
|
|
1606
|
+
if (isNonEmptySpec(currentSpec)) {
|
|
1607
|
+
const parts2 = [];
|
|
1608
|
+
parts2.push(
|
|
1609
|
+
`CURRENT UI STATE (already loaded, DO NOT recreate existing elements):`
|
|
1610
|
+
);
|
|
1611
|
+
parts2.push(JSON.stringify(currentSpec, null, 2));
|
|
1612
|
+
parts2.push("");
|
|
1613
|
+
parts2.push(`USER REQUEST: ${userText}`);
|
|
1614
|
+
if (state && Object.keys(state).length > 0) {
|
|
1615
|
+
parts2.push("");
|
|
1616
|
+
parts2.push(`AVAILABLE STATE:
|
|
1617
|
+
${JSON.stringify(state, null, 2)}`);
|
|
1618
|
+
}
|
|
1619
|
+
parts2.push("");
|
|
1620
|
+
parts2.push(PATCH_INSTRUCTIONS);
|
|
1621
|
+
return parts2.join("\n");
|
|
1622
|
+
}
|
|
1623
|
+
const parts = [userText];
|
|
1624
|
+
if (state && Object.keys(state).length > 0) {
|
|
1625
|
+
parts.push(`
|
|
1626
|
+
AVAILABLE STATE:
|
|
1627
|
+
${JSON.stringify(state, null, 2)}`);
|
|
1628
|
+
}
|
|
1629
|
+
parts.push(
|
|
1630
|
+
`
|
|
1631
|
+
Remember: Output /root first, then interleave /elements and /state patches so the UI fills in progressively as it streams. Output each state patch right after the elements that use it, one per array item.`
|
|
1632
|
+
);
|
|
1633
|
+
return parts.join("\n");
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1233
1636
|
// src/catalog.ts
|
|
1234
1637
|
var import_zod6 = require("zod");
|
|
1235
1638
|
function createCatalog(config) {
|
|
@@ -1339,7 +1742,7 @@ function generateCatalogPrompt(catalog) {
|
|
|
1339
1742
|
lines.push("");
|
|
1340
1743
|
lines.push("Components can have a `visible` property:");
|
|
1341
1744
|
lines.push("- `true` / `false` - Always visible/hidden");
|
|
1342
|
-
lines.push('- `{ "path": "/
|
|
1745
|
+
lines.push('- `{ "path": "/state/path" }` - Visible when path is truthy');
|
|
1343
1746
|
lines.push('- `{ "auth": "signedIn" }` - Visible when user is signed in');
|
|
1344
1747
|
lines.push('- `{ "and": [...] }` - All conditions must be true');
|
|
1345
1748
|
lines.push('- `{ "or": [...] }` - Any condition must be true');
|
|
@@ -1510,6 +1913,7 @@ function generateSystemPrompt(catalog, options = {}) {
|
|
|
1510
1913
|
}
|
|
1511
1914
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1512
1915
|
0 && (module.exports = {
|
|
1916
|
+
ActionBindingSchema,
|
|
1513
1917
|
ActionConfirmSchema,
|
|
1514
1918
|
ActionOnErrorSchema,
|
|
1515
1919
|
ActionOnSuccessSchema,
|
|
@@ -1523,8 +1927,11 @@ function generateSystemPrompt(catalog, options = {}) {
|
|
|
1523
1927
|
ValidationConfigSchema,
|
|
1524
1928
|
VisibilityConditionSchema,
|
|
1525
1929
|
action,
|
|
1930
|
+
actionBinding,
|
|
1526
1931
|
addByPath,
|
|
1527
1932
|
applySpecStreamPatch,
|
|
1933
|
+
autoFixSpec,
|
|
1934
|
+
buildUserPrompt,
|
|
1528
1935
|
builtInValidationFunctions,
|
|
1529
1936
|
check,
|
|
1530
1937
|
compileSpecStream,
|
|
@@ -1536,6 +1943,7 @@ function generateSystemPrompt(catalog, options = {}) {
|
|
|
1536
1943
|
evaluateVisibility,
|
|
1537
1944
|
executeAction,
|
|
1538
1945
|
findFormValue,
|
|
1946
|
+
formatSpecIssues,
|
|
1539
1947
|
generateCatalogPrompt,
|
|
1540
1948
|
generateSystemPrompt,
|
|
1541
1949
|
getByPath,
|
|
@@ -1544,9 +1952,12 @@ function generateSystemPrompt(catalog, options = {}) {
|
|
|
1544
1952
|
removeByPath,
|
|
1545
1953
|
resolveAction,
|
|
1546
1954
|
resolveDynamicValue,
|
|
1955
|
+
resolveElementProps,
|
|
1956
|
+
resolvePropValue,
|
|
1547
1957
|
runValidation,
|
|
1548
1958
|
runValidationCheck,
|
|
1549
1959
|
setByPath,
|
|
1960
|
+
validateSpec,
|
|
1550
1961
|
visibility
|
|
1551
1962
|
});
|
|
1552
1963
|
//# sourceMappingURL=index.js.map
|