@ai-matrx/design-system 0.18.10 → 0.18.12

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/content-transfer/alchemy.svg +1 -1
  3. package/dist/content-transfer/icon.cjs +3 -1
  4. package/dist/content-transfer/icon.cjs.map +1 -1
  5. package/dist/content-transfer/icon.d.cts +3 -2
  6. package/dist/content-transfer/icon.d.ts +3 -2
  7. package/dist/content-transfer/icon.js +3 -1
  8. package/dist/content-transfer/icon.js.map +1 -1
  9. package/dist/content-transfer.cjs +312 -278
  10. package/dist/content-transfer.cjs.map +1 -1
  11. package/dist/content-transfer.css +87 -24
  12. package/dist/content-transfer.d.cts +1 -1
  13. package/dist/content-transfer.d.ts +1 -1
  14. package/dist/content-transfer.js +312 -278
  15. package/dist/content-transfer.js.map +1 -1
  16. package/dist/data-table/copy-helpers.d.cts +1 -1
  17. package/dist/data-table/copy-helpers.d.ts +1 -1
  18. package/dist/data-table/copy-types.cjs.map +1 -1
  19. package/dist/data-table/copy-types.d.cts +1 -1
  20. package/dist/data-table/copy-types.d.ts +1 -1
  21. package/dist/data-table/data-row-inspector.cjs +314 -277
  22. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  23. package/dist/data-table/data-row-inspector.js +314 -277
  24. package/dist/data-table/data-row-inspector.js.map +1 -1
  25. package/dist/data-table/data-row-window.cjs +314 -277
  26. package/dist/data-table/data-row-window.cjs.map +1 -1
  27. package/dist/data-table/data-row-window.js +314 -277
  28. package/dist/data-table/data-row-window.js.map +1 -1
  29. package/dist/data-table/filter-engine.d.cts +1 -1
  30. package/dist/data-table/filter-engine.d.ts +1 -1
  31. package/dist/data-table/host.cjs.map +1 -1
  32. package/dist/data-table/host.d.cts +16 -2
  33. package/dist/data-table/host.d.ts +16 -2
  34. package/dist/data-table/host.js.map +1 -1
  35. package/dist/data-table/index.cjs +452 -399
  36. package/dist/data-table/index.cjs.map +1 -1
  37. package/dist/data-table/index.d.cts +3 -3
  38. package/dist/data-table/index.d.ts +3 -3
  39. package/dist/data-table/index.js +453 -400
  40. package/dist/data-table/index.js.map +1 -1
  41. package/dist/data-table/infer-filter.d.cts +1 -1
  42. package/dist/data-table/infer-filter.d.ts +1 -1
  43. package/dist/data-table/layered-filters.d.cts +1 -1
  44. package/dist/data-table/layered-filters.d.ts +1 -1
  45. package/dist/data-table/pagination.cjs.map +1 -1
  46. package/dist/data-table/pagination.js.map +1 -1
  47. package/dist/data-table/query-control.d.cts +1 -1
  48. package/dist/data-table/query-control.d.ts +1 -1
  49. package/dist/data-table/types.cjs.map +1 -1
  50. package/dist/data-table/types.d.cts +1 -1
  51. package/dist/data-table/types.d.ts +1 -1
  52. package/dist/data-table/url-state.d.cts +1 -1
  53. package/dist/data-table/url-state.d.ts +1 -1
  54. package/dist/data-table/uuid-cell.cjs.map +1 -1
  55. package/dist/data-table/uuid-cell.js.map +1 -1
  56. package/dist/data-table/xlsx.d.cts +1 -1
  57. package/dist/data-table/xlsx.d.ts +1 -1
  58. package/dist/index.cjs.map +1 -1
  59. package/dist/index.js.map +1 -1
  60. package/dist/{types-C2xN6W_q.d.ts → types-BuDKVpeF.d.ts} +2 -1
  61. package/dist/{types-D_tpuk6m.d.cts → types-Dqcb7jXO.d.cts} +2 -1
  62. package/package.json +2 -2
@@ -54,9 +54,31 @@ var GripVertical = (p) => /* @__PURE__ */ jsxs(Icon, { ...p, children: [
54
54
  /* @__PURE__ */ jsx("circle", { cx: "9", cy: "18", r: "1" }),
55
55
  /* @__PURE__ */ jsx("circle", { cx: "15", cy: "18", r: "1" })
56
56
  ] });
57
- var SlidersHorizontal = (p) => /* @__PURE__ */ jsx(Icon, { ...p, children: /* @__PURE__ */ jsx("path", { d: "M4 7h16M4 17h16M9 7v0M15 17v0" }) });
57
+ var SlidersHorizontal = (p) => /* @__PURE__ */ jsx(Icon, { ...p, children: /* @__PURE__ */ jsx("path", { d: "M21 4h-7M10 4H3M21 12h-9M8 12H3M21 20h-5M12 20H3M14 2v4M8 10v4M16 18v4" }) });
58
58
  var Trash2 = (p) => /* @__PURE__ */ jsx(Icon, { ...p, children: /* @__PURE__ */ jsx("path", { d: "M4 7h16M10 11v6M14 11v6M9 7l1-2h4l1 2M6 7l1 13h10l1-13" }) });
59
59
  var Loader2 = (p) => /* @__PURE__ */ jsx(Icon, { ...p, children: /* @__PURE__ */ jsx("path", { d: "M20 12a8 8 0 1 1-2.3-5.7" }) });
60
+ var RefreshCw = (p) => /* @__PURE__ */ jsxs(Icon, { ...p, children: [
61
+ /* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }),
62
+ /* @__PURE__ */ jsx("path", { d: "M21 3v5h-5" }),
63
+ /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }),
64
+ /* @__PURE__ */ jsx("path", { d: "M8 16H3v5" })
65
+ ] });
66
+ function RefreshControlIcon({
67
+ spinning = false,
68
+ className,
69
+ ...props
70
+ }) {
71
+ if (spinning) {
72
+ return /* @__PURE__ */ jsx(
73
+ Loader2,
74
+ {
75
+ className: [className, "animate-spin"].filter(Boolean).join(" "),
76
+ ...props
77
+ }
78
+ );
79
+ }
80
+ return /* @__PURE__ */ jsx(RefreshCw, { className, ...props });
81
+ }
60
82
  var Save = (p) => /* @__PURE__ */ jsx(Icon, { ...p, children: /* @__PURE__ */ jsx("path", { d: "M5 3h12l2 2v16H5zM8 3v6h8V3M8 21v-7h8v7" }) });
61
83
  var Pencil = (p) => /* @__PURE__ */ jsx(Icon, { ...p, children: /* @__PURE__ */ jsx("path", { d: "m4 20 4-1 11-11-3-3L5 16l-1 4z" }) });
62
84
  var Eye = (p) => /* @__PURE__ */ jsxs(Icon, { ...p, children: [
@@ -1939,14 +1961,14 @@ var PopoverContent = React12.forwardRef(
1939
1961
  );
1940
1962
  PopoverContent.displayName = PopoverPrimitive.Content.displayName;
1941
1963
 
1964
+ // src/content-transfer/icon.ts
1965
+ var ALCHEMY_GLYPH_PATHS = ["M9 3h6", "M10 3v6l-5.2 8.7A2 2 0 0 0 6.5 21h11a2 2 0 0 0 1.7-3.3L14 9V3", "M8 15h8"];
1966
+ var ALCHEMY_GLYPH_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">${ALCHEMY_GLYPH_PATHS.map((d) => `<path d="${d}"/>`).join("")}</svg>`;
1967
+
1942
1968
  // src/content-transfer/index.tsx
1943
1969
  import { Fragment as Fragment2, jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
1944
1970
  function AlchemyGlyph(props) {
1945
- return /* @__PURE__ */ jsxs13("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", ...props, children: [
1946
- /* @__PURE__ */ jsx21("path", { d: "M4.5 5.5h8v11h-8z" }),
1947
- /* @__PURE__ */ jsx21("path", { d: "M8.5 9.5h8v9h-8z" }),
1948
- /* @__PURE__ */ jsx21("path", { d: "m18.5 3 .65 1.85L21 5.5l-1.85.65L18.5 8l-.65-1.85L16 5.5l1.85-.65z" })
1949
- ] });
1971
+ return /* @__PURE__ */ jsx21("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", ...props, children: ALCHEMY_GLYPH_PATHS.map((d) => /* @__PURE__ */ jsx21("path", { d }, d)) });
1950
1972
  }
1951
1973
  var CapabilityContext = React13.createContext({});
1952
1974
  var useContentTransferCapabilities = () => React13.useContext(CapabilityContext);
@@ -1960,7 +1982,16 @@ function MenuPresentation({ label, hint, icon: Icon3 }) {
1960
1982
  ] })
1961
1983
  ] });
1962
1984
  }
1963
- function PaletteGlyph({ format, ai = false, file = false }) {
1985
+ function PaletteGlyph({ format, ai = false, file = false, kind }) {
1986
+ if (kind === "ai-copy") return /* @__PURE__ */ jsxs13("svg", { className: "matrx-alchemy-palette-glyph", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
1987
+ /* @__PURE__ */ jsx21("rect", { x: "5", y: "5", width: "11", height: "14", rx: "2" }),
1988
+ /* @__PURE__ */ jsx21("path", { d: "M9 3h6a2 2 0 0 1 2 2v10" }),
1989
+ /* @__PURE__ */ jsx21("path", { d: "m18.5 3 .55 1.45L20.5 5l-1.45.55L18.5 7l-.55-1.45L16.5 5l1.45-.55z" })
1990
+ ] });
1991
+ if (kind === "sliders") return /* @__PURE__ */ jsxs13("svg", { className: "matrx-alchemy-palette-glyph", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
1992
+ /* @__PURE__ */ jsx21("path", { d: "M4 6h16M4 12h16M4 18h16" }),
1993
+ /* @__PURE__ */ jsx21("path", { d: "M8 3v6M16 9v6M10 15v6" })
1994
+ ] });
1964
1995
  if (ai) return /* @__PURE__ */ jsxs13("svg", { className: "matrx-alchemy-palette-glyph", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
1965
1996
  /* @__PURE__ */ jsx21("path", { d: "M12 5a3 3 0 1 0-5.997.125A4 4 0 0 0 3.5 10.9a4 4 0 0 0 .556 6.588A4 4 0 0 0 12 19" }),
1966
1997
  /* @__PURE__ */ jsx21("path", { d: "M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.503 5.775 4 4 0 0 1-.556 6.588A4 4 0 0 1 12 19" }),
@@ -1993,15 +2024,15 @@ function PaletteGlyph({ format, ai = false, file = false }) {
1993
2024
  ] }) : format === "html" ? /* @__PURE__ */ jsx21(Fragment2, { children: /* @__PURE__ */ jsx21("path", { d: "M15 6h6M3 6h7M3 12h18M3 18h12" }) }) : /* @__PURE__ */ jsx21(Fragment2, { children: /* @__PURE__ */ jsx21("path", { d: "M4 7V4h16v3M9 20h6M12 4v16" }) });
