@ai-matrx/design-system 0.18.9 → 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 (68) hide show
  1. package/CHANGELOG.md +34 -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 +442 -447
  10. package/dist/content-transfer.cjs.map +1 -1
  11. package/dist/content-transfer.css +130 -54
  12. package/dist/content-transfer.d.cts +5 -1
  13. package/dist/content-transfer.d.ts +5 -1
  14. package/dist/content-transfer.js +467 -472
  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 +444 -446
  22. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  23. package/dist/data-table/data-row-inspector.js +489 -491
  24. package/dist/data-table/data-row-inspector.js.map +1 -1
  25. package/dist/data-table/data-row-window.cjs +444 -446
  26. package/dist/data-table/data-row-window.cjs.map +1 -1
  27. package/dist/data-table/data-row-window.js +489 -491
  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 +17 -1
  33. package/dist/data-table/host.d.ts +17 -1
  34. package/dist/data-table/host.js.map +1 -1
  35. package/dist/data-table/index.cjs +1524 -1011
  36. package/dist/data-table/index.cjs.map +1 -1
  37. package/dist/data-table/index.d.cts +25 -4
  38. package/dist/data-table/index.d.ts +25 -4
  39. package/dist/data-table/index.js +1560 -1047
  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 +5 -5
  46. package/dist/data-table/pagination.cjs.map +1 -1
  47. package/dist/data-table/pagination.js +5 -5
  48. package/dist/data-table/pagination.js.map +1 -1
  49. package/dist/data-table/query-control.d.cts +1 -1
  50. package/dist/data-table/query-control.d.ts +1 -1
  51. package/dist/data-table/types.cjs.map +1 -1
  52. package/dist/data-table/types.d.cts +1 -1
  53. package/dist/data-table/types.d.ts +1 -1
  54. package/dist/data-table/url-state.d.cts +1 -1
  55. package/dist/data-table/url-state.d.ts +1 -1
  56. package/dist/data-table/uuid-cell.cjs.map +1 -1
  57. package/dist/data-table/uuid-cell.js.map +1 -1
  58. package/dist/data-table/xlsx.d.cts +1 -1
  59. package/dist/data-table/xlsx.d.ts +1 -1
  60. package/dist/index.cjs +5 -5
  61. package/dist/index.cjs.map +1 -1
  62. package/dist/index.js +5 -5
  63. package/dist/index.js.map +1 -1
  64. package/dist/styles.css +4 -0
  65. package/dist/tokens.css +2 -0
  66. package/dist/{types-cH8oLqUx.d.ts → types-BuDKVpeF.d.ts} +47 -3
  67. package/dist/{types-0CNCWvdK.d.cts → types-Dqcb7jXO.d.cts} +47 -3
  68. package/package.json +2 -2
@@ -156,48 +156,6 @@ function XIcon(props) {
156
156
  /* @__PURE__ */ jsx2("path", { d: "m6 6 12 12" })
157
157
  ] });
158
158
  }
159
- function radixProps(props) {
160
- return {
161
- xmlns: "http://www.w3.org/2000/svg",
162
- viewBox: "0 0 15 15",
163
- width: 15,
164
- height: 15,
165
- fill: "none",
166
- "aria-hidden": true,
167
- ...props
168
- };
169
- }
170
- function CheckIcon(props) {
171
- return /* @__PURE__ */ jsx2("svg", { ...radixProps(props), children: /* @__PURE__ */ jsx2(
172
- "path",
173
- {
174
- d: "M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z",
175
- fill: "currentColor",
176
- fillRule: "evenodd",
177
- clipRule: "evenodd"
178
- }
179
- ) });
180
- }
181
- function DotFilledIcon(props) {
182
- return /* @__PURE__ */ jsx2("svg", { ...radixProps(props), children: /* @__PURE__ */ jsx2(
183
- "path",
184
- {
185
- d: "M9.875 7.5C9.875 8.81168 8.81168 9.875 7.5 9.875C6.18832 9.875 5.125 8.81168 5.125 7.5C5.125 6.18832 6.18832 5.125 7.5 5.125C8.81168 5.125 9.875 6.18832 9.875 7.5Z",
186
- fill: "currentColor"
187
- }
188
- ) });
189
- }
190
- function RadixChevronRightIcon(props) {
191
- return /* @__PURE__ */ jsx2("svg", { ...radixProps(props), children: /* @__PURE__ */ jsx2(
192
- "path",
193
- {
194
- d: "M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.6151 7.15788C10.7954 7.3502 10.7954 7.64949 10.6151 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z",
195
- fill: "currentColor",
196
- fillRule: "evenodd",
197
- clipRule: "evenodd"
198
- }
199
- ) });
200
- }
201
159
 
202
160
  // src/portal-container.tsx
203
161
  import * as React2 from "react";
