@wildwinter/expr-editor 0.4.0 → 0.5.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 +5 -0
- package/dist/index.cjs +43 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +43 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,6 +50,11 @@ Notable options beyond the basics:
|
|
|
50
50
|
outcome-style value cell: `valueEnumValues` offers a target's enum values on
|
|
51
51
|
the root literal, and `valueField` makes an empty value render one editable
|
|
52
52
|
"set a value…" pill instead of the condition clause-menu empty state.
|
|
53
|
+
- `flagValue: { target }` — flat compact editor for a `set_flags(@target, …)`
|
|
54
|
+
value whose target is implied by context: renders only the flag-delta pills
|
|
55
|
+
plus an "+ flag" chip, hiding the function name and target arg, and seeds the
|
|
56
|
+
call on the first flag add. Pair with `requireNonEmpty` so the last flag
|
|
57
|
+
can't be removed.
|
|
53
58
|
- `setText(on)` — the host's raw-text toggle (`</>`); unparseable input falls
|
|
54
59
|
back to raw text automatically.
|
|
55
60
|
|
package/dist/index.cjs
CHANGED
|
@@ -541,7 +541,9 @@ function flagEditor(ctx, path, node, anchor) {
|
|
|
541
541
|
const call = getNodeAt(ctx.getAst(), callPath);
|
|
542
542
|
const flagsVar = call?.kind === "call" ? call.args[0] : void 0;
|
|
543
543
|
const entry = flagsVar?.kind === "scopedvar" ? lookup(ctx.catalogue, flagsVar.scope, flagsVar.name) : null;
|
|
544
|
+
const flagCount = call?.kind === "call" ? call.args.filter((a) => a.kind === "flagdelta").length : 0;
|
|
544
545
|
const used = call?.kind === "call" ? call.args.filter((a, i) => a.kind === "flagdelta" && i !== path[path.length - 1]).map((a) => a.name) : [];
|
|
546
|
+
const canRemove = !(ctx.requireNonEmpty && flagCount <= 1);
|
|
545
547
|
ctx.openPopover(anchor, (close) => {
|
|
546
548
|
const wrap = el("div", "exed-menu");
|
|
547
549
|
wrap.append(el("div", "exed-menu-head", ["Flag set?"]));
|
|
@@ -566,6 +568,12 @@ function flagEditor(ctx, path, node, anchor) {
|
|
|
566
568
|
close();
|
|
567
569
|
} }));
|
|
568
570
|
}
|
|
571
|
+
if (canRemove) {
|
|
572
|
+
wrap.append(button("exed-opt danger", "Remove flag", () => {
|
|
573
|
+
ctx.apply(deleteAt(ctx.getAst(), path));
|
|
574
|
+
close();
|
|
575
|
+
}));
|
|
576
|
+
}
|
|
569
577
|
return wrap;
|
|
570
578
|
});
|
|
571
579
|
}
|
|
@@ -1075,8 +1083,12 @@ function mountExpressionEditor(host, opts) {
|
|
|
1075
1083
|
closePopover();
|
|
1076
1084
|
host.replaceChildren();
|
|
1077
1085
|
const v = validateSource(src, opts.schema, opts.dialect);
|
|
1078
|
-
|
|
1086
|
+
const flagCompact = !!opts.flagValue && (opts.mode ?? "tree") === "flat";
|
|
1087
|
+
const astIsFlagCall = v.ast?.kind === "call" && (v.ast.name === "set_flags" || v.ast.name === "check_flags");
|
|
1088
|
+
if (raw || v.unparseable || flagCompact && !!v.ast && !astIsFlagCall) {
|
|
1079
1089
|
host.append(rawArea());
|
|
1090
|
+
} else if (flagCompact) {
|
|
1091
|
+
host.append(flagValueBody(astIsFlagCall ? v.ast : null));
|
|
1080
1092
|
} else if (!src.trim() || !v.ast) {
|
|
1081
1093
|
host.append(opts.valueField ? valueEmptyState() : emptyState());
|
|
1082
1094
|
} else {
|
|
@@ -1126,6 +1138,36 @@ function mountExpressionEditor(host, opts) {
|
|
|
1126
1138
|
const ctx = buildCtx(strLit(""));
|
|
1127
1139
|
return el("div", "exed-flat", [renderNode(strLit(""), [], ctx)]);
|
|
1128
1140
|
}
|
|
1141
|
+
function parseRef(ref) {
|
|
1142
|
+
const bare = ref.replace(/^@/, "");
|
|
1143
|
+
const dot = bare.indexOf(".");
|
|
1144
|
+
return dot >= 0 ? scopedVar(bare.slice(0, dot), bare.slice(dot + 1)) : scopedVar(defaultScope, bare);
|
|
1145
|
+
}
|
|
1146
|
+
function flagValueBody(call) {
|
|
1147
|
+
const wrap = el("div", "exed-flat exed-flagvalue");
|
|
1148
|
+
if (call) {
|
|
1149
|
+
const ctx = buildCtx(call);
|
|
1150
|
+
call.args.forEach((arg, i) => {
|
|
1151
|
+
if (arg.kind === "flagdelta") wrap.append(renderNode(arg, ["args", i], ctx));
|
|
1152
|
+
});
|
|
1153
|
+
wrap.append(addFlagChip(call));
|
|
1154
|
+
} else {
|
|
1155
|
+
wrap.append(addFlagChip(null));
|
|
1156
|
+
}
|
|
1157
|
+
return wrap;
|
|
1158
|
+
}
|
|
1159
|
+
function addFlagChip(call) {
|
|
1160
|
+
return button("exed-add exed-addflag", "+ flag", () => {
|
|
1161
|
+
if (call) {
|
|
1162
|
+
pendingFocus = ["args", call.args.length];
|
|
1163
|
+
emit(toSrc({ ...call, args: [...call.args, flagDelta("+", "")] }));
|
|
1164
|
+
} else {
|
|
1165
|
+
const seeded = callNode("set_flags", [parseRef(opts.flagValue.target), flagDelta("+", "")]);
|
|
1166
|
+
pendingFocus = ["args", 1];
|
|
1167
|
+
emit(toSrc(seeded));
|
|
1168
|
+
}
|
|
1169
|
+
}, "add a flag");
|
|
1170
|
+
}
|
|
1129
1171
|
function addTermControl(ctx) {
|
|
1130
1172
|
const boolean = opts.addTerm === "boolean";
|
|
1131
1173
|
const ops = boolean ? ["and", "or"] : ARITHMETIC_OPS;
|