1994
2025
  return /* @__PURE__ */ jsx21("svg", { className: "matrx-alchemy-palette-glyph", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: path2 });
1995
2026
  }
1996
- function PaletteRows({ title, items, onRun, extra, ai = false }) {
2027
+ function PaletteRows({ title, items, onRun, extra, ai = false, glyphKind, fallbackHint }) {
1997
2028
  if (!items.length && !extra) return null;
1998
2029
  return /* @__PURE__ */ jsxs13("section", { className: "matrx-alchemy-palette-section", children: [
1999
2030
  /* @__PURE__ */ jsx21("h3", { children: title }),
2000
2031
  items.map((item) => /* @__PURE__ */ jsxs13("button", { type: "button", className: cn("matrx-alchemy-palette-row", ai && "matrx-alchemy-palette-row-ai"), "aria-label": item.ariaLabel, onClick: () => onRun?.(item), children: [
2001
- item.icon ? /* @__PURE__ */ jsx21(item.icon, { className: "matrx-alchemy-menu-icon" }) : /* @__PURE__ */ jsx21(PaletteGlyph, { ai }),
2032
+ item.icon ? /* @__PURE__ */ jsx21(item.icon, { className: "matrx-alchemy-menu-icon" }) : /* @__PURE__ */ jsx21(PaletteGlyph, { ai, ...glyphKind ? { kind: glyphKind } : {} }),
2002
2033
  /* @__PURE__ */ jsxs13("span", { children: [
2003
2034
  item.copyLabel ?? item.label,
2004
- item.hint ? /* @__PURE__ */ jsx21("small", { className: "matrx-alchemy-menu-hint", children: item.hint }) : null
2035
+ item.hint ?? fallbackHint ? /* @__PURE__ */ jsx21("small", { className: "matrx-alchemy-menu-hint", children: item.hint ?? fallbackHint }) : null
2005
2036
  ] })
2006
2037
  ] }, item.id)),
2007
2038
  extra
@@ -2398,45 +2429,54 @@ function ContentTransferMenuSession({ source, surface, label, projection, sectio
2398
2429
  }, children: [
2399
2430
  /* @__PURE__ */ jsx21(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx21("button", { ref: triggerRef, type: "button", className: "matrx-alchemy-trigger", disabled, "aria-label": `Copy, transform or export ${sourceLabel}`, title: "Alchemy \u2014 copy, transform, export", children: /* @__PURE__ */ jsx21(AlchemyGlyph, {}) }) }),
2400
2431
  /* @__PURE__ */ jsxs13(PopoverContent, { align: "end", className: "matrx-alchemy-menu matrx-alchemy-palette", "aria-label": "Alchemy output options", onCloseAutoFocus: () => triggerRef.current?.focus(), children: [
2401
- copyAvailable && downloadAvailable ? /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-mode", "aria-label": "Output action", children: [
2402
- /* @__PURE__ */ jsx21("button", { type: "button", "aria-label": "Copy mode", "aria-pressed": resolvedMode === "copy", onClick: () => setMode("copy"), children: "Copy" }),
2403
- /* @__PURE__ */ jsx21("button", { type: "button", "aria-label": "Download mode", "aria-pressed": resolvedMode === "download", onClick: () => setMode("download"), children: "Download" })
2404
- ] }) : null,
2405
2432
  menuStatus === "loading" ? /* @__PURE__ */ jsx21("p", { className: "matrx-alchemy-palette-status", children: "Inspecting content\u2026" }) : menuStatus !== "idle" ? /* @__PURE__ */ jsx21("p", { className: "matrx-alchemy-error", children: menuStatus }) : null,
2406
- resolvedMode === "copy" && copyAvailable ? /* @__PURE__ */ jsxs13(Fragment2, { children: [
2407
- /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-palette-grid", children: [
2408
- 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]}` })),
2409
- visibleAdapters.map((adapter) => tile(adapter.id, adapter.label, () => void transfer(adapter, false), { custom: true }))
2410
- ] }),
2411
- quickVariants("copy").length ? /* @__PURE__ */ jsx21(PaletteRows, { title: "Quick copy", items: quickVariants("copy"), onRun: (variant) => {
2433
+ copyAvailable || downloadAvailable ? /* @__PURE__ */ jsxs13("section", { className: "matrx-alchemy-output", children: [
2434
+ /* @__PURE__ */ jsx21("h3", { children: resolvedMode === "copy" ? "Copy as" : "Download as" }),
2435
+ copyAvailable && downloadAvailable ? /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-mode", "aria-label": "Output action", children: [
2436
+ /* @__PURE__ */ jsx21("button", { type: "button", "aria-label": "Copy mode", "aria-pressed": resolvedMode === "copy", onClick: () => setMode("copy"), children: "Copy" }),
2437
+ /* @__PURE__ */ jsx21("button", { type: "button", "aria-label": "Download mode", "aria-pressed": resolvedMode === "download", onClick: () => setMode("download"), children: "Download" })
2438
+ ] }) : null,
2439
+ resolvedMode === "copy" && copyAvailable ? /* @__PURE__ */ jsxs13(Fragment2, { children: [
2440
+ /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-palette-grid", children: [
2441
+ 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]}` })),
2442
+ visibleAdapters.map((adapter) => tile(adapter.id, adapter.label, () => void transfer(adapter, false), { custom: true }))
2443
+ ] }),
2444
+ quickVariants("copy").length ? /* @__PURE__ */ jsx21(PaletteRows, { title: "Quick copy", items: quickVariants("copy"), onRun: (variant) => {
2445
+ closePalette();
2446
+ void transfer("markdown", false, variant);
2447
+ } }) : null
2448
+ ] }) : null,
2449
+ resolvedMode === "download" && downloadAvailable ? /* @__PURE__ */ jsx21(Fragment2, { children: /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-palette-grid", children: [
2450
+ 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]}` })),
2451
+ visibleAdapters.map((adapter) => tile(adapter.id, adapter.label, () => void transfer(adapter, true), { custom: true })),
2452
+ downloadActions.map((action) => tile(action.id, action.label, () => void runAction(action), { custom: true, action, file: true }))
2453
+ ] }) }) : null
2454
+ ] }) : null,
2455
+ prepareAvailable ? /* @__PURE__ */ jsxs13(Fragment2, { children: [
2456
+ /* @__PURE__ */ jsx21(PaletteRows, { title: "Copy for AI", ai: true, glyphKind: "ai-copy", fallbackHint: "Copies immediately", items: quickVariants("ai"), onRun: (variant) => {
2412
2457
  closePalette();
2413
2458
  void transfer("markdown", false, variant);
2414
- } }) : null
2459
+ } }),
2460
+ /* @__PURE__ */ jsx21(PaletteRows, { title: "Edit and prepare", items: [], extra: /* @__PURE__ */ jsxs13("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": "Prepare for AI", onClick: () => {
2461
+ closePalette();
2462
+ void openWorkspace();
2463
+ }, children: [
2464
+ /* @__PURE__ */ jsx21(PaletteGlyph, { kind: "sliders" }),
2465
+ /* @__PURE__ */ jsxs13("span", { children: [
2466
+ "Prepare for AI",
2467
+ /* @__PURE__ */ jsx21("small", { className: "matrx-alchemy-menu-hint", children: "Review and edit before copying" })
2468
+ ] })
2469
+ ] }) })
2415
2470
  ] }) : null,
2416
- resolvedMode === "download" && downloadAvailable ? /* @__PURE__ */ jsx21(Fragment2, { children: /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-palette-grid", children: [
2417
- 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]}` })),
2418
- visibleAdapters.map((adapter) => tile(adapter.id, adapter.label, () => void transfer(adapter, true), { custom: true })),
2419
- downloadActions.map((action) => tile(action.id, action.label, () => void runAction(action), { custom: true, action, file: true }))
2420
- ] }) }) : null,
2421
- prepareAvailable ? /* @__PURE__ */ jsx21(PaletteRows, { title: "Prepare", ai: true, items: quickVariants("ai"), onRun: (variant) => {
2422
- closePalette();
2423
- void transfer("markdown", false, variant);
2424
- }, extra: /* @__PURE__ */ jsxs13("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => {
2425
- closePalette();
2426
- void openWorkspace();
2427
- }, children: [
2428
- /* @__PURE__ */ jsx21(PaletteGlyph, { ai: true }),
2429
- /* @__PURE__ */ jsx21("span", { children: "Prepare for AI\u2026" })
2430
- ] }) }) : null,
2431
- prepareAvailable && (nearestWorkspaceKey || variants.length) ? /* @__PURE__ */ jsx21(PaletteRows, { title: "Context", items: [], extra: /* @__PURE__ */ jsxs13(Fragment2, { children: [
2471
+ prepareAvailable && (nearestWorkspaceKey || variants.length) ? /* @__PURE__ */ jsx21(PaletteRows, { title: "Other sources", items: [], extra: /* @__PURE__ */ jsxs13(Fragment2, { children: [
2432
2472
  nearestWorkspaceKey && nearestSurface ? /* @__PURE__ */ jsx21("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => {
2433
2473
  closePalette();
2434
2474
  void openWorkspace(nearestWorkspaceKey, { source: nearestSurface, label: nearestSurface.surfaceName });
2435
- }, children: /* @__PURE__ */ jsx21("span", { children: "Prepare this surface\u2026" }) }) : null,
2475
+ }, children: /* @__PURE__ */ jsx21("span", { children: "Prepare this surface" }) }) : null,
2436
2476
  variants.map((variant) => /* @__PURE__ */ jsx21("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": variant.ariaLabel, onClick: () => {
2437
2477
  closePalette();
2438
2478
  void openWorkspace(variantWorkspaceKeys.get(variant.id), variant);
2439
- }, children: /* @__PURE__ */ jsx21(MenuPresentation, { ...variant, label: `Prepare ${variant.label}\u2026` }) }, variant.id))
2479
+ }, children: /* @__PURE__ */ jsx21(MenuPresentation, { ...variant, label: `Prepare ${variant.label}` }) }, variant.id))
2440
2480
  ] }) }) : null,