@@ -461,135 +419,49 @@ var DialogDescription = React5.forwardRef(({ className, ...props }, ref) => /* @
461
419
  ));
462
420
  DialogDescription.displayName = DialogPrimitive.Description.displayName;
463
421
 
464
- // src/dropdown-menu.tsx
465
- import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
422
+ // src/popover.tsx
423
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
466
424
  import * as React6 from "react";
467
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
468
- var DropdownMenu = DropdownMenuPrimitive.Root;
469
- var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
470
- var MENU_SURFACE_CLASS = "z-[10001] min-w-[8rem] max-h-[var(--radix-dropdown-menu-content-available-height)] overflow-y-auto overflow-x-hidden overscroll-contain rounded-md border bg-popover p-1 text-popover-foreground";
471
- var MENU_ITEM_CLASS = "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
472
- var MENU_INDICATOR_ITEM_CLASS = "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
473
- var DropdownMenuSubTrigger = React6.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs3(
474
- DropdownMenuPrimitive.SubTrigger,
475
- {
476
- ref,
477
- "data-slot": "dropdown-menu-sub-trigger",
478
- className: cn(
479
- "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
480
- inset && "pl-8",
481
- className
482
- ),
483
- ...props,
484
- children: [
485
- children,
486
- /* @__PURE__ */ jsx6(RadixChevronRightIcon, { className: "ml-auto h-4 w-4" })
487
- ]
488
- }
489
- ));
490
- DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
491
- var DropdownMenuSubContent = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
492
- DropdownMenuPrimitive.SubContent,
493
- {
494
- ref,
495
- "data-slot": "dropdown-menu-sub-content",
496
- className: cn(MENU_SURFACE_CLASS, "shadow-lg", MOTION_POPPER, className),
497
- ...props
498
- }
499
- ));
500
- DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
501
- var DropdownMenuContent = React6.forwardRef(({ className, sideOffset = 4, container, ...props }, ref) => {
502
- const portalContainer = usePortalContainer(container);
503
- return /* @__PURE__ */ jsx6(DropdownMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx6(
504
- DropdownMenuPrimitive.Content,
505
- {
506
- ref,
507
- "data-slot": "dropdown-menu-content",
508
- sideOffset,
509
- className: cn(
510
- MENU_SURFACE_CLASS,
511
- "shadow-md",
512
- MOTION_POPPER,
513
- className
514
- ),
515
- ...props
516
- }
517
- ) });
518
- });
519
- DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
520
- var DropdownMenuItem = React6.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx6(
521
- DropdownMenuPrimitive.Item,
522
- {
523
- ref,
524
- "data-slot": "dropdown-menu-item",
525
- className: cn(MENU_ITEM_CLASS, inset && "pl-8", className),
526
- ...props
527
- }
528
- ));
529
- DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
530
- var DropdownMenuCheckboxItem = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs3(
531
- DropdownMenuPrimitive.CheckboxItem,
532
- {
533
- ref,
534
- "data-slot": "dropdown-menu-checkbox-item",
535
- className: cn(MENU_INDICATOR_ITEM_CLASS, className),
536
- ...props,
537
- children: [
538
- /* @__PURE__ */ jsx6("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx6(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx6(CheckIcon, { className: "h-4 w-4" }) }) }),
539
- children
540
- ]
541
- }
542
- ));
543
- DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
544
- var DropdownMenuRadioItem = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs3(
545
- DropdownMenuPrimitive.RadioItem,
546
- {
547
- ref,
548
- "data-slot": "dropdown-menu-radio-item",
549
- className: cn(MENU_INDICATOR_ITEM_CLASS, className),
550
- ...props,
551
- children: [
552
- /* @__PURE__ */ jsx6("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx6(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx6(DotFilledIcon, { className: "h-4 w-4 fill-current" }) }) }),
553
- children
554
- ]
555
- }
556
- ));
557
- DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
558
- var DropdownMenuLabel = React6.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx6(
559
- DropdownMenuPrimitive.Label,
560
- {
561
- ref,
562
- "data-slot": "dropdown-menu-label",
563
- className: cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className),
564
- ...props
565
- }
566
- ));
567
- DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
568
- var DropdownMenuSeparator = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
569
- DropdownMenuPrimitive.Separator,
570
- {
571
- ref,
572
- "data-slot": "dropdown-menu-separator",
573
- className: cn("-mx-1 my-1 h-px bg-muted", className),
574
- ...props
575
- }
576
- ));
577
- DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
578
- var DropdownMenuShortcut = ({
579
- className,
580
- ...props
581
- }) => /* @__PURE__ */ jsx6(
582
- "span",
583
- {
584
- "data-slot": "dropdown-menu-shortcut",
585
- className: cn("ml-auto text-xs tracking-widest opacity-60", className),
425
+ import { jsx as jsx6 } from "react/jsx-runtime";
426
+ var Popover = PopoverPrimitive.Root;
427
+ var PopoverTrigger = PopoverPrimitive.Trigger;
428
+ var PopoverContent = React6.forwardRef(
429
+ ({
430
+ className,
431
+ align = "center",
432
+ sideOffset = 4,
433
+ container,
434
+ animated = true,
586
435
  ...props
436
+ }, ref) => {
437
+ const portalContainer = usePortalContainer(container);
438
+ return /* @__PURE__ */ jsx6(PopoverPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx6(
439
+ PopoverPrimitive.Content,
440
+ {
441
+ ref,
442
+ align,
443
+ sideOffset,
444
+ className: cn(
445
+ // Cap to the viewport space Radix measured and scroll — a popover taller
446
+ // than the screen must never trap the user with unreachable content.
447
+ // z must EQUAL the dialog layer (z-[10000]), never exceed it: with equal
448
+ // z, DOM portal order decides, so a dialog opened FROM a popover stacks
449
+ // above it, and a popover opened from a dialog still stacks above the
450
+ // dialog. z-[10001] buried dialogs behind fullscreen popovers.
451
+ "z-[10000] w-72 max-h-[var(--radix-popover-content-available-height)] overflow-y-auto overscroll-contain rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
452
+ animated && MOTION_POPPER,
453
+ className
454
+ ),
455
+ ...props
456
+ }
457
+ ) });
587
458
  }
588
459
  );
589
- DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
460
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
590
461
 
591
462
  // src/content-transfer/icon.ts
592
- 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"><path d="M4.5 5.5h8v11h-8z"/><path d="M8.5 9.5h8v9h-8z"/><path d="m18.5 3 .65 1.85L21 5.5l-1.85.65L18.5 8l-.65-1.85L16 5.5l1.85-.65z"/></svg>';
463
+ 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"];
464
+ 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>`;
593
465
 
594
466
  // src/content-transfer/matrx-copy.tsx
595
467
  import * as React7 from "react";
@@ -600,7 +472,7 @@ import {
600
472
  normalizeTransferJson,
601
473
  sealTransferArtifact
602
474
  } from "@ai-matrx/kit/content-transfer";
603
- import { Fragment, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
475
+ import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
604
476
  var resolve = (value) => typeof value === "function" ? value() : value;
605
477
  var asPayload = (value) => ({
606
478
  kind: "markdown",
@@ -746,7 +618,7 @@ function MatrxCopyMenuSession(props) {
746
618
  if (aiVisible && props.aiCustom)
747
619
  actions.push({
748
620
  id: "configure-source",
749
- label: props.aiCustom.label ?? "Customize source\u2026",
621
+ label: props.aiCustom.label ?? "Customize source",
750
622
  ...props.aiCustom.hint ? { hint: props.aiCustom.hint } : {},
751
623
  supports: () => true,
752
624
  run: async () => {
@@ -757,7 +629,7 @@ function MatrxCopyMenuSession(props) {
757
629
  if (aiVisible && props.groomer)
758
630
  actions.push({
759
631
  id: "groom-source",
760
- label: "Customize sections\u2026",
632
+ label: "Customize sections",
761
633
  supports: () => true,
762
634
  run: async () => {
763
635
  setConfiguration({ groomer: props.groomer() });
@@ -771,6 +643,7 @@ function MatrxCopyMenuSession(props) {
771
643
  label: item.label,
772
644
  supports: () => true,
773
645
  ...item.build && !item.onSelect ? {
646
+ placement: "download",
774
647
  source: make(
775
648
  `export:${item.id}`,
776
649
  async () => {
@@ -842,7 +715,7 @@ function MatrxCopyMenuSession(props) {
842
715
  const source = (props.primarySource === "table" ? table : void 0) ?? json ?? table ?? structuredAgent ?? human ?? builderVariants[0]?.source;
843
716
  if (!source && !actions.length) return null;
844
717
  const target = source ?? make("actions", () => ({ kind: "text", text: props.label }));
845
- return /* @__PURE__ */ jsxs4(Fragment, { children: [
718
+ return /* @__PURE__ */ jsxs3(Fragment, { children: [
846
719
  /* @__PURE__ */ jsx7(
847
720
  ContentTransferMenu,
848
721
  {
@@ -851,10 +724,11 @@ function MatrxCopyMenuSession(props) {
851
724
  label: props.label,
852
725
  variants,
853
726
  actions,
727
+ sourceFormats: Boolean(source),
854
728
  hide: [
855
729
  ...!copyVisible || !source ? ["copy"] : [],
856
730
  ...!aiVisible || !source ? ["prepare"] : [],
857
- ...!exportVisible || !source ? ["download"] : []
731
+ ...!exportVisible ? ["download"] : []
858
732
  ],
859
733
  formatSources: {
860
734
  ...human ? { plain: human, markdown: humanMarkdown, html: humanMarkdown } : {},
@@ -865,7 +739,8 @@ function MatrxCopyMenuSession(props) {
865
739
  className: cn(
866
740
  props.className,
867
741
  props.size === "xs" && "matrx-alchemy-xs",
868
- props.size === "sm" && "matrx-alchemy-sm"
742
+ props.size === "sm" && "matrx-alchemy-sm",
743
+ props.size === "toolbar" && "matrx-alchemy-toolbar-target"
869
744
  ),
870
745
  ...props.stopPropagation !== void 0 ? { stopPropagation: props.stopPropagation } : {}
871
746
  }
@@ -963,134 +838,139 @@ function SourceConfiguration({
963
838
  onOpenChange: (open) => {
964
839
  if (!open && !busy) onClose();
965
840
  },
966
- children: /* @__PURE__ */ jsxs4(
841
+ children: /* @__PURE__ */ jsxs3(
967
842
  DialogContent,
968
843
  {
969
844
  onCloseAutoFocus: (event) => {
970
845
  event.preventDefault();
971
846
  if (!handingOff.current) restoreFocus();
972
847
  },
973
- className: "matrx-alchemy-workspace",
848
+ className: "matrx-alchemy-workspace matrx-alchemy-configuration",
974
849
  children: [
975
- /* @__PURE__ */ jsxs4(DialogHeader, { children: [
850
+ /* @__PURE__ */ jsxs3(DialogHeader, { children: [
976
851
  /* @__PURE__ */ jsx7(DialogTitle, { children: title }),
977
852
  /* @__PURE__ */ jsx7(DialogDescription, { children: custom?.dialogDescription ?? "Choose the source detail, then prepare, edit, summarize, copy or export it in Alchemy." })
978
853
  ] }),
979
- /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-main matrx-alchemy-toolbar", children: [
980
- custom?.options.map((option) => /* @__PURE__ */ jsxs4("label", { children: [
981
- option.label,
982
- "hint" in option && option.hint ? /* @__PURE__ */ jsx7("small", { children: option.hint }) : null,
983
- option.kind === "toggle" ? /* @__PURE__ */ jsx7(
984
- "input",
985
- {
986
- type: "checkbox",
987
- checked: Boolean(values[option.key]),
988
- onChange: (event) => setValues({ ...values, [option.key]: event.target.checked })
989
- }
990
- ) : option.kind === "preset" ? /* @__PURE__ */ jsx7(
991
- "select",
992
- {
993
- value: Number(values[option.key]),
994
- onChange: (event) => setValues({
995
- ...values,
996
- [option.key]: Number(event.target.value)
997
- }),
998
- children: option.options.map((choice) => /* @__PURE__ */ jsx7("option", { value: choice.value, children: choice.label }, choice.value))
999
- }
1000
- ) : option.kind === "slider" ? /* @__PURE__ */ jsxs4(Fragment, { children: [
1001
- /* @__PURE__ */ jsx7(
854
+ /* @__PURE__ */ jsxs3("div", { className: "matrx-alchemy-workspace-body", children: [
855
+ /* @__PURE__ */ jsxs3("div", { className: "matrx-alchemy-main matrx-alchemy-toolbar", children: [
856
+ custom?.options.map((option) => /* @__PURE__ */ jsxs3("label", { children: [
857
+ option.label,
858
+ "hint" in option && option.hint ? /* @__PURE__ */ jsx7("small", { children: option.hint }) : null,
859
+ option.kind === "toggle" ? /* @__PURE__ */ jsx7(
1002
860
  "input",
1003
861
  {
1004
- type: "range",
1005
- min: 0,
1006
- max: Math.max(0, option.stops.length - 1),
1007
- step: 1,
1008
- value: option.stops.indexOf(Number(values[option.key])),
1009
- onChange: (event) => setValues({
1010
- ...values,
1011
- [option.key]: option.stops[Number(event.target.value)]
1012
- })
862
+ type: "checkbox",
863
+ checked: Boolean(values[option.key]),
864
+ onChange: (event) => setValues({ ...values, [option.key]: event.target.checked })
1013
865
  }
1014
- ),
1015
- /* @__PURE__ */ jsx7("span", { children: option.formatValue(Number(values[option.key])) })
1016
- ] }) : /* @__PURE__ */ jsxs4(Fragment, { children: [
1017
- /* @__PURE__ */ jsx7(
1018
- "input",
866
+ ) : option.kind === "preset" ? /* @__PURE__ */ jsx7(
867
+ "select",
1019
868
  {
1020
- type: "number",
1021
- min: option.min,
1022
- step: option.step,
1023
869
  value: Number(values[option.key]),
1024
870
  onChange: (event) => setValues({
1025
871
  ...values,
1026
872
  [option.key]: Number(event.target.value)
1027
- })
873
+ }),
874
+ children: option.options.map((choice) => /* @__PURE__ */ jsx7("option", { value: choice.value, children: choice.label }, choice.value))
1028
875
  }
1029
- ),
1030
- option.presets?.map((preset) => /* @__PURE__ */ jsx7(
876
+ ) : option.kind === "slider" ? /* @__PURE__ */ jsxs3(Fragment, { children: [
877
+ /* @__PURE__ */ jsx7(
878
+ "input",
879
+ {
880
+ type: "range",
881
+ min: 0,
882
+ max: Math.max(0, option.stops.length - 1),
883
+ step: 1,
884
+ value: option.stops.indexOf(Number(values[option.key])),
885
+ onChange: (event) => setValues({
886
+ ...values,
887
+ [option.key]: option.stops[Number(event.target.value)]
888
+ })
889
+ }
890
+ ),
891
+ /* @__PURE__ */ jsx7("span", { children: option.formatValue(Number(values[option.key])) })
892
+ ] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
893
+ /* @__PURE__ */ jsx7(
894
+ "input",
895
+ {
896
+ type: "number",
897
+ min: option.min,
898
+ step: option.step,
899
+ value: Number(values[option.key]),
900
+ onChange: (event) => setValues({
901
+ ...values,
902
+ [option.key]: Number(event.target.value)
903
+ })
904
+ }
905
+ ),
906
+ option.presets?.map((preset) => /* @__PURE__ */ jsx7(
907
+ Button,
908
+ {
909
+ type: "button",
910
+ variant: "ghost",
911
+ className: "matrx-alchemy-workspace-secondary",
912
+ onClick: () => setValues({ ...values, [option.key]: preset.value }),
913
+ children: preset.label
914
+ },
915
+ preset.value
916
+ ))
917
+ ] })
918
+ ] }, option.key)),
919
+ groomer ? /* @__PURE__ */ jsxs3(Fragment, { children: [
920
+ /* @__PURE__ */ jsx7("div", { children: ["full", "compact", "brief"].map((level) => /* @__PURE__ */ jsx7(
1031
921
  Button,
1032
922
  {
1033
923
  type: "button",
1034
924
  variant: "ghost",
1035
- onClick: () => setValues({ ...values, [option.key]: preset.value }),
1036
- children: preset.label
925
+ className: "matrx-alchemy-workspace-secondary",
926
+ onClick: () => setSections(
927
+ Object.fromEntries(
928
+ groomer.sections.map((section) => [
929
+ section.id,
930
+ level === "brief" && section.cuttable ? "off" : level
931
+ ])
932
+ )
933
+ ),
934
+ children: level
1037
935
  },
1038
- preset.value
1039
- ))
1040
- ] })
1041
- ] }, option.key)),
1042
- groomer ? /* @__PURE__ */ jsxs4(Fragment, { children: [
1043
- /* @__PURE__ */ jsx7("div", { children: ["full", "compact", "brief"].map((level) => /* @__PURE__ */ jsx7(
1044
- Button,
1045
- {
1046
- type: "button",
1047
- variant: "ghost",
1048
- onClick: () => setSections(
1049
- Object.fromEntries(
1050
- groomer.sections.map((section) => [
1051
- section.id,
1052
- level === "brief" && section.cuttable ? "off" : level
1053
- ])
1054
- )
936
+ level
937
+ )) }),
938
+ groomer.sections.map((section) => /* @__PURE__ */ jsxs3("label", { children: [
939
+ section.title,
940
+ /* @__PURE__ */ jsxs3(
941
+ "select",
942
+ {
943
+ value: sections[section.id],
944
+ onChange: (event) => setSections({
945
+ ...sections,
946
+ [section.id]: event.target.value
947
+ }),
948
+ children: [
949
+ ["full", "compact", "brief"].map((level) => /* @__PURE__ */ jsx7("option", { value: level, children: section.levelLabels?.[level] ?? level }, level)),
950
+ section.cuttable ? /* @__PURE__ */ jsx7("option", { value: "off", children: "Exclude" }) : null
951
+ ]
952
+ }
1055
953
  ),
1056
- children: level
1057
- },
1058
- level
1059
- )) }),
1060
- groomer.sections.map((section) => /* @__PURE__ */ jsxs4("label", { children: [
1061
- section.title,
1062
- /* @__PURE__ */ jsxs4(
1063
- "select",
1064
- {
1065
- value: sections[section.id],
1066
- onChange: (event) => setSections({
1067
- ...sections,
1068
- [section.id]: event.target.value
1069
- }),
1070
- children: [
1071
- ["full", "compact", "brief"].map((level) => /* @__PURE__ */ jsx7("option", { value: level, children: section.levelLabels?.[level] ?? level }, level)),
1072
- section.cuttable ? /* @__PURE__ */ jsx7("option", { value: "off", children: "Exclude" }) : null
1073
- ]
1074
- }
1075
- ),
1076
- section.description ? /* @__PURE__ */ jsx7("span", { children: section.description }) : null
1077
- ] }, section.id))
1078
- ] }) : null
1079
- ] }),
1080
- /* @__PURE__ */ jsxs4("p", { children: [
1081
- text.length.toLocaleString(),
1082
- " characters \xB7 approximately",
1083
- " ",
1084
- Math.ceil(text.length / 4).toLocaleString(),
1085
- " tokens"
954
+ section.description ? /* @__PURE__ */ jsx7("span", { children: section.description }) : null
955
+ ] }, section.id))
956
+ ] }) : null
957
+ ] }),
958
+ /* @__PURE__ */ jsxs3("p", { children: [
959
+ text.length.toLocaleString(),
960
+ " characters \xB7 approximately",
961
+ " ",
962
+ Math.ceil(text.length / 4).toLocaleString(),
963
+ " tokens"
964
+ ] }),
965
+ error || buildError ? /* @__PURE__ */ jsx7("p", { role: "alert", children: error ?? buildError }) : null
1086
966
  ] }),
1087
- error || buildError ? /* @__PURE__ */ jsx7("p", { role: "alert", children: error ?? buildError }) : null,
1088
- /* @__PURE__ */ jsxs4(DialogFooter, { children: [
967
+ /* @__PURE__ */ jsxs3(DialogFooter, { children: [
1089
968
  /* @__PURE__ */ jsx7(
1090
969
  Button,
1091
970
  {
1092
971
  type: "button",
1093
972
  variant: "ghost",
973
+ className: "matrx-alchemy-workspace-secondary",
1094
974
  disabled: busy,
1095
975
  onClick: onClose,
1096
976
  children: "Cancel"
@@ -1100,6 +980,7 @@ function SourceConfiguration({
1100
980
  Button,
1101
981
  {
1102
982
  type: "button",
983
+ className: "matrx-alchemy-workspace-primary",
1103
984
  disabled: busy || !prepared || Boolean(buildError),
1104
985
  onClick: async () => {
1105
986
  if (!prepared) return;
@@ -1186,13 +1067,9 @@ function groomerPresetVariants(getConfig) {
1186
1067
  }
1187
1068
 
1188
1069
  // src/content-transfer/index.tsx
1189
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1070
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
1190
1071
  function AlchemyGlyph(props) {
1191
- return /* @__PURE__ */ jsxs5("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", ...props, children: [
1192
- /* @__PURE__ */ jsx8("path", { d: "M4.5 5.5h8v11h-8z" }),
1193
- /* @__PURE__ */ jsx8("path", { d: "M8.5 9.5h8v9h-8z" }),
1194
- /* @__PURE__ */ jsx8("path", { d: "m18.5 3 .65 1.85L21 5.5l-1.85.65L18.5 8l-.65-1.85L16 5.5l1.85-.65z" })
1195
- ] });
1072
+ return /* @__PURE__ */ jsx8("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__ */ jsx8("path", { d }, d)) });
1196
1073
  }
1197
1074
  var CapabilityContext = React8.createContext({});
1198
1075
  function ContentTransferCapabilitiesProvider({ value, children }) {
@@ -1205,14 +1082,70 @@ function ContentTransferSurfaceProvider({ handle, children }) {
1205
1082
  }
1206
1083
  var useContentTransferSurface = () => React8.useContext(SurfaceContext);
1207
1084
  function MenuPresentation({ label, hint, icon: Icon }) {
1208
- return /* @__PURE__ */ jsxs5(Fragment2, { children: [
1085
+ return /* @__PURE__ */ jsxs4(Fragment2, { children: [
1209
1086
  Icon ? /* @__PURE__ */ jsx8(Icon, { className: "matrx-alchemy-menu-icon" }) : null,
1210
- /* @__PURE__ */ jsxs5("span", { children: [
1087
+ /* @__PURE__ */ jsxs4("span", { children: [
1211
1088
  label,
1212
1089
  hint ? /* @__PURE__ */ jsx8("small", { className: "matrx-alchemy-menu-hint", children: hint }) : null
1213
1090
  ] })
1214
1091
  ] });
1215
1092
  }
1093
+ function PaletteGlyph({ format, ai = false, file = false, kind }) {
1094
+ if (kind === "ai-copy") return /* @__PURE__ */ jsxs4("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: [
1095
+ /* @__PURE__ */ jsx8("rect", { x: "5", y: "5", width: "11", height: "14", rx: "2" }),
1096
+ /* @__PURE__ */ jsx8("path", { d: "M9 3h6a2 2 0 0 1 2 2v10" }),
1097
+ /* @__PURE__ */ jsx8("path", { d: "m18.5 3 .55 1.45L20.5 5l-1.45.55L18.5 7l-.55-1.45L16.5 5l1.45-.55z" })
1098
+ ] });
1099
+ if (kind === "sliders") return /* @__PURE__ */ jsxs4("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: [
1100
+ /* @__PURE__ */ jsx8("path", { d: "M4 6h16M4 12h16M4 18h16" }),
1101
+ /* @__PURE__ */ jsx8("path", { d: "M8 3v6M16 9v6M10 15v6" })
1102
+ ] });
1103
+ if (ai) return /* @__PURE__ */ jsxs4("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: [
1104
+ /* @__PURE__ */ jsx8("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" }),
1105
+ /* @__PURE__ */ jsx8("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" }),
1106
+ /* @__PURE__ */ jsx8("path", { d: "M12 5v14M8 9h1M15 9h1M8 15h1M15 15h1" })
1107
+ ] });
1108
+ if (file) return /* @__PURE__ */ jsxs4("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: [
1109
+ /* @__PURE__ */ jsx8("path", { d: "M6 3h8l4 4v14H6z" }),
1110
+ /* @__PURE__ */ jsx8("path", { d: "M14 3v5h5M9 13h6M9 17h6" })
1111
+ ] });
1112
+ const path = format === "json" ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1113
+ /* @__PURE__ */ jsx8("path", { d: "M9 4C7 4 7 7 5 7v3c2 0 2 1 2 2s0 2-2 2v3c2 0 2 3 4 3" }),
1114
+ /* @__PURE__ */ jsx8("path", { d: "M15 4c2 0 2 3 4 3v3c-2 0-2 1-2 2s0 2 2 2v3c-2 0-2 3-4 3" })
1115
+ ] }) : format === "compact-json" ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1116
+ /* @__PURE__ */ jsx8("path", { d: "m14 10 7-7" }),
1117
+ /* @__PURE__ */ jsx8("path", { d: "M20 10h-6V4" }),
1118
+ /* @__PURE__ */ jsx8("path", { d: "m3 21 7-7" }),
1119
+ /* @__PURE__ */ jsx8("path", { d: "M4 14h6v6" })
1120
+ ] }) : format === "csv" ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1121
+ /* @__PURE__ */ jsx8("rect", { x: "4", y: "4", width: "16", height: "16", rx: "1" }),
1122
+ /* @__PURE__ */ jsx8("path", { d: "M4 10h16M10 4v16" })
1123
+ ] }) : format === "tsv" ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1124
+ /* @__PURE__ */ jsx8("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1125
+ /* @__PURE__ */ jsx8("path", { d: "M14 2v6h6M8 13h2M14 13h2M8 17h2M14 17h2" })
1126
+ ] }) : format === "xlsx" ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1127
+ /* @__PURE__ */ jsx8("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1128
+ /* @__PURE__ */ jsx8("path", { d: "M14 2v6h6M8 13h8M8 17h8M12 11v8" })
1129
+ ] }) : format === "markdown" ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1130
+ /* @__PURE__ */ jsx8("path", { d: "M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5z" }),
1131
+ /* @__PURE__ */ jsx8("path", { d: "M14 2v6h6M10 13l-2 2 2 2M14 17l2-2-2-2" })
1132
+ ] }) : format === "html" ? /* @__PURE__ */ jsx8(Fragment2, { children: /* @__PURE__ */ jsx8("path", { d: "M15 6h6M3 6h7M3 12h18M3 18h12" }) }) : /* @__PURE__ */ jsx8(Fragment2, { children: /* @__PURE__ */ jsx8("path", { d: "M4 7V4h16v3M9 20h6M12 4v16" }) });
1133
+ return /* @__PURE__ */ jsx8("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: path });
1134
+ }
1135
+ function PaletteRows({ title, items, onRun, extra, ai = false, glyphKind, fallbackHint }) {
1136
+ if (!items.length && !extra) return null;
1137
+ return /* @__PURE__ */ jsxs4("section", { className: "matrx-alchemy-palette-section", children: [
1138
+ /* @__PURE__ */ jsx8("h3", { children: title }),
1139
+ items.map((item) => /* @__PURE__ */ jsxs4("button", { type: "button", className: cn("matrx-alchemy-palette-row", ai && "matrx-alchemy-palette-row-ai"), "aria-label": item.ariaLabel, onClick: () => onRun?.(item), children: [
1140
+ item.icon ? /* @__PURE__ */ jsx8(item.icon, { className: "matrx-alchemy-menu-icon" }) : /* @__PURE__ */ jsx8(PaletteGlyph, { ai, ...glyphKind ? { kind: glyphKind } : {} }),
1141
+ /* @__PURE__ */ jsxs4("span", { children: [
1142
+ item.copyLabel ?? item.label,
1143
+ item.hint ?? fallbackHint ? /* @__PURE__ */ jsx8("small", { className: "matrx-alchemy-menu-hint", children: item.hint ?? fallbackHint }) : null
1144
+ ] })
1145
+ ] }, item.id)),
1146
+ extra
1147
+ ] });
1148
+ }
1216
1149
  var LABEL = { plain: "Plain text", markdown: "Markdown", html: "Formatted", json: "JSON", "compact-json": "Compact JSON", csv: "CSV", tsv: "Google Sheets", xlsx: "Excel workbook" };
1217
1150
  var BUILT_INS = Object.freeze(Object.keys(LABEL).map((id) => ({ id })));
1218
1151
  var COPIES = ["plain", "markdown", "html", "json", "compact-json", "csv", "tsv"];
@@ -1301,7 +1234,7 @@ function ContentTransferMenu(props) {
1301
1234
  const identityKey = props.capabilities?.identityKey ?? inherited.identityKey;
1302
1235
  return /* @__PURE__ */ jsx8(ContentTransferMenuSession, { ...props }, identityKey ?? "anonymous");
1303
1236
  }
1304
- function ContentTransferMenuSession({ source, surface, label, projection, sections, preferences, table, formatSources, variants = EMPTY_VARIANTS, actions = [], capabilities: local, disabled, enabled = true, className, stopPropagation = true, hide = [], controllerRef }) {
1237
+ function ContentTransferMenuSession({ source, surface, label, projection, sections, preferences, table, formatSources, sourceFormats = true, variants = EMPTY_VARIANTS, actions = [], capabilities: local, disabled, enabled = true, className, stopPropagation = true, hide = [], controllerRef }) {
1305
1238
  const triggerRef = React8.useRef(null);
1306
1239
  const inherited = React8.useContext(CapabilityContext);
1307
1240
  const nearestSurface = React8.useContext(SurfaceContext);
@@ -1314,6 +1247,8 @@ function ContentTransferMenuSession({ source, surface, label, projection, sectio
1314
1247
  const workspaceCaptures = React8.useRef(/* @__PURE__ */ new Map());
1315
1248
  const externalWorkspaceKeys = React8.useRef(/* @__PURE__ */ new Set());
1316
1249
  const [notice, setNotice] = React8.useState(null);
1250
+ const [paletteOpen, setPaletteOpen] = React8.useState(false);
1251
+ const [mode, setMode] = React8.useState("copy");
1317
1252
  const scopes = React8.useMemo(() => table?.availableScopes ?? ["target"], [table]);
1318
1253
  const initialScope = table?.initialScope ?? "target";
1319
1254
  if (!scopes.includes(initialScope)) throw new Error("Alchemy initialScope must be included in availableScopes.");
@@ -1565,48 +1500,96 @@ function ContentTransferMenuSession({ source, surface, label, projection, sectio
1565
1500
  }, [captureOne, capturePrimary, fence, initialScope, preferences, providerPreferences, report]);
1566
1501
  if (!enabled) return null;
1567
1502
  const payload = menuCapture?.snapshot.payload ?? (source && "kind" in source ? source : void 0);
1568
- const quickVariants = (section) => variants.filter((v) => v.copyLabel && (v.section ?? "ai") === section).map((v) => /* @__PURE__ */ jsx8(DropdownMenuItem, { "aria-label": v.ariaLabel, onSelect: () => void transfer("markdown", false, v), children: /* @__PURE__ */ jsx8(MenuPresentation, { ...v, label: v.copyLabel }) }, `copy:${v.id}`));
1569
- const visibleCopies = COPIES.filter((f) => Boolean(formatSources?.[f]) || !["csv", "tsv"].includes(f) || payload?.kind === "rows");
1570
- const visibleDownloads = DOWNLOADS.filter((f) => f !== "xlsx" && Boolean(formatSources?.[f]) || !["csv", "tsv", "xlsx"].includes(f) || payload?.kind === "rows");
1571
- const visibleAdapters = menuCapture ? adapters.filter((a) => a.supports(menuCapture.snapshot.payload)) : [];
1503
+ const quickVariants = (section) => variants.filter((v) => v.copyLabel && (v.section ?? "ai") === section);
1504
+ const visibleCopies = sourceFormats ? COPIES.filter((f) => Boolean(formatSources?.[f]) || !["csv", "tsv"].includes(f) || payload?.kind === "rows") : [];
1505
+ const visibleDownloads = sourceFormats ? DOWNLOADS.filter((f) => f !== "xlsx" && Boolean(formatSources?.[f]) || !["csv", "tsv", "xlsx"].includes(f) || payload?.kind === "rows") : [];
1506
+ const visibleAdapters = sourceFormats && menuCapture ? adapters.filter((a) => a.supports(menuCapture.snapshot.payload)) : [];
1572
1507
  const visibleActions = menuCapture ? registeredActions.filter((a) => a.supports(menuCapture.snapshot)) : [];
1573
- return /* @__PURE__ */ jsxs5("span", { className: cn("matrx-alchemy", className), onClick: stopPropagation ? (event) => event.stopPropagation() : void 0, children: [
1574
- /* @__PURE__ */ jsxs5(DropdownMenu, { onOpenChange: (open) => {
1575
- if (open) void preflight();
1508
+ const downloadActions = visibleActions.filter((action) => action.placement === "download");
1509
+ const ordinaryActions = visibleActions.filter((action) => action.placement !== "download");
1510
+ const copyAvailable = !hide.includes("copy") && visibleCopies.length + visibleAdapters.length + quickVariants("copy").length > 0;
1511
+ const downloadAvailable = !hide.includes("download") && visibleDownloads.length + visibleAdapters.length + downloadActions.length > 0;
1512
+ const prepareAvailable = !hide.includes("prepare") && (quickVariants("ai").length > 0 || Boolean(primary) || Boolean(nearestWorkspaceKey) || variants.length > 0);
1513
+ const resolvedMode = mode === "copy" && !copyAvailable ? "download" : mode === "download" && !downloadAvailable ? "copy" : mode;
1514
+ const closePalette = () => setPaletteOpen(false);
1515
+ const tile = (id, label2, onClick, options = {}) => {
1516
+ const presentation = options.action;
1517
+ const Icon = presentation?.icon;
1518
+ const fallbackLabel = options.file && !/^download\b/i.test(label2) ? `Download ${label2}` : label2;
1519
+ return /* @__PURE__ */ jsxs4("button", { type: "button", className: "matrx-alchemy-palette-tile", "aria-label": presentation?.ariaLabel ?? (presentation ? fallbackLabel : options.ariaLabel ?? `${resolvedMode === "copy" ? "Copy" : "Download"} ${label2}`), onClick: () => {
1520
+ closePalette();
1521
+ onClick();
1576
1522
  }, children: [
1577
- /* @__PURE__ */ jsx8(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx8("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__ */ jsx8(AlchemyGlyph, {}) }) }),
1578
- /* @__PURE__ */ jsxs5(DropdownMenuContent, { align: "end", className: "matrx-alchemy-menu", children: [
1579
- menuStatus === "loading" ? /* @__PURE__ */ jsx8(DropdownMenuItem, { disabled: true, children: "Inspecting content\u2026" }) : menuStatus !== "idle" ? /* @__PURE__ */ jsx8(DropdownMenuItem, { disabled: true, children: menuStatus }) : null,
1580
- !hide.includes("copy") ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1581
- /* @__PURE__ */ jsx8(DropdownMenuLabel, { children: "Copy" }),
1582
- quickVariants("copy"),
1583
- visibleCopies.map((format) => /* @__PURE__ */ jsx8(DropdownMenuItem, { onSelect: () => void transfer(format, false), children: format === "plain" ? "Copy" : `Copy ${LABEL[format]}` }, format)),
1584
- visibleAdapters.map((adapter) => /* @__PURE__ */ jsxs5(DropdownMenuItem, { onSelect: () => void transfer(adapter, false), children: [
1585
- "Copy ",
1586
- adapter.label
1587
- ] }, adapter.id))
1588
- ] }) : null,
1589
- !hide.includes("prepare") ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1590
- /* @__PURE__ */ jsx8(DropdownMenuSeparator, {}),
1591
- quickVariants("ai"),
1592
- /* @__PURE__ */ jsx8(DropdownMenuItem, { onSelect: () => void openWorkspace(), children: "Prepare for AI\u2026" }),
1593
- nearestWorkspaceKey && nearestSurface ? /* @__PURE__ */ jsx8(DropdownMenuItem, { onSelect: () => void openWorkspace(nearestWorkspaceKey, { source: nearestSurface, label: nearestSurface.surfaceName }), children: "Prepare this surface\u2026" }) : null,
1594
- variants.map((variant) => /* @__PURE__ */ jsx8(DropdownMenuItem, { onSelect: () => void openWorkspace(variantWorkspaceKeys.get(variant.id), variant), children: /* @__PURE__ */ jsx8(MenuPresentation, { ...variant, label: `Prepare ${variant.label}\u2026` }) }, variant.id))
1523
+ Icon ? /* @__PURE__ */ jsx8(Icon, { className: "matrx-alchemy-menu-icon" }) : /* @__PURE__ */ jsx8(PaletteGlyph, { ...!options.custom ? { format: id } : {}, ...options.ai ? { ai: true } : {}, ...options.file ? { file: true } : {} }),
1524
+ /* @__PURE__ */ jsxs4("span", { children: [
1525
+ label2,
1526
+ presentation?.hint ? /* @__PURE__ */ jsx8("small", { className: "matrx-alchemy-menu-hint", children: presentation.hint }) : null
1527
+ ] })
1528
+ ] }, id);
1529
+ };
1530
+ return /* @__PURE__ */ jsxs4("span", { className: cn("matrx-alchemy", className), onClick: stopPropagation ? (event) => event.stopPropagation() : void 0, children: [
1531
+ /* @__PURE__ */ jsxs4(Popover, { open: paletteOpen, onOpenChange: (open) => {
1532
+ setPaletteOpen(open);
1533
+ if (open) {
1534
+ setMode("copy");
1535
+ void preflight();
1536
+ }
1537
+ }, children: [
1538
+ /* @__PURE__ */ jsx8(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx8("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__ */ jsx8(AlchemyGlyph, {}) }) }),
1539
+ /* @__PURE__ */ jsxs4(PopoverContent, { align: "end", className: "matrx-alchemy-menu matrx-alchemy-palette", "aria-label": "Alchemy output options", onCloseAutoFocus: () => triggerRef.current?.focus(), children: [
1540
+ menuStatus === "loading" ? /* @__PURE__ */ jsx8("p", { className: "matrx-alchemy-palette-status", children: "Inspecting content\u2026" }) : menuStatus !== "idle" ? /* @__PURE__ */ jsx8("p", { className: "matrx-alchemy-error", children: menuStatus }) : null,
1541
+ copyAvailable || downloadAvailable ? /* @__PURE__ */ jsxs4("section", { className: "matrx-alchemy-output", children: [
1542
+ /* @__PURE__ */ jsx8("h3", { children: resolvedMode === "copy" ? "Copy as" : "Download as" }),
1543
+ copyAvailable && downloadAvailable ? /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-mode", "aria-label": "Output action", children: [
1544
+ /* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Copy mode", "aria-pressed": resolvedMode === "copy", onClick: () => setMode("copy"), children: "Copy" }),
1545
+ /* @__PURE__ */ jsx8("button", { type: "button", "aria-label": "Download mode", "aria-pressed": resolvedMode === "download", onClick: () => setMode("download"), children: "Download" })
1546
+ ] }) : null,
1547
+ resolvedMode === "copy" && copyAvailable ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1548
+ /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-palette-grid", children: [
1549
+ 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]}` })),
1550
+ visibleAdapters.map((adapter) => tile(adapter.id, adapter.label, () => void transfer(adapter, false), { custom: true }))
1551
+ ] }),
1552
+ quickVariants("copy").length ? /* @__PURE__ */ jsx8(PaletteRows, { title: "Quick copy", items: quickVariants("copy"), onRun: (variant) => {
1553
+ closePalette();
1554
+ void transfer("markdown", false, variant);
1555
+ } }) : null
1556
+ ] }) : null,
1557
+ resolvedMode === "download" && downloadAvailable ? /* @__PURE__ */ jsx8(Fragment2, { children: /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-palette-grid", children: [
1558
+ 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]}` })),
1559
+ visibleAdapters.map((adapter) => tile(adapter.id, adapter.label, () => void transfer(adapter, true), { custom: true })),
1560
+ downloadActions.map((action) => tile(action.id, action.label, () => void runAction(action), { custom: true, action, file: true }))
1561
+ ] }) }) : null
1595
1562
  ] }) : null,
1596
- !hide.includes("download") ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1597
- /* @__PURE__ */ jsx8(DropdownMenuSeparator, {}),
1598
- /* @__PURE__ */ jsx8(DropdownMenuLabel, { children: "Download" }),
1599
- visibleDownloads.map((format) => /* @__PURE__ */ jsxs5(DropdownMenuItem, { onSelect: () => void transfer(format, true), children: [
1600
- "Download ",
1601
- LABEL[format]
1602
- ] }, format)),
1603
- visibleAdapters.map((adapter) => /* @__PURE__ */ jsxs5(DropdownMenuItem, { onSelect: () => void transfer(adapter, true), children: [
1604
- "Download ",
1605
- adapter.label
1606
- ] }, `download:${adapter.id}`))
1563
+ prepareAvailable ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1564
+ /* @__PURE__ */ jsx8(PaletteRows, { title: "Copy for AI", ai: true, glyphKind: "ai-copy", fallbackHint: "Copies immediately", items: quickVariants("ai"), onRun: (variant) => {
1565
+ closePalette();
1566
+ void transfer("markdown", false, variant);
1567
+ } }),
1568
+ /* @__PURE__ */ jsx8(PaletteRows, { title: "Edit and prepare", items: [], extra: /* @__PURE__ */ jsxs4("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": "Prepare for AI", onClick: () => {
1569
+ closePalette();
1570
+ void openWorkspace();
1571
+ }, children: [
1572
+ /* @__PURE__ */ jsx8(PaletteGlyph, { kind: "sliders" }),
1573
+ /* @__PURE__ */ jsxs4("span", { children: [
1574
+ "Prepare for AI",
1575
+ /* @__PURE__ */ jsx8("small", { className: "matrx-alchemy-menu-hint", children: "Review and edit before copying" })
1576
+ ] })
1577
+ ] }) })
1607
1578
  ] }) : null,
1608
- visibleActions.length ? /* @__PURE__ */ jsx8(DropdownMenuSeparator, {}) : null,
1609
- visibleActions.map((action) => /* @__PURE__ */ jsx8(DropdownMenuItem, { "aria-label": action.ariaLabel, onSelect: () => void runAction(action), children: /* @__PURE__ */ jsx8(MenuPresentation, { ...action, label: action.label }) }, action.id))
1579
+ prepareAvailable && (nearestWorkspaceKey || variants.length) ? /* @__PURE__ */ jsx8(PaletteRows, { title: "Other sources", items: [], extra: /* @__PURE__ */ jsxs4(Fragment2, { children: [
1580
+ nearestWorkspaceKey && nearestSurface ? /* @__PURE__ */ jsx8("button", { type: "button", className: "matrx-alchemy-palette-row", onClick: () => {
1581
+ closePalette();
1582
+ void openWorkspace(nearestWorkspaceKey, { source: nearestSurface, label: nearestSurface.surfaceName });
1583
+ }, children: /* @__PURE__ */ jsx8("span", { children: "Prepare this surface" }) }) : null,
1584
+ variants.map((variant) => /* @__PURE__ */ jsx8("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": variant.ariaLabel, onClick: () => {
1585
+ closePalette();
1586
+ void openWorkspace(variantWorkspaceKeys.get(variant.id), variant);
1587
+ }, children: /* @__PURE__ */ jsx8(MenuPresentation, { ...variant, label: `Prepare ${variant.label}` }) }, variant.id))
1588
+ ] }) }) : null,
1589
+ ordinaryActions.length ? /* @__PURE__ */ jsx8(PaletteRows, { title: "Actions", items: [], extra: ordinaryActions.map((action) => /* @__PURE__ */ jsx8("button", { type: "button", className: "matrx-alchemy-palette-row", "aria-label": action.ariaLabel, onClick: () => {
1590
+ closePalette();
1591
+ void runAction(action);
1592
+ }, children: /* @__PURE__ */ jsx8(MenuPresentation, { ...action, label: action.label }) }, action.id)) }) : null
1610
1593
  ] })
1611
1594
  ] }),
1612
1595
  notice ? /* @__PURE__ */ jsx8("span", { className: "matrx-alchemy-notice", role: "status", children: notice }) : null,
@@ -1869,212 +1852,224 @@ function PreparationWorkspace({ restoreFocus, open, state, scopes, onClose, onCh
1869
1852
  const limitText = Object.entries(state.preferences.limits).filter(([, value]) => value != null).map(([key, value]) => `${key.replace(/^max/, "max ")} ${Number(value).toLocaleString()}`).join(" \xB7 ");
1870
1853
  return /* @__PURE__ */ jsx8(Dialog, { open, onOpenChange: (next) => {
1871
1854
  if (!next) close();
1872
- }, children: /* @__PURE__ */ jsxs5(DialogContent, { onCloseAutoFocus: (event) => {
1855
+ }, children: /* @__PURE__ */ jsxs4(DialogContent, { onCloseAutoFocus: (event) => {
1873
1856
  event.preventDefault();
1874
1857
  restoreFocus();
1875
1858
  }, className: "matrx-alchemy-workspace max-w-5xl", "aria-busy": busy !== null, children: [
1876
- /* @__PURE__ */ jsxs5(DialogHeader, { children: [
1877
- /* @__PURE__ */ jsxs5(DialogTitle, { children: [
1859
+ /* @__PURE__ */ jsxs4(DialogHeader, { children: [
1860
+ /* @__PURE__ */ jsxs4(DialogTitle, { children: [
1878
1861
  "Prepare ",
1879
1862
  state.snapshot.label
1880
1863
  ] }),
1881
- /* @__PURE__ */ jsxs5(DialogDescription, { children: [
1882
- "Captured ",
1883
- state.snapshot.unsavedChanges ? "from your unsaved draft" : "as an immutable snapshot",
1884
- ". Your source is never edited."
1864
+ /* @__PURE__ */ jsxs4(DialogDescription, { children: [
1865
+ state.snapshot.unsavedChanges ? "Includes your unsaved changes. " : "",
1866
+ "Review and edit this copy. Your original stays unchanged."
1885
1867
  ] })
1886
1868
  ] }),
1887
- /* @__PURE__ */ jsxs5("div", { className: "matrx-alchemy-workspace-grid", children: [
1888
- /* @__PURE__ */ jsxs5("section", { className: "matrx-alchemy-main", children: [
1889
- /* @__PURE__ */ jsxs5("div", { className: "matrx-alchemy-toolbar", children: [
1890
- scopes.length > 1 ? /* @__PURE__ */ jsxs5("label", { children: [
1891
- "Scope",
1892
- /* @__PURE__ */ jsx8("select", { "aria-label": "Transfer scope", value: state.scope, disabled: busy !== null, onChange: (e) => void requestCapture(e.target.value), children: scopes.map((scope) => /* @__PURE__ */ jsx8("option", { value: scope, children: SCOPE_LABEL[scope] }, scope)) })
1893
- ] }) : null,
1894
- /* @__PURE__ */ jsxs5("label", { children: [
1895
- "Detail",
1896
- /* @__PURE__ */ jsxs5("select", { "aria-label": "Detail preset", value: controls.preset, onChange: (e) => changeControls({ ...controls, preset: e.target.value }), children: [
1897
- /* @__PURE__ */ jsx8("option", { value: "full", children: "Full" }),
1898
- /* @__PURE__ */ jsx8("option", { value: "compact", children: "Compact" }),
1899
- /* @__PURE__ */ jsx8("option", { value: "brief", children: "Brief" }),
1900
- /* @__PURE__ */ jsx8("option", { value: "custom", children: "Custom" })
1901
- ] })
1902
- ] }),
1903
- /* @__PURE__ */ jsx8(Button, { type: "button", size: "sm", variant: "outline", disabled: !state.draft.history?.length && !controlsHistory.length || busy !== null, onClick: () => {
1904
- setBufferError(null);
1905
- if (controlsHistory.length) {
1906
- const next = controlsHistory[controlsHistory.length - 1];
1869
+ /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-workspace-body", children: [
1870
+ /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-workspace-grid", children: [
1871
+ /* @__PURE__ */ jsxs4("section", { className: "matrx-alchemy-main", children: [
1872
+ /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-toolbar", children: [
1873
+ scopes.length > 1 ? /* @__PURE__ */ jsxs4("label", { children: [
1874
+ "Scope",
1875
+ /* @__PURE__ */ jsx8("select", { "aria-label": "Transfer scope", value: state.scope, disabled: busy !== null, onChange: (e) => void requestCapture(e.target.value), children: scopes.map((scope) => /* @__PURE__ */ jsx8("option", { value: scope, children: SCOPE_LABEL[scope] }, scope)) })
1876
+ ] }) : null,
1877
+ /* @__PURE__ */ jsxs4("label", { children: [
1878
+ "Detail",
1879
+ /* @__PURE__ */ jsxs4("select", { "aria-label": "Detail preset", value: controls.preset, onChange: (e) => changeControls({ ...controls, preset: e.target.value }), children: [
1880
+ /* @__PURE__ */ jsx8("option", { value: "full", children: "Full" }),
1881
+ /* @__PURE__ */ jsx8("option", { value: "compact", children: "Compact" }),
1882
+ /* @__PURE__ */ jsx8("option", { value: "brief", children: "Brief" }),
1883
+ /* @__PURE__ */ jsx8("option", { value: "custom", children: "Custom" })
1884
+ ] })
1885
+ ] }),
1886
+ /* @__PURE__ */ jsx8(Button, { type: "button", size: "sm", variant: "outline", className: "matrx-alchemy-workspace-secondary", disabled: !state.draft.history?.length && !controlsHistory.length || busy !== null, onClick: () => {
1887
+ setBufferError(null);
1888
+ if (controlsHistory.length) {
1889
+ const next = controlsHistory[controlsHistory.length - 1];
1890
+ setControls(next);
1891
+ setControlsHistory((history) => history.slice(0, -1));
1892
+ onChange({ ...state, draft: rebuild(state, next), error: void 0 });
1893
+ } else onChange({ ...state, draft: undoDraft(state.draft), error: void 0 });
1894
+ }, children: "Undo" }),
1895
+ /* @__PURE__ */ jsx8(Button, { type: "button", size: "sm", variant: "outline", className: "matrx-alchemy-workspace-secondary", disabled: busy !== null, onClick: () => {
1896
+ const next = initialControls(state);
1907
1897
  setControls(next);
1908
- setControlsHistory((history) => history.slice(0, -1));
1898
+ setControlsHistory([]);
1899
+ setPendingControls(null);
1900
+ setBufferError(null);
1909
1901
  onChange({ ...state, draft: rebuild(state, next), error: void 0 });
1910
- } else onChange({ ...state, draft: undoDraft(state.draft), error: void 0 });
1911
- }, children: "Undo" }),
1912
- /* @__PURE__ */ jsx8(Button, { type: "button", size: "sm", variant: "outline", disabled: busy !== null, onClick: () => {
1913
- const next = initialControls(state);
1914
- setControls(next);
1915
- setControlsHistory([]);
1916
- setPendingControls(null);
1917
- setBufferError(null);
1918
- onChange({ ...state, draft: rebuild(state, next), error: void 0 });
1919
- }, children: "Reset" }),
1920
- /* @__PURE__ */ jsx8(Button, { type: "button", size: "sm", variant: "outline", disabled: busy !== null, onClick: () => void requestCapture(state.scope), children: "Refresh source" })
1921
- ] }),
1922
- controls.preset === "custom" && (state.draft.payload.kind === "json" || state.draft.payload.kind === "registered") ? /* @__PURE__ */ jsxs5("fieldset", { className: "matrx-alchemy-options", children: [
1923
- /* @__PURE__ */ jsx8("legend", { children: "JSON limits" }),
1924
- [["maxDepth", "Maximum depth"], ["maxStringChars", "Maximum string characters"], ["maxArrayItems", "Maximum array items"]].map(([key, text]) => /* @__PURE__ */ jsxs5("label", { children: [
1925
- text,
1926
- /* @__PURE__ */ jsx8("input", { type: "number", min: "0", value: controls[key] ?? "", onChange: (e) => changeControls({ ...controls, [key]: Number.isNaN(e.target.valueAsNumber) ? null : e.target.valueAsNumber }) })
1927
- ] }, key))
1928
- ] }) : null,
1929
- rows ? /* @__PURE__ */ jsx8(RowControls, { rows, controls, change: changeControls }) : null,
1930
- state.snapshot.sections.length ? /* @__PURE__ */ jsxs5("fieldset", { className: "matrx-alchemy-options", children: [
1931
- /* @__PURE__ */ jsx8("legend", { children: "Sections" }),
1932
- state.snapshot.sections.map((section) => /* @__PURE__ */ jsxs5("label", { children: [
1933
- /* @__PURE__ */ jsx8("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) }) }),
1934
- " ",
1935
- section.label
1936
- ] }, section.id))
1937
- ] }) : null,
1938
- /* @__PURE__ */ jsxs5("div", { className: "matrx-alchemy-coverage", children: [
1939
- /* @__PURE__ */ jsxs5("span", { children: [
1940
- state.snapshot.coverage.included.toLocaleString(),
1941
- " included",
1942
- state.snapshot.coverage.total == null ? "" : ` of ${state.snapshot.coverage.total.toLocaleString()}`,
1943
- " \xB7 ",
1944
- state.snapshot.coverage.status
1902
+ }, children: "Reset" }),
1903
+ /* @__PURE__ */ jsx8(Button, { type: "button", size: "sm", variant: "outline", className: "matrx-alchemy-workspace-secondary", disabled: busy !== null, onClick: () => void requestCapture(state.scope), children: "Refresh source" })
1945
1904
  ] }),
1946
- state.snapshot.coverage.reason ? /* @__PURE__ */ jsx8("span", { children: state.snapshot.coverage.reason }) : null,
1947
- limitText ? /* @__PURE__ */ jsxs5("span", { children: [
1948
- "Limits: ",
1949
- limitText
1905
+ controls.preset === "custom" && (state.draft.payload.kind === "json" || state.draft.payload.kind === "registered") ? /* @__PURE__ */ jsxs4("fieldset", { className: "matrx-alchemy-options", children: [
1906
+ /* @__PURE__ */ jsx8("legend", { children: "JSON limits" }),
1907
+ [["maxDepth", "Maximum depth"], ["maxStringChars", "Maximum string characters"], ["maxArrayItems", "Maximum array items"]].map(([key, text]) => /* @__PURE__ */ jsxs4("label", { children: [
1908
+ text,
1909
+ /* @__PURE__ */ jsx8("input", { type: "number", min: "0", value: controls[key] ?? "", onChange: (e) => changeControls({ ...controls, [key]: Number.isNaN(e.target.valueAsNumber) ? null : e.target.valueAsNumber }) })
1910
+ ] }, key))
1911
+ ] }) : null,
1912
+ rows ? /* @__PURE__ */ jsx8(RowControls, { rows, controls, change: changeControls }) : null,
1913
+ state.snapshot.sections.length ? /* @__PURE__ */ jsxs4("fieldset", { className: "matrx-alchemy-options", children: [
1914
+ /* @__PURE__ */ jsx8("legend", { children: "Sections" }),
1915
+ state.snapshot.sections.map((section) => /* @__PURE__ */ jsxs4("label", { children: [
1916
+ /* @__PURE__ */ jsx8("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) }) }),
1917
+ " ",
1918
+ section.label
1919
+ ] }, section.id))
1950
1920
  ] }) : null,
1951
- displayedOmissions.length ? /* @__PURE__ */ jsxs5("details", { children: [
1952
- /* @__PURE__ */ jsxs5("summary", { children: [
1953
- displayedOmissions.length,
1954
- " omissions or adjustments"
1921
+ /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-coverage", children: [
1922
+ /* @__PURE__ */ jsxs4("span", { children: [
1923
+ state.snapshot.coverage.included.toLocaleString(),
1924
+ " included",
1925
+ state.snapshot.coverage.total == null ? "" : ` of ${state.snapshot.coverage.total.toLocaleString()}`,
1926
+ " \xB7 ",
1927
+ state.snapshot.coverage.status
1955
1928
  ] }),
1956
- /* @__PURE__ */ jsx8("ul", { children: displayedOmissions.map((o, i) => /* @__PURE__ */ jsxs5("li", { children: [
1957
- o.path || "/",
1958
- ": ",
1959
- o.reason,
1960
- o.count == null ? "" : ` (${o.count})`
1961
- ] }, `${o.path}-${o.reason}-${i}`)) })
1962
- ] }) : null
1963
- ] }),
1964
- /* @__PURE__ */ jsxs5("label", { className: "matrx-alchemy-preview-label", children: [
1965
- "Output format",
1966
- /* @__PURE__ */ jsxs5("select", { "aria-label": "Output format", value: format, onChange: (e) => setFormat(e.target.value), children: [
1967
- formats.map((f) => /* @__PURE__ */ jsx8("option", { value: f, children: LABEL[f] }, f)),
1968
- state.draft.payload.kind === "rows" ? /* @__PURE__ */ jsx8("option", { value: "xlsx", children: "Excel workbook" }) : null,
1969
- workspaceAdapters.map((adapter) => /* @__PURE__ */ jsx8("option", { value: adapter.id, children: adapter.label }, adapter.id))
1970
- ] })
1929
+ state.snapshot.coverage.reason ? /* @__PURE__ */ jsx8("span", { children: state.snapshot.coverage.reason }) : null,
1930
+ limitText ? /* @__PURE__ */ jsxs4("span", { children: [
1931
+ "Limits: ",
1932
+ limitText
1933
+ ] }) : null,
1934
+ displayedOmissions.length ? /* @__PURE__ */ jsxs4("details", { children: [
1935
+ /* @__PURE__ */ jsxs4("summary", { children: [
1936
+ displayedOmissions.length,
1937
+ " omissions or adjustments"
1938
+ ] }),
1939
+ /* @__PURE__ */ jsx8("ul", { children: displayedOmissions.map((o, i) => /* @__PURE__ */ jsxs4("li", { children: [
1940
+ o.path || "/",
1941
+ ": ",
1942
+ o.reason,
1943
+ o.count == null ? "" : ` (${o.count})`
1944
+ ] }, `${o.path}-${o.reason}-${i}`)) })
1945
+ ] }) : null
1946
+ ] }),
1947
+ /* @__PURE__ */ jsxs4("label", { className: "matrx-alchemy-preview-label", children: [
1948
+ "Output format",
1949
+ /* @__PURE__ */ jsxs4("select", { "aria-label": "Output format", value: format, onChange: (e) => setFormat(e.target.value), children: [
1950
+ formats.map((f) => /* @__PURE__ */ jsx8("option", { value: f, children: LABEL[f] }, f)),
1951
+ state.draft.payload.kind === "rows" ? /* @__PURE__ */ jsx8("option", { value: "xlsx", children: "Excel workbook" }) : null,
1952
+ workspaceAdapters.map((adapter) => /* @__PURE__ */ jsx8("option", { value: adapter.id, children: adapter.label }, adapter.id))
1953
+ ] })
1954
+ ] }),
1955
+ /* @__PURE__ */ jsx8("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) }),
1956
+ bufferError ? /* @__PURE__ */ jsx8("p", { id: "alchemy-buffer-error", role: "alert", className: "matrx-alchemy-error", children: bufferError }) : null,
1957
+ formatError ? /* @__PURE__ */ jsx8("p", { role: "alert", className: "matrx-alchemy-error", children: formatError }) : null,
1958
+ bufferError ? /* @__PURE__ */ jsx8(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", disabled: busy !== null, onClick: () => {
1959
+ const fallback = editDraft(state.draft, { kind: "text", text: buffer });
1960
+ setBufferError(null);
1961
+ onChange({ ...state, draft: fallback, error: void 0 });
1962
+ setFormat("plain");
1963
+ }, children: "Use invalid JSON as plain text" }) : null
1971
1964
  ] }),
1972
- /* @__PURE__ */ jsx8("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) }),
1973
- bufferError ? /* @__PURE__ */ jsx8("p", { id: "alchemy-buffer-error", role: "alert", className: "matrx-alchemy-error", children: bufferError }) : null,
1974
- formatError ? /* @__PURE__ */ jsx8("p", { role: "alert", className: "matrx-alchemy-error", children: formatError }) : null,
1975
- bufferError ? /* @__PURE__ */ jsx8(Button, { type: "button", variant: "outline", disabled: busy !== null, onClick: () => {
1976
- const fallback = editDraft(state.draft, { kind: "text", text: buffer });
1977
- setBufferError(null);
1978
- onChange({ ...state, draft: fallback, error: void 0 });
1979
- setFormat("plain");
1980
- }, children: "Use invalid JSON as plain text" }) : null
1965
+ ai || busy === "capture" || state.error ? /* @__PURE__ */ jsxs4("aside", { children: [
1966
+ ai ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1967
+ /* @__PURE__ */ jsxs4("label", { children: [
1968
+ "AI instruction",
1969
+ /* @__PURE__ */ jsx8("textarea", { value: instruction, onChange: (e) => setInstruction(e.target.value), placeholder: "Tell AI how to prepare this content" })
1970
+ ] }),
1971
+ /* @__PURE__ */ jsx8(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" }),
1972
+ busy === "ai" ? /* @__PURE__ */ jsx8(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => void cancelAi(), children: aiSession.current?.cancel ? "Cancel AI" : "Stop waiting" }) : null
1973
+ ] }) : null,
1974
+ busy === "capture" ? /* @__PURE__ */ jsx8(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => {
1975
+ activeCapture.current?.abort();
1976
+ activeCapture.current = null;
1977
+ setBusy(null);
1978
+ }, children: "Stop loading rows" }) : null,
1979
+ ai && aiFailed && aiSession.current?.recover && busy !== "ai" ? /* @__PURE__ */ jsx8(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,
1980
+ ai ? /* @__PURE__ */ jsx8("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,
1981
+ state.error ? /* @__PURE__ */ jsx8("p", { role: "alert", className: "matrx-alchemy-error", children: state.error }) : null
1982
+ ] }) : null
1981
1983
  ] }),
1982
- ai || busy === "capture" || state.error ? /* @__PURE__ */ jsxs5("aside", { children: [
1983
- ai ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
1984
- /* @__PURE__ */ jsxs5("label", { children: [
1985
- "AI instruction",
1986
- /* @__PURE__ */ jsx8("textarea", { value: instruction, onChange: (e) => setInstruction(e.target.value), placeholder: "Tell AI how to prepare this content" })
1987
- ] }),
1988
- /* @__PURE__ */ jsx8(Button, { type: "button", variant: "outline", disabled: !aiSession.current || !instruction.trim() || busy !== null || !aiSession.current.supports(state.snapshot), onClick: () => void runAi(false), children: "Generate preview" }),
1989
- busy === "ai" ? /* @__PURE__ */ jsx8(Button, { type: "button", variant: "outline", onClick: () => void cancelAi(), children: aiSession.current?.cancel ? "Cancel AI" : "Stop waiting" }) : null
1990
- ] }) : null,
1991
- busy === "capture" ? /* @__PURE__ */ jsx8(Button, { type: "button", variant: "outline", onClick: () => {
1992
- activeCapture.current?.abort();
1993
- activeCapture.current = null;
1994
- setBusy(null);
1995
- }, children: "Stop loading rows" }) : null,
1996
- ai && aiFailed && aiSession.current?.recover && busy !== "ai" ? /* @__PURE__ */ jsx8(Button, { type: "button", variant: "outline", onClick: () => void runAi(true), children: aiFailed ? "Retry or rejoin AI run" : "Rejoin AI run" }) : null,
1997
- ai ? /* @__PURE__ */ jsx8("p", { className: "matrx-alchemy-meta", children: "AI creates a preview. It never copies automatically. Closing detaches this view without cancelling server work." }) : null,
1998
- state.error ? /* @__PURE__ */ jsx8("p", { role: "alert", className: "matrx-alchemy-error", children: state.error }) : null
1999
- ] }) : null
1984
+ pendingControls ? /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-decision", role: "alert", children: [
1985
+ /* @__PURE__ */ jsx8("p", { children: "This control would replace your manual edit." }),
1986
+ /* @__PURE__ */ jsx8(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => setPendingControls(null), children: "Keep edited draft" }),
1987
+ /* @__PURE__ */ jsx8(Button, { className: "matrx-alchemy-workspace-primary", type: "button", onClick: applyPendingControls, children: "Rebuild from source" })
1988
+ ] }) : null,
1989
+ state.sourceStale ? /* @__PURE__ */ jsx8("p", { role: "alert", className: "matrx-alchemy-decision", children: "The source changed since this draft. Use Refresh source to review the latest data." }) : null,
1990
+ state.pending ? /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-decision", role: "alert", children: [
1991
+ /* @__PURE__ */ jsx8("p", { children: "A fresh source snapshot is ready." }),
1992
+ /* @__PURE__ */ jsx8(Button, { className: "matrx-alchemy-workspace-secondary", type: "button", variant: "outline", onClick: () => resolveCapture("keep"), children: "Keep current snapshot and draft" }),
1993
+ /* @__PURE__ */ jsx8(Button, { className: "matrx-alchemy-workspace-primary", type: "button", onClick: () => resolveCapture("regenerate"), children: "Regenerate from fresh source" })
1994
+ ] }) : null,
1995
+ deliveryNotice ? /* @__PURE__ */ jsx8("p", { role: "status", className: "matrx-alchemy-meta", children: deliveryNotice }) : null
2000
1996
  ] }),
2001
- pendingControls ? /* @__PURE__ */ jsxs5("div", { className: "matrx-alchemy-decision", role: "alert", children: [
2002
- /* @__PURE__ */ jsx8("p", { children: "This control would replace your manual edit." }),
2003
- /* @__PURE__ */ jsx8(Button, { type: "button", variant: "outline", onClick: () => setPendingControls(null), children: "Keep edited draft" }),
2004
- /* @__PURE__ */ jsx8(Button, { type: "button", onClick: applyPendingControls, children: "Rebuild from source" })
2005
- ] }) : null,
2006
- state.sourceStale ? /* @__PURE__ */ jsx8("p", { role: "alert", className: "matrx-alchemy-decision", children: "The source changed since this draft. Use Refresh source to review the latest data." }) : null,
2007
- state.pending ? /* @__PURE__ */ jsxs5("div", { className: "matrx-alchemy-decision", role: "alert", children: [
2008
- /* @__PURE__ */ jsx8("p", { children: "A fresh source snapshot is ready." }),
2009
- /* @__PURE__ */ jsx8(Button, { type: "button", variant: "outline", onClick: () => resolveCapture("keep"), children: "Keep current snapshot and draft" }),
2010
- /* @__PURE__ */ jsx8(Button, { type: "button", onClick: () => resolveCapture("regenerate"), children: "Regenerate from fresh source" })
2011
- ] }) : null,
2012
- deliveryNotice ? /* @__PURE__ */ jsx8("p", { role: "status", className: "matrx-alchemy-meta", children: deliveryNotice }) : null,
2013
- /* @__PURE__ */ jsxs5(DialogFooter, { children: [
2014
- /* @__PURE__ */ jsxs5("span", { className: "matrx-alchemy-meta", children: [
1997
+ /* @__PURE__ */ jsxs4(DialogFooter, { children: [
1998
+ /* @__PURE__ */ jsxs4("span", { className: "matrx-alchemy-meta", children: [
2015
1999
  buffer.length.toLocaleString(),
2016
2000
  " characters \xB7 ~",
2017
2001
  estimateTokens(buffer).toLocaleString(),
2018
2002
  " tokens"
2019
2003
  ] }),
2020
- /* @__PURE__ */ jsx8(Button, { type: "button", variant: "outline", onClick: close, children: "Close" }),
2021
- /* @__PURE__ */ jsx8(Button, { type: "button", variant: "outline", disabled: busy !== null || Boolean(bufferError || formatError) || !preparedArtifact, onClick: () => void deliver(true), children: "Download prepared output" }),
2022
- /* @__PURE__ */ jsx8(Button, { type: "button", disabled: busy !== null || Boolean(bufferError || formatError) || !preparedArtifact, onClick: () => void deliver(false), children: "Copy prepared output" })
2004
+ /* @__PURE__ */ jsx8(Button, { type: "button", variant: "outline", className: "matrx-alchemy-workspace-secondary", onClick: close, children: "Close" }),
2005
+ /* @__PURE__ */ jsx8(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" }),
2006
+ /* @__PURE__ */ jsx8(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" })
2023
2007
  ] })
2024
2008
  ] }) });
2025
2009
  }
2026
2010
  function RowControls({ rows, controls, change }) {
2027
- return /* @__PURE__ */ jsxs5(Fragment2, { children: [
2028
- /* @__PURE__ */ jsxs5("div", { className: "matrx-alchemy-toolbar", children: [
2029
- /* @__PURE__ */ jsxs5("label", { children: [
2011
+ const filterCount = Object.values(controls.filters).filter(Boolean).length;
2012
+ const selectionSummary = controls.selectedOnly ? `${controls.selectedIndices.length} selected row${controls.selectedIndices.length === 1 ? "" : "s"}` : "All rows";
2013
+ 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 ");
2014
+ return /* @__PURE__ */ jsxs4(Fragment2, { children: [
2015
+ /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-toolbar", children: [
2016
+ /* @__PURE__ */ jsxs4("label", { children: [
2030
2017
  "Search",
2031
2018
  /* @__PURE__ */ jsx8("input", { value: controls.search, onChange: (e) => change({ ...controls, search: e.target.value }) })
2032
2019
  ] }),
2033
- /* @__PURE__ */ jsxs5("label", { children: [
2020
+ /* @__PURE__ */ jsxs4("label", { children: [
2034
2021
  "Sort",
2035
- /* @__PURE__ */ jsxs5("select", { value: controls.sort, onChange: (e) => change({ ...controls, sort: e.target.value }), children: [
2022
+ /* @__PURE__ */ jsxs4("select", { value: controls.sort, onChange: (e) => change({ ...controls, sort: e.target.value }), children: [
2036
2023
  /* @__PURE__ */ jsx8("option", { value: "", children: "None" }),
2037
2024
  rows.columns.map((column) => /* @__PURE__ */ jsx8("option", { value: column.id, children: column.label }, column.id))
2038
2025
  ] })
2039
2026
  ] }),
2040
- /* @__PURE__ */ jsxs5("label", { children: [
2027
+ /* @__PURE__ */ jsxs4("label", { children: [
2041
2028
  "Direction",
2042
- /* @__PURE__ */ jsxs5("select", { value: controls.direction, disabled: !controls.sort, onChange: (e) => change({ ...controls, direction: e.target.value }), children: [
2029
+ /* @__PURE__ */ jsxs4("select", { value: controls.direction, disabled: !controls.sort, onChange: (e) => change({ ...controls, direction: e.target.value }), children: [
2043
2030
  /* @__PURE__ */ jsx8("option", { value: "asc", children: "Ascending" }),
2044
2031
  /* @__PURE__ */ jsx8("option", { value: "desc", children: "Descending" })
2045
2032
  ] })
2046
2033
  ] }),
2047
- /* @__PURE__ */ jsxs5("label", { children: [
2034
+ /* @__PURE__ */ jsxs4("label", { children: [
2048
2035
  "Top rows",
2049
2036
  /* @__PURE__ */ jsx8("input", { type: "number", min: "0", value: controls.top ?? "", onChange: (e) => change({ ...controls, top: Number.isNaN(e.target.valueAsNumber) ? null : e.target.valueAsNumber }) })
2050
2037
  ] })
2051
2038
  ] }),
2052
- /* @__PURE__ */ jsxs5("fieldset", { className: "matrx-alchemy-options", children: [
2053
- /* @__PURE__ */ jsx8("legend", { children: "Columns and filters" }),
2054
- rows.columns.map((column) => /* @__PURE__ */ jsxs5("div", { className: "matrx-alchemy-column", children: [
2055
- /* @__PURE__ */ jsxs5("label", { children: [
2039
+ /* @__PURE__ */ jsxs4("details", { className: "matrx-alchemy-options", children: [
2040
+ /* @__PURE__ */ jsxs4("summary", { children: [
2041
+ "Columns and filters",
2042
+ dataSummary ? ` \u2014 ${dataSummary}` : ""
2043
+ ] }),
2044
+ /* @__PURE__ */ jsx8("fieldset", { "aria-label": "Columns and filters", children: rows.columns.map((column) => /* @__PURE__ */ jsxs4("div", { className: "matrx-alchemy-column", children: [
2045
+ /* @__PURE__ */ jsxs4("label", { children: [
2056
2046
  /* @__PURE__ */ jsx8("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) }) }),
2057
2047
  " ",
2058
2048
  column.label
2059
2049
  ] }),
2060
2050
  /* @__PURE__ */ jsx8("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 } }) })
2061
- ] }, column.id))
2051
+ ] }, column.id)) })
2062
2052
  ] }),
2063
- /* @__PURE__ */ jsxs5("fieldset", { className: "matrx-alchemy-options", children: [
2064
- /* @__PURE__ */ jsx8("legend", { children: "Rows" }),
2065
- /* @__PURE__ */ jsxs5("label", { children: [
2066
- /* @__PURE__ */ jsx8("input", { type: "checkbox", checked: controls.selectedOnly, onChange: (e) => change({ ...controls, selectedOnly: e.target.checked }) }),
2067
- " Only selected rows"
2053
+ /* @__PURE__ */ jsxs4("details", { className: "matrx-alchemy-options", children: [
2054
+ /* @__PURE__ */ jsxs4("summary", { children: [
2055
+ "Rows \u2014 ",
2056
+ selectionSummary
2068
2057
  ] }),
2069
- /* @__PURE__ */ jsx8("div", { className: "matrx-alchemy-row-list", children: rows.rows.map((row, index) => {
2070
- const summary = rows.columns.filter((column) => column.visible).slice(0, 2).map((column) => String(readTransferCell(row, column) ?? "")).filter(Boolean).join(" \xB7 ");
2071
- return /* @__PURE__ */ jsxs5("label", { children: [
2072
- /* @__PURE__ */ jsx8("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) }) }),
2073
- " Row ",
2074
- index + 1,
2075
- summary ? ` \u2014 ${summary}` : ""
2076
- ] }, index);
2077
- }) })
2058
+ /* @__PURE__ */ jsxs4("fieldset", { "aria-label": "Row selection", children: [
2059
+ /* @__PURE__ */ jsxs4("label", { children: [
2060
+ /* @__PURE__ */ jsx8("input", { type: "checkbox", checked: controls.selectedOnly, onChange: (e) => change({ ...controls, selectedOnly: e.target.checked }) }),
2061
+ " Only selected rows"
2062
+ ] }),
2063
+ /* @__PURE__ */ jsx8("div", { className: "matrx-alchemy-row-list", children: rows.rows.map((row, index) => {
2064
+ const summary = rows.columns.filter((column) => column.visible).slice(0, 2).map((column) => String(readTransferCell(row, column) ?? "")).filter(Boolean).join(" \xB7 ");
2065
+ return /* @__PURE__ */ jsxs4("label", { children: [
2066
+ /* @__PURE__ */ jsx8("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) }) }),
2067
+ " Row ",
2068
+ index + 1,
2069
+ summary ? ` \u2014 ${summary}` : ""
2070
+ ] }, index);
2071
+ }) })
2072
+ ] })
2078
2073
  ] })
2079
2074
  ] });
2080
2075
  }