@ai-matrx/design-system 0.21.6 → 0.21.7

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.
@@ -5,7 +5,7 @@ import {
5
5
  cloneElement as cloneElement2,
6
6
  Fragment as Fragment6,
7
7
  isValidElement as isValidElement2,
8
- useCallback as useCallback6,
8
+ useCallback as useCallback7,
9
9
  useEffect as useEffect15,
10
10
  useId as useId2,
11
11
  useLayoutEffect as useLayoutEffect2,
@@ -3248,6 +3248,10 @@ function ContentTransferMenuSession({ references = [], referenceActions = [], so
3248
3248
  const [notice, setNotice] = React14.useState(null);
3249
3249
  const [receiptTarget, setReceiptTarget] = React14.useState();
3250
3250
  const [paletteOpen, setPaletteOpen] = React14.useState(false);
3251
+ const [paletteTarget, setPaletteTarget] = React14.useState(null);
3252
+ const externalPaletteClose = React14.useRef(null);
3253
+ const externalPaletteRestoreFocus = React14.useRef(null);
3254
+ const feedbackDocument = React14.useRef(null);
3251
3255
  const [mode, setMode] = React14.useState("copy");
3252
3256
  const scopes = React14.useMemo(() => table?.availableScopes ?? ["target"], [table]);
3253
3257
  const [requestedScope, setRequestedScope] = React14.useState(table?.initialScope ?? "target");
@@ -3344,6 +3348,40 @@ function ContentTransferMenuSession({ references = [], referenceActions = [], so
3344
3348
  fence.finish(controller);
3345
3349
  }
3346
3350
  }, [captureOne, fence, initialScope, primary]);
3351
+ const closePalette = React14.useCallback(() => {
3352
+ const onClose = externalPaletteClose.current;
3353
+ const restoreFocus = externalPaletteRestoreFocus.current;
3354
+ externalPaletteClose.current = null;
3355
+ externalPaletteRestoreFocus.current = null;
3356
+ onClose?.();
3357
+ restoreFocus?.();
3358
+ setPaletteTarget(null);
3359
+ setPaletteOpen(false);
3360
+ }, []);
3361
+ const mountPalette = React14.useCallback((target, onClose, restoreFocus) => {
3362
+ if (!target) {
3363
+ externalPaletteClose.current = null;
3364
+ externalPaletteRestoreFocus.current = null;
3365
+ setPaletteTarget(null);
3366
+ setPaletteOpen(false);
3367
+ return;
3368
+ }
3369
+ if (!enabled) throw new Error("Alchemy is not enabled for this record.");
3370
+ if (disabled) throw new Error("Alchemy is disabled for this record.");
3371
+ externalPaletteClose.current = onClose ?? null;
3372
+ externalPaletteRestoreFocus.current = restoreFocus ?? null;
3373
+ feedbackDocument.current = target.ownerDocument;
3374
+ restoreFocusRef.current = restoreFocus ?? (() => target.focus());
3375
+ setPaletteTarget(target);
3376
+ setPaletteOpen(true);
3377
+ setMode("copy");
3378
+ void preflight();
3379
+ }, [closePalette, disabled, enabled, preflight]);
3380
+ React14.useEffect(() => {
3381
+ if (!paletteTarget || !paletteOpen) return;
3382
+ const firstControl = paletteTarget.querySelector("button:not([disabled]), select:not([disabled]), input:not([disabled]), textarea:not([disabled]), [href]");
3383
+ firstControl?.focus();
3384
+ }, [paletteOpen, paletteTarget]);
3347
3385
  const transfer = React14.useCallback(async (format, download, alternate) => {
3348
3386
  const { controller, id } = fence.begin();
3349
3387
  try {
@@ -3484,6 +3522,7 @@ function ContentTransferMenuSession({ references = [], referenceActions = [], so
3484
3522
  );
3485
3523
  React14.useImperativeHandle(controllerRef, () => ({
3486
3524
  focusTrigger: () => triggerRef.current?.focus(),
3525
+ mountPalette,
3487
3526
  preparePrimary: async (options) => {
3488
3527
  if (!enabled) throw new Error("Alchemy is not enabled for this record.");
3489
3528
  if (disabled) throw new Error("Alchemy is disabled for this record.");
@@ -3498,7 +3537,7 @@ function ContentTransferMenuSession({ references = [], referenceActions = [], so
3498
3537
  externalWorkspaceKeys.current.add(requestedKey);
3499
3538
  await openWorkspace(requestedKey, { source: requestedSource, label: requestedLabel });
3500
3539
  }
3501
- }), [disabled, enabled, hide, openWorkspace, primary, primaryWorkspaceKey, sourceLabel]);
3540
+ }), [disabled, enabled, hide, mountPalette, openWorkspace, primary, primaryWorkspaceKey, sourceLabel]);
3502
3541
  const runAction = React14.useCallback(async (action) => {
3503
3542
  const { controller, id } = fence.begin();
3504
3543
  try {
@@ -3564,7 +3603,6 @@ function ContentTransferMenuSession({ references = [], referenceActions = [], so
3564
3603
  return sealTransferArtifact2({ snapshotId: draft.snapshotId, draftRevision: draft.revision, format: "ai-context", plainText: buildAgentPayload({ kind: "matrx_content", location: sourceLabel, description: "Captured content for an assistant", data: JSON.parse(json.plainText), attributes: { source: draft.sourceId } }), omissions: [...json.omissions] });
3565
3604
  }
3566
3605
  };
3567
- const closePalette = () => setPaletteOpen(false);
3568
3606
  const tile = (id, label2, onClick, options = {}) => {
3569
3607
  const presentation = options.action;
3570
3608
  const Icon3 = presentation?.icon;
@@ -3580,122 +3618,125 @@ function ContentTransferMenuSession({ references = [], referenceActions = [], so
3580
3618
  ] })
3581
3619
  ] }, id);
3582
3620
  };
3621
+ const palette = /* @__PURE__ */ jsxs17(Fragment2, { children: [
3622
+ menuStatus === "loading" ? /* @__PURE__ */ jsx25("p", { className: "matrx-alchemy-palette-status", children: "Inspecting content\u2026" }) : menuStatus !== "idle" ? /* @__PURE__ */ jsx25("p", { className: "matrx-alchemy-error", children: menuStatus }) : null,
3623
+ table && scopes.length > 1 ? /* @__PURE__ */ jsxs17("label", { className: "matrx-alchemy-scope", children: [
3624
+ "Content scope",
3625
+ /* @__PURE__ */ jsx25("select", { "aria-label": "Content scope", value: initialScope, onChange: (event) => {
3626
+ const next = scopes.find((scope) => scope === event.target.value);
3627
+ if (next) {
3628
+ setRequestedScope(next);
3629
+ void preflight(next);
3630
+ }
3631
+ }, children: scopes.map((scope) => /* @__PURE__ */ jsx25("option", { value: scope, children: table.scopeLabels?.[scope] ?? SCOPE_LABEL[scope] }, scope)) })
3632
+ ] }) : null,
3633
+ copyAvailable || downloadAvailable ? /* @__PURE__ */ jsxs17("section", { className: "matrx-alchemy-output", children: [
3634
+ /* @__PURE__ */ jsx25("h3", { children: resolvedMode === "copy" ? "Copy as" : "Download as" }),
3635
+ copyAvailable && downloadAvailable ? /* @__PURE__ */ jsxs17("div", { className: "matrx-alchemy-mode", "aria-label": "Output action", children: [
3636
+ /* @__PURE__ */ jsx25("button", { type: "button", "aria-label": "Copy mode", "aria-pressed": resolvedMode === "copy", onClick: () => setMode("copy"), children: "Copy" }),
3637
+ /* @__PURE__ */ jsx25("button", { type: "button", "aria-label": "Download mode", "aria-pressed": resolvedMode === "download", onClick: () => setMode("download"), children: "Download" })
3638
+ ] }) : null,
3639
+ resolvedMode === "copy" && copyAvailable ? /* @__PURE__ */ jsxs17(Fragment2, { children: [
3640
+ /* @__PURE__ */ jsxs17("div", { className: "matrx-alchemy-palette-grid", children: [
3641
+ visibleCopies.map((format) => tile(format, { plain: "Text", markdown: "Markdown", html: "Formatted", json: "JSON", "compact-json": "Compact", csv: "CSV", tsv: "Sheets" }[format], () => void transfer(format, false), { ariaLabel: `Copy ${LABEL[format]}` })),
3642
+ visibleAdapters.map((adapter) => tile(adapter.id, adapter.label, () => void transfer(adapter, false), { custom: true }))
3643
+ ] }),
3644
+ quickVariants("copy").length ? /* @__PURE__ */ jsx25(PaletteRows, { title: "Quick copy", items: quickVariants("copy"), onRun: (variant) => {
3645
+ closePalette();
3646
+ void transfer("markdown", false, variant);
3647
+ } }) : null
3648
+ ] }) : null,
3649
+ resolvedMode === "download" && downloadAvailable ? /* @__PURE__ */ jsx25(Fragment2, { children: /* @__PURE__ */ jsxs17("div", { className: "matrx-alchemy-palette-grid", children: [
3650
+ visibleDownloads.map((format) => tile(format, { plain: "Text", markdown: "Markdown", html: "Formatted", json: "JSON", "compact-json": "Compact", csv: "CSV", tsv: "Sheets", xlsx: "Excel" }[format], () => void transfer(format, true), { ariaLabel: `Download ${LABEL[format]}` })),
3651
+ visibleAdapters.map((adapter) => tile(adapter.id, adapter.label, () => void transfer(adapter, true), { custom: true })),
3652
+ downloadActions.map((action) => tile(action.id, action.label, () => void runAction(action), { custom: true, action, file: true }))
3653
+ ] }) }) : null
3654
+ ] }) : null,
3655
+ prepareAvailable ? /* @__PURE__ */ jsxs17(Fragment2, { children: [
3656
+ /* @__PURE__ */ jsx25(PaletteRows, { title: "Copy for AI", ai: true, glyphKind: "ai-copy", fallbackHint: "Copies immediately", extra: sourceFormats ? /* @__PURE__ */ jsxs17("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => {
3657
+ closePalette();
3658
+ void transfer(nativeAiFormat, false);
3659
+ }, children: [
3660
+ /* @__PURE__ */ jsx25(PaletteGlyph, { kind: "ai-copy" }),
3661
+ /* @__PURE__ */ jsxs17("span", { children: [
3662
+ "Copy with AI context",
3663
+ /* @__PURE__ */ jsx25("small", { className: "matrx-alchemy-menu-hint", children: "Include source context" })
3664
+ ] })
3665
+ ] }) : null, items: quickVariants("ai"), onRun: (variant) => {
3666
+ closePalette();
3667
+ void transfer("markdown", false, variant);
3668
+ } }),
3669
+ /* @__PURE__ */ jsx25(PaletteRows, { title: "Edit and prepare", items: [], extra: /* @__PURE__ */ jsxs17("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": "Prepare for AI", onClick: () => {
3670
+ closePalette();
3671
+ void openWorkspace();
3672
+ }, children: [
3673
+ /* @__PURE__ */ jsx25(PaletteGlyph, { kind: "sliders" }),
3674
+ /* @__PURE__ */ jsxs17("span", { children: [
3675
+ "Prepare for AI",
3676
+ /* @__PURE__ */ jsx25("small", { className: "matrx-alchemy-menu-hint", children: "Trim, edit or summarize" })
3677
+ ] })
3678
+ ] }) })
3679
+ ] }) : null,
3680
+ prepareAvailable && (nearestWorkspaceKey || variants.length) ? /* @__PURE__ */ jsx25(PaletteRows, { title: "Other sources", items: [], extra: /* @__PURE__ */ jsxs17(Fragment2, { children: [
3681
+ nearestWorkspaceKey && nearestSurface ? /* @__PURE__ */ jsxs17("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => {
3682
+ closePalette();
3683
+ void openWorkspace(nearestWorkspaceKey, { source: nearestSurface, label: nearestSurface.surfaceName });
3684
+ }, children: [
3685
+ /* @__PURE__ */ jsx25(PaletteGlyph, { kind: "surface" }),
3686
+ /* @__PURE__ */ jsx25("span", { children: "Prepare this page" })
3687
+ ] }) : null,
3688
+ variants.map((variant) => /* @__PURE__ */ jsx25("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": variant.ariaLabel, onClick: () => {
3689
+ closePalette();
3690
+ void openWorkspace(variantWorkspaceKeys.get(variant.id), variant);
3691
+ }, children: /* @__PURE__ */ jsx25(MenuPresentation, { ...variant, label: `Prepare ${variant.label}` }) }, variant.id))
3692
+ ] }) }) : null,
3693
+ references.length || referenceActions.length ? /* @__PURE__ */ jsxs17("section", { className: "matrx-alchemy-palette-section", children: [
3694
+ /* @__PURE__ */ jsx25("h3", { children: "References" }),
3695
+ referenceActions.map((action) => /* @__PURE__ */ jsxs17("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => void openReference(action), children: [
3696
+ /* @__PURE__ */ jsx25(PaletteGlyph, { kind: "link" }),
3697
+ /* @__PURE__ */ jsx25("span", { children: action.label }),
3698
+ /* @__PURE__ */ jsx25("svg", { className: "matrx-alchemy-disclosure", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: /* @__PURE__ */ jsx25("path", { d: "m6 4 4 4-4 4" }) })
3699
+ ] }, action.id)),
3700
+ references.map((reference) => /* @__PURE__ */ jsxs17("button", { type: "button", className: "matrx-alchemy-palette-row", title: "Copies a reference to saved data", onClick: () => void copyReference(reference), children: [
3701
+ /* @__PURE__ */ jsx25(PaletteGlyph, { kind: "link" }),
3702
+ /* @__PURE__ */ jsx25("span", { children: reference.label })
3703
+ ] }, reference.id))
3704
+ ] }) : null,
3705
+ ["save", "chat", "email", "other"].map((group) => {
3706
+ const entries = ordinaryActions.filter((action) => (action.group ?? "other") === group);
3707
+ return entries.length ? /* @__PURE__ */ jsxs17("details", { className: "matrx-alchemy-palette-destinations", children: [
3708
+ /* @__PURE__ */ jsxs17("summary", { children: [
3709
+ group === "save" ? "Save to Matrx" : group === "chat" ? "Continue with AI" : group === "email" ? "Email to me" : "Actions",
3710
+ /* @__PURE__ */ jsxs17("span", { className: "matrx-alchemy-disclosure-meta", children: [
3711
+ /* @__PURE__ */ jsx25("span", { children: entries.length }),
3712
+ /* @__PURE__ */ jsx25("svg", { className: "matrx-alchemy-disclosure", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: /* @__PURE__ */ jsx25("path", { d: "m6 4 4 4-4 4" }) })
3713
+ ] })
3714
+ ] }),
3715
+ /* @__PURE__ */ jsx25("div", { children: entries.map((action) => /* @__PURE__ */ jsx25("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": action.ariaLabel, onClick: () => {
3716
+ closePalette();
3717
+ void runAction(action);
3718
+ }, children: /* @__PURE__ */ jsx25(DestinationPresentation, { action }) }, action.id)) })
3719
+ ] }, group) : null;
3720
+ })
3721
+ ] });
3722
+ const feedbackOwner = paletteTarget ?? triggerRef.current ?? feedbackDocument.current?.body ?? null;
3583
3723
  return /* @__PURE__ */ jsxs17("span", { className: cn("matrx-alchemy", className), onClick: stopPropagation ? (event) => event.stopPropagation() : void 0, children: [
3584
- !triggerHidden ? /* @__PURE__ */ jsxs17(Popover, { open: paletteOpen, onOpenChange: (open) => {
3585
- setPaletteOpen(open);
3724
+ !triggerHidden && !paletteTarget ? /* @__PURE__ */ jsxs17(Popover, { open: paletteOpen, onOpenChange: (open) => {
3586
3725
  if (open) {
3726
+ setPaletteOpen(true);
3587
3727
  setMode("copy");
3588
3728
  void preflight();
3589
- }
3729
+ } else closePalette();
3590
3730
  }, children: [
3591
3731
  /* @__PURE__ */ jsx25(PopoverTrigger, { asChild: true, children: triggerVariant === "outline" ? /* @__PURE__ */ jsx25(Button, { ref: triggerRef, variant: "outline", size: "icon-sm", "aria-label": `Copy, transform or export ${sourceLabel}`, "data-alchemy-trigger": "outline", disabled, children: /* @__PURE__ */ jsx25(AlchemyGlyph, { icon }) }) : triggerVariant === "glass" ? /* @__PURE__ */ jsx25(TapTargetButton, { ref: triggerRef, icon: /* @__PURE__ */ jsx25(AlchemyGlyph, { icon }), tooltip: false, ariaLabel: `Copy, transform or export ${sourceLabel}`, "data-alchemy-trigger": "glass", "data-alchemy-size": triggerSize, disabled }) : /* @__PURE__ */ jsx25(TapTargetButtonTransparent, { ref: triggerRef, icon: /* @__PURE__ */ jsx25(AlchemyGlyph, { icon }), tooltip: false, ariaLabel: `Copy, transform or export ${sourceLabel}`, "data-alchemy-trigger": "transparent", "data-alchemy-size": triggerSize, disabled }) }),
3592
- /* @__PURE__ */ jsxs17(PopoverContent, { align: "end", className: "matrx-alchemy-menu matrx-alchemy-palette", "aria-label": "Alchemy output options", onCloseAutoFocus: () => triggerRef.current?.focus(), children: [
3593
- menuStatus === "loading" ? /* @__PURE__ */ jsx25("p", { className: "matrx-alchemy-palette-status", children: "Inspecting content\u2026" }) : menuStatus !== "idle" ? /* @__PURE__ */ jsx25("p", { className: "matrx-alchemy-error", children: menuStatus }) : null,
3594
- table && scopes.length > 1 ? /* @__PURE__ */ jsxs17("label", { className: "matrx-alchemy-scope", children: [
3595
- "Content scope",
3596
- /* @__PURE__ */ jsx25("select", { "aria-label": "Content scope", value: initialScope, onChange: (event) => {
3597
- const next = scopes.find((scope) => scope === event.target.value);
3598
- if (next) {
3599
- setRequestedScope(next);
3600
- void preflight(next);
3601
- }
3602
- }, children: scopes.map((scope) => /* @__PURE__ */ jsx25("option", { value: scope, children: table.scopeLabels?.[scope] ?? SCOPE_LABEL[scope] }, scope)) })
3603
- ] }) : null,
3604
- copyAvailable || downloadAvailable ? /* @__PURE__ */ jsxs17("section", { className: "matrx-alchemy-output", children: [
3605
- /* @__PURE__ */ jsx25("h3", { children: resolvedMode === "copy" ? "Copy as" : "Download as" }),
3606
- copyAvailable && downloadAvailable ? /* @__PURE__ */ jsxs17("div", { className: "matrx-alchemy-mode", "aria-label": "Output action", children: [
3607
- /* @__PURE__ */ jsx25("button", { type: "button", "aria-label": "Copy mode", "aria-pressed": resolvedMode === "copy", onClick: () => setMode("copy"), children: "Copy" }),
3608
- /* @__PURE__ */ jsx25("button", { type: "button", "aria-label": "Download mode", "aria-pressed": resolvedMode === "download", onClick: () => setMode("download"), children: "Download" })
3609
- ] }) : null,
3610
- resolvedMode === "copy" && copyAvailable ? /* @__PURE__ */ jsxs17(Fragment2, { children: [
3611
- /* @__PURE__ */ jsxs17("div", { className: "matrx-alchemy-palette-grid", children: [
3612
- visibleCopies.map((format) => tile(format, { plain: "Text", markdown: "Markdown", html: "Formatted", json: "JSON", "compact-json": "Compact", csv: "CSV", tsv: "Sheets" }[format], () => void transfer(format, false), { ariaLabel: `Copy ${LABEL[format]}` })),
3613
- visibleAdapters.map((adapter) => tile(adapter.id, adapter.label, () => void transfer(adapter, false), { custom: true }))
3614
- ] }),
3615
- quickVariants("copy").length ? /* @__PURE__ */ jsx25(PaletteRows, { title: "Quick copy", items: quickVariants("copy"), onRun: (variant) => {
3616
- closePalette();
3617
- void transfer("markdown", false, variant);
3618
- } }) : null
3619
- ] }) : null,
3620
- resolvedMode === "download" && downloadAvailable ? /* @__PURE__ */ jsx25(Fragment2, { children: /* @__PURE__ */ jsxs17("div", { className: "matrx-alchemy-palette-grid", children: [
3621
- visibleDownloads.map((format) => tile(format, { plain: "Text", markdown: "Markdown", html: "Formatted", json: "JSON", "compact-json": "Compact", csv: "CSV", tsv: "Sheets", xlsx: "Excel" }[format], () => void transfer(format, true), { ariaLabel: `Download ${LABEL[format]}` })),
3622
- visibleAdapters.map((adapter) => tile(adapter.id, adapter.label, () => void transfer(adapter, true), { custom: true })),
3623
- downloadActions.map((action) => tile(action.id, action.label, () => void runAction(action), { custom: true, action, file: true }))
3624
- ] }) }) : null
3625
- ] }) : null,
3626
- prepareAvailable ? /* @__PURE__ */ jsxs17(Fragment2, { children: [
3627
- /* @__PURE__ */ jsx25(PaletteRows, { title: "Copy for AI", ai: true, glyphKind: "ai-copy", fallbackHint: "Copies immediately", extra: sourceFormats ? /* @__PURE__ */ jsxs17("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => {
3628
- closePalette();
3629
- void transfer(nativeAiFormat, false);
3630
- }, children: [
3631
- /* @__PURE__ */ jsx25(PaletteGlyph, { kind: "ai-copy" }),
3632
- /* @__PURE__ */ jsxs17("span", { children: [
3633
- "Copy with AI context",
3634
- /* @__PURE__ */ jsx25("small", { className: "matrx-alchemy-menu-hint", children: "Include source context" })
3635
- ] })
3636
- ] }) : null, items: quickVariants("ai"), onRun: (variant) => {
3637
- closePalette();
3638
- void transfer("markdown", false, variant);
3639
- } }),
3640
- /* @__PURE__ */ jsx25(PaletteRows, { title: "Edit and prepare", items: [], extra: /* @__PURE__ */ jsxs17("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": "Prepare for AI", onClick: () => {
3641
- closePalette();
3642
- void openWorkspace();
3643
- }, children: [
3644
- /* @__PURE__ */ jsx25(PaletteGlyph, { kind: "sliders" }),
3645
- /* @__PURE__ */ jsxs17("span", { children: [
3646
- "Prepare for AI",
3647
- /* @__PURE__ */ jsx25("small", { className: "matrx-alchemy-menu-hint", children: "Trim, edit or summarize" })
3648
- ] })
3649
- ] }) })
3650
- ] }) : null,
3651
- prepareAvailable && (nearestWorkspaceKey || variants.length) ? /* @__PURE__ */ jsx25(PaletteRows, { title: "Other sources", items: [], extra: /* @__PURE__ */ jsxs17(Fragment2, { children: [
3652
- nearestWorkspaceKey && nearestSurface ? /* @__PURE__ */ jsxs17("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => {
3653
- closePalette();
3654
- void openWorkspace(nearestWorkspaceKey, { source: nearestSurface, label: nearestSurface.surfaceName });
3655
- }, children: [
3656
- /* @__PURE__ */ jsx25(PaletteGlyph, { kind: "surface" }),
3657
- /* @__PURE__ */ jsx25("span", { children: "Prepare this page" })
3658
- ] }) : null,
3659
- variants.map((variant) => /* @__PURE__ */ jsx25("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": variant.ariaLabel, onClick: () => {
3660
- closePalette();
3661
- void openWorkspace(variantWorkspaceKeys.get(variant.id), variant);
3662
- }, children: /* @__PURE__ */ jsx25(MenuPresentation, { ...variant, label: `Prepare ${variant.label}` }) }, variant.id))
3663
- ] }) }) : null,
3664
- references.length || referenceActions.length ? /* @__PURE__ */ jsxs17("section", { className: "matrx-alchemy-palette-section", children: [
3665
- /* @__PURE__ */ jsx25("h3", { children: "References" }),
3666
- referenceActions.map((action) => /* @__PURE__ */ jsxs17("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => void openReference(action), children: [
3667
- /* @__PURE__ */ jsx25(PaletteGlyph, { kind: "link" }),
3668
- /* @__PURE__ */ jsx25("span", { children: action.label }),
3669
- /* @__PURE__ */ jsx25("svg", { className: "matrx-alchemy-disclosure", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: /* @__PURE__ */ jsx25("path", { d: "m6 4 4 4-4 4" }) })
3670
- ] }, action.id)),
3671
- references.map((reference) => /* @__PURE__ */ jsxs17("button", { type: "button", className: "matrx-alchemy-palette-row", title: "Copies a reference to saved data", onClick: () => void copyReference(reference), children: [
3672
- /* @__PURE__ */ jsx25(PaletteGlyph, { kind: "link" }),
3673
- /* @__PURE__ */ jsx25("span", { children: reference.label })
3674
- ] }, reference.id))
3675
- ] }) : null,
3676
- ["save", "chat", "email", "other"].map((group) => {
3677
- const entries = ordinaryActions.filter((action) => (action.group ?? "other") === group);
3678
- return entries.length ? /* @__PURE__ */ jsxs17("details", { className: "matrx-alchemy-palette-destinations", children: [
3679
- /* @__PURE__ */ jsxs17("summary", { children: [
3680
- group === "save" ? "Save to Matrx" : group === "chat" ? "Continue with AI" : group === "email" ? "Email to me" : "Actions",
3681
- /* @__PURE__ */ jsxs17("span", { className: "matrx-alchemy-disclosure-meta", children: [
3682
- /* @__PURE__ */ jsx25("span", { children: entries.length }),
3683
- /* @__PURE__ */ jsx25("svg", { className: "matrx-alchemy-disclosure", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", children: /* @__PURE__ */ jsx25("path", { d: "m6 4 4 4-4 4" }) })
3684
- ] })
3685
- ] }),
3686
- /* @__PURE__ */ jsx25("div", { children: entries.map((action) => /* @__PURE__ */ jsx25("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": action.ariaLabel, onClick: () => {
3687
- closePalette();
3688
- void runAction(action);
3689
- }, children: /* @__PURE__ */ jsx25(DestinationPresentation, { action }) }, action.id)) })
3690
- ] }, group) : null;
3691
- })
3692
- ] })
3732
+ /* @__PURE__ */ jsx25(PopoverContent, { align: "end", className: "matrx-alchemy-menu matrx-alchemy-palette", "aria-label": "Alchemy output options", onCloseAutoFocus: () => triggerRef.current?.focus(), children: palette })
3693
3733
  ] }) : null,