2441
2481
  ordinaryActions.length ? /* @__PURE__ */ jsx21(PaletteRows, { title: "Actions", items: [], extra: ordinaryActions.map((action) => /* @__PURE__ */ jsx21("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": action.ariaLabel, onClick: () => {
2442
2482
  closePalette();
@@ -2714,137 +2754,138 @@ function PreparationWorkspace({ restoreFocus, open, state, scopes, onClose, onCh
2714
2754
  state.snapshot.label
2715
2755
  ] }),
2716
2756
  /* @__PURE__ */ jsxs13(DialogDescription, { children: [
2717
- "Captured ",
2718
- state.snapshot.unsavedChanges ? "from your unsaved draft" : "as an immutable snapshot",
2719
- ". Your source is never edited."
2757
+ state.snapshot.unsavedChanges ? "Includes your unsaved changes. " : "",
2758
+ "Review and edit this copy. Your original stays unchanged."
2720
2759
  ] })
2721
2760
  ] }),
2722
- /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-workspace-grid", children: [
2723
- /* @__PURE__ */ jsxs13("section", { className: "matrx-alchemy-main", children: [
2724
- /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-toolbar", children: [
2725
- scopes.length > 1 ? /* @__PURE__ */ jsxs13("label", { children: [
2726
- "Scope",
2727
- /* @__PURE__ */ jsx21("select", { "aria-label": "Transfer scope", value: state.scope, disabled: busy !== null, onChange: (e) => void requestCapture(e.target.value), children: scopes.map((scope) => /* @__PURE__ */ jsx21("option", { value: scope, children: SCOPE_LABEL[scope] }, scope)) })
2728
- ] }) : null,
2729
- /* @__PURE__ */ jsxs13("label", { children: [
2730
- "Detail",
2731
- /* @__PURE__ */ jsxs13("select", { "aria-label": "Detail preset", value: controls.preset, onChange: (e) => changeControls({ ...controls, preset: e.target.value }), children: [
2732
- /* @__PURE__ */ jsx21("option", { value: "full", children: "Full" }),
2733
- /* @__PURE__ */ jsx21("option", { value: "compact", children: "Compact" }),
2734
- /* @__PURE__ */ jsx21("option", { value: "brief", children: "Brief" }),
2735
- /* @__PURE__ */ jsx21("option", { value: "custom", children: "Custom" })
2736
- ] })
2737
- ] }),
2738
- /* @__PURE__ */ jsx21(Button, { type: "button", size: "sm", variant: "outline", disabled: !state.draft.history?.length && !controlsHistory.length || busy !== null, onClick: () => {
2739
- setBufferError(null);
2740
- if (controlsHistory.length) {
2741
- const next = controlsHistory[controlsHistory.length - 1];
2761
+ /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-workspace-body", children: [
2762
+ /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-workspace-grid", children: [
2763
+ /* @__PURE__ */ jsxs13("section", { className: "matrx-alchemy-main", children: [
2764
+ /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-toolbar", children: [
2765
+ scopes.length > 1 ? /* @__PURE__ */ jsxs13("label", { children: [
2766
+ "Scope",
2767
+ /* @__PURE__ */ jsx21("select", { "aria-label": "Transfer scope", value: state.scope, disabled: busy !== null, onChange: (e) => void requestCapture(e.target.value), children: scopes.map((scope) => /* @__PURE__ */ jsx21("option", { value: scope, children: SCOPE_LABEL[scope] }, scope)) })
2768
+ ] }) : null,
2769
+ /* @__PURE__ */ jsxs13("label", { children: [
2770
+ "Detail",
2771
+ /* @__PURE__ */ jsxs13("select", { "aria-label": "Detail preset", value: controls.preset, onChange: (e) => changeControls({ ...controls, preset: e.target.value }), children: [
2772
+ /* @__PURE__ */ jsx21("option", { value: "full", children: "Full" }),
2773
+ /* @__PURE__ */ jsx21("option", { value: "compact", children: "Compact" }),
2774
+ /* @__PURE__ */ jsx21("option", { value: "brief", children: "Brief" }),
2775
+ /* @__PURE__ */ jsx21("option", { value: "custom", children: "Custom" })
2776
+ ] })
2777
+ ] }),
2778
+ /* @__PURE__ */ jsx21(Button, { type: "button", size: "sm", variant: "outline", className: "matrx-alchemy-workspace-secondary", disabled: !state.draft.history?.length && !controlsHistory.length || busy !== null, onClick: () => {
2779
+ setBufferError(null);
2780
+ if (controlsHistory.length) {
2781
+ const next = controlsHistory[controlsHistory.length - 1];
2782
+ setControls(next);
2783
+ setControlsHistory((history) => history.slice(0, -1));
2784
+ onChange({ ...state, draft: rebuild(state, next), error: void 0 });
2785
+ } else onChange({ ...state, draft: undoDraft(state.draft), error: void 0 });
2786
+ }, children: "Undo" }),
2787
+ /* @__PURE__ */ jsx21(Button, { type: "button", size: "sm", variant: "outline", className: "matrx-alchemy-workspace-secondary", disabled: busy !== null, onClick: () => {
2788
+ const next = initialControls(state);
2742
2789
  setControls(next);
2743
- setControlsHistory((history) => history.slice(0, -1));
2790
+ setControlsHistory([]);
2791
+ setPendingControls(null);
2792
+ setBufferError(null);
2744
2793
  onChange({ ...state, draft: rebuild(state, next), error: void 0 });
2745
- } else onChange({ ...state, draft: undoDraft(state.draft), error: void 0 });
2746
- }, children: "Undo" }),
2747
- /* @__PURE__ */ jsx21(Button, { type: "button", size: "sm", variant: "outline", disabled: busy !== null, onClick: () => {
2748
- const next = initialControls(state);
2749
- setControls(next);
2750
- setControlsHistory([]);
2751
- setPendingControls(null);
2752
- setBufferError(null);
2753
- onChange({ ...state, draft: rebuild(state, next), error: void 0 });
2754
- }, children: "Reset" }),
2755
- /* @__PURE__ */ jsx21(Button, { type: "button", size: "sm", variant: "outline", disabled: busy !== null, onClick: () => void requestCapture(state.scope), children: "Refresh source" })
2756
- ] }),
2757
- controls.preset === "custom" && (state.draft.payload.kind === "json" || state.draft.payload.kind === "registered") ? /* @__PURE__ */ jsxs13("fieldset", { className: "matrx-alchemy-options", children: [
2758
- /* @__PURE__ */ jsx21("legend", { children: "JSON limits" }),
2759
- [["maxDepth", "Maximum depth"], ["maxStringChars", "Maximum string characters"], ["maxArrayItems", "Maximum array items"]].map(([key, text]) => /* @__PURE__ */ jsxs13("label", { children: [
2760
- text,
2761
- /* @__PURE__ */ jsx21("input", { type: "number", min: "0", value: controls[key] ?? "", onChange: (e) => changeControls({ ...controls, [key]: Number.isNaN(e.target.valueAsNumber) ? null : e.target.valueAsNumber }) })
2762
- ] }, key))
2763
- ] }) : null,
2764
- rows ? /* @__PURE__ */ jsx21(RowControls, { rows, controls, change: changeControls }) : null,
2765
- state.snapshot.sections.length ? /* @__PURE__ */ jsxs13("fieldset", { className: "matrx-alchemy-options", children: [
2766
- /* @__PURE__ */ jsx21("legend", { children: "Sections" }),
2767
- state.snapshot.sections.map((section) => /* @__PURE__ */ jsxs13("label", { children: [
2768
- /* @__PURE__ */ jsx21("input", { type: "checkbox", checked: controls.sections.includes(section.id), onChange: (e) => changeControls({ ...controls, sections: e.target.checked ? [...controls.sections, section.id] : controls.sections.filter((id) => id !== section.id) }) }),
2769
- " ",
2770
- section.label
2771
- ] }, section.id))
2772
- ] }) : null,
2773
- /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-coverage", children: [
2774
- /* @__PURE__ */ jsxs13("span", { children: [
2775
- state.snapshot.coverage.included.toLocaleString(),
2776
- " included",
2777
- state.snapshot.coverage.total == null ? "" : ` of ${state.snapshot.coverage.total.toLocaleString()}`,
2778
- " \xB7 ",
2779
- state.snapshot.coverage.status
2794
+ }, children: "Reset" }),
2795
+ /* @__PURE__ */ jsx21(Button, { type: "button", size: "sm", variant: "outline", className: "matrx-alchemy-workspace-secondary", disabled: busy !== null, onClick: () => void requestCapture(state.scope), children: "Refresh source" })
2780
2796
  ] }),
2781
- state.snapshot.coverage.reason ? /* @__PURE__ */ jsx21("span", { children: state.snapshot.coverage.reason }) : null,
2782
- limitText ? /* @__PURE__ */ jsxs13("span", { children: [
2783
- "Limits: ",
2784
- limitText
2797
+ controls.preset === "custom" && (state.draft.payload.kind === "json" || state.draft.payload.kind === "registered") ? /* @__PURE__ */ jsxs13("fieldset", { className: "matrx-alchemy-options", children: [
2798
+ /* @__PURE__ */ jsx21("legend", { children: "JSON limits" }),
2799
+ [["maxDepth", "Maximum depth"], ["maxStringChars", "Maximum string characters"], ["maxArrayItems", "Maximum array items"]].map(([key, text]) => /* @__PURE__ */ jsxs13("label", { children: [
2800
+ text,
2801
+ /* @__PURE__ */ jsx21("input", { type: "number", min: "0", value: controls[key] ?? "", onChange: (e) => changeControls({ ...controls, [key]: Number.isNaN(e.target.valueAsNumber) ? null : e.target.valueAsNumber }) })
2802
+ ] }, key))
2803
+ ] }) : null,
2804
+ rows ? /* @__PURE__ */ jsx21(RowControls, { rows, controls, change: changeControls }) : null,
2805
+ state.snapshot.sections.length ? /* @__PURE__ */ jsxs13("fieldset", { className: "matrx-alchemy-options", children: [
2806
+ /* @__PURE__ */ jsx21("legend", { children: "Sections" }),
2807
+ state.snapshot.sections.map((section) => /* @__PURE__ */ jsxs13("label", { children: [
2808
+ /* @__PURE__ */ jsx21("input", { type: "checkbox", checked: controls.sections.includes(section.id), onChange: (e) => changeControls({ ...controls, sections: e.target.checked ? [...controls.sections, section.id] : controls.sections.filter((id) => id !== section.id) }) }),
2809
+ " ",
2810
+ section.label
2811
+ ] }, section.id))
2785
2812
  ] }) : null,
2786
- displayedOmissions.length ? /* @__PURE__ */ jsxs13("details", { children: [
2787
- /* @__PURE__ */ jsxs13("summary", { children: [
2788
- displayedOmissions.length,
2789
- " omissions or adjustments"
2813
+ /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-coverage", children: [
2814
+ /* @__PURE__ */ jsxs13("span", { children: [
2815
+ state.snapshot.coverage.included.toLocaleString(),
2816
+ " included",
2817
+ state.snapshot.coverage.total == null ? "" : ` of ${state.snapshot.coverage.total.toLocaleString()}`,
2818
+ " \xB7 ",
2819
+ state.snapshot.coverage.status
2790
2820
  ] }),
2791
- /* @__PURE__ */ jsx21("ul", { children: displayedOmissions.map((o, i) => /* @__PURE__ */ jsxs13("li", { children: [
2792
- o.path || "/",
2793
- ": ",
2794
- o.reason,
2795
- o.count == null ? "" : ` (${o.count})`
2796
- ] }, `${o.path}-${o.reason}-${i}`)) })
2797
- ] }) : null
2798
- ] }),
2799
- /* @__PURE__ */ jsxs13("label", { className: "matrx-alchemy-preview-label", children: [
2800
- "Output format",
2801
- /* @__PURE__ */ jsxs13("select", { "aria-label": "Output format", value: format, onChange: (e) => setFormat(e.target.value), children: [
2802
- formats.map((f) => /* @__PURE__ */ jsx21("option", { value: f, children: LABEL[f] }, f)),
2803
- state.draft.payload.kind === "rows" ? /* @__PURE__ */ jsx21("option", { value: "xlsx", children: "Excel workbook" }) : null,
2804
- workspaceAdapters.map((adapter) => /* @__PURE__ */ jsx21("option", { value: adapter.id, children: adapter.label }, adapter.id))
2805
- ] })
2821
+ state.snapshot.coverage.reason ? /* @__PURE__ */ jsx21("span", { children: state.snapshot.coverage.reason }) : null,
2822
+ limitText ? /* @__PURE__ */ jsxs13("span", { children: [
2823
+ "Limits: ",
2824
+ limitText
2825
+ ] }) : null,
2826
+ displayedOmissions.length ? /* @__PURE__ */ jsxs13("details", { children: [
2827
+ /* @__PURE__ */ jsxs13("summary", { children: [
2828
+ displayedOmissions.length,
2829
+ " omissions or adjustments"
2830
+ ] }),
2831
+ /* @__PURE__ */ jsx21("ul", { children: displayedOmissions.map((o, i) => /* @__PURE__ */ jsxs13("li", { children: [
2832
+ o.path || "/",
2833
+ ": ",
2834
+ o.reason,
2835
+ o.count == null ? "" : ` (${o.count})`
2836
+ ] }, `${o.path}-${o.reason}-${i}`)) })
2837
+ ] }) : null
2838
+ ] }),
2839
+ /* @__PURE__ */ jsxs13("label", { className: "matrx-alchemy-preview-label", children: [
2840
+ "Output format",
2841
+ /* @__PURE__ */ jsxs13("select", { "aria-label": "Output format", value: format, onChange: (e) => setFormat(e.target.value), children: [
2842
+ formats.map((f) => /* @__PURE__ */ jsx21("option", { value: f, children: LABEL[f] }, f)),
2843
+ state.draft.payload.kind === "rows" ? /* @__PURE__ */ jsx21("option", { value: "xlsx", children: "Excel workbook" }) : null,
2844
+ workspaceAdapters.map((adapter) => /* @__PURE__ */ jsx21("option", { value: adapter.id, children: adapter.label }, adapter.id))
2845
+ ] })
2846
+ ] }),
2847
+ /* @__PURE__ */ jsx21("textarea", { className: "matrx-alchemy-preview", "aria-label": "Prepared output", "aria-invalid": bufferError ? true : void 0, "aria-describedby": bufferError ? "alchemy-buffer-error" : void 0, value: buffer, onChange: (e) => editBuffer(e.target.value) }),
2848
+ bufferError ? /* @__PURE__ */ jsx21("p", { id: "alchemy-buffer-error", role: "alert", className: "matrx-alchemy-error", children: bufferError }) : null,
2849
+ formatError ? /* @__PURE__ */ jsx21("p", { role: "alert", className: "matrx-alchemy-error", children: formatError }) : null,
2850
+ bufferError ? /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", disabled: busy !== null, onClick: () => {
2851
+ const fallback = editDraft(state.draft, { kind: "text", text: buffer });
2852
+ setBufferError(null);
2853
+ onChange({ ...state, draft: fallback, error: void 0 });
2854
+ setFormat("plain");
2855
+ }, children: "Use invalid JSON as plain text" }) : null
2806
2856
  ] }),
2807
- /* @__PURE__ */ jsx21("textarea", { className: "matrx-alchemy-preview", "aria-label": "Prepared output", "aria-invalid": bufferError ? true : void 0, "aria-describedby": bufferError ? "alchemy-buffer-error" : void 0, value: buffer, onChange: (e) => editBuffer(e.target.value) }),
2808
- bufferError ? /* @__PURE__ */ jsx21("p", { id: "alchemy-buffer-error", role: "alert", className: "matrx-alchemy-error", children: bufferError }) : null,
2809
- formatError ? /* @__PURE__ */ jsx21("p", { role: "alert", className: "matrx-alchemy-error", children: formatError }) : null,
2810
- bufferError ? /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", disabled: busy !== null, onClick: () => {
2811
- const fallback = editDraft(state.draft, { kind: "text", text: buffer });
2812
- setBufferError(null);
2813
- onChange({ ...state, draft: fallback, error: void 0 });
2814
- setFormat("plain");
2815
- }, children: "Use invalid JSON as plain text" }) : null
2857
+ ai || busy === "capture" || state.error ? /* @__PURE__ */ jsxs13("aside", { children: [
2858
+ ai ? /* @__PURE__ */ jsxs13(Fragment2, { children: [
2859
+ /* @__PURE__ */ jsxs13("label", { children: [
2860
+ "AI instruction",
2861
+ /* @__PURE__ */ jsx21("textarea", { value: instruction, onChange: (e) => setInstruction(e.target.value), placeholder: "Tell AI how to prepare this content" })
2862
+ ] }),
2863
+ /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", disabled: !aiSession.current || !instruction.trim() || busy !== null || !aiSession.current.supports(state.snapshot), onClick: () => void runAi(false), children: "Generate preview" }),
2864
+ busy === "ai" ? /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => void cancelAi(), children: aiSession.current?.cancel ? "Cancel AI" : "Stop waiting" }) : null
2865
+ ] }) : null,
2866
+ busy === "capture" ? /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => {
2867
+ activeCapture.current?.abort();
2868
+ activeCapture.current = null;
2869
+ setBusy(null);
2870
+ }, children: "Stop loading rows" }) : null,
2871
+ ai && aiFailed && aiSession.current?.recover && busy !== "ai" ? /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => void runAi(true), children: aiFailed ? "Retry or rejoin AI run" : "Rejoin AI run" }) : null,
2872
+ ai ? /* @__PURE__ */ jsx21("p", { className: "matrx-alchemy-meta", children: "AI updates the preview; copy it when you are ready. Closing this window lets the AI run continue." }) : null,
2873
+ state.error ? /* @__PURE__ */ jsx21("p", { role: "alert", className: "matrx-alchemy-error", children: state.error }) : null
2874
+ ] }) : null
2816
2875
  ] }),
