@wildwinter/expr-editor 0.3.0 → 0.4.0
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 +7 -0
- package/dist/index.cjs +22 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +22 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,6 +43,13 @@ Notable options beyond the basics:
|
|
|
43
43
|
`document.body`). Pass a container inside a focus-trapping dialog (Radix,
|
|
44
44
|
etc.) so opening a pill's popover counts as "inside" that layer and does not
|
|
45
45
|
dismiss the dialog; the popover is then positioned relative to that container.
|
|
46
|
+
- `requireNonEmpty` — block a delete that would empty the whole expression
|
|
47
|
+
(single-value fields that must always hold a term). Conditions leave it off
|
|
48
|
+
(an empty condition is the valid "always" state).
|
|
49
|
+
- `valueEnumValues` + `valueField` — flat single-value editing for an
|
|
50
|
+
outcome-style value cell: `valueEnumValues` offers a target's enum values on
|
|
51
|
+
the root literal, and `valueField` makes an empty value render one editable
|
|
52
|
+
"set a value…" pill instead of the condition clause-menu empty state.
|
|
46
53
|
- `setText(on)` — the host's raw-text toggle (`</>`); unparseable input falls
|
|
47
54
|
back to raw text automatically.
|
|
48
55
|
|
package/dist/index.cjs
CHANGED
|
@@ -490,11 +490,14 @@ function numberEditor(ctx, path, value, anchor) {
|
|
|
490
490
|
function stringEditor(ctx, path, node, anchor) {
|
|
491
491
|
const peer = findEnumPeer(ctx.getAst(), path);
|
|
492
492
|
const enumEntry = peer ? lookup(ctx.catalogue, peer.scope, peer.name) : null;
|
|
493
|
+
const rootValueEnums = path.length === 0 && ctx.valueEnumValues?.length ? ctx.valueEnumValues : null;
|
|
494
|
+
const enumValues = enumEntry?.enumValues?.length ? enumEntry.enumValues : rootValueEnums;
|
|
495
|
+
const enumHeadLabel = enumEntry ? `${displayName(enumEntry, ctx.defaultScope)} value` : "Value";
|
|
493
496
|
ctx.openPopover(anchor, (close) => {
|
|
494
|
-
if (
|
|
497
|
+
if (enumValues?.length) {
|
|
495
498
|
const wrap = el("div", "exed-menu");
|
|
496
|
-
wrap.append(el("div", "exed-menu-head", [
|
|
497
|
-
for (const v of
|
|
499
|
+
wrap.append(el("div", "exed-menu-head", [enumHeadLabel]));
|
|
500
|
+
for (const v of enumValues) {
|
|
498
501
|
wrap.append(button(`exed-opt${v === node.value ? " sel" : ""}`, v, () => {
|
|
499
502
|
replace(ctx, path, strLit(v));
|
|
500
503
|
close();
|
|
@@ -566,6 +569,7 @@ function flagEditor(ctx, path, node, anchor) {
|
|
|
566
569
|
return wrap;
|
|
567
570
|
});
|
|
568
571
|
}
|
|
572
|
+
var canDelete = (ctx, path) => !(ctx.requireNonEmpty && path.length === 0);
|
|
569
573
|
function callEditor(ctx, path, node, anchor) {
|
|
570
574
|
ctx.openPopover(anchor, (close) => {
|
|
571
575
|
const wrap = el("div", "exed-menu");
|
|
@@ -577,10 +581,12 @@ function callEditor(ctx, path, node, anchor) {
|
|
|
577
581
|
close();
|
|
578
582
|
}));
|
|
579
583
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
+
if (canDelete(ctx, path)) {
|
|
585
|
+
wrap.append(button("exed-opt danger", "Delete", () => {
|
|
586
|
+
ctx.apply(deleteAt(ctx.getAst(), path));
|
|
587
|
+
close();
|
|
588
|
+
}));
|
|
589
|
+
}
|
|
584
590
|
return wrap;
|
|
585
591
|
});
|
|
586
592
|
}
|
|
@@ -591,10 +597,10 @@ function variableEditor(ctx, path, node, anchor) {
|
|
|
591
597
|
replace(ctx, path, scopedVar(entry.scope, entry.name));
|
|
592
598
|
close();
|
|
593
599
|
},
|
|
594
|
-
footer: button("exed-opt danger", "Delete", () => {
|
|
600
|
+
...canDelete(ctx, path) ? { footer: button("exed-opt danger", "Delete", () => {
|
|
595
601
|
ctx.apply(deleteAt(ctx.getAst(), path));
|
|
596
602
|
close();
|
|
597
|
-
})
|
|
603
|
+
}) } : {}
|
|
598
604
|
}));
|
|
599
605
|
}
|
|
600
606
|
function propertyPicker(ctx, opts) {
|
|
@@ -1059,6 +1065,8 @@ function mountExpressionEditor(host, opts) {
|
|
|
1059
1065
|
requestFocus: (p) => {
|
|
1060
1066
|
pendingFocus = p;
|
|
1061
1067
|
},
|
|
1068
|
+
...opts.requireNonEmpty ? { requireNonEmpty: true } : {},
|
|
1069
|
+
...opts.valueEnumValues ? { valueEnumValues: opts.valueEnumValues } : {},
|
|
1062
1070
|
...opts.pickNode ? { pickNode: opts.pickNode } : {},
|
|
1063
1071
|
...opts.nodeLabel ? { nodeLabel: opts.nodeLabel } : {}
|
|
1064
1072
|
};
|
|
@@ -1070,7 +1078,7 @@ function mountExpressionEditor(host, opts) {
|
|
|
1070
1078
|
if (raw || v.unparseable) {
|
|
1071
1079
|
host.append(rawArea());
|
|
1072
1080
|
} else if (!src.trim() || !v.ast) {
|
|
1073
|
-
host.append(emptyState());
|
|
1081
|
+
host.append(opts.valueField ? valueEmptyState() : emptyState());
|
|
1074
1082
|
} else {
|
|
1075
1083
|
const ctx = buildCtx(v.ast);
|
|
1076
1084
|
const body = el("div", "exed-body");
|
|
@@ -1114,6 +1122,10 @@ function mountExpressionEditor(host, opts) {
|
|
|
1114
1122
|
}));
|
|
1115
1123
|
return wrap;
|
|
1116
1124
|
}
|
|
1125
|
+
function valueEmptyState() {
|
|
1126
|
+
const ctx = buildCtx(strLit(""));
|
|
1127
|
+
return el("div", "exed-flat", [renderNode(strLit(""), [], ctx)]);
|
|
1128
|
+
}
|
|
1117
1129
|
function addTermControl(ctx) {
|
|
1118
1130
|
const boolean = opts.addTerm === "boolean";
|
|
1119
1131
|
const ops = boolean ? ["and", "or"] : ARITHMETIC_OPS;
|