3694
- notice && triggerRef.current ? createPortal(/* @__PURE__ */ jsxs17("div", { className: "matrx-alchemy-feedback", children: [
3734
+ paletteTarget && paletteOpen ? createPortal(/* @__PURE__ */ jsx25("div", { className: "matrx-alchemy-menu matrx-alchemy-palette", role: "dialog", "aria-label": "Alchemy output options", children: palette }), paletteTarget) : null,
3735
+ notice && feedbackOwner ? createPortal(/* @__PURE__ */ jsxs17("div", { className: "matrx-alchemy-feedback", children: [
3695
3736
  /* @__PURE__ */ jsx25("span", { role: "status", children: notice }),
3696
3737
  /* @__PURE__ */ jsx25(ReceiptLink, { target: receiptTarget }),
3697
3738
  /* @__PURE__ */ jsx25("button", { type: "button", "aria-label": "Dismiss Alchemy feedback", onClick: () => setNotice(null), children: "\xD7" })
3698
- ] }), triggerRef.current.ownerDocument.body) : null,
3739
+ ] }), feedbackOwner.ownerDocument.body) : null,
3699
3740
  Object.values(workspaces).map((saved) => /* @__PURE__ */ jsx25(PreparationWorkspace, { restoreFocus: () => restoreFocusRef.current?.() ?? triggerRef.current?.focus(), open: workspaceOpen && workspaceKey === saved.key, state: saved, scopes, scopeLabels: table?.scopeLabels, onClose: () => setWorkspaceOpen(false), onChange: (next) => setWorkspaces((current) => ({ ...current, [saved.key]: next })), transport, adapters, actions: preparedActions, captureScope: workspaceCaptures.current.get(saved.key) ?? capturePrimary, ...ai ? { ai } : {}, onOutcome: report }, saved.key)),