2817
- ai || busy === "capture" || state.error ? /* @__PURE__ */ jsxs13("aside", { children: [
2818
- ai ? /* @__PURE__ */ jsxs13(Fragment2, { children: [
2819
- /* @__PURE__ */ jsxs13("label", { children: [
2820
- "AI instruction",
2821
- /* @__PURE__ */ jsx21("textarea", { value: instruction, onChange: (e) => setInstruction(e.target.value), placeholder: "Tell AI how to prepare this content" })
2822
- ] }),
2823
- /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", disabled: !aiSession.current || !instruction.trim() || busy !== null || !aiSession.current.supports(state.snapshot), onClick: () => void runAi(false), children: "Generate preview" }),
2824
- busy === "ai" ? /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", onClick: () => void cancelAi(), children: aiSession.current?.cancel ? "Cancel AI" : "Stop waiting" }) : null
2825
- ] }) : null,
2826
- busy === "capture" ? /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", onClick: () => {
2827
- activeCapture.current?.abort();
2828
- activeCapture.current = null;
2829
- setBusy(null);
2830
- }, children: "Stop loading rows" }) : null,
2831
- ai && aiFailed && aiSession.current?.recover && busy !== "ai" ? /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", onClick: () => void runAi(true), children: aiFailed ? "Retry or rejoin AI run" : "Rejoin AI run" }) : null,
2832
- ai ? /* @__PURE__ */ jsx21("p", { className: "matrx-alchemy-meta", children: "AI creates a preview. It never copies automatically. Closing detaches this view without cancelling server work." }) : null,
2833
- state.error ? /* @__PURE__ */ jsx21("p", { role: "alert", className: "matrx-alchemy-error", children: state.error }) : null
2834
- ] }) : null
2876
+ pendingControls ? /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-decision", role: "alert", children: [
2877
+ /* @__PURE__ */ jsx21("p", { children: "This control would replace your manual edit." }),
2878
+ /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => setPendingControls(null), children: "Keep edited draft" }),
2879
+ /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-primary", type: "button", onClick: applyPendingControls, children: "Rebuild from source" })
2880
+ ] }) : null,
2881
+ state.sourceStale ? /* @__PURE__ */ jsx21("p", { role: "alert", className: "matrx-alchemy-decision", children: "The source changed since this draft. Use Refresh source to review the latest data." }) : null,
2882
+ state.pending ? /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-decision", role: "alert", children: [
2883
+ /* @__PURE__ */ jsx21("p", { children: "A fresh source snapshot is ready." }),
2884
+ /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => resolveCapture("keep"), children: "Keep current snapshot and draft" }),
2885
+ /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-primary", type: "button", onClick: () => resolveCapture("regenerate"), children: "Regenerate from fresh source" })
2886
+ ] }) : null,
2887
+ deliveryNotice ? /* @__PURE__ */ jsx21("p", { role: "status", className: "matrx-alchemy-meta", children: deliveryNotice }) : null
2835
2888
  ] }),
