@wildwinter/expr-editor 0.5.0 → 0.7.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/dist/index.d.cts CHANGED
@@ -279,11 +279,12 @@ interface ExpressionEditorOptions {
279
279
  /** Flat compact editor for a `set_flags(@target, +a, -b)` value whose target is
280
280
  * implied by context (an outcome row's target column). Renders only the
281
281
  * flag-delta pills plus an "+ flag" chip, hiding the function name and target
282
- * arg. `target` is the name-form ref of the flags property (e.g. "@quests");
283
- * it seeds the call on the first flag add. Pairs with mode:"flat", and set
284
- * requireNonEmpty so the last flag can't be removed. */
282
+ * arg. `target` is the name-form ref of the flags property (e.g. "@quests"),
283
+ * `flags` its declared flag names (offered by the "+ flag" picker). Pairs
284
+ * with mode:"flat"; set requireNonEmpty so the last flag can't be removed. */
285
285
  flagValue?: {
286
286
  target: string;
287
+ flags: string[];
287
288
  };
288
289
  /** Emitted on every edit (name-form; "" when cleared). */
289
290
  onChange: (src: string) => void;
package/dist/index.d.ts CHANGED
@@ -279,11 +279,12 @@ interface ExpressionEditorOptions {
279
279
  /** Flat compact editor for a `set_flags(@target, +a, -b)` value whose target is
280
280
  * implied by context (an outcome row's target column). Renders only the
281
281
  * flag-delta pills plus an "+ flag" chip, hiding the function name and target
282
- * arg. `target` is the name-form ref of the flags property (e.g. "@quests");
283
- * it seeds the call on the first flag add. Pairs with mode:"flat", and set
284
- * requireNonEmpty so the last flag can't be removed. */
282
+ * arg. `target` is the name-form ref of the flags property (e.g. "@quests"),
283
+ * `flags` its declared flag names (offered by the "+ flag" picker). Pairs
284
+ * with mode:"flat"; set requireNonEmpty so the last flag can't be removed. */
285
285
  flagValue?: {
286
286
  target: string;
287
+ flags: string[];
287
288
  };
288
289
  /** Emitted on every edit (name-form; "" when cleared). */
289
290
  onChange: (src: string) => void;
package/dist/index.js CHANGED
@@ -456,6 +456,14 @@ function renderNode(node, path, ctx, parentOp, side) {
456
456
  }
457
457
  }
458
458
  }
459
+ function signToggle(current, onPick) {
460
+ const row = el("div", "exed-sign");
461
+ ["+", "-"].forEach((s) => {
462
+ const cls = `exed-signbtn${s === current ? s === "+" ? " sel-pos" : " sel-neg" : ""}`;
463
+ row.append(button(cls, s === "+" ? "+ set" : "\u2212 unset", () => onPick(s)));
464
+ });
465
+ return row;
466
+ }
459
467
  var deleteOrUnwrapNot = (ctx, path, node) => (
460
468
  // clicking the NOT pill strips it (keeps the operand)
461
469
  setNodeAt(ctx.getAst(), path, node.operand)
@@ -545,14 +553,10 @@ function flagEditor(ctx, path, node, anchor) {
545
553
  ctx.openPopover(anchor, (close) => {
546
554
  const wrap = el("div", "exed-menu");
547
555
  wrap.append(el("div", "exed-menu-head", ["Flag set?"]));
548
- const signRow = el("div", "exed-field-row");
549
- for (const s of ["+", "-"]) {
550
- signRow.append(button(`exed-opt${s === node.sign ? " sel" : ""}`, s === "+" ? "+ set" : "\u2212 unset", () => {
551
- replace(ctx, path, flagDelta(s, node.name));
552
- close();
553
- }));
554
- }
555
- wrap.append(signRow);
556
+ wrap.append(signToggle(node.sign, (s) => {
557
+ replace(ctx, path, flagDelta(s, node.name));
558
+ close();
559
+ }));
556
560
  const names = (entry?.enumValues ?? []).filter((n) => !used.includes(n));
557
561
  if (names.length) {
558
562
  wrap.append(el("div", "exed-menu-head", ["Flag"]));
@@ -1143,27 +1147,46 @@ function mountExpressionEditor(host, opts) {
1143
1147
  }
1144
1148
  function flagValueBody(call) {
1145
1149
  const wrap = el("div", "exed-flat exed-flagvalue");
1150
+ const ctx = buildCtx(call ?? boolLit(true));
1146
1151
  if (call) {
1147
- const ctx = buildCtx(call);
1148
1152
  call.args.forEach((arg, i) => {
1149
1153
  if (arg.kind === "flagdelta") wrap.append(renderNode(arg, ["args", i], ctx));
1150
1154
  });
1151
- wrap.append(addFlagChip(call));
1152
- } else {
1153
- wrap.append(addFlagChip(null));
1154
1155
  }
1156
+ wrap.append(addFlagChip(ctx, call));
1155
1157
  return wrap;
1156
1158
  }
1157
- function addFlagChip(call) {
1158
- return button("exed-add exed-addflag", "+ flag", () => {
1159
- if (call) {
1160
- pendingFocus = ["args", call.args.length];
1161
- emit(toSrc({ ...call, args: [...call.args, flagDelta("+", "")] }));
1162
- } else {
1163
- const seeded = callNode("set_flags", [parseRef(opts.flagValue.target), flagDelta("+", "")]);
1164
- pendingFocus = ["args", 1];
1165
- emit(toSrc(seeded));
1166
- }
1159
+ function addFlagChip(ctx, call) {
1160
+ const flags = opts.flagValue?.flags ?? [];
1161
+ const used = call ? call.args.filter((a) => a.kind === "flagdelta").map((a) => a.name) : [];
1162
+ const available = flags.filter((f) => !used.includes(f));
1163
+ return button("exed-add exed-addflag", "+ flag", (e) => {
1164
+ const anchor = e.currentTarget;
1165
+ ctx.openPopover(anchor, (close) => {
1166
+ let sign = "+";
1167
+ const wrap = el("div", "exed-menu");
1168
+ wrap.append(el("div", "exed-menu-head", ["Add flag"]));
1169
+ const signHost = el("div");
1170
+ const drawSign = () => {
1171
+ signHost.replaceChildren(signToggle(sign, (s) => {
1172
+ sign = s;
1173
+ drawSign();
1174
+ }));
1175
+ };
1176
+ drawSign();
1177
+ wrap.append(signHost);
1178
+ const commit = (name) => {
1179
+ const delta = flagDelta(sign, name);
1180
+ emit(toSrc(call ? { ...call, args: [...call.args, delta] } : callNode("set_flags", [parseRef(opts.flagValue.target), delta])));
1181
+ close();
1182
+ };
1183
+ if (available.length) {
1184
+ for (const n of available) wrap.append(button("exed-opt", n, () => commit(n)));
1185
+ } else {
1186
+ wrap.append(el("div", "exed-hint", [flags.length === 0 ? "This flags property declares no flag values yet." : "All declared flags are already used."]));
1187
+ }
1188
+ return wrap;
1189
+ });
1167
1190
  }, "add a flag");
1168
1191
  }
1169
1192
  function addTermControl(ctx) {