3700
3741
  emailReview
3701
3742
  ] });
@@ -5598,7 +5639,7 @@ import {
5598
5639
  } from "@ai-matrx/kit/url-state";
5599
5640
 
5600
5641
  // src/data-table/RowAlchemyLauncher.tsx
5601
- import { useEffect as useEffect8, useRef as useRef9, useState as useState13 } from "react";
5642
+ import { useCallback as useCallback5, useEffect as useEffect8, useRef as useRef9, useState as useState13 } from "react";
5602
5643
  import { jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
5603
5644
  function MatrxTableRowAlchemyProvider({ copy, placement, controls, children }) {
5604
5645
  const controller = useRef9(null);
@@ -5615,17 +5656,23 @@ function MatrxTableRowAlchemyProvider({ copy, placement, controls, children }) {
5615
5656
  }, 0);
5616
5657
  return () => window.clearTimeout(timer);
5617
5658
  }, [active, placement]);
5659
+ const activate = useCallback5(() => setActive(true), []);
5660
+ const mountMenu = useCallback5((target, onClose, restoreFocus) => {
5661
+ controller.current?.mountPalette(target, onClose, restoreFocus);
5662
+ }, []);
5663
+ const prepare = useCallback5(async (restoreFocus) => {
5664
+ if (copy.disabled) throw new Error("Alchemy is disabled for this record.");
5665
+ if (!controller.current) throw new Error("Alchemy is unavailable because its launcher did not mount.");
5666
+ await controller.current.preparePrimary(restoreFocus ? { restoreFocus } : void 0);
5667
+ }, [copy.disabled]);
5618
5668
  const value = {
5619
5669
  copy,
5620
5670
  controls,
5621
5671
  placement,
5622
5672
  ready: active,
5623
- activate: () => setActive(true),
5624
- prepare: async (restoreFocus) => {
5625
- if (copy.disabled) throw new Error("Alchemy is disabled for this record.");
5626
- if (!controller.current) throw new Error("Alchemy is unavailable because its launcher did not mount.");
5627
- await controller.current.preparePrimary(restoreFocus ? { restoreFocus } : void 0);
5628
- }
5673
+ activate,
5674
+ mountMenu,
5675
+ prepare
5629
5676
  };