2836
- pendingControls ? /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-decision", role: "alert", children: [
2837
- /* @__PURE__ */ jsx21("p", { children: "This control would replace your manual edit." }),
2838
- /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", onClick: () => setPendingControls(null), children: "Keep edited draft" }),
2839
- /* @__PURE__ */ jsx21(Button, { type: "button", onClick: applyPendingControls, children: "Rebuild from source" })
2840
- ] }) : null,
2841
- state.sourceStale ? /* @__PURE__ */ jsx21("p", { role: "alert", className: "matrx-alchemy-decision", children: "The source changed since this draft. Use Refresh source to review the latest data." }) : null,
2842
- state.pending ? /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-decision", role: "alert", children: [
2843
- /* @__PURE__ */ jsx21("p", { children: "A fresh source snapshot is ready." }),
2844
- /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", onClick: () => resolveCapture("keep"), children: "Keep current snapshot and draft" }),
2845
- /* @__PURE__ */ jsx21(Button, { type: "button", onClick: () => resolveCapture("regenerate"), children: "Regenerate from fresh source" })
2846
- ] }) : null,
2847
- deliveryNotice ? /* @__PURE__ */ jsx21("p", { role: "status", className: "matrx-alchemy-meta", children: deliveryNotice }) : null,
2848
2889
  /* @__PURE__ */ jsxs13(DialogFooter, { children: [
2849
2890
  /* @__PURE__ */ jsxs13("span", { className: "matrx-alchemy-meta", children: [
2850
2891
  buffer.length.toLocaleString(),
@@ -2852,13 +2893,16 @@ function PreparationWorkspace({ restoreFocus, open, state, scopes, onClose, onCh
2852
2893
  estimateTokens(buffer).toLocaleString(),
2853
2894
  " tokens"
2854
2895
  ] }),
2855
- /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", onClick: close, children: "Close" }),
2856
- /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", disabled: busy !== null || Boolean(bufferError || formatError) || !preparedArtifact, onClick: () => void deliver(true), children: "Download prepared output" }),
2857
- /* @__PURE__ */ jsx21(Button, { type: "button", disabled: busy !== null || Boolean(bufferError || formatError) || !preparedArtifact, onClick: () => void deliver(false), children: "Copy prepared output" })
2896
+ /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", className: "matrx-alchemy-workspace-secondary", onClick: close, children: "Close" }),
2897
+ /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", className: "matrx-alchemy-workspace-secondary", "aria-label": "Download prepared output", disabled: busy !== null || Boolean(bufferError || formatError) || !preparedArtifact, onClick: () => void deliver(true), children: "Download" }),
2898
+ /* @__PURE__ */ jsx21(Button, { type: "button", className: "matrx-alchemy-workspace-primary", "aria-label": "Copy prepared output", disabled: busy !== null || Boolean(bufferError || formatError) || !preparedArtifact, onClick: () => void deliver(false), children: "Copy" })
2858
2899
  ] })
2859
2900
  ] }) });
2860
2901
  }
2861
2902
  function RowControls({ rows, controls, change }) {
2903
+ const filterCount = Object.values(controls.filters).filter(Boolean).length;
2904
+ const selectionSummary = controls.selectedOnly ? `${controls.selectedIndices.length} selected row${controls.selectedIndices.length === 1 ? "" : "s"}` : "All rows";
2905
+ const dataSummary = [controls.search ? "search active" : "", controls.sort ? `sorted by ${rows.columns.find((column) => column.id === controls.sort)?.label ?? controls.sort}` : "", filterCount ? `${filterCount} filter${filterCount === 1 ? "" : "s"}` : ""].filter(Boolean).join(" \xB7 ");
2862
2906
  return /* @__PURE__ */ jsxs13(Fragment2, { children: [
2863
2907
  /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-toolbar", children: [
2864
2908
  /* @__PURE__ */ jsxs13("label", { children: [
@@ -2884,32 +2928,40 @@ function RowControls({ rows, controls, change }) {
2884
2928
  /* @__PURE__ */ jsx21("input", { type: "number", min: "0", value: controls.top ?? "", onChange: (e) => change({ ...controls, top: Number.isNaN(e.target.valueAsNumber) ? null : e.target.valueAsNumber }) })
2885
2929
  ] })
2886
2930
  ] }),
2887
- /* @__PURE__ */ jsxs13("fieldset", { className: "matrx-alchemy-options", children: [
2888
- /* @__PURE__ */ jsx21("legend", { children: "Columns and filters" }),
2889
- rows.columns.map((column) => /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-column", children: [
2931
+ /* @__PURE__ */ jsxs13("details", { className: "matrx-alchemy-options", children: [
2932
+ /* @__PURE__ */ jsxs13("summary", { children: [
2933
+ "Columns and filters",
2934
+ dataSummary ? ` \u2014 ${dataSummary}` : ""
2935
+ ] }),
2936
+ /* @__PURE__ */ jsx21("fieldset", { "aria-label": "Columns and filters", children: rows.columns.map((column) => /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-column", children: [
2890
2937
  /* @__PURE__ */ jsxs13("label", { children: [
2891
2938
  /* @__PURE__ */ jsx21("input", { type: "checkbox", checked: controls.visibleColumns.includes(column.id), onChange: (e) => change({ ...controls, visibleColumns: e.target.checked ? [...controls.visibleColumns, column.id] : controls.visibleColumns.filter((id) => id !== column.id) }) }),
2892
2939
  " ",
2893
2940
  column.label
2894
2941
  ] }),
2895
2942
  /* @__PURE__ */ jsx21("input", { "aria-label": `Filter ${column.label}`, placeholder: "Filter", value: controls.filters[column.id] ?? "", onChange: (e) => change({ ...controls, filters: { ...controls.filters, [column.id]: e.target.value } }) })
2896
- ] }, column.id))
2943
+ ] }, column.id)) })
2897
2944
  ] }),
