@wildwinter/expr-editor 0.14.1 → 0.15.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.cjs CHANGED
@@ -98,6 +98,7 @@ var normaliseRef = (ref, defaultScope) => {
98
98
  const prefix = `@${defaultScope.toLowerCase()}.`;
99
99
  return low.startsWith(prefix) ? `@${low.slice(prefix.length)}` : low;
100
100
  };
101
+ var flagChangeSrc = (targetRef, sign, flag) => `set_flags(${targetRef}, ${sign}${flag})`;
101
102
  function advancedRef(node, defaultScope) {
102
103
  if (node.kind !== "call" || node.name !== "advance" || node.args.length !== 1) return null;
103
104
  const arg = node.args[0];
@@ -296,6 +297,7 @@ var propertyTip = (e) => {
296
297
  return lines.length ? lines.join("\n") : void 0;
297
298
  };
298
299
  var refOf = (e, defaultScope) => e.scope === defaultScope ? `@${e.name}` : `@${e.scope}.${e.name}`;
300
+ var targetRefOf = (e) => `@${e.scope}.${e.name}`;
299
301
  var displayName = (e, defaultScope) => e.scope === defaultScope ? e.name : `${e.scope}.${e.name}`;
300
302
  function filterCatalogue(entries, filter = {}) {
301
303
  return entries.filter(
@@ -1084,7 +1086,7 @@ function seedClause(ctx) {
1084
1086
  function clauseMenu(ctx, anchor, onPick) {
1085
1087
  ctx.openPopover(anchor, (close) => {
1086
1088
  const wrap = el("div", "exed-menu");
1087
- wrap.append(el("div", "exed-menu-head", ["Add a clause"]));
1089
+ wrap.append(el("div", "exed-menu-head", ["Add a condition"]));
1088
1090
  const add = (label, hint, make, disabled = false) => {
1089
1091
  const b = button(`exed-opt${disabled ? " disabled" : ""}`, "", () => {
1090
1092
  if (disabled) return;
@@ -1383,7 +1385,8 @@ function valueWizard(opts) {
1383
1385
  host.append(body);
1384
1386
  const choices = opts.expectedChoices?.length ? opts.expectedChoices : opts.expectedEnumValues;
1385
1387
  const isStage = opts.expectedType === "quality";
1386
- let kind = opts.expectedType === "number" ? "number" : opts.expectedType === "string" ? "text" : opts.expectedType === "boolean" ? "bool" : (opts.expectedType === "enum" || opts.expectedType === "quality") && choices?.length ? "enum" : "menu";
1388
+ const flagsReady = opts.expectedType === "flags" && opts.expectedRef !== void 0;
1389
+ let kind = opts.expectedType === "number" ? "number" : opts.expectedType === "string" ? "text" : opts.expectedType === "boolean" ? "bool" : (opts.expectedType === "enum" || opts.expectedType === "quality") && choices?.length ? "enum" : flagsReady ? "flags" : "menu";
1387
1390
  const draw = () => {
1388
1391
  body.replaceChildren();
1389
1392
  const other = () => button("exed-vwiz-other", "\u21A9 a different kind", () => {
@@ -1392,6 +1395,10 @@ function valueWizard(opts) {
1392
1395
  });
1393
1396
  switch (kind) {
1394
1397
  case "menu":
1398
+ if (flagsReady) body.append(optBtn("Set or clear a flag\u2026", () => {
1399
+ kind = "flags";
1400
+ draw();
1401
+ }));
1395
1402
  body.append(optBtn("A property\u2026", () => {
1396
1403
  kind = "property";
1397
1404
  draw();
@@ -1413,6 +1420,22 @@ function valueWizard(opts) {
1413
1420
  draw();
1414
1421
  }));
1415
1422
  break;
1423
+ case "flags": {
1424
+ const flags = opts.expectedFlags ?? [];
1425
+ if (!flags.length) body.append(el("div", "exed-hint", ["This property declares no flag values yet."]));
1426
+ for (const sign of ["+", "-"]) {
1427
+ if (!flags.length) break;
1428
+ body.append(el("div", "exed-vwiz-note", [sign === "+" ? "Set a flag:" : "Clear a flag:"]));
1429
+ const row = el("div", "exed-field-row");
1430
+ for (const f of flags) row.append(optBtn(`${sign} ${f}`, () => opts.onCommit(flagChangeSrc(opts.expectedRef, sign, f))));
1431
+ body.append(row);
1432
+ }
1433
+ body.append(button("exed-vwiz-other", "\u21A9 a different kind (replaces every flag)", () => {
1434
+ kind = "menu";
1435
+ draw();
1436
+ }));
1437
+ break;
1438
+ }
1416
1439
  case "property":
1417
1440
  body.append(propertyPicker(pickCtx, { onPick: (e) => opts.onCommit(refOf(e, opts.defaultScope)) }));
1418
1441
  body.append(other());
@@ -1451,6 +1474,10 @@ function isSelfAdvance(eff, defaultScope, dialect) {
1451
1474
  return false;
1452
1475
  }
1453
1476
  }
1477
+ function entryForTarget(catalogue, target, defaultScope) {
1478
+ const want = normaliseRef(target, defaultScope);
1479
+ return catalogue.find((e) => normaliseRef(`@${e.scope}.${e.name}`, defaultScope) === want);
1480
+ }
1454
1481
  var clone = (list) => list.map((e) => e.kind === "set" ? { ...e } : { ...e, args: [...e.args] });
1455
1482
  var addSet = (list, target, value) => [...clone(list), { kind: "set", target, value }];
1456
1483
  var addEmit = (list, event) => [...clone(list), { kind: "emit", event, args: [] }];
@@ -1539,6 +1566,11 @@ function mountEffectsEditor(host, opts) {
1539
1566
  // choicesOf, never a raw field: a quality's ladder lives in `stages`, and reading `enumValues`
1540
1567
  // here told the wizard the type and withheld the values.
1541
1568
  ...choicesOf(expected) ? { expectedChoices: choicesOf(expected) } : {},
1569
+ // The flags step needs the target itself: its declared flags, and the
1570
+ // qualified ref its set_flags(...) is written against. choicesOf stays
1571
+ // out of it deliberately - flags are not a pick-one list, and a pinned
1572
+ // test holds it to that.
1573
+ ...expected?.type === "flags" ? { expectedRef: targetRefOf(expected), expectedFlags: expected.enumValues ?? [] } : {},
1542
1574
  onCommit: (src) => {
1543
1575
  onCommit(src);
1544
1576
  close();
@@ -1546,7 +1578,7 @@ function mountEffectsEditor(host, opts) {
1546
1578
  onCancel: close
1547
1579
  }), { container: opts.popoverContainer });
1548
1580
  };
1549
- const targetType = (target) => opts.catalogue.find((e) => refOf(e, defaultScope) === target)?.type;
1581
+ const targetType = (target) => entryForTarget(opts.catalogue, target, defaultScope)?.type;
1550
1582
  const valueDisplay = (value, onChange, type, selfAdvanceRef) => {
1551
1583
  const sub = el("div", "exed-effect-value");
1552
1584
  const addTerm = type === "number" ? "arithmetic" : type === "boolean" ? "boolean" : void 0;
@@ -1613,10 +1645,10 @@ function mountEffectsEditor(host, opts) {
1613
1645
  const row = el("div", "exed-effect exed-effect-set");
1614
1646
  const targetBtn = button("exed-pill exed-pill-prop", eff.target || "(pick property)", (e) => {
1615
1647
  pickTarget(e.currentTarget, void 0, (entry) => {
1616
- commit(updateAt(effects, i, { target: refOf(entry, defaultScope), value: initialValueFor(entry, defaultScope).src }));
1648
+ commit(updateAt(effects, i, { target: targetRefOf(entry), value: initialValueFor(entry, defaultScope).src }));
1617
1649
  });
1618
1650
  }, "change the target property");
1619
- const targetEntry = opts.catalogue.find((e) => refOf(e, defaultScope) === eff.target);
1651
+ const targetEntry = entryForTarget(opts.catalogue, eff.target, defaultScope);
1620
1652
  const tip = propertyTip(targetEntry);
1621
1653
  if (tip) targetBtn.title = tip;
1622
1654
  if (targetEntry && opts.propertyActions) {
@@ -1720,10 +1752,10 @@ function mountEffectsEditor(host, opts) {
1720
1752
  pickTarget(anchor, void 0, (entry) => {
1721
1753
  const { src, ask } = initialValueFor(entry, defaultScope);
1722
1754
  if (!ask) {
1723
- commit(addSet(effects, refOf(entry, defaultScope), src));
1755
+ commit(addSet(effects, targetRefOf(entry), src));
1724
1756
  return;
1725
1757
  }
1726
- openValueWizard(anchor, entry, (chosen) => commit(addSet(effects, refOf(entry, defaultScope), chosen)));
1758
+ openValueWizard(anchor, entry, (chosen) => commit(addSet(effects, targetRefOf(entry), chosen)));
1727
1759
  });
1728
1760
  }));
1729
1761
  if (opts.allowEmit !== false) {
@@ -1852,6 +1884,7 @@ exports.filterCatalogue = filterCatalogue;
1852
1884
  exports.findChoicePeer = findChoicePeer;
1853
1885
  exports.findEnumPeer = findEnumPeer;
1854
1886
  exports.firstEmptyLeafPath = firstEmptyLeafPath;
1887
+ exports.flagChangeSrc = flagChangeSrc;
1855
1888
  exports.flagDelta = flagDelta;
1856
1889
  exports.flipContainerOp = flipContainerOp;
1857
1890
  exports.formatNumber = formatNumber;
@@ -1889,6 +1922,7 @@ exports.seedValueSrc = seedValueSrc;
1889
1922
  exports.setArgAt = setArgAt;
1890
1923
  exports.setNodeAt = setNodeAt;
1891
1924
  exports.strLit = strLit;
1925
+ exports.targetRefOf = targetRefOf;
1892
1926
  exports.toggleContainerNot = toggleContainerNot;
1893
1927
  exports.toggleNotAt = toggleNotAt;
1894
1928
  exports.updateAt = updateAt;