5630
5677
  return /* @__PURE__ */ jsxs20(MatrxTableRowAlchemyScope, { value, children: [
5631
5678
  active || fallback ? CopyControls ? /* @__PURE__ */ jsx29(CopyControls, { ...copy, triggerHidden: active, controllerRef: controller }) : /* @__PURE__ */ jsx29(MatrxCopyMenu, { ...copy, triggerHidden: active, controllerRef: controller }) : null,
@@ -6469,7 +6516,7 @@ function parseOptionalNumber(raw) {
6469
6516
 
6470
6517
  // src/data-table/ColumnResizeHandle.tsx
6471
6518
  import {
6472
- useCallback as useCallback5,
6519
+ useCallback as useCallback6,
6473
6520
  useEffect as useEffect10,
6474
6521
  useRef as useRef10,
6475
6522
  useState as useState15
@@ -6523,16 +6570,16 @@ function ColumnResizeHandle({
6523
6570
  const [announcedWidth, setAnnouncedWidth] = useState15(null);
6524
6571
  const bounds = resolveColumnResizeBounds(minWidth, maxWidth);
6525
6572
  const cssVar = columnResizeCssVar(columnId2);
6526
- const readWidth = useCallback5(() => {
6573
+ const readWidth = useCallback6(() => {
6527
6574
  const header = handleRef.current?.closest("th");
6528
6575
  const measured = header?.getBoundingClientRect().width ?? 0;
6529
6576
  const computed = header ? Number.parseFloat(getComputedStyle(header).width) : 0;
6530
6577
  return clampColumnWidth(measured || computed || keyboardWidthRef.current || bounds.minWidth, bounds);
6531
6578
  }, [bounds]);
6532
- const writePreview = useCallback5((width) => {
6579
+ const writePreview = useCallback6((width) => {
6533
6580
  tableRef.current?.style.setProperty(cssVar, `${width}px`);
6534
6581
  }, [cssVar, tableRef]);
6535
- const queuePreview = useCallback5((width) => {
6582
+ const queuePreview = useCallback6((width) => {
6536
6583
  queuedWidthRef.current = width;
6537
6584
  if (previewRafRef.current !== null) return;
6538
6585
  previewRafRef.current = requestAnimationFrame(() => {
@@ -6542,12 +6589,12 @@ function ColumnResizeHandle({
6542
6589
  if (nextWidth !== null) writePreview(nextWidth);
6543
6590
  });
6544
6591
  }, [writePreview]);
6545
- const clearQueuedPreview = useCallback5(() => {
6592
+ const clearQueuedPreview = useCallback6(() => {
6546
6593
  if (previewRafRef.current !== null) cancelAnimationFrame(previewRafRef.current);
6547
6594
  previewRafRef.current = null;
6548
6595
  queuedWidthRef.current = null;
6549
6596
  }, []);
6550
- const finishPointerResize = useCallback5((commit) => {
6597
+ const finishPointerResize = useCallback6((commit) => {
6551
6598
  const active = activeResizeRef.current;
6552
6599
  if (!active) return;
6553
6600
  activeResizeRef.current = null;
@@ -8727,7 +8774,7 @@ function MatrxDataTableCore({
8727
8774
  const sourceOwnsIntelligentSearch = sourceProcessing?.intelligentSearch === "source";
8728
8775
  const sourceOwnsSearch = remoteQuery?.mode === "controlled" || appendQuery !== null && sourceProcessing === void 0 || sourceProcessing?.search === "source" || sourceOwnsIntelligentSearch;
8729
8776
  const intelligentSearchEnabled = toolbar?.intelligentSearch !== void 0 && (sourceOwnsIntelligentSearch || remoteQuery === null && !sourceOwnsSearch);
8730
- const emitControlledQueryChange = useCallback6(
8777
+ const emitControlledQueryChange = useCallback7(
8731
8778
  (patch, options) => {
8732
8779
  if (!controlledQuery) return;
8733
8780
  controlledQuery.onStateChange(
@@ -8979,7 +9026,7 @@ function MatrxDataTableCore({
8979
9026
  });
8980
9027
  const [scrollHintRight, setScrollHintRight] = useState21(false);
8981
9028
  const [scrollHintLeft, setScrollHintLeft] = useState21(false);
8982
- const updateScrollHint = useCallback6(() => {
9029
+ const updateScrollHint = useCallback7(() => {
8983
9030
  const el = scrollRef.current;
8984
9031
  if (!el) return;
8985
9032
  setScrollHintRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 2);
@@ -9081,7 +9128,7 @@ function MatrxDataTableCore({
9081
9128
  const columnDragRaf = useRef13(null);
9082
9129
  const columnDragScrollDirection = useRef13(0);
9083
9130
  const [columnDragPreview, setColumnDragPreview] = useState21(null);
9084
- const stopColumnDragScroll = useCallback6(() => {
9131
+ const stopColumnDragScroll = useCallback7(() => {
9085
9132
  if (columnDragRaf.current !== null) cancelAnimationFrame(columnDragRaf.current);
9086
9133
  columnDragRaf.current = null;
9087
9134
  columnDragScrollDirection.current = 0;
@@ -9090,7 +9137,7 @@ function MatrxDataTableCore({
9090
9137
  columnDragActive.current = false;
9091
9138
  stopColumnDragScroll();
9092
9139
  }, [stopColumnDragScroll]);
9093
- const startColumnDragScroll = useCallback6(() => {
9140
+ const startColumnDragScroll = useCallback7(() => {
9094
9141
  if (!columnDragActive.current || columnDragRaf.current !== null) return;
9095
9142
  const scrollStep = () => {
9096
9143
  const scroll = scrollRef.current;
@@ -9117,7 +9164,7 @@ function MatrxDataTableCore({
9117
9164
  };
9118
9165
  columnDragRaf.current = requestAnimationFrame(scrollStep);
9119
9166
  }, []);
9120
- const commitColumnState = useCallback6((order, hidden) => {
9167
+ const commitColumnState = useCallback7((order, hidden) => {
9121
9168
  if (columnState) columnState.onChange({ order, hidden: [...hidden] });
9122
9169
  else {
9123
9170
  setColumnOrder(order);
@@ -9135,7 +9182,7 @@ function MatrxDataTableCore({
9135
9182
  [columns, columnState?.widths, columnWidths]
9136
9183
  );
9137
9184
  const resizeGestureSnapshotRef = useRef13(null);
9138
- const measureVisibleColumnWidths = useCallback6(() => {
9185
+ const measureVisibleColumnWidths = useCallback7(() => {
9139
9186
  const measured = {};
9140
9187
  const headers = tableRef.current ? Array.from(tableRef.current.querySelectorAll(
9141
9188
  "thead th[data-matrx-table-column-id]"
@@ -9149,7 +9196,7 @@ function MatrxDataTableCore({
9149
9196
  }
9150
9197
  return normalizeColumnWidthsForColumns(measured, columns);
9151
9198
  }, [columns]);
9152
- const measureFixedTableGeometry = useCallback6(() => {
9199
+ const measureFixedTableGeometry = useCallback7(() => {
9153
9200
  const table = tableRef.current;
9154
9201
  const headers = table ? Array.from(table.querySelectorAll("thead th")) : [];
9155
9202
  const widthFor = (selector) => {
@@ -9179,16 +9226,16 @@ function MatrxDataTableCore({
9179
9226
  ...actionsWidth === void 0 ? {} : { actionsWidth }
9180
9227
  };
9181
9228
  }, [resolvedDensity]);
9182
- const captureResizeGestureSnapshot = useCallback6(() => {
9229
+ const captureResizeGestureSnapshot = useCallback7(() => {
9183
9230
  resizeGestureSnapshotRef.current = {
9184
9231
  widths: measureVisibleColumnWidths(),
9185
9232
  geometry: measureFixedTableGeometry()
9186
9233
  };
9187
9234
  }, [measureFixedTableGeometry, measureVisibleColumnWidths]);
9188
- const clearResizeGestureSnapshot = useCallback6(() => {
9235
+ const clearResizeGestureSnapshot = useCallback7(() => {
9189
9236
  resizeGestureSnapshotRef.current = null;
9190
9237
  }, []);
9191
- const commitColumnWidths = useCallback6((next, captureInitialWidths = false) => {
9238
+ const commitColumnWidths = useCallback7((next, captureInitialWidths = false) => {
9192
9239
  const gestureSnapshot = captureInitialWidths ? resizeGestureSnapshotRef.current : null;
9193
9240
  resizeGestureSnapshotRef.current = null;
9194
9241
  const normalized = normalizeColumnWidthsForColumns(
@@ -10004,7 +10051,7 @@ function MatrxDataTableCore({
10004
10051
  },
10005
10052
  [columns, defaultPageSize, defaultSort, defaultViewSnapshot]
10006
10053
  );
10007
- const applySavedView = useCallback6(
10054
+ const applySavedView = useCallback7(
10008
10055
  (rawSnapshot) => {
10009
10056
  const snapshot = parseTableViewSnapshot(rawSnapshot);
10010
10057
  if (!snapshot) {