@wildwinter/expr-editor 0.8.0 → 0.9.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
@@ -214,6 +214,10 @@ interface EditCtx {
214
214
  apply(next: ExprNode | null): void;
215
215
  /** Open a popover anchored to `anchor`; `render(close)` builds the content. */
216
216
  openPopover(anchor: HTMLElement, render: (close: () => void) => Node): void;
217
+ /** Opener for the property right-click menu; falls back to openPopover. The
218
+ * read-only preview sets this (a real popover) while leaving openPopover a
219
+ * no-op, so property pills get their menu but left-click editing stays inert. */
220
+ openMenu?(anchor: HTMLElement, render: (close: () => void) => Node): void;
217
221
  /** Host-provided picker for a flow-node reference arg (e.g. `seen(...)` / `visits(...)`). When set,
218
222
  * the node-ref arg renders as a pill that opens this instead of a free-text field; `onPick` receives
219
223
  * the chosen node id. Absent in dialects / hosts that have no node catalogue. */
@@ -383,6 +387,18 @@ interface PreviewOptions {
383
387
  scopeOrder?: string[];
384
388
  /** Resolve a node id to a readable label for seen()/visits() node pills. */
385
389
  nodeLabel?: (id: string) => string;
390
+ /** Host actions for a property pill (e.g. "Go to definition"). When set, the
391
+ * preview becomes right-click interactive on property pills (left-click still
392
+ * falls through to the host); otherwise the preview is fully non-interactive. */
393
+ propertyActions?(ref: {
394
+ scope: string;
395
+ name: string;
396
+ }): Array<{
397
+ label: string;
398
+ run: () => void;
399
+ }>;
400
+ /** Where the property menu mounts (default document.body). */
401
+ popoverContainer?: HTMLElement;
386
402
  }
387
403
  /** Read-only pill strip for a condition (name-form). Empty/unparseable is the caller's concern; a
388
404
  * non-empty unparseable string falls back to its raw text. */
package/dist/index.d.ts CHANGED
@@ -214,6 +214,10 @@ interface EditCtx {
214
214
  apply(next: ExprNode | null): void;
215
215
  /** Open a popover anchored to `anchor`; `render(close)` builds the content. */
216
216
  openPopover(anchor: HTMLElement, render: (close: () => void) => Node): void;
217
+ /** Opener for the property right-click menu; falls back to openPopover. The
218
+ * read-only preview sets this (a real popover) while leaving openPopover a
219
+ * no-op, so property pills get their menu but left-click editing stays inert. */
220
+ openMenu?(anchor: HTMLElement, render: (close: () => void) => Node): void;
217
221
  /** Host-provided picker for a flow-node reference arg (e.g. `seen(...)` / `visits(...)`). When set,
218
222
  * the node-ref arg renders as a pill that opens this instead of a free-text field; `onPick` receives
219
223
  * the chosen node id. Absent in dialects / hosts that have no node catalogue. */
@@ -383,6 +387,18 @@ interface PreviewOptions {
383
387
  scopeOrder?: string[];
384
388
  /** Resolve a node id to a readable label for seen()/visits() node pills. */
385
389
  nodeLabel?: (id: string) => string;
390
+ /** Host actions for a property pill (e.g. "Go to definition"). When set, the
391
+ * preview becomes right-click interactive on property pills (left-click still
392
+ * falls through to the host); otherwise the preview is fully non-interactive. */
393
+ propertyActions?(ref: {
394
+ scope: string;
395
+ name: string;
396
+ }): Array<{
397
+ label: string;
398
+ run: () => void;
399
+ }>;
400
+ /** Where the property menu mounts (default document.body). */
401
+ popoverContainer?: HTMLElement;
386
402
  }
387
403
  /** Read-only pill strip for a condition (name-form). Empty/unparseable is the caller's concern; a
388
404
  * non-empty unparseable string falls back to its raw text. */
package/dist/index.js CHANGED
@@ -490,9 +490,10 @@ function attachPropertyMenu(ctx, node, pillEl) {
490
490
  if (!ctx.propertyActions) return;
491
491
  const actions = ctx.propertyActions({ scope: node.scope, name: node.name });
492
492
  if (!actions.length) return;
493
+ const open = ctx.openMenu ?? ctx.openPopover;
493
494
  pillEl.addEventListener("contextmenu", (e) => {
494
495
  e.preventDefault();
495
- ctx.openPopover(pillEl, (close) => {
496
+ open(pillEl, (close) => {
496
497
  const wrap = el("div", "exed-menu");
497
498
  for (const a of actions) wrap.append(button("exed-opt", a.label, () => {
498
499
  a.run();
@@ -1662,7 +1663,13 @@ function frozenCtx(src, o) {
1662
1663
  pickNode: () => {
1663
1664
  },
1664
1665
  // enables labelled node pills; never fires (preview is read-only)
1665
- ...o.nodeLabel ? { nodeLabel: o.nodeLabel } : {}
1666
+ ...o.nodeLabel ? { nodeLabel: o.nodeLabel } : {},
1667
+ ...o.propertyActions ? {
1668
+ propertyActions: o.propertyActions,
1669
+ openMenu: (anchor, render) => {
1670
+ openPopover(anchor, render, { container: o.popoverContainer });
1671
+ }
1672
+ } : {}
1666
1673
  };
1667
1674
  return { ctx, ast: v.ast };
1668
1675
  }
@@ -1671,7 +1678,8 @@ function exprPills(src, o) {
1671
1678
  return ast ? renderNode(ast, [], ctx) : el("span", "exed-preview-raw", [src]);
1672
1679
  }
1673
1680
  function renderConditionPreview(src, o) {
1674
- return el("div", "exed-preview", [exprPills(src, o)]);
1681
+ const cls = o.propertyActions ? "exed-preview exed-preview-interactive" : "exed-preview";
1682
+ return el("div", cls, [exprPills(src, o)]);
1675
1683
  }
1676
1684
  function renderEffectsPreview(effects, o) {
1677
1685
  const wrap = el("div", "exed-preview exed-preview-effects");