@ai-matrx/design-system 0.18.10 → 0.18.13

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 +29 -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 +323 -277
  10. package/dist/content-transfer.cjs.map +1 -1
  11. package/dist/content-transfer.css +93 -25
  12. package/dist/content-transfer.d.cts +1 -1
  13. package/dist/content-transfer.d.ts +1 -1
  14. package/dist/content-transfer.js +323 -277
  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 +325 -276
  22. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  23. package/dist/data-table/data-row-inspector.js +325 -276
  24. package/dist/data-table/data-row-inspector.js.map +1 -1
  25. package/dist/data-table/data-row-window.cjs +325 -276
  26. package/dist/data-table/data-row-window.cjs.map +1 -1
  27. package/dist/data-table/data-row-window.js +325 -276
  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 +463 -398
  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 +464 -399
  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,150 @@ 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))
2785
2803
  ] }) : null,
2786
- displayedOmissions.length ? /* @__PURE__ */ jsxs13("details", { children: [
2804
+ rows ? /* @__PURE__ */ jsxs13("details", { className: "matrx-alchemy-options matrx-alchemy-data-controls", children: [
2787
2805
  /* @__PURE__ */ jsxs13("summary", { children: [
2788
- displayedOmissions.length,
2789
- " omissions or adjustments"
2806
+ "Data selection \xB7 ",
2807
+ controls.visibleColumns.length,
2808
+ " columns",
2809
+ controls.search || controls.sort || controls.top != null || controls.selectedOnly || Object.values(controls.filters).some(Boolean) ? " \xB7 customized" : " \xB7 all rows"
2790
2810
  ] }),
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
- ] })
2811
+ /* @__PURE__ */ jsx21("div", { className: "matrx-alchemy-data-controls-body", children: /* @__PURE__ */ jsx21(RowControls, { rows, controls, change: changeControls }) })
2812
+ ] }) : null,
2813
+ state.snapshot.sections.length ? /* @__PURE__ */ jsxs13("details", { className: "matrx-alchemy-options", children: [
2814
+ /* @__PURE__ */ jsxs13("summary", { children: [
2815
+ "Sections \xB7 ",
2816
+ controls.sections.length,
2817
+ " included"
2818
+ ] }),
2819
+ /* @__PURE__ */ jsx21("fieldset", { "aria-label": "Included sections", children: state.snapshot.sections.map((section) => /* @__PURE__ */ jsxs13("label", { children: [
2820
+ /* @__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) }) }),
2821
+ " ",
2822
+ section.label
2823
+ ] }, section.id)) })
2824
+ ] }) : null,
2825
+ /* @__PURE__ */ jsxs13("label", { className: "matrx-alchemy-preview-label", children: [
2826
+ "Output format",
2827
+ /* @__PURE__ */ jsxs13("select", { "aria-label": "Output format", value: format, onChange: (e) => setFormat(e.target.value), children: [
2828
+ formats.map((f) => /* @__PURE__ */ jsx21("option", { value: f, children: LABEL[f] }, f)),
2829
+ state.draft.payload.kind === "rows" ? /* @__PURE__ */ jsx21("option", { value: "xlsx", children: "Excel workbook" }) : null,
2830
+ workspaceAdapters.map((adapter) => /* @__PURE__ */ jsx21("option", { value: adapter.id, children: adapter.label }, adapter.id))
2831
+ ] })
2832
+ ] }),
2833
+ /* @__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) }),
2834
+ /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-coverage", children: [
2835
+ /* @__PURE__ */ jsxs13("span", { children: [
2836
+ state.snapshot.coverage.included.toLocaleString(),
2837
+ " included",
2838
+ state.snapshot.coverage.total == null ? "" : ` of ${state.snapshot.coverage.total.toLocaleString()}`,
2839
+ " \xB7 ",
2840
+ state.snapshot.coverage.status
2841
+ ] }),
2842
+ state.snapshot.coverage.reason ? /* @__PURE__ */ jsx21("span", { children: state.snapshot.coverage.reason }) : null,
2843
+ limitText ? /* @__PURE__ */ jsxs13("span", { children: [
2844
+ "Limits: ",
2845
+ limitText
2846
+ ] }) : null,
2847
+ displayedOmissions.length ? /* @__PURE__ */ jsxs13("details", { children: [
2848
+ /* @__PURE__ */ jsxs13("summary", { children: [
2849
+ displayedOmissions.length,
2850
+ " omissions or adjustments"
2851
+ ] }),
2852
+ /* @__PURE__ */ jsx21("ul", { children: displayedOmissions.map((o, i) => /* @__PURE__ */ jsxs13("li", { children: [
2853
+ o.path || "/",
2854
+ ": ",
2855
+ o.reason,
2856
+ o.count == null ? "" : ` (${o.count})`
2857
+ ] }, `${o.path}-${o.reason}-${i}`)) })
2858
+ ] }) : null
2859
+ ] }),
2860
+ bufferError ? /* @__PURE__ */ jsx21("p", { id: "alchemy-buffer-error", role: "alert", className: "matrx-alchemy-error", children: bufferError }) : null,
2861
+ formatError ? /* @__PURE__ */ jsx21("p", { role: "alert", className: "matrx-alchemy-error", children: formatError }) : null,
2862
+ bufferError ? /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", disabled: busy !== null, onClick: () => {
2863
+ const fallback = editDraft(state.draft, { kind: "text", text: buffer });
2864
+ setBufferError(null);
2865
+ onChange({ ...state, draft: fallback, error: void 0 });
2866
+ setFormat("plain");
2867
+ }, children: "Use invalid JSON as plain text" }) : null
2806
2868
  ] }),
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
2869
+ ai || busy === "capture" || state.error ? /* @__PURE__ */ jsxs13("aside", { children: [
2870
+ ai ? /* @__PURE__ */ jsxs13(Fragment2, { children: [
2871
+ /* @__PURE__ */ jsxs13("label", { children: [
2872
+ "AI instruction",
2873
+ /* @__PURE__ */ jsx21("textarea", { value: instruction, onChange: (e) => setInstruction(e.target.value), placeholder: "Tell AI how to prepare this content" })
2874
+ ] }),
2875
+ /* @__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" }),
2876
+ 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
2877
+ ] }) : null,
2878
+ busy === "capture" ? /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => {
2879
+ activeCapture.current?.abort();
2880
+ activeCapture.current = null;
2881
+ setBusy(null);
2882
+ }, children: "Stop loading rows" }) : null,
2883
+ 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,
2884
+ 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,
2885
+ state.error ? /* @__PURE__ */ jsx21("p", { role: "alert", className: "matrx-alchemy-error", children: state.error }) : null
2886
+ ] }) : null
2816
2887
  ] }),
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
2888
+ pendingControls ? /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-decision", role: "alert", children: [
2889
+ /* @__PURE__ */ jsx21("p", { children: "This control would replace your manual edit." }),
2890
+ /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => setPendingControls(null), children: "Keep edited draft" }),
2891
+ /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-primary", type: "button", onClick: applyPendingControls, children: "Rebuild from source" })
2892
+ ] }) : null,
2893
+ 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,
2894
+ state.pending ? /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-decision", role: "alert", children: [
2895
+ /* @__PURE__ */ jsx21("p", { children: "A fresh source snapshot is ready." }),
2896
+ /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => resolveCapture("keep"), children: "Keep current snapshot and draft" }),
2897
+ /* @__PURE__ */ jsx21(Button, { className: "matrx-alchemy-workspace-primary", type: "button", onClick: () => resolveCapture("regenerate"), children: "Regenerate from fresh source" })
2898
+ ] }) : null,
2899
+ deliveryNotice ? /* @__PURE__ */ jsx21("p", { role: "status", className: "matrx-alchemy-meta", children: deliveryNotice }) : null
2835
2900
  ] }),
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
2901
  /* @__PURE__ */ jsxs13(DialogFooter, { children: [
2849
2902
  /* @__PURE__ */ jsxs13("span", { className: "matrx-alchemy-meta", children: [
2850
2903
  buffer.length.toLocaleString(),
@@ -2852,13 +2905,16 @@ function PreparationWorkspace({ restoreFocus, open, state, scopes, onClose, onCh
2852
2905
  estimateTokens(buffer).toLocaleString(),
2853
2906
  " tokens"
2854
2907
  ] }),
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" })
2908
+ /* @__PURE__ */ jsx21(Button, { type: "button", variant: "outline", className: "matrx-alchemy-workspace-secondary", onClick: close, children: "Close" }),
2909
+ /* @__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" }),
2910
+ /* @__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
2911
  ] })
2859
2912
  ] }) });
2860
2913
  }
2861
2914
  function RowControls({ rows, controls, change }) {
2915
+ const filterCount = Object.values(controls.filters).filter(Boolean).length;
2916
+ const selectionSummary = controls.selectedOnly ? `${controls.selectedIndices.length} selected row${controls.selectedIndices.length === 1 ? "" : "s"}` : "All rows";
2917
+ 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
2918
  return /* @__PURE__ */ jsxs13(Fragment2, { children: [
2863
2919
  /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-toolbar", children: [
2864
2920
  /* @__PURE__ */ jsxs13("label", { children: [
@@ -2884,32 +2940,40 @@ function RowControls({ rows, controls, change }) {
2884
2940
  /* @__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
2941
  ] })
2886
2942
  ] }),
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: [
2943
+ /* @__PURE__ */ jsxs13("details", { className: "matrx-alchemy-options", children: [
2944
+ /* @__PURE__ */ jsxs13("summary", { children: [
2945
+ "Columns and filters",
2946
+ dataSummary ? ` \u2014 ${dataSummary}` : ""
2947
+ ] }),
2948
+ /* @__PURE__ */ jsx21("fieldset", { "aria-label": "Columns and filters", children: rows.columns.map((column) => /* @__PURE__ */ jsxs13("div", { className: "matrx-alchemy-column", children: [
2890
2949
  /* @__PURE__ */ jsxs13("label", { children: [
2891
2950
  /* @__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
2951
  " ",
2893
2952
  column.label
2894
2953
  ] }),
2895
2954
  /* @__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))
2955
+ ] }, column.id)) })
2897
2956
  ] }),
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"
2957
+ /* @__PURE__ */ jsxs13("details", { className: "matrx-alchemy-options", children: [
2958
+ /* @__PURE__ */ jsxs13("summary", { children: [
2959
+ "Rows \u2014 ",
2960
+ selectionSummary
2903
2961
  ] }),
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
- }) })
2962
+ /* @__PURE__ */ jsxs13("fieldset", { "aria-label": "Row selection", children: [
2963
+ /* @__PURE__ */ jsxs13("label", { children: [
2964
+ /* @__PURE__ */ jsx21("input", { type: "checkbox", checked: controls.selectedOnly, onChange: (e) => change({ ...controls, selectedOnly: e.target.checked }) }),
2965
+ " Only selected rows"
2966
+ ] }),
2967
+ /* @__PURE__ */ jsx21("div", { className: "matrx-alchemy-row-list", children: rows.rows.map((row, index) => {
2968
+ const summary = rows.columns.filter((column) => column.visible).slice(0, 2).map((column) => String(readTransferCell(row, column) ?? "")).filter(Boolean).join(" \xB7 ");
2969
+ return /* @__PURE__ */ jsxs13("label", { children: [
2970
+ /* @__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) }) }),
2971
+ " Row ",
2972
+ index + 1,
2973
+ summary ? ` \u2014 ${summary}` : ""
2974
+ ] }, index);
2975
+ }) })
2976
+ ] })
2913
2977
  ] })
2914
2978
  ] });
2915
2979
  }
@@ -3061,7 +3125,7 @@ function MatrxCopyMenuSession(props) {
3061
3125
  if (aiVisible && props.aiCustom)
3062
3126
  actions.push({
3063
3127
  id: "configure-source",
3064
- label: props.aiCustom.label ?? "Customize source\u2026",
3128
+ label: props.aiCustom.label ?? "Customize source",
3065
3129
  ...props.aiCustom.hint ? { hint: props.aiCustom.hint } : {},
3066
3130
  supports: () => true,
3067
3131
  run: async () => {
@@ -3072,7 +3136,7 @@ function MatrxCopyMenuSession(props) {
3072
3136
  if (aiVisible && props.groomer)
3073
3137
  actions.push({
3074
3138
  id: "groom-source",
3075
- label: "Customize sections\u2026",
3139
+ label: "Customize sections",
3076
3140
  supports: () => true,
3077
3141
  run: async () => {
3078
3142
  setConfiguration({ groomer: props.groomer() });
@@ -3182,7 +3246,8 @@ function MatrxCopyMenuSession(props) {
3182
3246
  className: cn(
3183
3247
  props.className,
3184
3248
  props.size === "xs" && "matrx-alchemy-xs",
3185
- props.size === "sm" && "matrx-alchemy-sm"
3249
+ props.size === "sm" && "matrx-alchemy-sm",
3250
+ props.size === "toolbar" && "matrx-alchemy-toolbar-target"
3186
3251
  ),
3187
3252
  ...props.stopPropagation !== void 0 ? { stopPropagation: props.stopPropagation } : {}
3188
3253
  }
@@ -3287,127 +3352,132 @@ function SourceConfiguration({
3287
3352
  event.preventDefault();
3288
3353
  if (!handingOff.current) restoreFocus();
3289
3354
  },
3290
- className: "matrx-alchemy-workspace",
3355
+ className: "matrx-alchemy-workspace matrx-alchemy-configuration",
3291
3356
  children: [
3292
3357
  /* @__PURE__ */ jsxs14(DialogHeader, { children: [
3293
3358
  /* @__PURE__ */ jsx22(DialogTitle, { children: title }),
3294
3359
  /* @__PURE__ */ jsx22(DialogDescription, { children: custom?.dialogDescription ?? "Choose the source detail, then prepare, edit, summarize, copy or export it in Alchemy." })
3295
3360
  ] }),
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(
3361
+ /* @__PURE__ */ jsxs14("div", { className: "matrx-alchemy-workspace-body", children: [
3362
+ /* @__PURE__ */ jsxs14("div", { className: "matrx-alchemy-main matrx-alchemy-toolbar", children: [
3363
+ custom?.options.map((option) => /* @__PURE__ */ jsxs14("label", { children: [
3364
+ option.label,
3365
+ "hint" in option && option.hint ? /* @__PURE__ */ jsx22("small", { children: option.hint }) : null,
3366
+ option.kind === "toggle" ? /* @__PURE__ */ jsx22(
3319
3367
  "input",
3320
3368
  {
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
- })
3369
+ type: "checkbox",
3370
+ checked: Boolean(values[option.key]),
3371
+ onChange: (event) => setValues({ ...values, [option.key]: event.target.checked })
3330
3372
  }
3331
- ),
3332
- /* @__PURE__ */ jsx22("span", { children: option.formatValue(Number(values[option.key])) })
3333
- ] }) : /* @__PURE__ */ jsxs14(Fragment3, { children: [
3334
- /* @__PURE__ */ jsx22(
3335
- "input",
3373
+ ) : option.kind === "preset" ? /* @__PURE__ */ jsx22(
3374
+ "select",
3336
3375
  {
3337
- type: "number",
3338
- min: option.min,
3339
- step: option.step,
3340
3376
  value: Number(values[option.key]),
3341
3377
  onChange: (event) => setValues({
3342
3378
  ...values,
3343
3379
  [option.key]: Number(event.target.value)
3344
- })
3380
+ }),
3381
+ children: option.options.map((choice) => /* @__PURE__ */ jsx22("option", { value: choice.value, children: choice.label }, choice.value))
3345
3382
  }
3346
- ),
3347
- option.presets?.map((preset) => /* @__PURE__ */ jsx22(
3383
+ ) : option.kind === "slider" ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
3384
+ /* @__PURE__ */ jsx22(
3385
+ "input",
3386
+ {
3387
+ type: "range",
3388
+ min: 0,
3389
+ max: Math.max(0, option.stops.length - 1),
3390
+ step: 1,
3391
+ value: option.stops.indexOf(Number(values[option.key])),
3392
+ onChange: (event) => setValues({
3393
+ ...values,
3394
+ [option.key]: option.stops[Number(event.target.value)]
3395
+ })
3396
+ }
3397
+ ),
3398
+ /* @__PURE__ */ jsx22("span", { children: option.formatValue(Number(values[option.key])) })
3399
+ ] }) : /* @__PURE__ */ jsxs14(Fragment3, { children: [
3400
+ /* @__PURE__ */ jsx22(
3401
+ "input",
3402
+ {
3403
+ type: "number",
3404
+ min: option.min,
3405
+ step: option.step,
3406
+ value: Number(values[option.key]),
3407
+ onChange: (event) => setValues({
3408
+ ...values,
3409
+ [option.key]: Number(event.target.value)
3410
+ })
3411
+ }
3412
+ ),
3413
+ option.presets?.map((preset) => /* @__PURE__ */ jsx22(
3414
+ Button,
3415
+ {
3416
+ type: "button",
3417
+ variant: "ghost",
3418
+ className: "matrx-alchemy-workspace-secondary",
3419
+ onClick: () => setValues({ ...values, [option.key]: preset.value }),
3420
+ children: preset.label
3421
+ },
3422
+ preset.value
3423
+ ))
3424
+ ] })
3425
+ ] }, option.key)),
3426
+ groomer ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
3427
+ /* @__PURE__ */ jsx22("div", { children: ["full", "compact", "brief"].map((level) => /* @__PURE__ */ jsx22(
3348
3428
  Button,
3349
3429
  {
3350
3430
  type: "button",
3351
3431
  variant: "ghost",
3352
- onClick: () => setValues({ ...values, [option.key]: preset.value }),
3353
- children: preset.label
3432
+ className: "matrx-alchemy-workspace-secondary",
3433
+ onClick: () => setSections(
3434
+ Object.fromEntries(
3435
+ groomer.sections.map((section) => [
3436
+ section.id,
3437
+ level === "brief" && section.cuttable ? "off" : level
3438
+ ])
3439
+ )
3440
+ ),
3441
+ children: level
3354
3442
  },
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
- )
3443
+ level
3444
+ )) }),
3445
+ groomer.sections.map((section) => /* @__PURE__ */ jsxs14("label", { children: [
3446
+ section.title,
3447
+ /* @__PURE__ */ jsxs14(
3448
+ "select",
3449
+ {
3450
+ value: sections[section.id],
3451
+ onChange: (event) => setSections({
3452
+ ...sections,
3453
+ [section.id]: event.target.value
3454
+ }),
3455
+ children: [
3456
+ ["full", "compact", "brief"].map((level) => /* @__PURE__ */ jsx22("option", { value: level, children: section.levelLabels?.[level] ?? level }, level)),
3457
+ section.cuttable ? /* @__PURE__ */ jsx22("option", { value: "off", children: "Exclude" }) : null
3458
+ ]
3459
+ }
3372
3460
  ),
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"
3461
+ section.description ? /* @__PURE__ */ jsx22("span", { children: section.description }) : null
3462
+ ] }, section.id))
3463
+ ] }) : null
3464
+ ] }),
3465
+ /* @__PURE__ */ jsxs14("p", { children: [
3466
+ text.length.toLocaleString(),
3467
+ " characters \xB7 approximately",
3468
+ " ",
3469
+ Math.ceil(text.length / 4).toLocaleString(),
3470
+ " tokens"
3471
+ ] }),
3472
+ error || buildError ? /* @__PURE__ */ jsx22("p", { role: "alert", children: error ?? buildError }) : null
3403
3473
  ] }),
3404
- error || buildError ? /* @__PURE__ */ jsx22("p", { role: "alert", children: error ?? buildError }) : null,
3405
3474
  /* @__PURE__ */ jsxs14(DialogFooter, { children: [
3406
3475
  /* @__PURE__ */ jsx22(
3407
3476
  Button,
3408
3477
  {
3409
3478
  type: "button",
3410
3479
  variant: "ghost",
3480
+ className: "matrx-alchemy-workspace-secondary",
3411
3481
  disabled: busy,
3412
3482
  onClick: onClose,
3413
3483
  children: "Cancel"
@@ -3417,6 +3487,7 @@ function SourceConfiguration({
3417
3487
  Button,
3418
3488
  {
3419
3489
  type: "button",
3490
+ className: "matrx-alchemy-workspace-primary",
3420
3491
  disabled: busy || !prepared || Boolean(buildError),
3421
3492
  onClick: async () => {
3422
3493
  if (!prepared) return;
@@ -4031,7 +4102,7 @@ function CopySubsetDialog({ source, onClose }) {
4031
4102
  ] }) });
4032
4103
  }
4033
4104
  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 });
4105
+ 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
4106
  }
4036
4107
 
4037
4108
  // src/data-table/clipping.ts
@@ -6751,6 +6822,23 @@ function safeQueryPage(requestedPage, totalItems, pageSize) {
6751
6822
 
6752
6823
  // src/data-table/MatrxDataTable.tsx
6753
6824
  import { Fragment as Fragment7, jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
6825
+ function TableToolbarAction({
6826
+ HostAction,
6827
+ ariaLabel,
6828
+ tooltip,
6829
+ disabled,
6830
+ busy,
6831
+ onClick,
6832
+ children
6833
+ }) {
6834
+ if (HostAction) {
6835
+ return /* @__PURE__ */ jsx35(HostAction, { ariaLabel, tooltip, disabled, busy, onClick, children });
6836
+ }
6837
+ return /* @__PURE__ */ jsxs26(Tooltip, { children: [
6838
+ /* @__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 }) }) }),
6839
+ /* @__PURE__ */ jsx35(TooltipContent, { children: tooltip ?? ariaLabel })
6840
+ ] });
6841
+ }
6754
6842
  function hasSameRowReferences(previous, next) {
6755
6843
  return previous.length === next.length && previous.every((row, index) => row === next[index]);
6756
6844
  }
@@ -8188,29 +8276,21 @@ function MatrxDataTableCore({
8188
8276
  ]
8189
8277
  }
8190
8278
  ) : 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
- ] }),
8279
+ /* @__PURE__ */ jsx35(
8280
+ TableToolbarAction,
8281
+ {
8282
+ HostAction: host.ToolbarAction,
8283
+ ariaLabel: "Clear all filters",
8284
+ tooltip: hasActiveFilters ? "Clear search and filters; keep columns and sort" : "No search or filters to clear",
8285
+ disabled: !hasActiveFilters,
8286
+ onClick: clearAllFilters,
8287
+ children: /* @__PURE__ */ jsx35(Eraser, {})
8288
+ }
8289
+ ),
8210
8290
  showToolbarCopy && effectiveCopy ? /* @__PURE__ */ jsx35(
8211
8291
  CopyButtons,
8212
8292
  {
8213
- size: "icon",
8293
+ size: "toolbar",
8214
8294
  sourceId: `${tableCopySourceNamespace}:view`,
8215
8295
  label: effectiveCopy.listLabel ?? `${effectiveCopy.label} view`,
8216
8296
  ...copy === void 0 ? {} : {
@@ -8247,92 +8327,66 @@ function MatrxDataTableCore({
8247
8327
  }
8248
8328
  }
8249
8329
  ) : 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,
8330
+ columns.length > 0 ? /* @__PURE__ */ jsx35(
8331
+ TableToolbarAction,
8332
+ {
8333
+ HostAction: host.ToolbarAction,
8334
+ ariaLabel: "Columns",
8335
+ tooltip: "Show, hide, or reorder columns",
8336
+ onClick: () => setColumnManagerOpen(true),
8337
+ children: /* @__PURE__ */ jsx35(SlidersHorizontal, {})
8338
+ }
8339
+ ) : null,
8340
+ toolbar?.refresh ? /* @__PURE__ */ jsx35(
8341
+ TableToolbarAction,
8342
+ {
8343
+ HostAction: host.ToolbarAction,
8344
+ ariaLabel: toolbar.refresh.label ?? "Refresh",
8345
+ tooltip: isFetching ? "Refreshing table data" : toolbar.refresh.label ?? "Refresh",
8346
+ disabled: isFetching || toolbarActionPending.refresh,
8347
+ busy: isFetching || toolbarActionPending.refresh,
8348
+ onClick: () => {
8349
+ if (toolbarActionPendingRef.current.refresh) return;
8350
+ toolbarActionPendingRef.current.refresh = true;
8351
+ setToolbarActionPending((current) => ({ ...current, refresh: true }));
8352
+ setToolbarActionError(null);
8353
+ void Promise.resolve().then(() => toolbar.refresh?.onRefresh()).catch((cause) => {
8354
+ const message = cause instanceof Error ? cause.message : String(cause);
8355
+ setToolbarActionError(`Refresh failed: ${message}`);
8356
+ toast.error(`Refresh failed: ${message}`);
8357
+ }).finally(() => {
8358
+ toolbarActionPendingRef.current.refresh = false;
8359
+ setToolbarActionPending((current) => ({ ...current, refresh: false }));
8360
+ });
8361
+ },
8362
+ children: /* @__PURE__ */ jsx35(RefreshControlIcon, { spinning: isFetching || toolbarActionPending.refresh })
8363
+ }
8364
+ ) : null,
8365
+ toolbar?.add ? /* @__PURE__ */ jsx35(
8366
+ TableToolbarAction,
8367
+ {
8368
+ HostAction: host.ToolbarAction,
8369
+ ariaLabel: "Add",
8370
+ tooltip: toolbar.add.disabled ? toolbar.add.disabledReason ?? "Add unavailable" : "Add",
8371
+ disabled: toolbar.add.disabled || toolbarActionPending.add,
8372
+ busy: toolbarActionPending.add,
8373
+ onClick: () => {
8374
+ if (toolbarActionPendingRef.current.add) return;
8375
+ toolbarActionPendingRef.current.add = true;
8376
+ setToolbarActionPending((current) => ({ ...current, add: true }));
8377
+ setToolbarActionError(null);
8378
+ void Promise.resolve().then(() => toolbar.add?.onAdd()).catch((cause) => {
8379
+ const message = cause instanceof Error ? cause.message : String(cause);
8380
+ setToolbarActionError(`Add failed: ${message}`);
8381
+ toast.error(`Add failed: ${message}`);
8382
+ }).finally(() => {
8383
+ toolbarActionPendingRef.current.add = false;
8384
+ setToolbarActionPending((current) => ({ ...current, add: false }));
8385
+ });
8386
+ },
8387
+ children: /* @__PURE__ */ jsx35(Plus, {})
8388
+ }
8389
+ ) : null,
8336
8390
  toolbar?.actions
8337
8391
  ]
8338
8392
  }
@@ -8455,13 +8509,13 @@ function MatrxDataTableCore({
8455
8509
  actions: showRowCopy || rowActions ? /* @__PURE__ */ jsxs26(
8456
8510
  "div",
8457
8511
  {
8458
- className: "inline-flex items-center gap-1",
8512
+ className: "inline-flex items-center gap-0",
8459
8513
  onClick: (event) => event.stopPropagation(),
8460
8514
  children: [
8461
8515
  showRowCopy && effectiveCopy ? /* @__PURE__ */ jsx35(
8462
8516
  TableRowCopyControl,
8463
8517
  {
8464
- size: "xs",
8518
+ size: "toolbar",
8465
8519
  copy: effectiveCopy,
8466
8520
  row: displayRow,
8467
8521
  sourceId: `${tableCopySourceNamespace}:row:${getRowId(displayRow)}`,
@@ -8758,13 +8812,13 @@ function MatrxDataTableCore({
8758
8812
  showActionsCol && /* @__PURE__ */ jsx35("td", { className: "px-2 py-1.5 text-right align-middle lg:py-0.5", children: /* @__PURE__ */ jsxs26(
8759
8813
  "div",
8760
8814
  {
8761
- className: "inline-flex items-center justify-end gap-0.5",
8815
+ className: "inline-flex items-center justify-end gap-0",
8762
8816
  onClick: (e) => e.stopPropagation(),
8763
8817
  children: [
8764
8818
  showRowCopy && effectiveCopy ? /* @__PURE__ */ jsx35(
8765
8819
  TableRowCopyControl,
8766
8820
  {
8767
- size: "xs",
8821
+ size: "toolbar",
8768
8822
  copy: effectiveCopy,
8769
8823
  row: displayRow,
8770
8824
  sourceId: `${tableCopySourceNamespace}:row:${getRowId(displayRow)}`,
@@ -9458,7 +9512,7 @@ function resolveStringTitle(title, fallback) {
9458
9512
  }
9459
9513
 
9460
9514
  // src/data-table/SavedViewsControl.tsx
9461
- import { useState as useState16 } from "react";
9515
+ import { useId as useId3, useState as useState16 } from "react";
9462
9516
 
9463
9517
  // src/dropdown-menu.tsx
9464
9518
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
@@ -9601,6 +9655,7 @@ function SavedViewsControl({
9601
9655
  onUpdate,
9602
9656
  onReload
9603
9657
  }) {
9658
+ const unsavedChangesId = useId3();
9604
9659
  const [saveOpen, setSaveOpen] = useState16(false);
9605
9660
  const [name, setName] = useState16("");
9606
9661
  const [saving, setSaving] = useState16(false);
@@ -9646,10 +9701,26 @@ function SavedViewsControl({
9646
9701
  }
9647
9702
  };
9648
9703
  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: [
9704
+ return /* @__PURE__ */ jsxs28("div", { className: "flex min-w-0 flex-wrap items-center gap-1", "data-matrx-table-saved-views": true, children: [
9650
9705
  /* @__PURE__ */ jsxs28(DropdownMenu, { children: [
9651
9706
  /* @__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" : ""}` }) }) }),
9707
+ /* @__PURE__ */ jsx37(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx37(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs28(
9708
+ Button,
9709
+ {
9710
+ type: "button",
9711
+ variant: "ghost",
9712
+ size: "sm",
9713
+ className: "h-8 min-w-0 max-w-52 gap-1 px-2 text-xs font-medium",
9714
+ "aria-label": `Table view: ${loading ? "Loading views" : activeName ?? "Default view"}${dirty ? ", unsaved changes" : ""}`,
9715
+ "aria-describedby": dirty ? unsavedChangesId : void 0,
9716
+ disabled: saving,
9717
+ children: [
9718
+ /* @__PURE__ */ jsx37("span", { className: "min-w-0 flex-1 truncate", children: loading ? "Loading views\u2026" : activeName ?? "Default view" }),
9719
+ dirty ? /* @__PURE__ */ jsx37("span", { "aria-hidden": "true", className: "size-1.5 shrink-0 rounded-full bg-amber-500" }) : null,
9720
+ /* @__PURE__ */ jsx37(ChevronDown, { className: "size-3.5 shrink-0" })
9721
+ ]
9722
+ }
9723
+ ) }) }),
9653
9724
  /* @__PURE__ */ jsx37(TooltipContent, { children: "Choose or save a table view" })
9654
9725
  ] }),
9655
9726
  /* @__PURE__ */ jsxs28(DropdownMenuContent, { align: "end", children: [
@@ -9667,14 +9738,8 @@ function SavedViewsControl({
9667
9738
  onReload ? /* @__PURE__ */ jsx37(DropdownMenuItem, { disabled: saving || loading, onSelect: () => void reload(), children: "Reload views" }) : null
9668
9739
  ] })
9669
9740
  ] }),
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,
9741
+ 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,
9742
+ visibleError ? /* @__PURE__ */ jsx37("p", { role: "alert", className: "basis-full break-words text-xs text-destructive", children: visibleError }) : null,
9678
9743
  /* @__PURE__ */ jsx37(Dialog, { open: saveOpen, onOpenChange: setSaveOpen, children: /* @__PURE__ */ jsxs28(DialogContent, { children: [
9679
9744
  /* @__PURE__ */ jsx37(DialogHeader, { children: /* @__PURE__ */ jsx37(DialogTitle, { children: "Save current view" }) }),
9680
9745
  visibleError ? /* @__PURE__ */ jsx37("p", { role: "alert", className: "text-sm text-destructive", children: visibleError }) : null,