2898
- /* @__PURE__ */ jsxs13("fieldset", { className: "matrx-alchemy-options", children: [
2899
- /* @__PURE__ */ jsx21("legend", { children: "Rows" }),
2900
- /* @__PURE__ */ jsxs13("label", { children: [
2901
- /* @__PURE__ */ jsx21("input", { type: "checkbox", checked: controls.selectedOnly, onChange: (e) => change({ ...controls, selectedOnly: e.target.checked }) }),
2902
- " Only selected rows"
2945
+ /* @__PURE__ */ jsxs13("details", { className: "matrx-alchemy-options", children: [
2946
+ /* @__PURE__ */ jsxs13("summary", { children: [
2947
+ "Rows \u2014 ",
2948
+ selectionSummary
2903
2949
  ] }),
2904
- /* @__PURE__ */ jsx21("div", { className: "matrx-alchemy-row-list", children: rows.rows.map((row, index) => {
2905
- const summary = rows.columns.filter((column) => column.visible).slice(0, 2).map((column) => String(readTransferCell(row, column) ?? "")).filter(Boolean).join(" \xB7 ");
2906
- return /* @__PURE__ */ jsxs13("label", { children: [
2907
- /* @__PURE__ */ jsx21("input", { type: "checkbox", checked: controls.selectedIndices.includes(index), onChange: (e) => change({ ...controls, selectedIndices: e.target.checked ? [...controls.selectedIndices, index] : controls.selectedIndices.filter((value) => value !== index) }) }),
2908
- " Row ",
2909
- index + 1,
2910
- summary ? ` \u2014 ${summary}` : ""
2911
- ] }, index);
2912
- }) })
2950
+ /* @__PURE__ */ jsxs13("fieldset", { "aria-label": "Row selection", children: [
2951
+ /* @__PURE__ */ jsxs13("label", { children: [
2952
+ /* @__PURE__ */ jsx21("input", { type: "checkbox", checked: controls.selectedOnly, onChange: (e) => change({ ...controls, selectedOnly: e.target.checked }) }),
2953
+ " Only selected rows"
2954
+ ] }),
2955
+ /* @__PURE__ */ jsx21("div", { className: "matrx-alchemy-row-list", children: rows.rows.map((row, index) => {
2956
+ const summary = rows.columns.filter((column) => column.visible).slice(0, 2).map((column) => String(readTransferCell(row, column) ?? "")).filter(Boolean).join(" \xB7 ");
2957
+ return /* @__PURE__ */ jsxs13("label", { children: [
2958
+ /* @__PURE__ */ jsx21("input", { type: "checkbox", checked: controls.selectedIndices.includes(index), onChange: (e) => change({ ...controls, selectedIndices: e.target.checked ? [...controls.selectedIndices, index] : controls.selectedIndices.filter((value) => value !== index) }) }),
2959
+ " Row ",
2960
+ index + 1,
2961
+ summary ? ` \u2014 ${summary}` : ""
2962
+ ] }, index);
2963
+ }) })
2964
+ ] })
2913
2965
  ] })
2914
2966
  ] });
2915
2967
  }
@@ -3061,7 +3113,7 @@ function MatrxCopyMenuSession(props) {
3061
3113
  if (aiVisible && props.aiCustom)
3062
3114
  actions.push({
3063
3115
  id: "configure-source",
3064
- label: props.aiCustom.label ?? "Customize source\u2026",
3116
+ label: props.aiCustom.label ?? "Customize source",
3065
3117
  ...props.aiCustom.hint ? { hint: props.aiCustom.hint } : {},
3066
3118
  supports: () => true,
3067
3119
  run: async () => {
@@ -3072,7 +3124,7 @@ function MatrxCopyMenuSession(props) {
3072
3124
  if (aiVisible && props.groomer)
3073
3125
  actions.push({
3074
3126
  id: "groom-source",
3075
- label: "Customize sections\u2026",
3127
+ label: "Customize sections",
3076
3128
  supports: () => true,
3077
3129
  run: async () => {
3078
3130
  setConfiguration({ groomer: props.groomer() });
@@ -3182,7 +3234,8 @@ function MatrxCopyMenuSession(props) {
3182
3234
  className: cn(
3183
3235
  props.className,
3184
3236
  props.size === "xs" && "matrx-alchemy-xs",
3185
- props.size === "sm" && "matrx-alchemy-sm"
3237
+ props.size === "sm" && "matrx-alchemy-sm",
3238
+ props.size === "toolbar" && "matrx-alchemy-toolbar-target"
3186
3239
  ),
3187
3240
  ...props.stopPropagation !== void 0 ? { stopPropagation: props.stopPropagation } : {}
3188
3241
  }
@@ -3287,127 +3340,132 @@ function SourceConfiguration({
3287
3340
  event.preventDefault();
3288
3341
  if (!handingOff.current) restoreFocus();
3289
3342
  },
3290
- className: "matrx-alchemy-workspace",
3343
+ className: "matrx-alchemy-workspace matrx-alchemy-configuration",
3291
3344
  children: [
3292
3345
  /* @__PURE__ */ jsxs14(DialogHeader, { children: [
3293
3346
  /* @__PURE__ */ jsx22(DialogTitle, { children: title }),
3294
3347
  /* @__PURE__ */ jsx22(DialogDescription, { children: custom?.dialogDescription ?? "Choose the source detail, then prepare, edit, summarize, copy or export it in Alchemy." })
3295
3348
  ] }),
3296
- /* @__PURE__ */ jsxs14("div", { className: "matrx-alchemy-main matrx-alchemy-toolbar", children: [
3297
- custom?.options.map((option) => /* @__PURE__ */ jsxs14("label", { children: [
3298
- option.label,
3299
- "hint" in option && option.hint ? /* @__PURE__ */ jsx22("small", { children: option.hint }) : null,
3300
- option.kind === "toggle" ? /* @__PURE__ */ jsx22(
3301
- "input",
3302
- {
3303
- type: "checkbox",
3304
- checked: Boolean(values[option.key]),
3305
- onChange: (event) => setValues({ ...values, [option.key]: event.target.checked })
3306
- }
3307
- ) : option.kind === "preset" ? /* @__PURE__ */ jsx22(
3308
- "select",
3309
- {
3310
- value: Number(values[option.key]),
3311
- onChange: (event) => setValues({
3312
- ...values,
3313
- [option.key]: Number(event.target.value)
3314
- }),
3315
- children: option.options.map((choice) => /* @__PURE__ */ jsx22("option", { value: choice.value, children: choice.label }, choice.value))
3316
- }
3317
- ) : option.kind === "slider" ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
3318
- /* @__PURE__ */ jsx22(
3349
+ /* @__PURE__ */ jsxs14("div", { className: "matrx-alchemy-workspace-body", children: [
3350
+ /* @__PURE__ */ jsxs14("div", { className: "matrx-alchemy-main matrx-alchemy-toolbar", children: [
3351
+ custom?.options.map((option) => /* @__PURE__ */ jsxs14("label", { children: [
3352
+ option.label,
3353
+ "hint" in option && option.hint ? /* @__PURE__ */ jsx22("small", { children: option.hint }) : null,
3354
+ option.kind === "toggle" ? /* @__PURE__ */ jsx22(
3319
3355
  "input",
3320
3356
  {
3321
- type: "range",
3322
- min: 0,
3323
- max: Math.max(0, option.stops.length - 1),
3324
- step: 1,
3325
- value: option.stops.indexOf(Number(values[option.key])),
3326
- onChange: (event) => setValues({
3327
- ...values,
3328
- [option.key]: option.stops[Number(event.target.value)]
3329
- })
3357
+ type: "checkbox",
3358
+ checked: Boolean(values[option.key]),
3359
+ onChange: (event) => setValues({ ...values, [option.key]: event.target.checked })
3330
3360
  }
3331
- ),
3332
- /* @__PURE__ */ jsx22("span", { children: option.formatValue(Number(values[option.key])) })
3333
- ] }) : /* @__PURE__ */ jsxs14(Fragment3, { children: [
3334
- /* @__PURE__ */ jsx22(
3335
- "input",
3361
+ ) : option.kind === "preset" ? /* @__PURE__ */ jsx22(
3362
+ "select",
3336
3363
  {
3337
- type: "number",
3338
- min: option.min,
3339
- step: option.step,
3340
3364
  value: Number(values[option.key]),
3341
3365
  onChange: (event) => setValues({
3342
3366
  ...values,
3343
3367
  [option.key]: Number(event.target.value)
3344
- })
3368
+ }),
3369
+ children: option.options.map((choice) => /* @__PURE__ */ jsx22("option", { value: choice.value, children: choice.label }, choice.value))
3345
3370
  }
3346
- ),
3347
- option.presets?.map((preset) => /* @__PURE__ */ jsx22(
3371
+ ) : option.kind === "slider" ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
3372
+ /* @__PURE__ */ jsx22(
3373
+ "input",
3374
+ {
3375
+ type: "range",
3376
+ min: 0,
3377
+ max: Math.max(0, option.stops.length - 1),
3378
+ step: 1,
3379
+ value: option.stops.indexOf(Number(values[option.key])),
3380
+ onChange: (event) => setValues({
3381
+ ...values,
3382
+ [option.key]: option.stops[Number(event.target.value)]
3383
+ })
3384
+ }
3385
+ ),
3386
+ /* @__PURE__ */ jsx22("span", { children: option.formatValue(Number(values[option.key])) })
3387
+ ] }) : /* @__PURE__ */ jsxs14(Fragment3, { children: [
3388
+ /* @__PURE__ */ jsx22(
3389
+ "input",
3390
+ {
3391
+ type: "number",
3392
+ min: option.min,
3393
+ step: option.step,
3394
+ value: Number(values[option.key]),
3395
+ onChange: (event) => setValues({
3396
+ ...values,
3397
+ [option.key]: Number(event.target.value)
3398
+ })
3399
+ }
3400
+ ),
3401
+ option.presets?.map((preset) => /* @__PURE__ */ jsx22(
3402
+ Button,
3403
+ {
3404
+ type: "button",
3405
+ variant: "ghost",
3406
+ className: "matrx-alchemy-workspace-secondary",
3407
+ onClick: () => setValues({ ...values, [option.key]: preset.value }),
3408
+ children: preset.label
3409
+ },
3410
+ preset.value
3411
+ ))
3412
+ ] })
3413
+ ] }, option.key)),
3414
+ groomer ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
3415
+ /* @__PURE__ */ jsx22("div", { children: ["full", "compact", "brief"].map((level) => /* @__PURE__ */ jsx22(
3348
3416
  Button,
3349
3417
  {
3350
3418
  type: "button",
3351
3419
  variant: "ghost",
3352
- onClick: () => setValues({ ...values, [option.key]: preset.value }),
3353
- children: preset.label
3420
+ className: "matrx-alchemy-workspace-secondary",
3421
+ onClick: () => setSections(
3422
+ Object.fromEntries(
3423
+ groomer.sections.map((section) => [
3424
+ section.id,
3425
+ level === "brief" && section.cuttable ? "off" : level
3426
+ ])
3427
+ )
3428
+ ),
3429
+ children: level
3354
3430
  },
3355
- preset.value
3356
- ))
3357
- ] })
3358
- ] }, option.key)),
3359
- groomer ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
3360
- /* @__PURE__ */ jsx22("div", { children: ["full", "compact", "brief"].map((level) => /* @__PURE__ */ jsx22(
3361
- Button,
3362
- {
3363
- type: "button",
3364
- variant: "ghost",
3365
- onClick: () => setSections(
3366
- Object.fromEntries(
3367
- groomer.sections.map((section) => [
3368
- section.id,
3369
- level === "brief" && section.cuttable ? "off" : level
3370
- ])
3371
- )
3431
+ level
3432
+ )) }),
3433
+ groomer.sections.map((section) => /* @__PURE__ */ jsxs14("label", { children: [
3434
+ section.title,
3435
+ /* @__PURE__ */ jsxs14(
3436
+ "select",
3437
+ {
3438
+ value: sections[section.id],
3439
+ onChange: (event) => setSections({
3440
+ ...sections,
3441
+ [section.id]: event.target.value
3442
+ }),
3443
+ children: [
3444
+ ["full", "compact", "brief"].map((level) => /* @__PURE__ */ jsx22("option", { value: level, children: section.levelLabels?.[level] ?? level }, level)),
3445
+ section.cuttable ? /* @__PURE__ */ jsx22("option", { value: "off", children: "Exclude" }) : null
3446
+ ]
3447
+ }
3372
3448
  ),
3373
- children: level
3374
- },
3375
- level
3376
- )) }),
3377
- groomer.sections.map((section) => /* @__PURE__ */ jsxs14("label", { children: [
3378
- section.title,
3379
- /* @__PURE__ */ jsxs14(
3380
- "select",
3381
- {
3382
- value: sections[section.id],
3383
- onChange: (event) => setSections({
3384
- ...sections,
3385
- [section.id]: event.target.value
3386
- }),
3387
- children: [
3388
- ["full", "compact", "brief"].map((level) => /* @__PURE__ */ jsx22("option", { value: level, children: section.levelLabels?.[level] ?? level }, level)),
3389
- section.cuttable ? /* @__PURE__ */ jsx22("option", { value: "off", children: "Exclude" }) : null
3390
- ]
3391
- }
3392
- ),
3393
- section.description ? /* @__PURE__ */ jsx22("span", { children: section.description }) : null
3394
- ] }, section.id))
3395
- ] }) : null
3396
- ] }),
3397
- /* @__PURE__ */ jsxs14("p", { children: [
3398
- text.length.toLocaleString(),
3399
- " characters \xB7 approximately",
3400
- " ",
3401
- Math.ceil(text.length / 4).toLocaleString(),
3402
- " tokens"
3449
+ section.description ? /* @__PURE__ */ jsx22("span", { children: section.description }) : null
3450
+ ] }, section.id))
3451
+ ] }) : null
3452
+ ] }),
3453
+ /* @__PURE__ */ jsxs14("p", { children: [
3454
+ text.length.toLocaleString(),
3455
+ " characters \xB7 approximately",
3456
+ " ",
3457
+ Math.ceil(text.length / 4).toLocaleString(),
3458
+ " tokens"
3459
+ ] }),
3460
+ error || buildError ? /* @__PURE__ */ jsx22("p", { role: "alert", children: error ?? buildError }) : null
3403
3461
  ] }),
3404
- error || buildError ? /* @__PURE__ */ jsx22("p", { role: "alert", children: error ?? buildError }) : null,
3405
3462
  /* @__PURE__ */ jsxs14(DialogFooter, { children: [
3406
3463
  /* @__PURE__ */ jsx22(
3407
3464
  Button,
3408
3465
  {
3409
3466
  type: "button",
3410
3467
  variant: "ghost",
3468
+ className: "matrx-alchemy-workspace-secondary",
3411
3469
  disabled: busy,
3412
3470
  onClick: onClose,
3413
3471
  children: "Cancel"
@@ -3417,6 +3475,7 @@ function SourceConfiguration({
3417
3475
  Button,
3418
3476
  {
3419
3477
  type: "button",
3478
+ className: "matrx-alchemy-workspace-primary",
3420
3479
  disabled: busy || !prepared || Boolean(buildError),
3421
3480
  onClick: async () => {
3422
3481
  if (!prepared) return;
@@ -4031,7 +4090,7 @@ function CopySubsetDialog({ source, onClose }) {
4031
4090
  ] }) });
4032
4091
  }
4033
4092
  function useCopySubsetVariant() {
4034
- return (getSource) => ({ id: "copy-subset", label: "Filter & sort before copying\u2026", section: "ai", modal: ({ open, onOpenChange }) => open ? /* @__PURE__ */ jsx24(CopySubsetDialog, { source: getSource(), onClose: () => onOpenChange(false) }) : null });
4093
+ return (getSource) => ({ id: "copy-subset", label: "Filter & sort before copying", section: "ai", modal: ({ open, onOpenChange }) => open ? /* @__PURE__ */ jsx24(CopySubsetDialog, { source: getSource(), onClose: () => onOpenChange(false) }) : null });
4035
4094
  }
4036
4095
 
4037
4096
  // src/data-table/clipping.ts
@@ -6751,6 +6810,23 @@ function safeQueryPage(requestedPage, totalItems, pageSize) {
6751
6810
 
6752
6811
  // src/data-table/MatrxDataTable.tsx
6753
6812
  import { Fragment as Fragment7, jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
6813
+ function TableToolbarAction({
6814
+ HostAction,
6815
+ ariaLabel,
6816
+ tooltip,
6817
+ disabled,
6818
+ busy,
6819
+ onClick,
6820
+ children
6821
+ }) {
6822
+ if (HostAction) {
6823
+ return /* @__PURE__ */ jsx35(HostAction, { ariaLabel, tooltip, disabled, busy, onClick, children });
6824
+ }
6825
+ return /* @__PURE__ */ jsxs26(Tooltip, { children: [
6826
+ /* @__PURE__ */ jsx35(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx35("span", { className: "inline-flex", children: /* @__PURE__ */ jsx35(Button, { type: "button", variant: "ghost", size: "icon", className: "h-8 w-8", "aria-label": ariaLabel, "aria-busy": busy || void 0, disabled, onClick, children: isValidElement(children) ? cloneElement(children, { className: cn("h-4 w-4", children.props.className) }) : children }) }) }),
6827
+ /* @__PURE__ */ jsx35(TooltipContent, { children: tooltip ?? ariaLabel })
6828
+ ] });
6829
+ }
6754
6830
  function hasSameRowReferences(previous, next) {
6755
6831
  return previous.length === next.length && previous.every((row, index) => row === next[index]);
6756
6832
  }
@@ -8188,29 +8264,21 @@ function MatrxDataTableCore({
8188
8264
  ]
8189
8265
  }
8190
8266
  ) : null,
8191
- /* @__PURE__ */ jsxs26(Tooltip, { children: [
8192
- /* @__PURE__ */ jsx35(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx35("span", { className: "inline-flex", children: /* @__PURE__ */ jsxs26(
8193
- Button,
8194
- {
8195
- type: "button",
8196
- variant: "ghost",
8197
- size: "sm",
8198
- className: "h-7 gap-1 px-2 text-xs text-muted-foreground",
8199
- onClick: clearAllFilters,
8200
- disabled: !hasActiveFilters,
8201
- "aria-label": "Clear all filters",
8202
- children: [
8203
- /* @__PURE__ */ jsx35(Eraser, { className: "h-3.5 w-3.5" }),
8204
- /* @__PURE__ */ jsx35("span", { className: "max-sm:sr-only", children: "Clear all" })
8205
- ]
8206
- }
8207
- ) }) }),
8208
- /* @__PURE__ */ jsx35(TooltipContent, { children: hasActiveFilters ? "Clear search and filters; keep columns and sort" : "No search or filters to clear" })
8209
- ] }),
8267
+ /* @__PURE__ */ jsx35(
8268
+ TableToolbarAction,
8269
+ {
8270
+ HostAction: host.ToolbarAction,
8271
+ ariaLabel: "Clear all filters",
8272
+ tooltip: hasActiveFilters ? "Clear search and filters; keep columns and sort" : "No search or filters to clear",
8273
+ disabled: !hasActiveFilters,
8274
+ onClick: clearAllFilters,
8275
+ children: /* @__PURE__ */ jsx35(Eraser, {})
8276
+ }
8277
+ ),
8210
8278
  showToolbarCopy && effectiveCopy ? /* @__PURE__ */ jsx35(
8211
8279
  CopyButtons,
8212
8280
  {
8213
- size: "icon",
8281
+ size: "toolbar",
8214
8282
  sourceId: `${tableCopySourceNamespace}:view`,
8215
8283
  label: effectiveCopy.listLabel ?? `${effectiveCopy.label} view`,
8216
8284
  ...copy === void 0 ? {} : {
@@ -8247,92 +8315,66 @@ function MatrxDataTableCore({
8247
8315
  }
8248
8316
  }
8249
8317
  ) : null,
8250
- columns.length > 0 ? /* @__PURE__ */ jsxs26(Tooltip, { children: [
8251
- /* @__PURE__ */ jsx35(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs26(
8252
- Button,
8253
- {
8254
- type: "button",
8255
- variant: "ghost",
8256
- size: "icon",
8257
- "aria-label": "Columns",
8258
- className: "h-8 w-8",
8259
- onClick: () => setColumnManagerOpen(true),
8260
- children: [
8261
- /* @__PURE__ */ jsx35(SlidersHorizontal, { className: "h-4 w-4" }),
8262
- effectiveHiddenColumnIds.size > 0 ? /* @__PURE__ */ jsxs26("span", { className: "sr-only", children: [
8263
- effectiveHiddenColumnIds.size,
8264
- " hidden"
8265
- ] }) : null
8266
- ]
8267
- }
8268
- ) }),
8269
- /* @__PURE__ */ jsx35(TooltipContent, { children: "Show, hide, or reorder columns" })
8270
- ] }) : null,
8271
- toolbar?.refresh ? /* @__PURE__ */ jsxs26(Tooltip, { children: [
8272
- /* @__PURE__ */ jsx35(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx35("span", { className: "inline-flex", children: /* @__PURE__ */ jsx35(
8273
- Button,
8274
- {
8275
- type: "button",
8276
- variant: "ghost",
8277
- size: "icon",
8278
- className: "h-8 w-8",
8279
- "aria-label": toolbar.refresh.label ?? "Refresh",
8280
- disabled: isFetching || toolbarActionPending.refresh,
8281
- onClick: () => {
8282
- if (toolbarActionPendingRef.current.refresh) return;
8283
- toolbarActionPendingRef.current.refresh = true;
8284
- setToolbarActionPending((current) => ({ ...current, refresh: true }));
8285
- setToolbarActionError(null);
8286
- void Promise.resolve().then(() => toolbar.refresh?.onRefresh()).catch((cause) => {
8287
- const message = cause instanceof Error ? cause.message : String(cause);
8288
- setToolbarActionError(`Refresh failed: ${message}`);
8289
- toast.error(`Refresh failed: ${message}`);
8290
- }).finally(() => {
8291
- toolbarActionPendingRef.current.refresh = false;
8292
- setToolbarActionPending((current) => ({ ...current, refresh: false }));
8293
- });
8294
- },
8295
- children: /* @__PURE__ */ jsx35(
8296
- Loader2,
8297
- {
8298
- className: cn(
8299
- "h-4 w-4",
8300
- (isFetching || toolbarActionPending.refresh) && "animate-spin"
8301
- )
8302
- }
8303
- )
8304
- }
8305
- ) }) }),
8306
- /* @__PURE__ */ jsx35(TooltipContent, { children: isFetching ? "Refreshing table data" : toolbar.refresh.label ?? "Refresh" })
8307
- ] }) : null,
8308
- toolbar?.add ? /* @__PURE__ */ jsxs26(Tooltip, { children: [
8309
- /* @__PURE__ */ jsx35(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx35("span", { className: "inline-flex", children: /* @__PURE__ */ jsx35(
8310
- Button,
8311
- {
8312
- type: "button",
8313
- size: "icon",
8314
- className: "h-8 w-8",
8315
- "aria-label": "Add",
8316
- disabled: toolbar.add.disabled || toolbarActionPending.add,
8317
- onClick: () => {
8318
- if (toolbarActionPendingRef.current.add) return;
8319
- toolbarActionPendingRef.current.add = true;
8320
- setToolbarActionPending((current) => ({ ...current, add: true }));
8321
- setToolbarActionError(null);
8322
- void Promise.resolve().then(() => toolbar.add?.onAdd()).catch((cause) => {
8323
- const message = cause instanceof Error ? cause.message : String(cause);
8324
- setToolbarActionError(`Add failed: ${message}`);
8325
- toast.error(`Add failed: ${message}`);
8326
- }).finally(() => {
8327
- toolbarActionPendingRef.current.add = false;
8328
- setToolbarActionPending((current) => ({ ...current, add: false }));
8329
- });
8330
- },
8331
- children: /* @__PURE__ */ jsx35(Plus, { className: "h-4 w-4" })
8332
- }
8333
- ) }) }),
8334
- /* @__PURE__ */ jsx35(TooltipContent, { children: toolbar.add.disabled ? toolbar.add.disabledReason ?? "Add unavailable" : "Add" })
8335
- ] }) : null,
8318
+ columns.length > 0 ? /* @__PURE__ */ jsx35(
8319
+ TableToolbarAction,
8320
+ {
8321
+ HostAction: host.ToolbarAction,
8322
+ ariaLabel: "Columns",
8323
+ tooltip: "Show, hide, or reorder columns",
8324
+ onClick: () => setColumnManagerOpen(true),
8325
+ children: /* @__PURE__ */ jsx35(SlidersHorizontal, {})
8326
+ }
8327
+ ) : null,
8328
+ toolbar?.refresh ? /* @__PURE__ */ jsx35(
8329
+ TableToolbarAction,
8330
+ {
8331
+ HostAction: host.ToolbarAction,
8332
+ ariaLabel: toolbar.refresh.label ?? "Refresh",
8333
+ tooltip: isFetching ? "Refreshing table data" : toolbar.refresh.label ?? "Refresh",
8334
+ disabled: isFetching || toolbarActionPending.refresh,
8335
+ busy: isFetching || toolbarActionPending.refresh,
8336
+ onClick: () => {
8337
+ if (toolbarActionPendingRef.current.refresh) return;
8338
+ toolbarActionPendingRef.current.refresh = true;
8339
+ setToolbarActionPending((current) => ({ ...current, refresh: true }));
8340
+ setToolbarActionError(null);
8341
+ void Promise.resolve().then(() => toolbar.refresh?.onRefresh()).catch((cause) => {
8342
+ const message = cause instanceof Error ? cause.message : String(cause);
8343
+ setToolbarActionError(`Refresh failed: ${message}`);
8344
+ toast.error(`Refresh failed: ${message}`);
8345
+ }).finally(() => {
8346
+ toolbarActionPendingRef.current.refresh = false;
8347
+ setToolbarActionPending((current) => ({ ...current, refresh: false }));
8348
+ });
8349
+ },
8350
+ children: /* @__PURE__ */ jsx35(RefreshControlIcon, { spinning: isFetching || toolbarActionPending.refresh })
8351
+ }
8352
+ ) : null,
8353
+ toolbar?.add ? /* @__PURE__ */ jsx35(
8354
+ TableToolbarAction,
8355
+ {
8356
+ HostAction: host.ToolbarAction,
8357
+ ariaLabel: "Add",
8358
+ tooltip: toolbar.add.disabled ? toolbar.add.disabledReason ?? "Add unavailable" : "Add",
8359
+ disabled: toolbar.add.disabled || toolbarActionPending.add,
8360
+ busy: toolbarActionPending.add,
8361
+ onClick: () => {
8362
+ if (toolbarActionPendingRef.current.add) return;
8363
+ toolbarActionPendingRef.current.add = true;
8364
+ setToolbarActionPending((current) => ({ ...current, add: true }));
8365
+ setToolbarActionError(null);
8366
+ void Promise.resolve().then(() => toolbar.add?.onAdd()).catch((cause) => {
8367
+ const message = cause instanceof Error ? cause.message : String(cause);
8368
+ setToolbarActionError(`Add failed: ${message}`);
8369
+ toast.error(`Add failed: ${message}`);
8370
+ }).finally(() => {
8371
+ toolbarActionPendingRef.current.add = false;
8372
+ setToolbarActionPending((current) => ({ ...current, add: false }));
8373
+ });
8374
+ },
8375
+ children: /* @__PURE__ */ jsx35(Plus, {})
8376
+ }
8377
+ ) : null,
8336
8378
  toolbar?.actions
8337
8379
  ]
8338
8380
  }
@@ -8455,13 +8497,13 @@ function MatrxDataTableCore({
8455
8497
  actions: showRowCopy || rowActions ? /* @__PURE__ */ jsxs26(
8456
8498
  "div",
8457
8499
  {
8458
- className: "inline-flex items-center gap-1",
8500
+ className: "inline-flex items-center gap-0",
8459
8501
  onClick: (event) => event.stopPropagation(),
8460
8502
  children: [
8461
8503
  showRowCopy && effectiveCopy ? /* @__PURE__ */ jsx35(
8462
8504
  TableRowCopyControl,
8463
8505
  {
8464
- size: "xs",
8506
+ size: "toolbar",
8465
8507
  copy: effectiveCopy,
8466
8508
  row: displayRow,
8467
8509
  sourceId: `${tableCopySourceNamespace}:row:${getRowId(displayRow)}`,
@@ -8758,13 +8800,13 @@ function MatrxDataTableCore({
8758
8800
  showActionsCol && /* @__PURE__ */ jsx35("td", { className: "px-2 py-1.5 text-right align-middle lg:py-0.5", children: /* @__PURE__ */ jsxs26(
8759
8801
  "div",
8760
8802
  {
8761
- className: "inline-flex items-center justify-end gap-0.5",
8803
+ className: "inline-flex items-center justify-end gap-0",
8762
8804
  onClick: (e) => e.stopPropagation(),
8763
8805
  children: [
8764
8806
  showRowCopy && effectiveCopy ? /* @__PURE__ */ jsx35(
8765
8807
  TableRowCopyControl,
8766
8808
  {
8767
- size: "xs",
8809
+ size: "toolbar",
8768
8810
  copy: effectiveCopy,
8769
8811
  row: displayRow,
8770
8812
  sourceId: `${tableCopySourceNamespace}:row:${getRowId(displayRow)}`,
@@ -9458,7 +9500,7 @@ function resolveStringTitle(title, fallback) {
9458
9500
  }
9459
9501
 
9460
9502
  // src/data-table/SavedViewsControl.tsx
9461
- import { useState as useState16 } from "react";
9503
+ import { useId as useId3, useState as useState16 } from "react";
9462
9504
 
9463
9505
  // src/dropdown-menu.tsx
9464
9506
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
@@ -9601,6 +9643,7 @@ function SavedViewsControl({
9601
9643
  onUpdate,
9602
9644
  onReload
9603
9645
  }) {
9646
+ const unsavedChangesId = useId3();
9604
9647
  const [saveOpen, setSaveOpen] = useState16(false);
9605
9648
  const [name, setName] = useState16("");
9606
9649
  const [saving, setSaving] = useState16(false);
@@ -9646,10 +9689,26 @@ function SavedViewsControl({
9646
9689
  }
9647
9690
  };
9648
9691
  const activeName = activeId ? views.find((view) => view.id === activeId)?.name : void 0;
9649
- return /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-1", "data-matrx-table-saved-views": true, children: [
9692
+ return /* @__PURE__ */ jsxs28("div", { className: "flex min-w-0 flex-wrap items-center gap-1", "data-matrx-table-saved-views": true, children: [
9650
9693
  /* @__PURE__ */ jsxs28(DropdownMenu, { children: [
9651
9694
  /* @__PURE__ */ jsxs28(Tooltip, { children: [
9652
- /* @__PURE__ */ jsx37(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(Button, { type: "button", variant: "outline", size: "sm", className: "h-8 max-w-40 truncate text-xs", "aria-label": "Saved views", disabled: saving, children: loading ? "Loading views\u2026" : `${activeName ?? "Default view"}${dirty ? " \u2022" : ""}` }) }) }),
9695
+ /* @__PURE__ */ jsx37(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs28(
9696
+ Button,
9697
+ {
9698
+ type: "button",
9699
+ variant: "ghost",
9700
+ size: "sm",
9701
+ className: "h-8 min-w-0 max-w-52 gap-1 px-2 text-xs font-medium",
9702
+ "aria-label": `Table view: ${loading ? "Loading views" : activeName ?? "Default view"}${dirty ? ", unsaved changes" : ""}`,
9703
+ "aria-describedby": dirty ? unsavedChangesId : void 0,
9704
+ disabled: saving,
9705
+ children: [
9706
+ /* @__PURE__ */ jsx37("span", { className: "min-w-0 flex-1 truncate", children: loading ? "Loading views\u2026" : activeName ?? "Default view" }),
9707
+ dirty ? /* @__PURE__ */ jsx37("span", { "aria-hidden": "true", className: "size-1.5 shrink-0 rounded-full bg-amber-500" }) : null,
9708
+ /* @__PURE__ */ jsx37(ChevronDown, { className: "size-3.5 shrink-0" })
9709
+ ]
9710
+ }
9711
+ ) }) }),
9653
9712
  /* @__PURE__ */ jsx37(TooltipContent, { children: "Choose or save a table view" })
9654
9713
  ] }),
9655
9714
  /* @__PURE__ */ jsxs28(DropdownMenuContent, { align: "end", children: [
@@ -9667,14 +9726,8 @@ function SavedViewsControl({
9667
9726
  onReload ? /* @__PURE__ */ jsx37(DropdownMenuItem, { disabled: saving || loading, onSelect: () => void reload(), children: "Reload views" }) : null
9668
9727
  ] })
9669
9728
  ] }),
9670
- /* @__PURE__ */ jsxs28(Tooltip, { children: [
9671
- /* @__PURE__ */ jsx37(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(Button, { type: "button", variant: "ghost", size: "icon", className: "h-8 w-8", "aria-label": "Save current view", disabled: saving, onClick: () => {
9672
- setActionError(null);
9673
- setSaveOpen(true);
9674
- }, children: /* @__PURE__ */ jsx37(Save, { className: "h-4 w-4" }) }) }),
9675
- /* @__PURE__ */ jsx37(TooltipContent, { children: "Save current view" })
9676
- ] }),
9677
- visibleError ? /* @__PURE__ */ jsx37("p", { role: "alert", className: "basis-full text-xs text-destructive", children: visibleError }) : null,
9729
+ dirty ? /* @__PURE__ */ jsx37("span", { id: unsavedChangesId, className: "sr-only", children: "This table view has unsaved changes. Open the view menu to save or update it." }) : null,
9730
+ visibleError ? /* @__PURE__ */ jsx37("p", { role: "alert", className: "basis-full break-words text-xs text-destructive", children: visibleError }) : null,
9678
9731
  /* @__PURE__ */ jsx37(Dialog, { open: saveOpen, onOpenChange: setSaveOpen, children: /* @__PURE__ */ jsxs28(DialogContent, { children: [
9679
9732
  /* @__PURE__ */ jsx37(DialogHeader, { children: /* @__PURE__ */ jsx37(DialogTitle, { children: "Save current view" }) }),
9680
9733
  visibleError ? /* @__PURE__ */ jsx37("p", { role: "alert", className: "text-sm text-destructive", children: visibleError }) : null,