@goplasmatic/datalogic-ui 0.1.0 → 0.1.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/dist/datalogic_wasm-BN8H01AG.cjs +458 -0
- package/dist/datalogic_wasm-Cl34E6jc.js +354 -0
- package/dist/index.cjs +854 -265
- package/dist/index.d.ts +35 -5
- package/dist/index.js +948 -329
- package/dist/styles.css +136 -0
- package/package.json +12 -5
- package/dist/datalogic_wasm-r9jsW6oT.js +0 -314
- package/dist/datalogic_wasm-r9jsW6oT.js.map +0 -1
- package/dist/datalogic_wasm-vS4KZjmk.cjs +0 -410
- package/dist/datalogic_wasm-vS4KZjmk.cjs.map +0 -1
- package/dist/demo.gif +0 -0
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/manifest.json +0 -11
- package/dist/robots.txt +0 -4
package/dist/index.cjs
CHANGED
|
@@ -21,147 +21,6 @@ const CATEGORY_COLORS = {
|
|
|
21
21
|
literal: "#6B7280"
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
function isPlainObject(value) {
|
|
25
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26
|
-
}
|
|
27
|
-
function getValueType$1(value) {
|
|
28
|
-
if (value === null) return "null";
|
|
29
|
-
if (typeof value === "boolean") return "boolean";
|
|
30
|
-
if (typeof value === "number") return "number";
|
|
31
|
-
if (typeof value === "string") return "string";
|
|
32
|
-
if (Array.isArray(value)) return "array";
|
|
33
|
-
return "string";
|
|
34
|
-
}
|
|
35
|
-
function looksLikeDate(str) {
|
|
36
|
-
const datePatterns = [
|
|
37
|
-
/^\d{4}-\d{2}-\d{2}/,
|
|
38
|
-
// ISO date
|
|
39
|
-
/^\d{2}\/\d{2}\/\d{4}/,
|
|
40
|
-
// MM/DD/YYYY
|
|
41
|
-
/^\d{2}-\d{2}-\d{4}/
|
|
42
|
-
// DD-MM-YYYY
|
|
43
|
-
];
|
|
44
|
-
return datePatterns.some((pattern) => pattern.test(str));
|
|
45
|
-
}
|
|
46
|
-
function isSimpleOperand(operand) {
|
|
47
|
-
if (operand === null || typeof operand !== "object") {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
if (Array.isArray(operand)) {
|
|
51
|
-
return operand.length === 0;
|
|
52
|
-
}
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const COMPARISON_OPERATORS$1 = ["==", "===", "!=", "!==", ">", ">=", "<", "<="];
|
|
57
|
-
const ITERATOR_OPERATORS = ["map", "reduce", "filter", "some", "none", "all"];
|
|
58
|
-
const UNARY_OPERATORS$2 = ["!", "!!"];
|
|
59
|
-
const ARITHMETIC_BINARY_OPERATORS = ["+", "-", "*", "/", "%"];
|
|
60
|
-
function generateExpressionText(value, maxLength = 100) {
|
|
61
|
-
function getOperator(val) {
|
|
62
|
-
if (isPlainObject(val)) {
|
|
63
|
-
const keys = Object.keys(val);
|
|
64
|
-
if (keys.length === 1) return keys[0];
|
|
65
|
-
}
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
function needsParens(subVal, parentOp) {
|
|
69
|
-
const subOp = getOperator(subVal);
|
|
70
|
-
if (!subOp) return false;
|
|
71
|
-
if (parentOp === "and" && subOp === "or" || parentOp === "or" && subOp === "and") {
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
if (COMPARISON_OPERATORS$1.includes(parentOp) && (subOp === "and" || subOp === "or")) {
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
if ((parentOp === "*" || parentOp === "/") && (subOp === "+" || subOp === "-")) {
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
function toText(val, _parentOp) {
|
|
83
|
-
if (val === null) return "null";
|
|
84
|
-
if (typeof val === "boolean") return String(val);
|
|
85
|
-
if (typeof val === "number") return String(val);
|
|
86
|
-
if (typeof val === "string") return `"${val}"`;
|
|
87
|
-
if (Array.isArray(val)) {
|
|
88
|
-
if (val.length === 0) return "[]";
|
|
89
|
-
const items = val.map((v) => toText(v)).join(", ");
|
|
90
|
-
return `[${items}]`;
|
|
91
|
-
}
|
|
92
|
-
if (isPlainObject(val)) {
|
|
93
|
-
const keys = Object.keys(val);
|
|
94
|
-
if (keys.length !== 1) return JSON.stringify(val);
|
|
95
|
-
const op = keys[0];
|
|
96
|
-
const operands = val[op];
|
|
97
|
-
if (op === "var") {
|
|
98
|
-
const path = Array.isArray(operands) ? operands[0] : operands;
|
|
99
|
-
return String(path ?? "");
|
|
100
|
-
}
|
|
101
|
-
if (op === "val") {
|
|
102
|
-
const path = Array.isArray(operands) ? operands[0] : operands;
|
|
103
|
-
return `val(${path ?? ""})`;
|
|
104
|
-
}
|
|
105
|
-
if (op === "exists") {
|
|
106
|
-
return `exists(${operands})`;
|
|
107
|
-
}
|
|
108
|
-
const args = Array.isArray(operands) ? operands : [operands];
|
|
109
|
-
const wrapIfNeeded = (subVal) => {
|
|
110
|
-
const text2 = toText(subVal);
|
|
111
|
-
return needsParens(subVal, op) ? `(${text2})` : text2;
|
|
112
|
-
};
|
|
113
|
-
if ([...COMPARISON_OPERATORS$1, ...ARITHMETIC_BINARY_OPERATORS].includes(op)) {
|
|
114
|
-
if (args.length === 2) {
|
|
115
|
-
return `${wrapIfNeeded(args[0])} ${op} ${wrapIfNeeded(args[1])}`;
|
|
116
|
-
}
|
|
117
|
-
if (args.length > 2) {
|
|
118
|
-
return args.map(wrapIfNeeded).join(` ${op} `);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
if (op === "and") {
|
|
122
|
-
return args.map(wrapIfNeeded).join(" AND ");
|
|
123
|
-
}
|
|
124
|
-
if (op === "or") {
|
|
125
|
-
return args.map(wrapIfNeeded).join(" OR ");
|
|
126
|
-
}
|
|
127
|
-
if (UNARY_OPERATORS$2.includes(op)) {
|
|
128
|
-
const argText = toText(args[0]);
|
|
129
|
-
const subOp = getOperator(args[0]);
|
|
130
|
-
if (subOp && (subOp === "and" || subOp === "or" || COMPARISON_OPERATORS$1.includes(subOp))) {
|
|
131
|
-
return `${op}(${argText})`;
|
|
132
|
-
}
|
|
133
|
-
return `${op}${argText}`;
|
|
134
|
-
}
|
|
135
|
-
if (ITERATOR_OPERATORS.includes(op)) {
|
|
136
|
-
const [arr] = args;
|
|
137
|
-
return `${op}(${toText(arr)}, ...)`;
|
|
138
|
-
}
|
|
139
|
-
if (op === "if" || op === "?:") {
|
|
140
|
-
const parts = [];
|
|
141
|
-
let i = 0;
|
|
142
|
-
while (i < args.length) {
|
|
143
|
-
if (i + 1 < args.length) {
|
|
144
|
-
const prefix = i === 0 ? "if" : "else if";
|
|
145
|
-
parts.push(`${prefix} ${toText(args[i])} then ${toText(args[i + 1])}`);
|
|
146
|
-
i += 2;
|
|
147
|
-
} else {
|
|
148
|
-
parts.push(`else ${toText(args[i])}`);
|
|
149
|
-
i++;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return parts.join(" ");
|
|
153
|
-
}
|
|
154
|
-
return `${op}(${args.map((a) => toText(a)).join(", ")})`;
|
|
155
|
-
}
|
|
156
|
-
return String(val);
|
|
157
|
-
}
|
|
158
|
-
const text = toText(value);
|
|
159
|
-
if (text.length > maxLength) {
|
|
160
|
-
return text.slice(0, maxLength - 3) + "...";
|
|
161
|
-
}
|
|
162
|
-
return text;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
24
|
const OPERATORS = {
|
|
166
25
|
// Variable operators
|
|
167
26
|
var: {
|
|
@@ -658,6 +517,162 @@ function getOperatorMeta(operator) {
|
|
|
658
517
|
description: `Unknown operator: ${operator}`
|
|
659
518
|
};
|
|
660
519
|
}
|
|
520
|
+
function isOperator(key) {
|
|
521
|
+
return key in OPERATORS;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
function isPlainObject(value) {
|
|
525
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
526
|
+
}
|
|
527
|
+
function isJsonLogicExpression(value) {
|
|
528
|
+
if (!isPlainObject(value)) return false;
|
|
529
|
+
const keys = Object.keys(value);
|
|
530
|
+
return keys.length === 1 && isOperator(keys[0]);
|
|
531
|
+
}
|
|
532
|
+
function isDataStructure(value) {
|
|
533
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
534
|
+
if (!isPlainObject(value)) return false;
|
|
535
|
+
const keys = Object.keys(value);
|
|
536
|
+
if (keys.length > 1) return true;
|
|
537
|
+
return keys.length === 1 && !isOperator(keys[0]);
|
|
538
|
+
}
|
|
539
|
+
function getValueType$1(value) {
|
|
540
|
+
if (value === null) return "null";
|
|
541
|
+
if (typeof value === "boolean") return "boolean";
|
|
542
|
+
if (typeof value === "number") return "number";
|
|
543
|
+
if (typeof value === "string") return "string";
|
|
544
|
+
if (Array.isArray(value)) return "array";
|
|
545
|
+
return "string";
|
|
546
|
+
}
|
|
547
|
+
function looksLikeDate(str) {
|
|
548
|
+
const datePatterns = [
|
|
549
|
+
/^\d{4}-\d{2}-\d{2}/,
|
|
550
|
+
// ISO date
|
|
551
|
+
/^\d{2}\/\d{2}\/\d{4}/,
|
|
552
|
+
// MM/DD/YYYY
|
|
553
|
+
/^\d{2}-\d{2}-\d{4}/
|
|
554
|
+
// DD-MM-YYYY
|
|
555
|
+
];
|
|
556
|
+
return datePatterns.some((pattern) => pattern.test(str));
|
|
557
|
+
}
|
|
558
|
+
function isSimpleOperand(operand) {
|
|
559
|
+
if (operand === null || typeof operand !== "object") {
|
|
560
|
+
return true;
|
|
561
|
+
}
|
|
562
|
+
if (Array.isArray(operand)) {
|
|
563
|
+
return operand.length === 0;
|
|
564
|
+
}
|
|
565
|
+
return false;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const COMPARISON_OPERATORS$1 = ["==", "===", "!=", "!==", ">", ">=", "<", "<="];
|
|
569
|
+
const ITERATOR_OPERATORS = ["map", "reduce", "filter", "some", "none", "all"];
|
|
570
|
+
const UNARY_OPERATORS$2 = ["!", "!!"];
|
|
571
|
+
const ARITHMETIC_BINARY_OPERATORS = ["+", "-", "*", "/", "%"];
|
|
572
|
+
function generateExpressionText(value, maxLength = 100) {
|
|
573
|
+
function getOperator(val) {
|
|
574
|
+
if (isPlainObject(val)) {
|
|
575
|
+
const keys = Object.keys(val);
|
|
576
|
+
if (keys.length === 1) return keys[0];
|
|
577
|
+
}
|
|
578
|
+
return null;
|
|
579
|
+
}
|
|
580
|
+
function needsParens(subVal, parentOp) {
|
|
581
|
+
const subOp = getOperator(subVal);
|
|
582
|
+
if (!subOp) return false;
|
|
583
|
+
if (parentOp === "and" && subOp === "or" || parentOp === "or" && subOp === "and") {
|
|
584
|
+
return true;
|
|
585
|
+
}
|
|
586
|
+
if (COMPARISON_OPERATORS$1.includes(parentOp) && (subOp === "and" || subOp === "or")) {
|
|
587
|
+
return true;
|
|
588
|
+
}
|
|
589
|
+
if ((parentOp === "*" || parentOp === "/") && (subOp === "+" || subOp === "-")) {
|
|
590
|
+
return true;
|
|
591
|
+
}
|
|
592
|
+
return false;
|
|
593
|
+
}
|
|
594
|
+
function toText(val, _parentOp) {
|
|
595
|
+
if (val === null) return "null";
|
|
596
|
+
if (typeof val === "boolean") return String(val);
|
|
597
|
+
if (typeof val === "number") return String(val);
|
|
598
|
+
if (typeof val === "string") return `"${val}"`;
|
|
599
|
+
if (Array.isArray(val)) {
|
|
600
|
+
if (val.length === 0) return "[]";
|
|
601
|
+
const items = val.map((v) => toText(v)).join(", ");
|
|
602
|
+
return `[${items}]`;
|
|
603
|
+
}
|
|
604
|
+
if (isPlainObject(val)) {
|
|
605
|
+
const keys = Object.keys(val);
|
|
606
|
+
if (keys.length !== 1) return JSON.stringify(val);
|
|
607
|
+
const op = keys[0];
|
|
608
|
+
const operands = val[op];
|
|
609
|
+
if (op === "var") {
|
|
610
|
+
const path = Array.isArray(operands) ? operands[0] : operands;
|
|
611
|
+
return String(path ?? "");
|
|
612
|
+
}
|
|
613
|
+
if (op === "val") {
|
|
614
|
+
const path = Array.isArray(operands) ? operands[0] : operands;
|
|
615
|
+
return `val(${path ?? ""})`;
|
|
616
|
+
}
|
|
617
|
+
if (op === "exists") {
|
|
618
|
+
return `exists(${operands})`;
|
|
619
|
+
}
|
|
620
|
+
const args = Array.isArray(operands) ? operands : [operands];
|
|
621
|
+
const wrapIfNeeded = (subVal) => {
|
|
622
|
+
const text2 = toText(subVal);
|
|
623
|
+
return needsParens(subVal, op) ? `(${text2})` : text2;
|
|
624
|
+
};
|
|
625
|
+
if ([...COMPARISON_OPERATORS$1, ...ARITHMETIC_BINARY_OPERATORS].includes(op)) {
|
|
626
|
+
if (args.length === 2) {
|
|
627
|
+
return `${wrapIfNeeded(args[0])} ${op} ${wrapIfNeeded(args[1])}`;
|
|
628
|
+
}
|
|
629
|
+
if (args.length > 2) {
|
|
630
|
+
return args.map(wrapIfNeeded).join(` ${op} `);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
if (op === "and") {
|
|
634
|
+
return args.map(wrapIfNeeded).join(" AND ");
|
|
635
|
+
}
|
|
636
|
+
if (op === "or") {
|
|
637
|
+
return args.map(wrapIfNeeded).join(" OR ");
|
|
638
|
+
}
|
|
639
|
+
if (UNARY_OPERATORS$2.includes(op)) {
|
|
640
|
+
const argText = toText(args[0]);
|
|
641
|
+
const subOp = getOperator(args[0]);
|
|
642
|
+
if (subOp && (subOp === "and" || subOp === "or" || COMPARISON_OPERATORS$1.includes(subOp))) {
|
|
643
|
+
return `${op}(${argText})`;
|
|
644
|
+
}
|
|
645
|
+
return `${op}${argText}`;
|
|
646
|
+
}
|
|
647
|
+
if (ITERATOR_OPERATORS.includes(op)) {
|
|
648
|
+
const [arr] = args;
|
|
649
|
+
return `${op}(${toText(arr)}, ...)`;
|
|
650
|
+
}
|
|
651
|
+
if (op === "if" || op === "?:") {
|
|
652
|
+
const parts = [];
|
|
653
|
+
let i = 0;
|
|
654
|
+
while (i < args.length) {
|
|
655
|
+
if (i + 1 < args.length) {
|
|
656
|
+
const prefix = i === 0 ? "if" : "else if";
|
|
657
|
+
parts.push(`${prefix} ${toText(args[i])} then ${toText(args[i + 1])}`);
|
|
658
|
+
i += 2;
|
|
659
|
+
} else {
|
|
660
|
+
parts.push(`else ${toText(args[i])}`);
|
|
661
|
+
i++;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return parts.join(" ");
|
|
665
|
+
}
|
|
666
|
+
return `${op}(${args.map((a) => toText(a)).join(", ")})`;
|
|
667
|
+
}
|
|
668
|
+
return String(val);
|
|
669
|
+
}
|
|
670
|
+
const text = toText(value);
|
|
671
|
+
if (text.length > maxLength) {
|
|
672
|
+
return text.slice(0, maxLength - 3) + "...";
|
|
673
|
+
}
|
|
674
|
+
return text;
|
|
675
|
+
}
|
|
661
676
|
|
|
662
677
|
const TRUNCATION_LIMITS = {
|
|
663
678
|
shortLabel: 20,
|
|
@@ -829,11 +844,11 @@ const createLucideIcon = (iconName, iconNode) => {
|
|
|
829
844
|
*/
|
|
830
845
|
|
|
831
846
|
|
|
832
|
-
const __iconNode$
|
|
847
|
+
const __iconNode$w = [
|
|
833
848
|
["path", { d: "M4.929 4.929 19.07 19.071", key: "196cmz" }],
|
|
834
849
|
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]
|
|
835
850
|
];
|
|
836
|
-
const Ban = createLucideIcon("ban", __iconNode$
|
|
851
|
+
const Ban = createLucideIcon("ban", __iconNode$w);
|
|
837
852
|
|
|
838
853
|
/**
|
|
839
854
|
* @license lucide-react v0.562.0 - ISC
|
|
@@ -843,7 +858,7 @@ const Ban = createLucideIcon("ban", __iconNode$v);
|
|
|
843
858
|
*/
|
|
844
859
|
|
|
845
860
|
|
|
846
|
-
const __iconNode$
|
|
861
|
+
const __iconNode$v = [
|
|
847
862
|
[
|
|
848
863
|
"path",
|
|
849
864
|
{
|
|
@@ -854,7 +869,7 @@ const __iconNode$u = [
|
|
|
854
869
|
["path", { d: "m3.3 7 8.7 5 8.7-5", key: "g66t2b" }],
|
|
855
870
|
["path", { d: "M12 22V12", key: "d0xqtd" }]
|
|
856
871
|
];
|
|
857
|
-
const Box = createLucideIcon("box", __iconNode$
|
|
872
|
+
const Box = createLucideIcon("box", __iconNode$v);
|
|
858
873
|
|
|
859
874
|
/**
|
|
860
875
|
* @license lucide-react v0.562.0 - ISC
|
|
@@ -864,7 +879,7 @@ const Box = createLucideIcon("box", __iconNode$u);
|
|
|
864
879
|
*/
|
|
865
880
|
|
|
866
881
|
|
|
867
|
-
const __iconNode$
|
|
882
|
+
const __iconNode$u = [
|
|
868
883
|
[
|
|
869
884
|
"path",
|
|
870
885
|
{
|
|
@@ -896,7 +911,30 @@ const __iconNode$t = [
|
|
|
896
911
|
["path", { d: "m12 8 4.74-2.85", key: "3rx089" }],
|
|
897
912
|
["path", { d: "M12 13.5V8", key: "1io7kd" }]
|
|
898
913
|
];
|
|
899
|
-
const Boxes = createLucideIcon("boxes", __iconNode$
|
|
914
|
+
const Boxes = createLucideIcon("boxes", __iconNode$u);
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* @license lucide-react v0.562.0 - ISC
|
|
918
|
+
*
|
|
919
|
+
* This source code is licensed under the ISC license.
|
|
920
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
921
|
+
*/
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
const __iconNode$t = [
|
|
925
|
+
[
|
|
926
|
+
"path",
|
|
927
|
+
{ d: "M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1", key: "ezmyqa" }
|
|
928
|
+
],
|
|
929
|
+
[
|
|
930
|
+
"path",
|
|
931
|
+
{
|
|
932
|
+
d: "M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1",
|
|
933
|
+
key: "e1hn23"
|
|
934
|
+
}
|
|
935
|
+
]
|
|
936
|
+
];
|
|
937
|
+
const Braces = createLucideIcon("braces", __iconNode$t);
|
|
900
938
|
|
|
901
939
|
/**
|
|
902
940
|
* @license lucide-react v0.562.0 - ISC
|
|
@@ -1404,7 +1442,8 @@ const ICON_COMPONENTS = {
|
|
|
1404
1442
|
"git-commit-horizontal": GitCommitHorizontal,
|
|
1405
1443
|
"search": Search,
|
|
1406
1444
|
"divide": Divide,
|
|
1407
|
-
"quote": Quote
|
|
1445
|
+
"quote": Quote,
|
|
1446
|
+
"braces": Braces
|
|
1408
1447
|
};
|
|
1409
1448
|
function Icon({ name, size = 14, className, style }) {
|
|
1410
1449
|
const IconComponent = ICON_COMPONENTS[name];
|
|
@@ -1905,7 +1944,8 @@ function convertIfElse(ifArgs, context, convertValue) {
|
|
|
1905
1944
|
edges: context.edges,
|
|
1906
1945
|
parentId: parentInfo.parentId,
|
|
1907
1946
|
argIndex: parentInfo.argIndex,
|
|
1908
|
-
branchType: parentInfo.branchType
|
|
1947
|
+
branchType: parentInfo.branchType,
|
|
1948
|
+
preserveStructure: context.preserveStructure
|
|
1909
1949
|
});
|
|
1910
1950
|
}
|
|
1911
1951
|
const cells = [];
|
|
@@ -1920,7 +1960,8 @@ function convertIfElse(ifArgs, context, convertValue) {
|
|
|
1920
1960
|
nodes: context.nodes,
|
|
1921
1961
|
edges: context.edges,
|
|
1922
1962
|
parentId: nodeId,
|
|
1923
|
-
argIndex: idx
|
|
1963
|
+
argIndex: idx,
|
|
1964
|
+
preserveStructure: context.preserveStructure
|
|
1924
1965
|
});
|
|
1925
1966
|
context.edges.push({
|
|
1926
1967
|
id: `${nodeId}-cond-${conditionBranchId}`,
|
|
@@ -1945,7 +1986,8 @@ function convertIfElse(ifArgs, context, convertValue) {
|
|
|
1945
1986
|
edges: context.edges,
|
|
1946
1987
|
parentId: nodeId,
|
|
1947
1988
|
argIndex: idx + 1,
|
|
1948
|
-
branchType: "yes"
|
|
1989
|
+
branchType: "yes",
|
|
1990
|
+
preserveStructure: context.preserveStructure
|
|
1949
1991
|
});
|
|
1950
1992
|
context.edges.push({
|
|
1951
1993
|
id: `${nodeId}-then-${thenBranchId}`,
|
|
@@ -1975,7 +2017,8 @@ function convertIfElse(ifArgs, context, convertValue) {
|
|
|
1975
2017
|
edges: context.edges,
|
|
1976
2018
|
parentId: nodeId,
|
|
1977
2019
|
argIndex: ifArgs.length - 1,
|
|
1978
|
-
branchType: "no"
|
|
2020
|
+
branchType: "no",
|
|
2021
|
+
preserveStructure: context.preserveStructure
|
|
1979
2022
|
});
|
|
1980
2023
|
context.edges.push({
|
|
1981
2024
|
id: `${nodeId}-else-${elseBranchId}`,
|
|
@@ -2049,7 +2092,8 @@ function convertToVerticalCell(operator, operandArray, context, convertValue) {
|
|
|
2049
2092
|
nodes: context.nodes,
|
|
2050
2093
|
edges: context.edges,
|
|
2051
2094
|
parentId: nodeId,
|
|
2052
|
-
argIndex: idx
|
|
2095
|
+
argIndex: idx,
|
|
2096
|
+
preserveStructure: context.preserveStructure
|
|
2053
2097
|
});
|
|
2054
2098
|
const summary = generateArgSummary(operand);
|
|
2055
2099
|
summary.label = generateExpressionText(operand, TRUNCATION_LIMITS.expressionText);
|
|
@@ -2137,7 +2181,8 @@ function convertOperatorWithChildren(operator, operandArray, value, context, con
|
|
|
2137
2181
|
nodes: context.nodes,
|
|
2138
2182
|
edges: context.edges,
|
|
2139
2183
|
parentId: nodeId,
|
|
2140
|
-
argIndex: idx
|
|
2184
|
+
argIndex: idx,
|
|
2185
|
+
preserveStructure: context.preserveStructure
|
|
2141
2186
|
});
|
|
2142
2187
|
childIds.push(childId);
|
|
2143
2188
|
});
|
|
@@ -2172,7 +2217,120 @@ function isUnaryOperator(operator) {
|
|
|
2172
2217
|
return UNARY_OPERATORS$1.includes(operator);
|
|
2173
2218
|
}
|
|
2174
2219
|
|
|
2220
|
+
const EXPR_PLACEHOLDER$1 = "{{EXPR}}";
|
|
2221
|
+
const EXPR_PLACEHOLDER_QUOTED$1 = `"${EXPR_PLACEHOLDER$1}"`;
|
|
2222
|
+
function convertStructure(value, context, convertValue) {
|
|
2223
|
+
const parentInfo = getParentInfo(context);
|
|
2224
|
+
const nodeId = v4();
|
|
2225
|
+
const isArray = Array.isArray(value);
|
|
2226
|
+
const elements = [];
|
|
2227
|
+
let expressionIndex = 0;
|
|
2228
|
+
const structureWithPlaceholders = walkAndCollect(
|
|
2229
|
+
value,
|
|
2230
|
+
[],
|
|
2231
|
+
(path, item, key) => {
|
|
2232
|
+
if (isJsonLogicExpression(item)) {
|
|
2233
|
+
const branchId = convertValue(item, {
|
|
2234
|
+
nodes: context.nodes,
|
|
2235
|
+
edges: context.edges,
|
|
2236
|
+
parentId: nodeId,
|
|
2237
|
+
argIndex: expressionIndex,
|
|
2238
|
+
preserveStructure: context.preserveStructure
|
|
2239
|
+
});
|
|
2240
|
+
elements.push({
|
|
2241
|
+
type: "expression",
|
|
2242
|
+
path,
|
|
2243
|
+
key,
|
|
2244
|
+
branchId,
|
|
2245
|
+
startOffset: 0,
|
|
2246
|
+
// Will be calculated after formatting
|
|
2247
|
+
endOffset: 0
|
|
2248
|
+
});
|
|
2249
|
+
expressionIndex++;
|
|
2250
|
+
return EXPR_PLACEHOLDER$1;
|
|
2251
|
+
} else {
|
|
2252
|
+
return item;
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
);
|
|
2256
|
+
const formattedJson = JSON.stringify(structureWithPlaceholders, null, 2);
|
|
2257
|
+
let searchPos = 0;
|
|
2258
|
+
for (const element of elements) {
|
|
2259
|
+
if (element.type === "expression") {
|
|
2260
|
+
const placeholderPos = formattedJson.indexOf(EXPR_PLACEHOLDER_QUOTED$1, searchPos);
|
|
2261
|
+
if (placeholderPos !== -1) {
|
|
2262
|
+
element.startOffset = placeholderPos;
|
|
2263
|
+
element.endOffset = placeholderPos + EXPR_PLACEHOLDER_QUOTED$1.length;
|
|
2264
|
+
searchPos = element.endOffset;
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
const expressionText = generateExpressionText(value, 100);
|
|
2269
|
+
const node = {
|
|
2270
|
+
id: nodeId,
|
|
2271
|
+
type: "structure",
|
|
2272
|
+
position: { x: 0, y: 0 },
|
|
2273
|
+
data: {
|
|
2274
|
+
type: "structure",
|
|
2275
|
+
isArray,
|
|
2276
|
+
formattedJson,
|
|
2277
|
+
elements,
|
|
2278
|
+
collapsed: false,
|
|
2279
|
+
expressionText,
|
|
2280
|
+
expression: value,
|
|
2281
|
+
parentId: parentInfo.parentId,
|
|
2282
|
+
argIndex: parentInfo.argIndex,
|
|
2283
|
+
branchType: parentInfo.branchType
|
|
2284
|
+
}
|
|
2285
|
+
};
|
|
2286
|
+
context.nodes.push(node);
|
|
2287
|
+
if (parentInfo.parentId && !parentInfo.branchType) {
|
|
2288
|
+
const edge = createArgEdge(parentInfo.parentId, nodeId, parentInfo.argIndex ?? 0);
|
|
2289
|
+
context.edges.push(edge);
|
|
2290
|
+
}
|
|
2291
|
+
let branchIdx = 0;
|
|
2292
|
+
for (const element of elements) {
|
|
2293
|
+
if (element.type === "expression" && element.branchId) {
|
|
2294
|
+
const edge = createBranchEdge(nodeId, element.branchId, branchIdx);
|
|
2295
|
+
context.edges.push(edge);
|
|
2296
|
+
branchIdx++;
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
return nodeId;
|
|
2300
|
+
}
|
|
2301
|
+
function walkAndCollect(value, path, onValue) {
|
|
2302
|
+
if (Array.isArray(value)) {
|
|
2303
|
+
return value.map((item, index) => {
|
|
2304
|
+
const itemPath = [...path, String(index)];
|
|
2305
|
+
if (isJsonLogicExpression(item)) {
|
|
2306
|
+
return onValue(itemPath, item);
|
|
2307
|
+
} else if (typeof item === "object" && item !== null) {
|
|
2308
|
+
return walkAndCollect(item, itemPath, onValue);
|
|
2309
|
+
}
|
|
2310
|
+
return item;
|
|
2311
|
+
});
|
|
2312
|
+
}
|
|
2313
|
+
if (typeof value === "object" && value !== null) {
|
|
2314
|
+
const result = {};
|
|
2315
|
+
for (const [key, item] of Object.entries(value)) {
|
|
2316
|
+
const itemPath = [...path, key];
|
|
2317
|
+
if (isJsonLogicExpression(item)) {
|
|
2318
|
+
result[key] = onValue(itemPath, item, key);
|
|
2319
|
+
} else if (typeof item === "object" && item !== null) {
|
|
2320
|
+
result[key] = walkAndCollect(item, itemPath, onValue);
|
|
2321
|
+
} else {
|
|
2322
|
+
result[key] = item;
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
return result;
|
|
2326
|
+
}
|
|
2327
|
+
return value;
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2175
2330
|
function convertValue(value, context) {
|
|
2331
|
+
if (context.preserveStructure && isDataStructure(value)) {
|
|
2332
|
+
return convertStructure(value, context, convertValue);
|
|
2333
|
+
}
|
|
2176
2334
|
if (!isPlainObject(value)) {
|
|
2177
2335
|
return convertPrimitive(value, context);
|
|
2178
2336
|
}
|
|
@@ -2202,13 +2360,17 @@ function convertValue(value, context) {
|
|
|
2202
2360
|
return convertOperatorWithChildren(operator, operandArray, value, context, convertValue);
|
|
2203
2361
|
}
|
|
2204
2362
|
|
|
2205
|
-
function jsonLogicToNodes(expr) {
|
|
2363
|
+
function jsonLogicToNodes(expr, options = {}) {
|
|
2206
2364
|
if (expr === null || expr === void 0) {
|
|
2207
2365
|
return { nodes: [], edges: [], rootId: null };
|
|
2208
2366
|
}
|
|
2209
2367
|
const nodes = [];
|
|
2210
2368
|
const edges = [];
|
|
2211
|
-
const rootId = convertValue(expr, {
|
|
2369
|
+
const rootId = convertValue(expr, {
|
|
2370
|
+
nodes,
|
|
2371
|
+
edges,
|
|
2372
|
+
preserveStructure: options.preserveStructure
|
|
2373
|
+
});
|
|
2212
2374
|
return { nodes, edges, rootId };
|
|
2213
2375
|
}
|
|
2214
2376
|
|
|
@@ -2239,14 +2401,20 @@ function buildEvaluationResultsFromTrace(trace) {
|
|
|
2239
2401
|
}
|
|
2240
2402
|
return results;
|
|
2241
2403
|
}
|
|
2242
|
-
function traceToNodes(trace) {
|
|
2404
|
+
function traceToNodes(trace, options = {}) {
|
|
2243
2405
|
if (!trace.expression_tree) {
|
|
2244
2406
|
return { nodes: [], edges: [], rootId: null, traceNodeMap: /* @__PURE__ */ new Map() };
|
|
2245
2407
|
}
|
|
2246
2408
|
const nodes = [];
|
|
2247
2409
|
const edges = [];
|
|
2248
2410
|
const traceNodeMap = /* @__PURE__ */ new Map();
|
|
2249
|
-
|
|
2411
|
+
const rootExpression = options.originalValue ?? JSON.parse(trace.expression_tree.expression);
|
|
2412
|
+
processExpressionNode(trace.expression_tree, {
|
|
2413
|
+
nodes,
|
|
2414
|
+
edges,
|
|
2415
|
+
traceNodeMap,
|
|
2416
|
+
preserveStructure: options.preserveStructure ?? false
|
|
2417
|
+
}, {}, rootExpression);
|
|
2250
2418
|
return {
|
|
2251
2419
|
nodes,
|
|
2252
2420
|
edges,
|
|
@@ -2263,11 +2431,11 @@ function mapInlinedChildren(children, parentVisualId, traceNodeMap) {
|
|
|
2263
2431
|
}
|
|
2264
2432
|
}
|
|
2265
2433
|
}
|
|
2266
|
-
function processExpressionNode(exprNode, context, parentInfo = {}) {
|
|
2434
|
+
function processExpressionNode(exprNode, context, parentInfo = {}, originalExpression) {
|
|
2267
2435
|
const nodeId = traceIdToNodeId(exprNode.id);
|
|
2268
|
-
const expression = JSON.parse(exprNode.expression);
|
|
2436
|
+
const expression = originalExpression ?? JSON.parse(exprNode.expression);
|
|
2269
2437
|
context.traceNodeMap.set(nodeId, nodeId);
|
|
2270
|
-
const nodeType = determineNodeType(expression);
|
|
2438
|
+
const nodeType = determineNodeType(expression, context.preserveStructure);
|
|
2271
2439
|
switch (nodeType) {
|
|
2272
2440
|
case "literal":
|
|
2273
2441
|
createLiteralNodeFromTrace(nodeId, expression, exprNode.children, context, parentInfo);
|
|
@@ -2284,10 +2452,39 @@ function processExpressionNode(exprNode, context, parentInfo = {}) {
|
|
|
2284
2452
|
case "operator":
|
|
2285
2453
|
createOperatorNodeFromTrace(nodeId, expression, exprNode.children, context, parentInfo);
|
|
2286
2454
|
break;
|
|
2455
|
+
case "structure":
|
|
2456
|
+
createStructureNodeFromTrace(nodeId, expression, exprNode.children, context, parentInfo);
|
|
2457
|
+
break;
|
|
2287
2458
|
}
|
|
2288
2459
|
return nodeId;
|
|
2289
2460
|
}
|
|
2290
|
-
function
|
|
2461
|
+
function createFallbackNode(nodeId, value, context, parentInfo) {
|
|
2462
|
+
const nodeType = determineNodeType(value, context.preserveStructure);
|
|
2463
|
+
switch (nodeType) {
|
|
2464
|
+
case "literal":
|
|
2465
|
+
createLiteralNodeFromTrace(nodeId, value, [], context, parentInfo);
|
|
2466
|
+
break;
|
|
2467
|
+
case "variable":
|
|
2468
|
+
createVariableNodeFromTrace(nodeId, value, [], context, parentInfo);
|
|
2469
|
+
break;
|
|
2470
|
+
case "if":
|
|
2471
|
+
createIfElseNodeFromTrace(nodeId, value, [], context, parentInfo);
|
|
2472
|
+
break;
|
|
2473
|
+
case "verticalCell":
|
|
2474
|
+
createVerticalCellNodeFromTrace(nodeId, value, [], context, parentInfo);
|
|
2475
|
+
break;
|
|
2476
|
+
case "operator":
|
|
2477
|
+
createOperatorNodeFromTrace(nodeId, value, [], context, parentInfo);
|
|
2478
|
+
break;
|
|
2479
|
+
case "structure":
|
|
2480
|
+
createStructureNodeFromTrace(nodeId, value, [], context, parentInfo);
|
|
2481
|
+
break;
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
function determineNodeType(expr, preserveStructure) {
|
|
2485
|
+
if (preserveStructure && isDataStructure(expr)) {
|
|
2486
|
+
return "structure";
|
|
2487
|
+
}
|
|
2291
2488
|
if (expr === null || typeof expr !== "object" || Array.isArray(expr)) {
|
|
2292
2489
|
return "literal";
|
|
2293
2490
|
}
|
|
@@ -2326,6 +2523,9 @@ function createLiteralNodeFromTrace(nodeId, value, children, context, parentInfo
|
|
|
2326
2523
|
}
|
|
2327
2524
|
};
|
|
2328
2525
|
context.nodes.push(node);
|
|
2526
|
+
if (parentInfo.parentId && !parentInfo.branchType) {
|
|
2527
|
+
context.edges.push(createArgEdge(parentInfo.parentId, nodeId, parentInfo.argIndex ?? 0));
|
|
2528
|
+
}
|
|
2329
2529
|
}
|
|
2330
2530
|
function createVariableNodeFromTrace(nodeId, expression, children, context, parentInfo) {
|
|
2331
2531
|
if (children && children.length > 0) {
|
|
@@ -2358,6 +2558,9 @@ function createVariableNodeFromTrace(nodeId, expression, children, context, pare
|
|
|
2358
2558
|
}
|
|
2359
2559
|
};
|
|
2360
2560
|
context.nodes.push(node);
|
|
2561
|
+
if (parentInfo.parentId && !parentInfo.branchType) {
|
|
2562
|
+
context.edges.push(createArgEdge(parentInfo.parentId, nodeId, parentInfo.argIndex ?? 0));
|
|
2563
|
+
}
|
|
2361
2564
|
}
|
|
2362
2565
|
function createIfElseNodeFromTrace(nodeId, expression, children, context, parentInfo) {
|
|
2363
2566
|
const obj = expression;
|
|
@@ -2382,20 +2585,10 @@ function createIfElseNodeFromTrace(nodeId, expression, children, context, parent
|
|
|
2382
2585
|
});
|
|
2383
2586
|
} else {
|
|
2384
2587
|
conditionBranchId = `${nodeId}-cond-${idx}`;
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
data: {
|
|
2390
|
-
type: "literal",
|
|
2391
|
-
value: condition,
|
|
2392
|
-
valueType: getValueType$1(condition),
|
|
2393
|
-
expression: condition,
|
|
2394
|
-
parentId: nodeId,
|
|
2395
|
-
argIndex: idx
|
|
2396
|
-
}
|
|
2397
|
-
};
|
|
2398
|
-
context.nodes.push(condNode);
|
|
2588
|
+
createFallbackNode(conditionBranchId, condition, context, {
|
|
2589
|
+
parentId: nodeId,
|
|
2590
|
+
argIndex: idx
|
|
2591
|
+
});
|
|
2399
2592
|
}
|
|
2400
2593
|
context.edges.push(createBranchEdge(nodeId, conditionBranchId, branchIndex));
|
|
2401
2594
|
const conditionText = generateExpressionText(condition, 40);
|
|
@@ -2420,21 +2613,11 @@ function createIfElseNodeFromTrace(nodeId, expression, children, context, parent
|
|
|
2420
2613
|
});
|
|
2421
2614
|
} else {
|
|
2422
2615
|
thenBranchId = `${nodeId}-then-${idx}`;
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
type: "literal",
|
|
2429
|
-
value: thenValue,
|
|
2430
|
-
valueType: getValueType$1(thenValue),
|
|
2431
|
-
expression: thenValue,
|
|
2432
|
-
parentId: nodeId,
|
|
2433
|
-
argIndex: idx + 1,
|
|
2434
|
-
branchType: "yes"
|
|
2435
|
-
}
|
|
2436
|
-
};
|
|
2437
|
-
context.nodes.push(thenNode);
|
|
2616
|
+
createFallbackNode(thenBranchId, thenValue, context, {
|
|
2617
|
+
parentId: nodeId,
|
|
2618
|
+
argIndex: idx + 1,
|
|
2619
|
+
branchType: "yes"
|
|
2620
|
+
});
|
|
2438
2621
|
}
|
|
2439
2622
|
context.edges.push(createBranchEdge(nodeId, thenBranchId, branchIndex));
|
|
2440
2623
|
const thenText = generateExpressionText(thenValue, 40);
|
|
@@ -2464,21 +2647,11 @@ function createIfElseNodeFromTrace(nodeId, expression, children, context, parent
|
|
|
2464
2647
|
});
|
|
2465
2648
|
} else {
|
|
2466
2649
|
elseBranchId = `${nodeId}-else`;
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
type: "literal",
|
|
2473
|
-
value: elseValue,
|
|
2474
|
-
valueType: getValueType$1(elseValue),
|
|
2475
|
-
expression: elseValue,
|
|
2476
|
-
parentId: nodeId,
|
|
2477
|
-
argIndex: ifArgs.length - 1,
|
|
2478
|
-
branchType: "no"
|
|
2479
|
-
}
|
|
2480
|
-
};
|
|
2481
|
-
context.nodes.push(elseNode);
|
|
2650
|
+
createFallbackNode(elseBranchId, elseValue, context, {
|
|
2651
|
+
parentId: nodeId,
|
|
2652
|
+
argIndex: ifArgs.length - 1,
|
|
2653
|
+
branchType: "no"
|
|
2654
|
+
});
|
|
2482
2655
|
}
|
|
2483
2656
|
context.edges.push(createBranchEdge(nodeId, elseBranchId, branchIndex));
|
|
2484
2657
|
const elseText = generateExpressionText(elseValue, 40);
|
|
@@ -2513,6 +2686,9 @@ function createIfElseNodeFromTrace(nodeId, expression, children, context, parent
|
|
|
2513
2686
|
}
|
|
2514
2687
|
};
|
|
2515
2688
|
context.nodes.push(ifElseNode);
|
|
2689
|
+
if (parentInfo.parentId && !parentInfo.branchType) {
|
|
2690
|
+
context.edges.push(createArgEdge(parentInfo.parentId, nodeId, parentInfo.argIndex ?? 0));
|
|
2691
|
+
}
|
|
2516
2692
|
}
|
|
2517
2693
|
function findMatchingChild(operand, children, usedIndices) {
|
|
2518
2694
|
const operandStr = JSON.stringify(operand);
|
|
@@ -2573,6 +2749,10 @@ function createVerticalCellNodeFromTrace(nodeId, expression, children, context,
|
|
|
2573
2749
|
});
|
|
2574
2750
|
} else {
|
|
2575
2751
|
branchId = `${nodeId}-arg-${idx}`;
|
|
2752
|
+
createFallbackNode(branchId, operand, context, {
|
|
2753
|
+
parentId: nodeId,
|
|
2754
|
+
argIndex: idx
|
|
2755
|
+
});
|
|
2576
2756
|
}
|
|
2577
2757
|
const summary = generateArgSummary(operand);
|
|
2578
2758
|
summary.label = generateExpressionText(operand, TRUNCATION_LIMITS.expressionText);
|
|
@@ -2608,6 +2788,9 @@ function createVerticalCellNodeFromTrace(nodeId, expression, children, context,
|
|
|
2608
2788
|
}
|
|
2609
2789
|
};
|
|
2610
2790
|
context.nodes.push(node);
|
|
2791
|
+
if (parentInfo.parentId && !parentInfo.branchType) {
|
|
2792
|
+
context.edges.push(createArgEdge(parentInfo.parentId, nodeId, parentInfo.argIndex ?? 0));
|
|
2793
|
+
}
|
|
2611
2794
|
}
|
|
2612
2795
|
function createOperatorNodeFromTrace(nodeId, expression, children, context, parentInfo) {
|
|
2613
2796
|
const obj = expression;
|
|
@@ -2648,6 +2831,9 @@ function createOperatorNodeFromTrace(nodeId, expression, children, context, pare
|
|
|
2648
2831
|
}
|
|
2649
2832
|
};
|
|
2650
2833
|
context.nodes.push(node2);
|
|
2834
|
+
if (parentInfo.parentId && !parentInfo.branchType) {
|
|
2835
|
+
context.edges.push(createArgEdge(parentInfo.parentId, nodeId, parentInfo.argIndex ?? 0));
|
|
2836
|
+
}
|
|
2651
2837
|
return;
|
|
2652
2838
|
}
|
|
2653
2839
|
const usedChildIndices = /* @__PURE__ */ new Set();
|
|
@@ -2693,6 +2879,121 @@ function createOperatorNodeFromTrace(nodeId, expression, children, context, pare
|
|
|
2693
2879
|
}
|
|
2694
2880
|
};
|
|
2695
2881
|
context.nodes.push(node);
|
|
2882
|
+
if (parentInfo.parentId && !parentInfo.branchType) {
|
|
2883
|
+
context.edges.push(createArgEdge(parentInfo.parentId, nodeId, parentInfo.argIndex ?? 0));
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2886
|
+
const EXPR_PLACEHOLDER = "{{EXPR}}";
|
|
2887
|
+
const EXPR_PLACEHOLDER_QUOTED = `"${EXPR_PLACEHOLDER}"`;
|
|
2888
|
+
function createStructureNodeFromTrace(nodeId, expression, children, context, parentInfo) {
|
|
2889
|
+
const isArray = Array.isArray(expression);
|
|
2890
|
+
const elements = [];
|
|
2891
|
+
const usedChildIndices = /* @__PURE__ */ new Set();
|
|
2892
|
+
let expressionIndex = 0;
|
|
2893
|
+
const structureWithPlaceholders = walkAndCollectFromTrace(
|
|
2894
|
+
expression,
|
|
2895
|
+
[],
|
|
2896
|
+
(path, item, key) => {
|
|
2897
|
+
if (isJsonLogicExpression(item)) {
|
|
2898
|
+
const match = findMatchingChild(item, children, usedChildIndices);
|
|
2899
|
+
let branchId;
|
|
2900
|
+
if (match) {
|
|
2901
|
+
usedChildIndices.add(match.index);
|
|
2902
|
+
branchId = processExpressionNode(match.child, context, {
|
|
2903
|
+
parentId: nodeId,
|
|
2904
|
+
argIndex: expressionIndex
|
|
2905
|
+
});
|
|
2906
|
+
} else {
|
|
2907
|
+
branchId = `${nodeId}-expr-${expressionIndex}`;
|
|
2908
|
+
createFallbackNode(branchId, item, context, {
|
|
2909
|
+
parentId: nodeId,
|
|
2910
|
+
argIndex: expressionIndex,
|
|
2911
|
+
branchType: "branch"
|
|
2912
|
+
// Prevents edge creation in fallback
|
|
2913
|
+
});
|
|
2914
|
+
}
|
|
2915
|
+
elements.push({
|
|
2916
|
+
type: "expression",
|
|
2917
|
+
path,
|
|
2918
|
+
key,
|
|
2919
|
+
branchId,
|
|
2920
|
+
startOffset: 0,
|
|
2921
|
+
endOffset: 0
|
|
2922
|
+
});
|
|
2923
|
+
expressionIndex++;
|
|
2924
|
+
return EXPR_PLACEHOLDER;
|
|
2925
|
+
}
|
|
2926
|
+
return item;
|
|
2927
|
+
});
|
|
2928
|
+
const formattedJson = JSON.stringify(structureWithPlaceholders, null, 2);
|
|
2929
|
+
let searchPos = 0;
|
|
2930
|
+
for (const element of elements) {
|
|
2931
|
+
if (element.type === "expression") {
|
|
2932
|
+
const placeholderPos = formattedJson.indexOf(EXPR_PLACEHOLDER_QUOTED, searchPos);
|
|
2933
|
+
if (placeholderPos !== -1) {
|
|
2934
|
+
element.startOffset = placeholderPos;
|
|
2935
|
+
element.endOffset = placeholderPos + EXPR_PLACEHOLDER_QUOTED.length;
|
|
2936
|
+
searchPos = element.endOffset;
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
const expressionText = generateExpressionText(expression, 100);
|
|
2941
|
+
const node = {
|
|
2942
|
+
id: nodeId,
|
|
2943
|
+
type: "structure",
|
|
2944
|
+
position: { x: 0, y: 0 },
|
|
2945
|
+
data: {
|
|
2946
|
+
type: "structure",
|
|
2947
|
+
isArray,
|
|
2948
|
+
formattedJson,
|
|
2949
|
+
elements,
|
|
2950
|
+
collapsed: false,
|
|
2951
|
+
expressionText,
|
|
2952
|
+
expression,
|
|
2953
|
+
parentId: parentInfo.parentId,
|
|
2954
|
+
argIndex: parentInfo.argIndex,
|
|
2955
|
+
branchType: parentInfo.branchType
|
|
2956
|
+
}
|
|
2957
|
+
};
|
|
2958
|
+
context.nodes.push(node);
|
|
2959
|
+
if (parentInfo.parentId && !parentInfo.branchType) {
|
|
2960
|
+
context.edges.push(createArgEdge(parentInfo.parentId, nodeId, parentInfo.argIndex ?? 0));
|
|
2961
|
+
}
|
|
2962
|
+
let branchIdx = 0;
|
|
2963
|
+
for (const element of elements) {
|
|
2964
|
+
if (element.type === "expression" && element.branchId) {
|
|
2965
|
+
context.edges.push(createBranchEdge(nodeId, element.branchId, branchIdx));
|
|
2966
|
+
branchIdx++;
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
function walkAndCollectFromTrace(value, path, onValue, context) {
|
|
2971
|
+
if (Array.isArray(value)) {
|
|
2972
|
+
return value.map((item, index) => {
|
|
2973
|
+
const itemPath = [...path, String(index)];
|
|
2974
|
+
if (isJsonLogicExpression(item)) {
|
|
2975
|
+
return onValue(itemPath, item);
|
|
2976
|
+
} else if (typeof item === "object" && item !== null) {
|
|
2977
|
+
return walkAndCollectFromTrace(item, itemPath, onValue);
|
|
2978
|
+
}
|
|
2979
|
+
return item;
|
|
2980
|
+
});
|
|
2981
|
+
}
|
|
2982
|
+
if (typeof value === "object" && value !== null) {
|
|
2983
|
+
const result = {};
|
|
2984
|
+
for (const [key, item] of Object.entries(value)) {
|
|
2985
|
+
const itemPath = [...path, key];
|
|
2986
|
+
if (isJsonLogicExpression(item)) {
|
|
2987
|
+
result[key] = onValue(itemPath, item, key);
|
|
2988
|
+
} else if (typeof item === "object" && item !== null) {
|
|
2989
|
+
result[key] = walkAndCollectFromTrace(item, itemPath, onValue);
|
|
2990
|
+
} else {
|
|
2991
|
+
result[key] = item;
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
return result;
|
|
2995
|
+
}
|
|
2996
|
+
return value;
|
|
2696
2997
|
}
|
|
2697
2998
|
|
|
2698
2999
|
function getDefaultExportFromCjs (x) {
|
|
@@ -7456,6 +7757,9 @@ function isLiteralNode(node) {
|
|
|
7456
7757
|
function isVerticalCellNode(node) {
|
|
7457
7758
|
return node.data.type === "verticalCell";
|
|
7458
7759
|
}
|
|
7760
|
+
function isStructureNode(node) {
|
|
7761
|
+
return node.data.type === "structure";
|
|
7762
|
+
}
|
|
7459
7763
|
|
|
7460
7764
|
function estimateTextWidth(text, isMonospace = false) {
|
|
7461
7765
|
const charWidth = isMonospace ? TEXT_METRICS.charWidthMono : TEXT_METRICS.charWidthRegular;
|
|
@@ -7494,12 +7798,32 @@ function calculateNodeWidth(node) {
|
|
|
7494
7798
|
maxCellWidth = Math.max(maxCellWidth, estimateTextWidth(vcData.expressionText, true));
|
|
7495
7799
|
}
|
|
7496
7800
|
contentWidth = maxCellWidth;
|
|
7801
|
+
} else if (isStructureNode(node)) {
|
|
7802
|
+
const structData = node.data;
|
|
7803
|
+
if (structData.collapsed && structData.expressionText) {
|
|
7804
|
+
contentWidth = estimateTextWidth(structData.expressionText, true);
|
|
7805
|
+
} else {
|
|
7806
|
+
const lines = structData.formattedJson.split("\n");
|
|
7807
|
+
let maxLineWidth = 0;
|
|
7808
|
+
for (const line of lines) {
|
|
7809
|
+
const lineWidth = estimateTextWidth(line, true);
|
|
7810
|
+
maxLineWidth = Math.max(maxLineWidth, lineWidth);
|
|
7811
|
+
}
|
|
7812
|
+
contentWidth = maxLineWidth;
|
|
7813
|
+
}
|
|
7497
7814
|
} else {
|
|
7498
7815
|
contentWidth = FIXED_WIDTHS.fallbackNode;
|
|
7499
7816
|
}
|
|
7500
7817
|
const totalWidth = contentWidth + NODE_PADDING.contentPadding;
|
|
7501
7818
|
return Math.max(NODE_DIMENSIONS.minWidth, Math.min(NODE_DIMENSIONS.maxWidth, totalWidth));
|
|
7502
7819
|
}
|
|
7820
|
+
const STRUCTURE_DIMENSIONS = {
|
|
7821
|
+
headerHeight: 32,
|
|
7822
|
+
lineHeight: 18,
|
|
7823
|
+
bodyPadding: 16,
|
|
7824
|
+
// 8px top + 8px bottom
|
|
7825
|
+
collapsedBodyHeight: 30
|
|
7826
|
+
};
|
|
7503
7827
|
function getNodeDimensions(node) {
|
|
7504
7828
|
const width = calculateNodeWidth(node);
|
|
7505
7829
|
if (isVerticalCellNode(node)) {
|
|
@@ -7516,6 +7840,20 @@ function getNodeDimensions(node) {
|
|
|
7516
7840
|
height: VERTICAL_CELL_DIMENSIONS.headerHeight + cellCount * VERTICAL_CELL_DIMENSIONS.rowHeight
|
|
7517
7841
|
};
|
|
7518
7842
|
}
|
|
7843
|
+
if (isStructureNode(node)) {
|
|
7844
|
+
const structData = node.data;
|
|
7845
|
+
if (structData.collapsed) {
|
|
7846
|
+
return {
|
|
7847
|
+
width,
|
|
7848
|
+
height: STRUCTURE_DIMENSIONS.headerHeight + STRUCTURE_DIMENSIONS.collapsedBodyHeight
|
|
7849
|
+
};
|
|
7850
|
+
}
|
|
7851
|
+
const lineCount = structData.formattedJson.split("\n").length;
|
|
7852
|
+
return {
|
|
7853
|
+
width,
|
|
7854
|
+
height: STRUCTURE_DIMENSIONS.headerHeight + STRUCTURE_DIMENSIONS.bodyPadding + lineCount * STRUCTURE_DIMENSIONS.lineHeight
|
|
7855
|
+
};
|
|
7856
|
+
}
|
|
7519
7857
|
return { width, height: NODE_DIMENSIONS.defaultHeight };
|
|
7520
7858
|
}
|
|
7521
7859
|
function applyTreeLayout(nodes, edges) {
|
|
@@ -7533,7 +7871,7 @@ function applyTreeLayout(nodes, edges) {
|
|
|
7533
7871
|
const { width, height } = getNodeDimensions(node);
|
|
7534
7872
|
g.setNode(node.id, { width, height });
|
|
7535
7873
|
});
|
|
7536
|
-
const edgesToUse = edges || buildEdgesFromNodes(nodes);
|
|
7874
|
+
const edgesToUse = edges || buildEdgesFromNodes$1(nodes);
|
|
7537
7875
|
const nodeIdSet = new Set(nodes.map((n) => n.id));
|
|
7538
7876
|
const sourceEdgeCount = /* @__PURE__ */ new Map();
|
|
7539
7877
|
edgesToUse.forEach((edge) => {
|
|
@@ -7566,7 +7904,7 @@ function applyTreeLayout(nodes, edges) {
|
|
|
7566
7904
|
return node;
|
|
7567
7905
|
});
|
|
7568
7906
|
}
|
|
7569
|
-
function buildEdgesFromNodes(nodes) {
|
|
7907
|
+
function buildEdgesFromNodes$1(nodes) {
|
|
7570
7908
|
const edges = [];
|
|
7571
7909
|
nodes.forEach((node) => {
|
|
7572
7910
|
if (isOperatorNode(node)) {
|
|
@@ -7587,38 +7925,34 @@ function buildEdgesFromNodes(nodes) {
|
|
|
7587
7925
|
const vcData = node.data;
|
|
7588
7926
|
if (!vcData.collapsed) {
|
|
7589
7927
|
const collapsedIndices = vcData.collapsedCellIndices || [];
|
|
7590
|
-
let branchIndex = 0;
|
|
7591
7928
|
vcData.cells.forEach((cell) => {
|
|
7592
7929
|
if (collapsedIndices.includes(cell.index)) return;
|
|
7593
|
-
if (cell.branchId) {
|
|
7594
|
-
edges.push({
|
|
7595
|
-
id: `${node.id}-branch-${cell.branchId}`,
|
|
7596
|
-
source: node.id,
|
|
7597
|
-
target: cell.branchId,
|
|
7598
|
-
sourceHandle: `branch-${branchIndex}`,
|
|
7599
|
-
targetHandle: "left"
|
|
7600
|
-
});
|
|
7601
|
-
branchIndex++;
|
|
7602
|
-
}
|
|
7603
7930
|
if (cell.conditionBranchId) {
|
|
7604
7931
|
edges.push({
|
|
7605
7932
|
id: `${node.id}-cond-${cell.conditionBranchId}`,
|
|
7606
7933
|
source: node.id,
|
|
7607
7934
|
target: cell.conditionBranchId,
|
|
7608
|
-
sourceHandle: `branch-${
|
|
7935
|
+
sourceHandle: `branch-${cell.index}-cond`,
|
|
7609
7936
|
targetHandle: "left"
|
|
7610
7937
|
});
|
|
7611
|
-
branchIndex++;
|
|
7612
7938
|
}
|
|
7613
7939
|
if (cell.thenBranchId) {
|
|
7614
7940
|
edges.push({
|
|
7615
7941
|
id: `${node.id}-then-${cell.thenBranchId}`,
|
|
7616
7942
|
source: node.id,
|
|
7617
7943
|
target: cell.thenBranchId,
|
|
7618
|
-
sourceHandle: `branch-${
|
|
7944
|
+
sourceHandle: `branch-${cell.index}-then`,
|
|
7945
|
+
targetHandle: "left"
|
|
7946
|
+
});
|
|
7947
|
+
}
|
|
7948
|
+
if (cell.branchId && !cell.conditionBranchId && !cell.thenBranchId) {
|
|
7949
|
+
edges.push({
|
|
7950
|
+
id: `${node.id}-branch-${cell.branchId}`,
|
|
7951
|
+
source: node.id,
|
|
7952
|
+
target: cell.branchId,
|
|
7953
|
+
sourceHandle: `branch-${cell.index}`,
|
|
7619
7954
|
targetHandle: "left"
|
|
7620
7955
|
});
|
|
7621
|
-
branchIndex++;
|
|
7622
7956
|
}
|
|
7623
7957
|
});
|
|
7624
7958
|
}
|
|
@@ -7646,7 +7980,8 @@ const emptyTraceNodeMap = /* @__PURE__ */ new Map();
|
|
|
7646
7980
|
function useLogicEditor({
|
|
7647
7981
|
value,
|
|
7648
7982
|
evaluateWithTrace,
|
|
7649
|
-
data
|
|
7983
|
+
data,
|
|
7984
|
+
preserveStructure = false
|
|
7650
7985
|
}) {
|
|
7651
7986
|
const [nodes, setNodes] = react.useState([]);
|
|
7652
7987
|
const [edges, setEdges] = react.useState([]);
|
|
@@ -7658,11 +7993,12 @@ function useLogicEditor({
|
|
|
7658
7993
|
const [lastExternalValue, setLastExternalValue] = react.useState("");
|
|
7659
7994
|
const [lastData, setLastData] = react.useState("");
|
|
7660
7995
|
const [lastHadTrace, setLastHadTrace] = react.useState(false);
|
|
7996
|
+
const [lastPreserveStructure, setLastPreserveStructure] = react.useState(false);
|
|
7661
7997
|
react.useEffect(() => {
|
|
7662
7998
|
const valueStr = JSON.stringify(value);
|
|
7663
7999
|
const dataStr = JSON.stringify(data);
|
|
7664
8000
|
const hasTrace = !!evaluateWithTrace;
|
|
7665
|
-
if (valueStr === lastExternalValue && dataStr === lastData && hasTrace === lastHadTrace) {
|
|
8001
|
+
if (valueStr === lastExternalValue && dataStr === lastData && hasTrace === lastHadTrace && preserveStructure === lastPreserveStructure) {
|
|
7666
8002
|
return;
|
|
7667
8003
|
}
|
|
7668
8004
|
try {
|
|
@@ -7677,12 +8013,13 @@ function useLogicEditor({
|
|
|
7677
8013
|
setLastExternalValue(valueStr);
|
|
7678
8014
|
setLastData(dataStr);
|
|
7679
8015
|
setLastHadTrace(hasTrace);
|
|
8016
|
+
setLastPreserveStructure(preserveStructure);
|
|
7680
8017
|
return;
|
|
7681
8018
|
}
|
|
7682
8019
|
if (evaluateWithTrace && value) {
|
|
7683
8020
|
try {
|
|
7684
8021
|
const trace = evaluateWithTrace(value, data ?? {});
|
|
7685
|
-
const { nodes: newNodes2, edges: newEdges2, traceNodeMap: newTraceNodeMap } = traceToNodes(trace);
|
|
8022
|
+
const { nodes: newNodes2, edges: newEdges2, traceNodeMap: newTraceNodeMap } = traceToNodes(trace, { preserveStructure, originalValue: value });
|
|
7686
8023
|
const layoutedNodes2 = applyTreeLayout(newNodes2, newEdges2);
|
|
7687
8024
|
const traceResults = buildEvaluationResultsFromTrace(trace);
|
|
7688
8025
|
setNodes(layoutedNodes2);
|
|
@@ -7695,12 +8032,13 @@ function useLogicEditor({
|
|
|
7695
8032
|
setLastExternalValue(valueStr);
|
|
7696
8033
|
setLastData(dataStr);
|
|
7697
8034
|
setLastHadTrace(hasTrace);
|
|
8035
|
+
setLastPreserveStructure(preserveStructure);
|
|
7698
8036
|
return;
|
|
7699
8037
|
} catch (traceErr) {
|
|
7700
8038
|
console.warn("Trace conversion failed, falling back to JS:", traceErr);
|
|
7701
8039
|
}
|
|
7702
8040
|
}
|
|
7703
|
-
const { nodes: newNodes, edges: newEdges } = jsonLogicToNodes(value);
|
|
8041
|
+
const { nodes: newNodes, edges: newEdges } = jsonLogicToNodes(value, { preserveStructure });
|
|
7704
8042
|
const layoutedNodes = applyTreeLayout(newNodes, newEdges);
|
|
7705
8043
|
setNodes(layoutedNodes);
|
|
7706
8044
|
setEdges(newEdges);
|
|
@@ -7722,7 +8060,8 @@ function useLogicEditor({
|
|
|
7722
8060
|
setLastExternalValue(valueStr);
|
|
7723
8061
|
setLastData(dataStr);
|
|
7724
8062
|
setLastHadTrace(hasTrace);
|
|
7725
|
-
|
|
8063
|
+
setLastPreserveStructure(preserveStructure);
|
|
8064
|
+
}, [value, data, evaluateWithTrace, preserveStructure, lastExternalValue, lastData, lastHadTrace, lastPreserveStructure]);
|
|
7726
8065
|
return react.useMemo(
|
|
7727
8066
|
() => ({
|
|
7728
8067
|
nodes,
|
|
@@ -8041,7 +8380,8 @@ function useDebugEvaluation({
|
|
|
8041
8380
|
}, [nodes, data, evaluate, enabled]);
|
|
8042
8381
|
}
|
|
8043
8382
|
|
|
8044
|
-
function useWasmEvaluator() {
|
|
8383
|
+
function useWasmEvaluator(options = {}) {
|
|
8384
|
+
const { preserveStructure = false } = options;
|
|
8045
8385
|
const [ready, setReady] = react.useState(false);
|
|
8046
8386
|
const [loading, setLoading] = react.useState(true);
|
|
8047
8387
|
const [error, setError] = react.useState(null);
|
|
@@ -8052,7 +8392,7 @@ function useWasmEvaluator() {
|
|
|
8052
8392
|
try {
|
|
8053
8393
|
setLoading(true);
|
|
8054
8394
|
setError(null);
|
|
8055
|
-
const wasm = await Promise.resolve().then(() => require('./datalogic_wasm-
|
|
8395
|
+
const wasm = await Promise.resolve().then(() => require('./datalogic_wasm-BN8H01AG.cjs'));
|
|
8056
8396
|
await wasm.default();
|
|
8057
8397
|
if (!cancelled) {
|
|
8058
8398
|
moduleRef.current = {
|
|
@@ -8082,12 +8422,12 @@ function useWasmEvaluator() {
|
|
|
8082
8422
|
try {
|
|
8083
8423
|
const logicStr = JSON.stringify(logic);
|
|
8084
8424
|
const dataStr = JSON.stringify(data);
|
|
8085
|
-
const resultStr = moduleRef.current.evaluate(logicStr, dataStr);
|
|
8425
|
+
const resultStr = moduleRef.current.evaluate(logicStr, dataStr, preserveStructure);
|
|
8086
8426
|
return JSON.parse(resultStr);
|
|
8087
8427
|
} catch (err) {
|
|
8088
8428
|
throw new Error(err instanceof Error ? err.message : "Evaluation failed");
|
|
8089
8429
|
}
|
|
8090
|
-
}, []);
|
|
8430
|
+
}, [preserveStructure]);
|
|
8091
8431
|
const evaluateWithTrace = react.useCallback((logic, data) => {
|
|
8092
8432
|
if (!moduleRef.current) {
|
|
8093
8433
|
throw new Error("WASM module not initialized");
|
|
@@ -8098,12 +8438,12 @@ function useWasmEvaluator() {
|
|
|
8098
8438
|
try {
|
|
8099
8439
|
const logicStr = JSON.stringify(logic);
|
|
8100
8440
|
const dataStr = JSON.stringify(data);
|
|
8101
|
-
const resultStr = moduleRef.current.evaluate_with_trace(logicStr, dataStr);
|
|
8441
|
+
const resultStr = moduleRef.current.evaluate_with_trace(logicStr, dataStr, preserveStructure);
|
|
8102
8442
|
return JSON.parse(resultStr);
|
|
8103
8443
|
} catch (err) {
|
|
8104
8444
|
throw new Error(err instanceof Error ? err.message : "Trace evaluation failed");
|
|
8105
8445
|
}
|
|
8106
|
-
}, []);
|
|
8446
|
+
}, [preserveStructure]);
|
|
8107
8447
|
return {
|
|
8108
8448
|
ready,
|
|
8109
8449
|
loading,
|
|
@@ -8493,16 +8833,16 @@ const LiteralNode = react.memo(function LiteralNode2({
|
|
|
8493
8833
|
|
|
8494
8834
|
const CellHandles = react.memo(function CellHandles2({
|
|
8495
8835
|
cell,
|
|
8496
|
-
branchIndex,
|
|
8497
8836
|
color
|
|
8498
8837
|
}) {
|
|
8838
|
+
const cellIndex = cell.index;
|
|
8499
8839
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8500
8840
|
cell.conditionBranchId && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8501
8841
|
react$1.Handle,
|
|
8502
8842
|
{
|
|
8503
8843
|
type: "source",
|
|
8504
8844
|
position: react$1.Position.Right,
|
|
8505
|
-
id: `branch-${
|
|
8845
|
+
id: `branch-${cellIndex}-cond`,
|
|
8506
8846
|
className: "cell-handle condition-handle",
|
|
8507
8847
|
style: { background: color, top: `${HANDLE_POSITIONS.conditionTop}px` }
|
|
8508
8848
|
}
|
|
@@ -8512,7 +8852,7 @@ const CellHandles = react.memo(function CellHandles2({
|
|
|
8512
8852
|
{
|
|
8513
8853
|
type: "source",
|
|
8514
8854
|
position: react$1.Position.Right,
|
|
8515
|
-
id: `branch-${
|
|
8855
|
+
id: `branch-${cellIndex}-then`,
|
|
8516
8856
|
className: "cell-handle then-handle",
|
|
8517
8857
|
style: { background: "#22C55E", top: `${HANDLE_POSITIONS.thenTop}px` }
|
|
8518
8858
|
}
|
|
@@ -8522,7 +8862,7 @@ const CellHandles = react.memo(function CellHandles2({
|
|
|
8522
8862
|
{
|
|
8523
8863
|
type: "source",
|
|
8524
8864
|
position: react$1.Position.Right,
|
|
8525
|
-
id: `branch-${
|
|
8865
|
+
id: `branch-${cellIndex}`,
|
|
8526
8866
|
className: "cell-handle",
|
|
8527
8867
|
style: { background: color, top: `${HANDLE_POSITIONS.centeredTop}px` }
|
|
8528
8868
|
}
|
|
@@ -8530,21 +8870,8 @@ const CellHandles = react.memo(function CellHandles2({
|
|
|
8530
8870
|
] });
|
|
8531
8871
|
});
|
|
8532
8872
|
|
|
8533
|
-
function calculateBranchIndex(cells, currentIndex) {
|
|
8534
|
-
let branchIdx = 0;
|
|
8535
|
-
for (let i = 0; i < currentIndex; i++) {
|
|
8536
|
-
const prevCell = cells.find((c) => c.index === i);
|
|
8537
|
-
if (prevCell) {
|
|
8538
|
-
if (prevCell.conditionBranchId) branchIdx++;
|
|
8539
|
-
if (prevCell.thenBranchId) branchIdx++;
|
|
8540
|
-
if (prevCell.branchId) branchIdx++;
|
|
8541
|
-
}
|
|
8542
|
-
}
|
|
8543
|
-
return branchIdx;
|
|
8544
|
-
}
|
|
8545
8873
|
const CellRow = react.memo(function CellRow2({
|
|
8546
8874
|
cell,
|
|
8547
|
-
cells,
|
|
8548
8875
|
collapsedIndices,
|
|
8549
8876
|
color,
|
|
8550
8877
|
onToggleCollapse
|
|
@@ -8553,7 +8880,6 @@ const CellRow = react.memo(function CellRow2({
|
|
|
8553
8880
|
const isIfThenCell = cell.conditionBranchId || cell.thenBranchId;
|
|
8554
8881
|
const hasAnyBranch = cell.type === "branch" || isIfThenCell;
|
|
8555
8882
|
const isExpanded = hasAnyBranch && !isCellCollapsed;
|
|
8556
|
-
const branchIndex = calculateBranchIndex(cells, cell.index);
|
|
8557
8883
|
const handleToggle = react.useCallback(
|
|
8558
8884
|
(e) => {
|
|
8559
8885
|
onToggleCollapse(cell.index, e);
|
|
@@ -8573,7 +8899,7 @@ const CellRow = react.memo(function CellRow2({
|
|
|
8573
8899
|
variant: "cell"
|
|
8574
8900
|
}
|
|
8575
8901
|
),
|
|
8576
|
-
isExpanded && /* @__PURE__ */ jsxRuntime.jsx(CellHandles, { cell,
|
|
8902
|
+
isExpanded && /* @__PURE__ */ jsxRuntime.jsx(CellHandles, { cell, color: isThenRow ? BRANCH_COLORS.yes : color })
|
|
8577
8903
|
] });
|
|
8578
8904
|
});
|
|
8579
8905
|
|
|
@@ -8633,7 +8959,6 @@ const VerticalCellNode = react.memo(function VerticalCellNode2({
|
|
|
8633
8959
|
CellRow,
|
|
8634
8960
|
{
|
|
8635
8961
|
cell,
|
|
8636
|
-
cells: data.cells,
|
|
8637
8962
|
collapsedIndices,
|
|
8638
8963
|
color,
|
|
8639
8964
|
onToggleCollapse: toggleCellCollapse
|
|
@@ -8645,11 +8970,197 @@ const VerticalCellNode = react.memo(function VerticalCellNode2({
|
|
|
8645
8970
|
);
|
|
8646
8971
|
});
|
|
8647
8972
|
|
|
8973
|
+
const STRUCTURE_COLOR = "#64748B";
|
|
8974
|
+
const LINE_HEIGHT = 18;
|
|
8975
|
+
const HEADER_HEIGHT = 32;
|
|
8976
|
+
const BODY_PADDING = 8;
|
|
8977
|
+
const StructureNode = react.memo(function StructureNode2({
|
|
8978
|
+
id,
|
|
8979
|
+
data,
|
|
8980
|
+
selected
|
|
8981
|
+
}) {
|
|
8982
|
+
const debugClassName = useDebugClassName(id);
|
|
8983
|
+
const toggleNodeCollapse = useNodeCollapse(id);
|
|
8984
|
+
const isCollapsed = data.collapsed ?? false;
|
|
8985
|
+
const expressionElements = react.useMemo(
|
|
8986
|
+
() => data.elements.filter((e) => e.type === "expression"),
|
|
8987
|
+
[data.elements]
|
|
8988
|
+
);
|
|
8989
|
+
const hasExpressions = expressionElements.length > 0;
|
|
8990
|
+
const expressionLineNumbers = react.useMemo(() => {
|
|
8991
|
+
return expressionElements.map((element) => {
|
|
8992
|
+
const textBefore = data.formattedJson.slice(0, element.startOffset);
|
|
8993
|
+
const lineNumber = textBefore.split("\n").length;
|
|
8994
|
+
return lineNumber;
|
|
8995
|
+
});
|
|
8996
|
+
}, [expressionElements, data.formattedJson]);
|
|
8997
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8998
|
+
"div",
|
|
8999
|
+
{
|
|
9000
|
+
className: `structure-node ${selected ? "selected" : ""} ${isCollapsed ? "collapsed" : ""} ${debugClassName}`,
|
|
9001
|
+
style: {
|
|
9002
|
+
borderColor: STRUCTURE_COLOR,
|
|
9003
|
+
backgroundColor: `${STRUCTURE_COLOR}10`
|
|
9004
|
+
},
|
|
9005
|
+
children: [
|
|
9006
|
+
/* @__PURE__ */ jsxRuntime.jsx(NodeDebugBubble, { nodeId: id, position: "top" }),
|
|
9007
|
+
/* @__PURE__ */ jsxRuntime.jsx(NodeInputHandles, { nodeId: id, color: STRUCTURE_COLOR }),
|
|
9008
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "structure-node-header", style: { backgroundColor: STRUCTURE_COLOR }, children: [
|
|
9009
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "structure-node-icon", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: data.isArray ? "list" : "braces", size: 14 }) }),
|
|
9010
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "structure-node-label", children: data.isArray ? "Array" : "Object" }),
|
|
9011
|
+
hasExpressions && /* @__PURE__ */ jsxRuntime.jsx(CollapseToggleButton, { isCollapsed, onClick: toggleNodeCollapse })
|
|
9012
|
+
] }),
|
|
9013
|
+
isCollapsed ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "structure-node-body collapsed-body", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "expression-text", children: /* @__PURE__ */ jsxRuntime.jsx(ExpressionSyntax, { text: data.expressionText || "..." }) }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "structure-node-body", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9014
|
+
FormattedJson,
|
|
9015
|
+
{
|
|
9016
|
+
json: data.formattedJson,
|
|
9017
|
+
elements: data.elements
|
|
9018
|
+
}
|
|
9019
|
+
) }),
|
|
9020
|
+
!isCollapsed && expressionElements.map((_element, idx) => {
|
|
9021
|
+
const lineNumber = expressionLineNumbers[idx];
|
|
9022
|
+
const topPosition = HEADER_HEIGHT + BODY_PADDING + (lineNumber - 1) * LINE_HEIGHT + LINE_HEIGHT / 2;
|
|
9023
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9024
|
+
react$1.Handle,
|
|
9025
|
+
{
|
|
9026
|
+
type: "source",
|
|
9027
|
+
position: react$1.Position.Right,
|
|
9028
|
+
id: `branch-${idx}`,
|
|
9029
|
+
className: "structure-branch-handle",
|
|
9030
|
+
style: {
|
|
9031
|
+
background: "#3B82F6",
|
|
9032
|
+
top: `${topPosition}px`,
|
|
9033
|
+
right: "-4px"
|
|
9034
|
+
}
|
|
9035
|
+
},
|
|
9036
|
+
`branch-${idx}`
|
|
9037
|
+
);
|
|
9038
|
+
})
|
|
9039
|
+
]
|
|
9040
|
+
}
|
|
9041
|
+
);
|
|
9042
|
+
});
|
|
9043
|
+
function FormattedJson({ json, elements }) {
|
|
9044
|
+
const expressionElements = elements.filter((e) => e.type === "expression").sort((a, b) => a.startOffset - b.startOffset);
|
|
9045
|
+
if (expressionElements.length === 0) {
|
|
9046
|
+
return /* @__PURE__ */ jsxRuntime.jsx(JsonSyntax, { text: json });
|
|
9047
|
+
}
|
|
9048
|
+
const parts = [];
|
|
9049
|
+
let lastEnd = 0;
|
|
9050
|
+
let markerIndex = 0;
|
|
9051
|
+
for (const element of expressionElements) {
|
|
9052
|
+
if (element.startOffset > lastEnd) {
|
|
9053
|
+
const textBefore = json.slice(lastEnd, element.startOffset);
|
|
9054
|
+
parts.push(
|
|
9055
|
+
/* @__PURE__ */ jsxRuntime.jsx(JsonSyntax, { text: textBefore }, `text-${lastEnd}`)
|
|
9056
|
+
);
|
|
9057
|
+
}
|
|
9058
|
+
parts.push(
|
|
9059
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "structure-expression-marker", children: element.key || `[${markerIndex}]` }, `marker-${markerIndex}`)
|
|
9060
|
+
);
|
|
9061
|
+
lastEnd = element.endOffset;
|
|
9062
|
+
markerIndex++;
|
|
9063
|
+
}
|
|
9064
|
+
if (lastEnd < json.length) {
|
|
9065
|
+
parts.push(
|
|
9066
|
+
/* @__PURE__ */ jsxRuntime.jsx(JsonSyntax, { text: json.slice(lastEnd) }, `text-${lastEnd}`)
|
|
9067
|
+
);
|
|
9068
|
+
}
|
|
9069
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: parts });
|
|
9070
|
+
}
|
|
9071
|
+
function JsonSyntax({ text }) {
|
|
9072
|
+
const highlighted = highlightJson(text);
|
|
9073
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: highlighted });
|
|
9074
|
+
}
|
|
9075
|
+
function highlightJson(text) {
|
|
9076
|
+
const result = [];
|
|
9077
|
+
let i = 0;
|
|
9078
|
+
while (i < text.length) {
|
|
9079
|
+
const char = text[i];
|
|
9080
|
+
if (/\s/.test(char)) {
|
|
9081
|
+
let whitespace = "";
|
|
9082
|
+
while (i < text.length && /\s/.test(text[i])) {
|
|
9083
|
+
whitespace += text[i];
|
|
9084
|
+
i++;
|
|
9085
|
+
}
|
|
9086
|
+
result.push(whitespace);
|
|
9087
|
+
continue;
|
|
9088
|
+
}
|
|
9089
|
+
if (char === '"') {
|
|
9090
|
+
let str = '"';
|
|
9091
|
+
i++;
|
|
9092
|
+
while (i < text.length && text[i] !== '"') {
|
|
9093
|
+
if (text[i] === "\\" && i + 1 < text.length) {
|
|
9094
|
+
str += text[i] + text[i + 1];
|
|
9095
|
+
i += 2;
|
|
9096
|
+
} else {
|
|
9097
|
+
str += text[i];
|
|
9098
|
+
i++;
|
|
9099
|
+
}
|
|
9100
|
+
}
|
|
9101
|
+
if (i < text.length) {
|
|
9102
|
+
str += '"';
|
|
9103
|
+
i++;
|
|
9104
|
+
}
|
|
9105
|
+
let j = i;
|
|
9106
|
+
while (j < text.length && /\s/.test(text[j])) j++;
|
|
9107
|
+
const isKey = text[j] === ":";
|
|
9108
|
+
result.push(
|
|
9109
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: isKey ? "json-syntax-key" : "json-syntax-string", children: str }, `str-${i}`)
|
|
9110
|
+
);
|
|
9111
|
+
continue;
|
|
9112
|
+
}
|
|
9113
|
+
if (/[-\d]/.test(char)) {
|
|
9114
|
+
let num = "";
|
|
9115
|
+
while (i < text.length && /[-\d.eE+]/.test(text[i])) {
|
|
9116
|
+
num += text[i];
|
|
9117
|
+
i++;
|
|
9118
|
+
}
|
|
9119
|
+
result.push(
|
|
9120
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "json-syntax-number", children: num }, `num-${i}`)
|
|
9121
|
+
);
|
|
9122
|
+
continue;
|
|
9123
|
+
}
|
|
9124
|
+
if (text.slice(i, i + 4) === "true") {
|
|
9125
|
+
result.push(
|
|
9126
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "json-syntax-boolean-true", children: "true" }, `bool-${i}`)
|
|
9127
|
+
);
|
|
9128
|
+
i += 4;
|
|
9129
|
+
continue;
|
|
9130
|
+
}
|
|
9131
|
+
if (text.slice(i, i + 5) === "false") {
|
|
9132
|
+
result.push(
|
|
9133
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "json-syntax-boolean-false", children: "false" }, `bool-${i}`)
|
|
9134
|
+
);
|
|
9135
|
+
i += 5;
|
|
9136
|
+
continue;
|
|
9137
|
+
}
|
|
9138
|
+
if (text.slice(i, i + 4) === "null") {
|
|
9139
|
+
result.push(
|
|
9140
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "json-syntax-null", children: "null" }, `null-${i}`)
|
|
9141
|
+
);
|
|
9142
|
+
i += 4;
|
|
9143
|
+
continue;
|
|
9144
|
+
}
|
|
9145
|
+
if (/[{}[\]:,]/.test(char)) {
|
|
9146
|
+
result.push(
|
|
9147
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "json-syntax-punctuation", children: char }, `punct-${i}`)
|
|
9148
|
+
);
|
|
9149
|
+
i++;
|
|
9150
|
+
continue;
|
|
9151
|
+
}
|
|
9152
|
+
result.push(char);
|
|
9153
|
+
i++;
|
|
9154
|
+
}
|
|
9155
|
+
return result;
|
|
9156
|
+
}
|
|
9157
|
+
|
|
8648
9158
|
const nodeTypes = {
|
|
8649
9159
|
operator: OperatorNode,
|
|
8650
9160
|
variable: VariableNode,
|
|
8651
9161
|
literal: LiteralNode,
|
|
8652
|
-
verticalCell: VerticalCellNode
|
|
9162
|
+
verticalCell: VerticalCellNode,
|
|
9163
|
+
structure: StructureNode
|
|
8653
9164
|
};
|
|
8654
9165
|
|
|
8655
9166
|
function collectCellBranchIds(cell, target) {
|
|
@@ -8715,6 +9226,82 @@ function getHiddenNodeIds(nodes) {
|
|
|
8715
9226
|
return hiddenIds;
|
|
8716
9227
|
}
|
|
8717
9228
|
|
|
9229
|
+
function buildEdgesFromNodes(nodes) {
|
|
9230
|
+
const edges = [];
|
|
9231
|
+
nodes.forEach((node) => {
|
|
9232
|
+
if (node.type === "operator") {
|
|
9233
|
+
const opData = node.data;
|
|
9234
|
+
if (!opData.collapsed) {
|
|
9235
|
+
opData.childIds.forEach((childId, idx) => {
|
|
9236
|
+
edges.push({
|
|
9237
|
+
id: `${node.id}-${childId}`,
|
|
9238
|
+
source: node.id,
|
|
9239
|
+
target: childId,
|
|
9240
|
+
sourceHandle: `arg-${idx}`,
|
|
9241
|
+
targetHandle: "left"
|
|
9242
|
+
});
|
|
9243
|
+
});
|
|
9244
|
+
}
|
|
9245
|
+
}
|
|
9246
|
+
if (node.type === "verticalCell") {
|
|
9247
|
+
const vcData = node.data;
|
|
9248
|
+
if (!vcData.collapsed) {
|
|
9249
|
+
const collapsedIndices = vcData.collapsedCellIndices || [];
|
|
9250
|
+
vcData.cells.forEach((cell) => {
|
|
9251
|
+
if (collapsedIndices.includes(cell.index)) return;
|
|
9252
|
+
if (cell.conditionBranchId) {
|
|
9253
|
+
edges.push({
|
|
9254
|
+
id: `${node.id}-cond-${cell.conditionBranchId}`,
|
|
9255
|
+
source: node.id,
|
|
9256
|
+
target: cell.conditionBranchId,
|
|
9257
|
+
sourceHandle: `branch-${cell.index}-cond`,
|
|
9258
|
+
targetHandle: "left"
|
|
9259
|
+
});
|
|
9260
|
+
}
|
|
9261
|
+
if (cell.thenBranchId) {
|
|
9262
|
+
edges.push({
|
|
9263
|
+
id: `${node.id}-then-${cell.thenBranchId}`,
|
|
9264
|
+
source: node.id,
|
|
9265
|
+
target: cell.thenBranchId,
|
|
9266
|
+
sourceHandle: `branch-${cell.index}-then`,
|
|
9267
|
+
targetHandle: "left"
|
|
9268
|
+
});
|
|
9269
|
+
}
|
|
9270
|
+
if (cell.branchId && !cell.conditionBranchId && !cell.thenBranchId) {
|
|
9271
|
+
edges.push({
|
|
9272
|
+
id: `${node.id}-branch-${cell.branchId}`,
|
|
9273
|
+
source: node.id,
|
|
9274
|
+
target: cell.branchId,
|
|
9275
|
+
sourceHandle: `branch-${cell.index}`,
|
|
9276
|
+
targetHandle: "left"
|
|
9277
|
+
});
|
|
9278
|
+
}
|
|
9279
|
+
});
|
|
9280
|
+
}
|
|
9281
|
+
}
|
|
9282
|
+
if (node.type === "structure") {
|
|
9283
|
+
const structData = node.data;
|
|
9284
|
+
if (!structData.collapsed && structData.elements) {
|
|
9285
|
+
const expressionElements = structData.elements.filter(
|
|
9286
|
+
(el) => el.type === "expression" && el.branchId
|
|
9287
|
+
);
|
|
9288
|
+
expressionElements.forEach((element, idx) => {
|
|
9289
|
+
if (element.branchId) {
|
|
9290
|
+
edges.push({
|
|
9291
|
+
id: `${node.id}-expr-${element.branchId}`,
|
|
9292
|
+
source: node.id,
|
|
9293
|
+
target: element.branchId,
|
|
9294
|
+
sourceHandle: `expr-${idx}`,
|
|
9295
|
+
targetHandle: "left"
|
|
9296
|
+
});
|
|
9297
|
+
}
|
|
9298
|
+
});
|
|
9299
|
+
}
|
|
9300
|
+
}
|
|
9301
|
+
});
|
|
9302
|
+
return edges;
|
|
9303
|
+
}
|
|
9304
|
+
|
|
8718
9305
|
function DebuggerControls() {
|
|
8719
9306
|
const {
|
|
8720
9307
|
state,
|
|
@@ -8888,22 +9475,22 @@ function DataLogicEditorInner({
|
|
|
8888
9475
|
}) {
|
|
8889
9476
|
const bgColor = theme === "dark" ? "#404040" : "#cccccc";
|
|
8890
9477
|
const [nodes, setNodes, onNodesChange] = react$1.useNodesState(initialNodes);
|
|
8891
|
-
const [
|
|
9478
|
+
const [, , onEdgesChange] = react$1.useEdgesState(initialEdges);
|
|
8892
9479
|
react.useEffect(() => {
|
|
8893
9480
|
setNodes(initialNodes);
|
|
8894
|
-
|
|
8895
|
-
}, [initialNodes, initialEdges, setNodes, setEdges]);
|
|
9481
|
+
}, [initialNodes, setNodes]);
|
|
8896
9482
|
const hiddenNodeIds = react.useMemo(() => getHiddenNodeIds(nodes), [nodes]);
|
|
8897
9483
|
const nodeIds = react.useMemo(() => new Set(nodes.map((n) => n.id)), [nodes]);
|
|
8898
9484
|
const visibleNodes = react.useMemo(
|
|
8899
9485
|
() => nodes.filter((node) => !hiddenNodeIds.has(node.id)),
|
|
8900
9486
|
[nodes, hiddenNodeIds]
|
|
8901
9487
|
);
|
|
9488
|
+
const currentEdges = react.useMemo(() => buildEdgesFromNodes(nodes), [nodes]);
|
|
8902
9489
|
const visibleEdges = react.useMemo(
|
|
8903
|
-
() =>
|
|
9490
|
+
() => currentEdges.filter(
|
|
8904
9491
|
(edge) => nodeIds.has(edge.source) && nodeIds.has(edge.target) && !hiddenNodeIds.has(edge.source) && !hiddenNodeIds.has(edge.target)
|
|
8905
9492
|
),
|
|
8906
|
-
[
|
|
9493
|
+
[currentEdges, nodeIds, hiddenNodeIds]
|
|
8907
9494
|
);
|
|
8908
9495
|
return /* @__PURE__ */ jsxRuntime.jsx(EvaluationContext.Provider, { value: evaluationResults, children: /* @__PURE__ */ jsxRuntime.jsxs(ConnectedHandlesProvider, { edges: visibleEdges, children: [
|
|
8909
9496
|
/* @__PURE__ */ jsxRuntime.jsx(react$1.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -8942,7 +9529,8 @@ function DataLogicEditor({
|
|
|
8942
9529
|
data,
|
|
8943
9530
|
mode = "visualize",
|
|
8944
9531
|
theme: themeProp,
|
|
8945
|
-
className = ""
|
|
9532
|
+
className = "",
|
|
9533
|
+
preserveStructure = false
|
|
8946
9534
|
}) {
|
|
8947
9535
|
if (mode === "edit") {
|
|
8948
9536
|
console.warn("[DataLogicEditor] Edit mode is not yet implemented. Component will render in read-only mode with debug evaluation if data is provided.");
|
|
@@ -8953,14 +9541,15 @@ function DataLogicEditor({
|
|
|
8953
9541
|
ready: wasmReady,
|
|
8954
9542
|
evaluate,
|
|
8955
9543
|
evaluateWithTrace
|
|
8956
|
-
} = useWasmEvaluator();
|
|
9544
|
+
} = useWasmEvaluator({ preserveStructure });
|
|
8957
9545
|
const debugEnabled = mode === "debug" && data !== void 0;
|
|
8958
9546
|
const editor = useLogicEditor({
|
|
8959
9547
|
value,
|
|
8960
9548
|
evaluateWithTrace: debugEnabled && wasmReady ? evaluateWithTrace : void 0,
|
|
8961
|
-
data: debugEnabled ? data : void 0
|
|
9549
|
+
data: debugEnabled ? data : void 0,
|
|
9550
|
+
preserveStructure
|
|
8962
9551
|
});
|
|
8963
|
-
const expressionKey = editor.nodes.length
|
|
9552
|
+
const expressionKey = `${editor.nodes.length}-${editor.edges.length}-${editor.nodes[0]?.id ?? "empty"}`;
|
|
8964
9553
|
const fallbackResults = useDebugEvaluation({
|
|
8965
9554
|
nodes: editor.nodes,
|
|
8966
9555
|
data,
|
|
@@ -8975,7 +9564,7 @@ function DataLogicEditor({
|
|
|
8975
9564
|
] }) });
|
|
8976
9565
|
}
|
|
8977
9566
|
const showDebugger = debugEnabled && editor.usingTraceMode && editor.steps.length > 0;
|
|
8978
|
-
const readOnly =
|
|
9567
|
+
const readOnly = false;
|
|
8979
9568
|
const editorInner = /* @__PURE__ */ jsxRuntime.jsx(
|
|
8980
9569
|
DataLogicEditorInner,
|
|
8981
9570
|
{
|