@wildwinter/expr-editor 0.14.0 → 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 +66 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -2
- package/dist/index.d.ts +25 -2
- package/dist/index.js +65 -26
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2 -1
- package/dist/styles.css.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -56,6 +56,12 @@ declare const findEnumPeer: typeof findChoicePeer;
|
|
|
56
56
|
/** A name-form ref in ONE form, so two spellings of the same property compare equal: the default
|
|
57
57
|
* scope may be written or left off (`@patter.debt` and `@debt`), and refs are case-insensitive. */
|
|
58
58
|
declare const normaliseRef: (ref: string, defaultScope: string) => string;
|
|
59
|
+
/** The set/clear-a-flag value: `set_flags(@scope.name, +flag)` - adjust one
|
|
60
|
+
* flag, keep the rest, which is what outcomes on a flags property
|
|
61
|
+
* overwhelmingly do (and the form a whole-value change cannot express).
|
|
62
|
+
* Lives here with the other pure ref helpers so the value wizard can build
|
|
63
|
+
* it without importing the effects mount (which imports the wizard). */
|
|
64
|
+
declare const flagChangeSrc: (targetRef: string, sign: "+" | "-", flag: string) => string;
|
|
59
65
|
/** The name-form ref a call ADVANCES, when the call is the plain `advance(@x)` shape: one scopedvar
|
|
60
66
|
* argument and nothing else. Null for any other call, and for an argument that is not a property
|
|
61
67
|
* (`advance(f(@x))` keeps its explicit form, since collapsing it would hide the middle).
|
|
@@ -183,11 +189,21 @@ interface Filter {
|
|
|
183
189
|
acceptTypes?: PropertyType[];
|
|
184
190
|
acceptScopes?: string[];
|
|
185
191
|
}
|
|
186
|
-
/** The reference string for an entry: `@name` for the default scope, else `@scope.name`.
|
|
192
|
+
/** The reference string for an entry: `@name` for the default scope, else `@scope.name`.
|
|
193
|
+
* CONDITION-side sugar only: a change TARGET must use {@link targetRefOf} - the storylets
|
|
194
|
+
* compiler requires `@scope.name` there, and emitting this shorthand for a default-scope
|
|
195
|
+
* target made every picker-authored change invalid (the Storyletter antagonist audit's
|
|
196
|
+
* find, 2026-08-29). Patter's grammar takes both forms, so the split costs it nothing. */
|
|
187
197
|
declare const refOf: (e: {
|
|
188
198
|
scope: string;
|
|
189
199
|
name: string;
|
|
190
200
|
}, defaultScope: string) => string;
|
|
201
|
+
/** The reference a change TARGET is written as: always fully qualified. A target is a
|
|
202
|
+
* reference, not an expression, and the shorthand is condition-side sugar (see refOf). */
|
|
203
|
+
declare const targetRefOf: (e: {
|
|
204
|
+
scope: string;
|
|
205
|
+
name: string;
|
|
206
|
+
}) => string;
|
|
191
207
|
/** The label shown in the picker / on a property pill. */
|
|
192
208
|
declare const displayName: (e: {
|
|
193
209
|
scope: string;
|
|
@@ -529,6 +545,13 @@ interface ValueWizardOptions {
|
|
|
529
545
|
expectedChoices?: string[];
|
|
530
546
|
/** @deprecated Use `expectedChoices`. Kept so a 0.11.x caller keeps working. */
|
|
531
547
|
expectedEnumValues?: string[];
|
|
548
|
+
/** A FLAGS target's qualified ref and declared flags: together they unlock the
|
|
549
|
+
* set/clear-a-flag step, which is what outcomes on a flags property
|
|
550
|
+
* overwhelmingly want and which a whole-value change cannot express (the
|
|
551
|
+
* Storyletter antagonist audit's find, 2026-08-29). Absent, the generic
|
|
552
|
+
* kinds stand alone as before. */
|
|
553
|
+
expectedRef?: string;
|
|
554
|
+
expectedFlags?: string[];
|
|
532
555
|
/** Receives the chosen value as name-form source. */
|
|
533
556
|
onCommit: (src: string) => void;
|
|
534
557
|
/** Optional cancel (the ✕ on the step). */
|
|
@@ -537,4 +560,4 @@ interface ValueWizardOptions {
|
|
|
537
560
|
/** Build the wizard UI into a fresh element (drive it via the host's popover). */
|
|
538
561
|
declare function valueWizard(opts: ValueWizardOptions): HTMLElement;
|
|
539
562
|
|
|
540
|
-
export { ARITHMETIC_OPS, BINARY_LABEL, COMPARABLE_TYPES, COMPARISON_OPS, type CatalogueEntry, EQUALITY_OPS, type EditCtx, type EditorEffect, type EffectsEditorHandle, type EffectsEditorOptions, type ExpressionEditorHandle, type ExpressionEditorOptions, type Filter, type FunctionTemplateSpec, OP_WORD, type PreviewOptions, type TreeRow, UNARY_LABEL, type Validation, type ValueWizardOptions, type WizardSpec, type WizardStepSpec, type WizardValue, addArg, addChildToContainer, addEmit, addSet, advancedRef, astToTree, binary, boolLit, buildSubGroupClause, callNode, choicesOf, comparisonOpsFor, deleteAt, displayName, filterCatalogue, findChoicePeer, findEnumPeer, firstEmptyLeafPath, flagDelta, flipContainerOp, formatNumber, getNodeAt, groupByScope, initialValueFor, insertSiblingClauseAt, isComparisonOp, isPlaceholderForOp, isWrappedInNot, issuesAt, lookup, mountEffectsEditor, mountExpressionEditor, moveAt, moveChildInContainer, needsParens, normaliseRef, notNode, numLit, opSwapGroup, pathKey, placeholderForOp, propertyTip, redirectDeleteForPlaceholderSibling, refOf, removeArgAt, removeAt, renderConditionPreview, renderEffectsPreview, rhsTypesFor, scopedVar, searchCatalogue, seedValueSrc, setArgAt, setNodeAt, strLit, toggleContainerNot, toggleNotAt, updateAt, validateSource, valueWizard, wrapInNotAt };
|
|
563
|
+
export { ARITHMETIC_OPS, BINARY_LABEL, COMPARABLE_TYPES, COMPARISON_OPS, type CatalogueEntry, EQUALITY_OPS, type EditCtx, type EditorEffect, type EffectsEditorHandle, type EffectsEditorOptions, type ExpressionEditorHandle, type ExpressionEditorOptions, type Filter, type FunctionTemplateSpec, OP_WORD, type PreviewOptions, type TreeRow, UNARY_LABEL, type Validation, type ValueWizardOptions, type WizardSpec, type WizardStepSpec, type WizardValue, addArg, addChildToContainer, addEmit, addSet, advancedRef, astToTree, binary, boolLit, buildSubGroupClause, callNode, choicesOf, comparisonOpsFor, deleteAt, displayName, filterCatalogue, findChoicePeer, findEnumPeer, firstEmptyLeafPath, flagChangeSrc, flagDelta, flipContainerOp, formatNumber, getNodeAt, groupByScope, initialValueFor, insertSiblingClauseAt, isComparisonOp, isPlaceholderForOp, isWrappedInNot, issuesAt, lookup, mountEffectsEditor, mountExpressionEditor, moveAt, moveChildInContainer, needsParens, normaliseRef, notNode, numLit, opSwapGroup, pathKey, placeholderForOp, propertyTip, redirectDeleteForPlaceholderSibling, refOf, removeArgAt, removeAt, renderConditionPreview, renderEffectsPreview, rhsTypesFor, scopedVar, searchCatalogue, seedValueSrc, setArgAt, setNodeAt, strLit, targetRefOf, toggleContainerNot, toggleNotAt, updateAt, validateSource, valueWizard, wrapInNotAt };
|
package/dist/index.d.ts
CHANGED
|
@@ -56,6 +56,12 @@ declare const findEnumPeer: typeof findChoicePeer;
|
|
|
56
56
|
/** A name-form ref in ONE form, so two spellings of the same property compare equal: the default
|
|
57
57
|
* scope may be written or left off (`@patter.debt` and `@debt`), and refs are case-insensitive. */
|
|
58
58
|
declare const normaliseRef: (ref: string, defaultScope: string) => string;
|
|
59
|
+
/** The set/clear-a-flag value: `set_flags(@scope.name, +flag)` - adjust one
|
|
60
|
+
* flag, keep the rest, which is what outcomes on a flags property
|
|
61
|
+
* overwhelmingly do (and the form a whole-value change cannot express).
|
|
62
|
+
* Lives here with the other pure ref helpers so the value wizard can build
|
|
63
|
+
* it without importing the effects mount (which imports the wizard). */
|
|
64
|
+
declare const flagChangeSrc: (targetRef: string, sign: "+" | "-", flag: string) => string;
|
|
59
65
|
/** The name-form ref a call ADVANCES, when the call is the plain `advance(@x)` shape: one scopedvar
|
|
60
66
|
* argument and nothing else. Null for any other call, and for an argument that is not a property
|
|
61
67
|
* (`advance(f(@x))` keeps its explicit form, since collapsing it would hide the middle).
|
|
@@ -183,11 +189,21 @@ interface Filter {
|
|
|
183
189
|
acceptTypes?: PropertyType[];
|
|
184
190
|
acceptScopes?: string[];
|
|
185
191
|
}
|
|
186
|
-
/** The reference string for an entry: `@name` for the default scope, else `@scope.name`.
|
|
192
|
+
/** The reference string for an entry: `@name` for the default scope, else `@scope.name`.
|
|
193
|
+
* CONDITION-side sugar only: a change TARGET must use {@link targetRefOf} - the storylets
|
|
194
|
+
* compiler requires `@scope.name` there, and emitting this shorthand for a default-scope
|
|
195
|
+
* target made every picker-authored change invalid (the Storyletter antagonist audit's
|
|
196
|
+
* find, 2026-08-29). Patter's grammar takes both forms, so the split costs it nothing. */
|
|
187
197
|
declare const refOf: (e: {
|
|
188
198
|
scope: string;
|
|
189
199
|
name: string;
|
|
190
200
|
}, defaultScope: string) => string;
|
|
201
|
+
/** The reference a change TARGET is written as: always fully qualified. A target is a
|
|
202
|
+
* reference, not an expression, and the shorthand is condition-side sugar (see refOf). */
|
|
203
|
+
declare const targetRefOf: (e: {
|
|
204
|
+
scope: string;
|
|
205
|
+
name: string;
|
|
206
|
+
}) => string;
|
|
191
207
|
/** The label shown in the picker / on a property pill. */
|
|
192
208
|
declare const displayName: (e: {
|
|
193
209
|
scope: string;
|
|
@@ -529,6 +545,13 @@ interface ValueWizardOptions {
|
|
|
529
545
|
expectedChoices?: string[];
|
|
530
546
|
/** @deprecated Use `expectedChoices`. Kept so a 0.11.x caller keeps working. */
|
|
531
547
|
expectedEnumValues?: string[];
|
|
548
|
+
/** A FLAGS target's qualified ref and declared flags: together they unlock the
|
|
549
|
+
* set/clear-a-flag step, which is what outcomes on a flags property
|
|
550
|
+
* overwhelmingly want and which a whole-value change cannot express (the
|
|
551
|
+
* Storyletter antagonist audit's find, 2026-08-29). Absent, the generic
|
|
552
|
+
* kinds stand alone as before. */
|
|
553
|
+
expectedRef?: string;
|
|
554
|
+
expectedFlags?: string[];
|
|
532
555
|
/** Receives the chosen value as name-form source. */
|
|
533
556
|
onCommit: (src: string) => void;
|
|
534
557
|
/** Optional cancel (the ✕ on the step). */
|
|
@@ -537,4 +560,4 @@ interface ValueWizardOptions {
|
|
|
537
560
|
/** Build the wizard UI into a fresh element (drive it via the host's popover). */
|
|
538
561
|
declare function valueWizard(opts: ValueWizardOptions): HTMLElement;
|
|
539
562
|
|
|
540
|
-
export { ARITHMETIC_OPS, BINARY_LABEL, COMPARABLE_TYPES, COMPARISON_OPS, type CatalogueEntry, EQUALITY_OPS, type EditCtx, type EditorEffect, type EffectsEditorHandle, type EffectsEditorOptions, type ExpressionEditorHandle, type ExpressionEditorOptions, type Filter, type FunctionTemplateSpec, OP_WORD, type PreviewOptions, type TreeRow, UNARY_LABEL, type Validation, type ValueWizardOptions, type WizardSpec, type WizardStepSpec, type WizardValue, addArg, addChildToContainer, addEmit, addSet, advancedRef, astToTree, binary, boolLit, buildSubGroupClause, callNode, choicesOf, comparisonOpsFor, deleteAt, displayName, filterCatalogue, findChoicePeer, findEnumPeer, firstEmptyLeafPath, flagDelta, flipContainerOp, formatNumber, getNodeAt, groupByScope, initialValueFor, insertSiblingClauseAt, isComparisonOp, isPlaceholderForOp, isWrappedInNot, issuesAt, lookup, mountEffectsEditor, mountExpressionEditor, moveAt, moveChildInContainer, needsParens, normaliseRef, notNode, numLit, opSwapGroup, pathKey, placeholderForOp, propertyTip, redirectDeleteForPlaceholderSibling, refOf, removeArgAt, removeAt, renderConditionPreview, renderEffectsPreview, rhsTypesFor, scopedVar, searchCatalogue, seedValueSrc, setArgAt, setNodeAt, strLit, toggleContainerNot, toggleNotAt, updateAt, validateSource, valueWizard, wrapInNotAt };
|
|
563
|
+
export { ARITHMETIC_OPS, BINARY_LABEL, COMPARABLE_TYPES, COMPARISON_OPS, type CatalogueEntry, EQUALITY_OPS, type EditCtx, type EditorEffect, type EffectsEditorHandle, type EffectsEditorOptions, type ExpressionEditorHandle, type ExpressionEditorOptions, type Filter, type FunctionTemplateSpec, OP_WORD, type PreviewOptions, type TreeRow, UNARY_LABEL, type Validation, type ValueWizardOptions, type WizardSpec, type WizardStepSpec, type WizardValue, addArg, addChildToContainer, addEmit, addSet, advancedRef, astToTree, binary, boolLit, buildSubGroupClause, callNode, choicesOf, comparisonOpsFor, deleteAt, displayName, filterCatalogue, findChoicePeer, findEnumPeer, firstEmptyLeafPath, flagChangeSrc, flagDelta, flipContainerOp, formatNumber, getNodeAt, groupByScope, initialValueFor, insertSiblingClauseAt, isComparisonOp, isPlaceholderForOp, isWrappedInNot, issuesAt, lookup, mountEffectsEditor, mountExpressionEditor, moveAt, moveChildInContainer, needsParens, normaliseRef, notNode, numLit, opSwapGroup, pathKey, placeholderForOp, propertyTip, redirectDeleteForPlaceholderSibling, refOf, removeArgAt, removeAt, renderConditionPreview, renderEffectsPreview, rhsTypesFor, scopedVar, searchCatalogue, seedValueSrc, setArgAt, setNodeAt, strLit, targetRefOf, toggleContainerNot, toggleNotAt, updateAt, validateSource, valueWizard, wrapInNotAt };
|
package/dist/index.js
CHANGED
|
@@ -96,6 +96,7 @@ var normaliseRef = (ref, defaultScope) => {
|
|
|
96
96
|
const prefix = `@${defaultScope.toLowerCase()}.`;
|
|
97
97
|
return low.startsWith(prefix) ? `@${low.slice(prefix.length)}` : low;
|
|
98
98
|
};
|
|
99
|
+
var flagChangeSrc = (targetRef, sign, flag) => `set_flags(${targetRef}, ${sign}${flag})`;
|
|
99
100
|
function advancedRef(node, defaultScope) {
|
|
100
101
|
if (node.kind !== "call" || node.name !== "advance" || node.args.length !== 1) return null;
|
|
101
102
|
const arg = node.args[0];
|
|
@@ -294,6 +295,7 @@ var propertyTip = (e) => {
|
|
|
294
295
|
return lines.length ? lines.join("\n") : void 0;
|
|
295
296
|
};
|
|
296
297
|
var refOf = (e, defaultScope) => e.scope === defaultScope ? `@${e.name}` : `@${e.scope}.${e.name}`;
|
|
298
|
+
var targetRefOf = (e) => `@${e.scope}.${e.name}`;
|
|
297
299
|
var displayName = (e, defaultScope) => e.scope === defaultScope ? e.name : `${e.scope}.${e.name}`;
|
|
298
300
|
function filterCatalogue(entries, filter = {}) {
|
|
299
301
|
return entries.filter(
|
|
@@ -427,6 +429,14 @@ function textField(opts) {
|
|
|
427
429
|
setTimeout(() => input.focus(), 0);
|
|
428
430
|
return wrap;
|
|
429
431
|
}
|
|
432
|
+
function propertyMenuBody(actions, close) {
|
|
433
|
+
const wrap = el("div", "exed-menu");
|
|
434
|
+
for (const a of actions) wrap.append(button("exed-opt", a.label, () => {
|
|
435
|
+
a.run();
|
|
436
|
+
close();
|
|
437
|
+
}));
|
|
438
|
+
return wrap;
|
|
439
|
+
}
|
|
430
440
|
|
|
431
441
|
// src/flat.ts
|
|
432
442
|
var FLAG_FNS = /* @__PURE__ */ new Set(["check_flags", "set_flags"]);
|
|
@@ -545,14 +555,7 @@ function attachPropertyMenu(ctx, node, pillEl) {
|
|
|
545
555
|
const open = ctx.openMenu ?? ctx.openPopover;
|
|
546
556
|
pillEl.addEventListener("contextmenu", (e) => {
|
|
547
557
|
e.preventDefault();
|
|
548
|
-
open(pillEl, (close) =>
|
|
549
|
-
const wrap = el("div", "exed-menu");
|
|
550
|
-
for (const a of actions) wrap.append(button("exed-opt", a.label, () => {
|
|
551
|
-
a.run();
|
|
552
|
-
close();
|
|
553
|
-
}));
|
|
554
|
-
return wrap;
|
|
555
|
-
});
|
|
558
|
+
open(pillEl, (close) => propertyMenuBody(actions, close));
|
|
556
559
|
});
|
|
557
560
|
}
|
|
558
561
|
function isCompoundComparison(node, ctx) {
|
|
@@ -1081,7 +1084,7 @@ function seedClause(ctx) {
|
|
|
1081
1084
|
function clauseMenu(ctx, anchor, onPick) {
|
|
1082
1085
|
ctx.openPopover(anchor, (close) => {
|
|
1083
1086
|
const wrap = el("div", "exed-menu");
|
|
1084
|
-
wrap.append(el("div", "exed-menu-head", ["Add a
|
|
1087
|
+
wrap.append(el("div", "exed-menu-head", ["Add a condition"]));
|
|
1085
1088
|
const add = (label, hint, make, disabled = false) => {
|
|
1086
1089
|
const b = button(`exed-opt${disabled ? " disabled" : ""}`, "", () => {
|
|
1087
1090
|
if (disabled) return;
|
|
@@ -1380,7 +1383,8 @@ function valueWizard(opts) {
|
|
|
1380
1383
|
host.append(body);
|
|
1381
1384
|
const choices = opts.expectedChoices?.length ? opts.expectedChoices : opts.expectedEnumValues;
|
|
1382
1385
|
const isStage = opts.expectedType === "quality";
|
|
1383
|
-
|
|
1386
|
+
const flagsReady = opts.expectedType === "flags" && opts.expectedRef !== void 0;
|
|
1387
|
+
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";
|
|
1384
1388
|
const draw = () => {
|
|
1385
1389
|
body.replaceChildren();
|
|
1386
1390
|
const other = () => button("exed-vwiz-other", "\u21A9 a different kind", () => {
|
|
@@ -1389,6 +1393,10 @@ function valueWizard(opts) {
|
|
|
1389
1393
|
});
|
|
1390
1394
|
switch (kind) {
|
|
1391
1395
|
case "menu":
|
|
1396
|
+
if (flagsReady) body.append(optBtn("Set or clear a flag\u2026", () => {
|
|
1397
|
+
kind = "flags";
|
|
1398
|
+
draw();
|
|
1399
|
+
}));
|
|
1392
1400
|
body.append(optBtn("A property\u2026", () => {
|
|
1393
1401
|
kind = "property";
|
|
1394
1402
|
draw();
|
|
@@ -1410,6 +1418,22 @@ function valueWizard(opts) {
|
|
|
1410
1418
|
draw();
|
|
1411
1419
|
}));
|
|
1412
1420
|
break;
|
|
1421
|
+
case "flags": {
|
|
1422
|
+
const flags = opts.expectedFlags ?? [];
|
|
1423
|
+
if (!flags.length) body.append(el("div", "exed-hint", ["This property declares no flag values yet."]));
|
|
1424
|
+
for (const sign of ["+", "-"]) {
|
|
1425
|
+
if (!flags.length) break;
|
|
1426
|
+
body.append(el("div", "exed-vwiz-note", [sign === "+" ? "Set a flag:" : "Clear a flag:"]));
|
|
1427
|
+
const row = el("div", "exed-field-row");
|
|
1428
|
+
for (const f of flags) row.append(optBtn(`${sign} ${f}`, () => opts.onCommit(flagChangeSrc(opts.expectedRef, sign, f))));
|
|
1429
|
+
body.append(row);
|
|
1430
|
+
}
|
|
1431
|
+
body.append(button("exed-vwiz-other", "\u21A9 a different kind (replaces every flag)", () => {
|
|
1432
|
+
kind = "menu";
|
|
1433
|
+
draw();
|
|
1434
|
+
}));
|
|
1435
|
+
break;
|
|
1436
|
+
}
|
|
1413
1437
|
case "property":
|
|
1414
1438
|
body.append(propertyPicker(pickCtx, { onPick: (e) => opts.onCommit(refOf(e, opts.defaultScope)) }));
|
|
1415
1439
|
body.append(other());
|
|
@@ -1448,6 +1472,10 @@ function isSelfAdvance(eff, defaultScope, dialect) {
|
|
|
1448
1472
|
return false;
|
|
1449
1473
|
}
|
|
1450
1474
|
}
|
|
1475
|
+
function entryForTarget(catalogue, target, defaultScope) {
|
|
1476
|
+
const want = normaliseRef(target, defaultScope);
|
|
1477
|
+
return catalogue.find((e) => normaliseRef(`@${e.scope}.${e.name}`, defaultScope) === want);
|
|
1478
|
+
}
|
|
1451
1479
|
var clone = (list) => list.map((e) => e.kind === "set" ? { ...e } : { ...e, args: [...e.args] });
|
|
1452
1480
|
var addSet = (list, target, value) => [...clone(list), { kind: "set", target, value }];
|
|
1453
1481
|
var addEmit = (list, event) => [...clone(list), { kind: "emit", event, args: [] }];
|
|
@@ -1536,6 +1564,11 @@ function mountEffectsEditor(host, opts) {
|
|
|
1536
1564
|
// choicesOf, never a raw field: a quality's ladder lives in `stages`, and reading `enumValues`
|
|
1537
1565
|
// here told the wizard the type and withheld the values.
|
|
1538
1566
|
...choicesOf(expected) ? { expectedChoices: choicesOf(expected) } : {},
|
|
1567
|
+
// The flags step needs the target itself: its declared flags, and the
|
|
1568
|
+
// qualified ref its set_flags(...) is written against. choicesOf stays
|
|
1569
|
+
// out of it deliberately - flags are not a pick-one list, and a pinned
|
|
1570
|
+
// test holds it to that.
|
|
1571
|
+
...expected?.type === "flags" ? { expectedRef: targetRefOf(expected), expectedFlags: expected.enumValues ?? [] } : {},
|
|
1539
1572
|
onCommit: (src) => {
|
|
1540
1573
|
onCommit(src);
|
|
1541
1574
|
close();
|
|
@@ -1543,7 +1576,7 @@ function mountEffectsEditor(host, opts) {
|
|
|
1543
1576
|
onCancel: close
|
|
1544
1577
|
}), { container: opts.popoverContainer });
|
|
1545
1578
|
};
|
|
1546
|
-
const targetType = (target) => opts.catalogue
|
|
1579
|
+
const targetType = (target) => entryForTarget(opts.catalogue, target, defaultScope)?.type;
|
|
1547
1580
|
const valueDisplay = (value, onChange, type, selfAdvanceRef) => {
|
|
1548
1581
|
const sub = el("div", "exed-effect-value");
|
|
1549
1582
|
const addTerm = type === "number" ? "arithmetic" : type === "boolean" ? "boolean" : void 0;
|
|
@@ -1610,10 +1643,10 @@ function mountEffectsEditor(host, opts) {
|
|
|
1610
1643
|
const row = el("div", "exed-effect exed-effect-set");
|
|
1611
1644
|
const targetBtn = button("exed-pill exed-pill-prop", eff.target || "(pick property)", (e) => {
|
|
1612
1645
|
pickTarget(e.currentTarget, void 0, (entry) => {
|
|
1613
|
-
commit(updateAt(effects, i, { target:
|
|
1646
|
+
commit(updateAt(effects, i, { target: targetRefOf(entry), value: initialValueFor(entry, defaultScope).src }));
|
|
1614
1647
|
});
|
|
1615
1648
|
}, "change the target property");
|
|
1616
|
-
const targetEntry = opts.catalogue
|
|
1649
|
+
const targetEntry = entryForTarget(opts.catalogue, eff.target, defaultScope);
|
|
1617
1650
|
const tip = propertyTip(targetEntry);
|
|
1618
1651
|
if (tip) targetBtn.title = tip;
|
|
1619
1652
|
if (targetEntry && opts.propertyActions) {
|
|
@@ -1621,14 +1654,7 @@ function mountEffectsEditor(host, opts) {
|
|
|
1621
1654
|
if (actions.length) targetBtn.addEventListener("contextmenu", (e) => {
|
|
1622
1655
|
e.preventDefault();
|
|
1623
1656
|
closePopover();
|
|
1624
|
-
popover = openPopover(targetBtn, (close) => {
|
|
1625
|
-
const wrap = el("div", "exed-menu");
|
|
1626
|
-
for (const a of actions) wrap.append(button("exed-opt", a.label, () => {
|
|
1627
|
-
a.run();
|
|
1628
|
-
close();
|
|
1629
|
-
}));
|
|
1630
|
-
return wrap;
|
|
1631
|
-
}, { container: opts.popoverContainer });
|
|
1657
|
+
popover = openPopover(targetBtn, (close) => propertyMenuBody(actions, close), { container: opts.popoverContainer });
|
|
1632
1658
|
});
|
|
1633
1659
|
}
|
|
1634
1660
|
const advances = isSelfAdvance(eff, defaultScope, opts.dialect);
|
|
@@ -1724,10 +1750,10 @@ function mountEffectsEditor(host, opts) {
|
|
|
1724
1750
|
pickTarget(anchor, void 0, (entry) => {
|
|
1725
1751
|
const { src, ask } = initialValueFor(entry, defaultScope);
|
|
1726
1752
|
if (!ask) {
|
|
1727
|
-
commit(addSet(effects,
|
|
1753
|
+
commit(addSet(effects, targetRefOf(entry), src));
|
|
1728
1754
|
return;
|
|
1729
1755
|
}
|
|
1730
|
-
openValueWizard(anchor, entry, (chosen) => commit(addSet(effects,
|
|
1756
|
+
openValueWizard(anchor, entry, (chosen) => commit(addSet(effects, targetRefOf(entry), chosen)));
|
|
1731
1757
|
});
|
|
1732
1758
|
}));
|
|
1733
1759
|
if (opts.allowEmit !== false) {
|
|
@@ -1794,13 +1820,26 @@ function renderConditionPreview(src, o) {
|
|
|
1794
1820
|
const cls = o.propertyActions ? "exed-preview exed-preview-interactive" : "exed-preview";
|
|
1795
1821
|
return el("div", cls, [exprPills(src, o)]);
|
|
1796
1822
|
}
|
|
1823
|
+
function targetPill(ref, o) {
|
|
1824
|
+
const pill2 = el("span", "exed-pill exed-pill-prop", [ref || "(property)"]);
|
|
1825
|
+
const entry = o.catalogue.find((e) => refOf(e, o.dialect.defaultScope) === ref);
|
|
1826
|
+
if (!entry) return pill2;
|
|
1827
|
+
const tip = propertyTip(entry);
|
|
1828
|
+
if (tip) pill2.title = tip;
|
|
1829
|
+
const actions = o.propertyActions?.({ scope: entry.scope, name: entry.name }) ?? [];
|
|
1830
|
+
if (actions.length) pill2.addEventListener("contextmenu", (e) => {
|
|
1831
|
+
e.preventDefault();
|
|
1832
|
+
openPopover(pill2, (close) => propertyMenuBody(actions, close), { container: o.popoverContainer });
|
|
1833
|
+
});
|
|
1834
|
+
return pill2;
|
|
1835
|
+
}
|
|
1797
1836
|
function renderEffectsPreview(effects, o) {
|
|
1798
|
-
const wrap = el("div",
|
|
1837
|
+
const wrap = el("div", `exed-preview exed-preview-effects${o.propertyActions ? " exed-preview-interactive" : ""}`);
|
|
1799
1838
|
for (const eff of effects) {
|
|
1800
1839
|
const row = el("div", "exed-preview-eff");
|
|
1801
1840
|
if (eff.kind === "set") {
|
|
1802
1841
|
const advances = isSelfAdvance(eff, o.dialect.defaultScope, o.dialect);
|
|
1803
|
-
row.append(
|
|
1842
|
+
row.append(targetPill(eff.target, o));
|
|
1804
1843
|
if (!advances) row.append(el("span", "exed-effect-eq", ["="]));
|
|
1805
1844
|
row.append(exprPills(eff.value, o, advances ? eff.target : void 0));
|
|
1806
1845
|
} else {
|
|
@@ -1818,6 +1857,6 @@ function renderEffectsPreview(effects, o) {
|
|
|
1818
1857
|
return wrap;
|
|
1819
1858
|
}
|
|
1820
1859
|
|
|
1821
|
-
export { ARITHMETIC_OPS, BINARY_LABEL, COMPARABLE_TYPES, COMPARISON_OPS, EQUALITY_OPS, OP_WORD, UNARY_LABEL, addArg, addChildToContainer, addEmit, addSet, advancedRef, astToTree, binary, boolLit, buildSubGroupClause, callNode, choicesOf, comparisonOpsFor, deleteAt, displayName, filterCatalogue, findChoicePeer, findEnumPeer, firstEmptyLeafPath, flagDelta, flipContainerOp, formatNumber, getNodeAt, groupByScope, initialValueFor, insertSiblingClauseAt, isComparisonOp, isPlaceholderForOp, isWrappedInNot, issuesAt, lookup, mountEffectsEditor, mountExpressionEditor, moveAt, moveChildInContainer, needsParens, normaliseRef, notNode, numLit, opSwapGroup, pathKey, placeholderForOp, propertyTip, redirectDeleteForPlaceholderSibling, refOf, removeArgAt, removeAt, renderConditionPreview, renderEffectsPreview, rhsTypesFor, scopedVar, searchCatalogue, seedValueSrc, setArgAt, setNodeAt, strLit, toggleContainerNot, toggleNotAt, updateAt, validateSource, valueWizard, wrapInNotAt };
|
|
1860
|
+
export { ARITHMETIC_OPS, BINARY_LABEL, COMPARABLE_TYPES, COMPARISON_OPS, EQUALITY_OPS, OP_WORD, UNARY_LABEL, addArg, addChildToContainer, addEmit, addSet, advancedRef, astToTree, binary, boolLit, buildSubGroupClause, callNode, choicesOf, comparisonOpsFor, deleteAt, displayName, filterCatalogue, findChoicePeer, findEnumPeer, firstEmptyLeafPath, flagChangeSrc, flagDelta, flipContainerOp, formatNumber, getNodeAt, groupByScope, initialValueFor, insertSiblingClauseAt, isComparisonOp, isPlaceholderForOp, isWrappedInNot, issuesAt, lookup, mountEffectsEditor, mountExpressionEditor, moveAt, moveChildInContainer, needsParens, normaliseRef, notNode, numLit, opSwapGroup, pathKey, placeholderForOp, propertyTip, redirectDeleteForPlaceholderSibling, refOf, removeArgAt, removeAt, renderConditionPreview, renderEffectsPreview, rhsTypesFor, scopedVar, searchCatalogue, seedValueSrc, setArgAt, setNodeAt, strLit, targetRefOf, toggleContainerNot, toggleNotAt, updateAt, validateSource, valueWizard, wrapInNotAt };
|
|
1822
1861
|
//# sourceMappingURL=index.js.map
|
|
1823
1862
|
//# sourceMappingURL=index.js.map
|