@commenda/pathfinder 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/components/accordion/AccordionSection.js +9 -3
  3. package/dist/components/address-input/AddressInput.js +1 -1
  4. package/dist/components/artifact-card/ArtifactCard.js +1 -1
  5. package/dist/components/artifact-panel/ArtifactPanel.js +81 -55
  6. package/dist/components/attachment/Attachment.d.ts +2 -6
  7. package/dist/components/attachment/Attachment.js +59 -36
  8. package/dist/components/attachment/AttachmentCard.d.ts +1 -1
  9. package/dist/components/attachment/AttachmentCard.js +56 -43
  10. package/dist/components/attachment/attachment-class-names.d.ts +1 -1
  11. package/dist/components/attachment/attachment-class-names.js +1 -1
  12. package/dist/components/attachment-group/AttachmentGroup.js +1 -1
  13. package/dist/components/avatar/avatar-helper.d.ts +1 -1
  14. package/dist/components/banner/Banner.js +5 -2
  15. package/dist/components/button/Button.js +1 -1
  16. package/dist/components/calendar/CalendarAgenda.js +1 -1
  17. package/dist/components/calendar/CalendarArtwork.js +16 -22
  18. package/dist/components/calendar/CalendarEventContent.js +2 -2
  19. package/dist/components/calendar/CalendarPopup.js +102 -82
  20. package/dist/components/calendar/CalendarToolbar.js +10 -10
  21. package/dist/components/card/Card.js +47 -41
  22. package/dist/components/checkbox/Checkbox.js +31 -13
  23. package/dist/components/choices/choice-motion.d.ts +12 -0
  24. package/dist/components/choices/choice-motion.js +22 -0
  25. package/dist/components/code-block/CodeBlock.js +3 -2
  26. package/dist/components/controls/control-class-names.d.ts +1 -0
  27. package/dist/components/controls/control-class-names.js +8 -8
  28. package/dist/components/controls/useHoverHighlight.d.ts +12 -0
  29. package/dist/components/controls/useHoverHighlight.js +51 -0
  30. package/dist/components/controls/useSelectionIndicator.d.ts +3 -4
  31. package/dist/components/controls/useSelectionIndicator.js +43 -28
  32. package/dist/components/data-grid/DataGrid.js +7 -7
  33. package/dist/components/data-grid/DataGridHeaders.js +1 -1
  34. package/dist/components/date-picker/DateCalendar.js +3 -3
  35. package/dist/components/date-picker/DatePicker.js +10 -10
  36. package/dist/components/date-picker/field/DateField.js +1 -1
  37. package/dist/components/description-list/DescriptionList.js +2 -2
  38. package/dist/components/dialog/ConfirmDialog.js +1 -1
  39. package/dist/components/dialog/Dialog.js +1 -1
  40. package/dist/components/distribution-bar/DistributionBar.js +45 -35
  41. package/dist/components/drag-handle/DragHandle.d.ts +1 -1
  42. package/dist/components/dropdown/Dropdown.js +27 -26
  43. package/dist/components/dropdown/MenuContent.js +100 -69
  44. package/dist/components/dropdown/dropdown-types.d.ts +1 -0
  45. package/dist/components/dropdown/menu-motion.d.ts +2 -0
  46. package/dist/components/dropdown/menu-motion.js +4 -0
  47. package/dist/components/feedback/FeedbackIcon.d.ts +2 -1
  48. package/dist/components/feedback/FeedbackIcon.js +4 -4
  49. package/dist/components/feedback/FeedbackSurface.d.ts +3 -3
  50. package/dist/components/feedback/FeedbackSurface.js +49 -21
  51. package/dist/components/fields/FieldAction.d.ts +1 -0
  52. package/dist/components/fields/FieldAction.js +2 -2
  53. package/dist/components/icon-button/IconButton.js +37 -37
  54. package/dist/components/icons/index.js +776 -776
  55. package/dist/components/inline-reference/InlineReference.js +1 -8
  56. package/dist/components/list/List.js +2 -2
  57. package/dist/components/list/ListGroup.js +35 -30
  58. package/dist/components/list/ListTask.js +1 -1
  59. package/dist/components/list/SettingRow.js +1 -1
  60. package/dist/components/markdown/Markdown.js +11 -10
  61. package/dist/components/markdown/MarkdownTable.d.ts +1 -1
  62. package/dist/components/markdown/MarkdownTable.js +71 -54
  63. package/dist/components/otp/OTP.js +44 -43
  64. package/dist/components/output-sections/OutputRow.js +2 -3
  65. package/dist/components/overlays/OverlayFrame.js +2 -2
  66. package/dist/components/overlays/overlay-class-names.d.ts +3 -3
  67. package/dist/components/overlays/overlay-class-names.js +1 -1
  68. package/dist/components/phone-input/CountryPicker.js +11 -8
  69. package/dist/components/popover/Popover.js +2 -2
  70. package/dist/components/question-card/QuestionOptions.js +3 -3
  71. package/dist/components/radio-group/RadioGroup.js +59 -50
  72. package/dist/components/search/Search.js +51 -47
  73. package/dist/components/segmented-control/SegmentedControl.js +7 -6
  74. package/dist/components/selection/ChoiceField.js +1 -1
  75. package/dist/components/selection/ChoiceList.js +2 -1
  76. package/dist/components/selection/SearchableChoice.js +129 -114
  77. package/dist/components/selection/SelectedTags.js +1 -1
  78. package/dist/components/selection/SimpleChoice.js +95 -77
  79. package/dist/components/selection/choice-styles.d.ts +2 -2
  80. package/dist/components/selection/choice-styles.js +1 -1
  81. package/dist/components/sheet/Sheet.js +7 -7
  82. package/dist/components/side-nav/SideNav.d.ts +2 -5
  83. package/dist/components/side-nav/SideNav.js +98 -56
  84. package/dist/components/side-nav/SideNavItemView.d.ts +1 -1
  85. package/dist/components/side-nav/SideNavItemView.js +83 -98
  86. package/dist/components/side-nav/index.d.ts +2 -0
  87. package/dist/components/side-nav/index.js +1 -1
  88. package/dist/components/split-button/SplitButton.js +3 -2
  89. package/dist/components/stepper/StepMarker.js +32 -28
  90. package/dist/components/stepper/Stepper.js +30 -22
  91. package/dist/components/suggested-prompt/SuggestedPrompt.js +1 -1
  92. package/dist/components/switch/Switch.d.ts +1 -1
  93. package/dist/components/switch/Switch.js +38 -28
  94. package/dist/components/table/Table.js +134 -110
  95. package/dist/components/table/TableColumnHeader.js +20 -2
  96. package/dist/components/table/TableColumnResize.js +1 -1
  97. package/dist/components/table/TableColumnsMenu.js +1 -0
  98. package/dist/components/table/TableFilterChip.js +1 -1
  99. package/dist/components/table/TableFilterEditor.js +6 -6
  100. package/dist/components/table/TableFilters.js +1 -0
  101. package/dist/components/table/TableOptionMenu.d.ts +1 -1
  102. package/dist/components/table/TableOptionMenu.js +16 -17
  103. package/dist/components/table/TablePagination.js +1 -0
  104. package/dist/components/table/TableSelectionBar.js +4 -1
  105. package/dist/components/table/index.js +6 -6
  106. package/dist/components/table/table-column-style.js +0 -1
  107. package/dist/components/table/table-types.d.ts +5 -0
  108. package/dist/components/table/useTableData.js +2 -2
  109. package/dist/components/tabs/Tabs.js +61 -53
  110. package/dist/components/tabs/tab-class-names.d.ts +1 -1
  111. package/dist/components/tabs/tab-class-names.js +1 -1
  112. package/dist/components/tabular/TableEditCell.js +3 -1
  113. package/dist/components/tabular/tabular-class-names.d.ts +1 -0
  114. package/dist/components/tabular/tabular-class-names.js +1 -0
  115. package/dist/components/tabular/useCellEdit.js +1 -1
  116. package/dist/components/tabular/useTabularPinning.js +7 -6
  117. package/dist/components/tag/Tag.js +1 -1
  118. package/dist/components/tag-input/TagInput.js +64 -53
  119. package/dist/components/tag-input/useTagMotion.d.ts +6 -0
  120. package/dist/components/tag-input/useTagMotion.js +36 -0
  121. package/dist/components/text-area/TextArea.js +2 -1
  122. package/dist/components/thread/ThreadReply.js +10 -7
  123. package/dist/components/tool-call/ToolCall.js +2 -2
  124. package/dist/components/tree/TreeItemView.js +3 -3
  125. package/dist/index.d.ts +2 -2
  126. package/dist/index.js +37 -37
  127. package/dist/styles.css +1 -1
  128. package/package.json +5 -1
  129. package/dist/_virtual/_rolldown/runtime.js +0 -11
  130. package/dist/components/date-picker/date-values.d.ts +0 -23
  131. package/dist/components/date-picker/date-values.js +0 -52
  132. package/dist/components/table/TableHeaderPin.d.ts +0 -6
  133. package/dist/components/table/TableHeaderPin.js +0 -66
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @commenda/pathfinder
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Polish component interactions, accessibility, motion, and documentation across the design system.
8
+ - Add the `Sidebar` name and types while retaining the existing `SideNav` exports.
9
+ - Add Table `controlsConfig` for embedding read-only tables and Dropdown `trailingIcon` support.
10
+ - Improve table filtering, date editing, pin menus, scroll shadows, resize guides, and pinned-column layering. Seal DataGrid pinned edges and prevent number changes from wheel scrolling.
11
+ - Reuse shared controls in Calendar and AI content, including Markdown tables, hover previews, attachment dialogs, and Toast feedback.
12
+ - Refine navigation, form controls, overlays, and feedback transitions, preserving keyboard and reduced-motion behavior.
13
+ - Refresh component documentation and restore inherited form props and stable design-rule references in AI documentation.
14
+
3
15
  ## 0.1.0
4
16
 
5
17
  Initial public registry release of Commenda's design system: React components,
@@ -16,9 +16,15 @@ var c = ({ item: c, variant: l, headingLevel: u, keepMounted: d }) => {
16
16
  6: "h6"
17
17
  }[u], m = c.disableConfig?.isDisabled, h = m && c.disableConfig?.reason ? c.disableConfig.reason : c.description;
18
18
  return /* @__PURE__ */ o(s.Item, {
19
+ onPointerDownCapture: (e) => {
20
+ e.currentTarget.setAttribute("data-motion", "pointer");
21
+ },
22
+ onKeyDownCapture: (e) => {
23
+ e.currentTarget.removeAttribute("data-motion");
24
+ },
19
25
  value: c.value,
20
26
  disabled: m,
21
- className: r("pf:min-w-0 pf:box-border", l === "card" ? "pf:border-[0.5px] pf:border-solid pf:border-soft-pearl-300 pf:rounded-lg pf:bg-background" : "pf:py-xs pf:border-0 pf:border-b-[0.5px] pf:border-solid pf:border-soft-pearl-300"),
27
+ className: r("pf:group/accordion-item pf:min-w-0 pf:box-border", l === "card" ? "pf:border-[0.5px] pf:border-solid pf:border-soft-pearl-300 pf:rounded-lg pf:bg-background" : "pf:py-xs pf:border-0 pf:border-b-[0.5px] pf:border-solid pf:border-soft-pearl-300"),
22
28
  children: [/* @__PURE__ */ a(s.Header, {
23
29
  render: /* @__PURE__ */ a(p, {}),
24
30
  className: "pf:m-0",
@@ -43,7 +49,7 @@ var c = ({ item: c, variant: l, headingLevel: u, keepMounted: d }) => {
43
49
  }),
44
50
  /* @__PURE__ */ a("span", {
45
51
  "aria-hidden": "true",
46
- className: "pf:flex pf:items-center pf:justify-center pf:size-xl pf:shrink-0 pf:text-soft-pearl-800 pf:group-hover:text-soft-pearl-1000 pf:group-data-panel-open:rotate-180 pf:transition-transform pf:duration-(--pf-duration-base) pf:ease-(--pf-easing-out) pf:motion-reduce:transition-none",
52
+ className: "pf:flex pf:items-center pf:justify-center pf:size-xl pf:shrink-0 pf:text-soft-pearl-800 pf:group-hover:text-soft-pearl-1000 pf:group-data-panel-open:rotate-180 pf:transition-none pf:motion-safe:group-data-[motion=pointer]/accordion-item:transition-transform pf:duration-200 pf:ease-[cubic-bezier(0.23,1,0.32,1)] pf:motion-reduce:transition-none",
47
53
  children: /* @__PURE__ */ a(t, {
48
54
  size: 16,
49
55
  tone: "inherit"
@@ -53,7 +59,7 @@ var c = ({ item: c, variant: l, headingLevel: u, keepMounted: d }) => {
53
59
  })
54
60
  }), /* @__PURE__ */ a(s.Panel, {
55
61
  keepMounted: d,
56
- className: "pf:h-(--accordion-panel-height) pf:overflow-hidden pf:transition-[height] pf:duration-(--pf-duration-base) pf:ease-(--pf-easing-out) pf:data-starting-style:h-0 pf:data-ending-style:h-0 pf:motion-reduce:transition-none",
62
+ className: "pf:h-(--accordion-panel-height) pf:overflow-hidden pf:transition-none pf:motion-safe:group-data-[motion=pointer]/accordion-item:transition-[height] pf:duration-200 pf:ease-[cubic-bezier(0.23,1,0.32,1)] pf:data-starting-style:h-0 pf:data-ending-style:h-0 pf:motion-reduce:transition-none",
57
63
  children: /* @__PURE__ */ a("div", {
58
64
  className: r("pf:min-w-0 pf:font-body pf:text-copy-13 pf:text-soft-pearl-900 pf:wrap-anywhere", l === "card" ? "pf:px-xl pf:pb-xl" : "pf:px-md pf:pb-lg"),
59
65
  children: c.content
@@ -156,7 +156,7 @@ var m = l(() => import("./AddressCountryFlag.js")), h = {
156
156
  disableConfig: { isDisabled: !!c.disableConfig?.isDisabled },
157
157
  ...C("region"),
158
158
  errorConfig: T("region").errorConfig,
159
- placeholder: g.value.country || c.regionConfig ? "Select state or region" : "Select country first"
159
+ placeholder: g.value.country || c.regionConfig ? "Select state or region" : "State or region"
160
160
  }) : /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f(e, {
161
161
  ...T("region"),
162
162
  name: c.readOnly && y ? void 0 : S("region"),
@@ -13,7 +13,7 @@ function l({ title: l, meta: u, leading: d, onOpen: f, isOpen: p, stateConfig: m
13
13
  return /* @__PURE__ */ c("article", {
14
14
  "aria-label": l,
15
15
  "aria-busy": m?.status === "generating" || void 0,
16
- className: o("pf:relative pf:box-border pf:flex pf:min-w-0 pf:min-h-[64px] pf:flex-wrap pf:items-center pf:gap-lg pf:rounded-lg pf:border-[0.5px] pf:border-solid pf:p-lg pf:font-body pf:hover:bg-soft-pearl-200", p ? "pf:bg-soft-pearl-200" : "pf:bg-background", m?.status === "failed" ? "pf:border-red-300" : "pf:border-soft-pearl-300", g),
16
+ className: o("pf:relative pf:box-border pf:flex pf:min-w-0 pf:min-h-[64px] pf:flex-wrap pf:items-center pf:gap-lg pf:rounded-lg pf:border-[0.5px] pf:border-solid pf:p-lg pf:font-body pf:hover:bg-soft-pearl-200 pf:transition-colors pf:duration-120 pf:ease-[cubic-bezier(0.23,1,0.32,1)] pf:focus-visible:transition-none pf:motion-reduce:transition-none", p ? "pf:bg-soft-pearl-200" : "pf:bg-background", m?.status === "failed" ? "pf:border-red-300" : "pf:border-soft-pearl-300", g),
17
17
  children: [
18
18
  /* @__PURE__ */ s("span", {
19
19
  "aria-hidden": "true",
@@ -20,30 +20,56 @@ import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
20
20
  //#region src/components/artifact-panel/ArtifactPanel.tsx
21
21
  var C = "pf:box-border pf:flex pf:shrink-0 pf:max-w-[244px] pf:min-w-0 pf:h-[28px] pf:items-center pf:gap-xs pf:rounded-sm pf:px-sm pf:text-label-12-strong";
22
22
  function w({ label: w, items: T, value: E, onValueChange: D, onCloseTab: O, onClose: k, layout: A = "docked", onExpand: j, resizeConfig: M, className: N }) {
23
- let P = _(), F = y(null), I = y(null), L = T.find((e) => e.id === E) ?? T.at(0), R = v(() => T.map((e) => ({
23
+ let P = _(), F = y(null), I = y(null), L = y(!1), R = T.find((e) => e.id === E) ?? T.at(0);
24
+ g(() => {
25
+ let e = L.current;
26
+ L.current = !1;
27
+ let t = I.current;
28
+ if (!e || !t || typeof t.animate != "function" || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
29
+ let n = t.animate([{
30
+ opacity: 0,
31
+ transform: "translateY(4px)"
32
+ }, {
33
+ opacity: 1,
34
+ transform: "translateY(0)"
35
+ }], {
36
+ duration: 140,
37
+ easing: "cubic-bezier(0.23, 1, 0.32, 1)"
38
+ });
39
+ return () => {
40
+ n.cancel();
41
+ };
42
+ }, [R?.id]);
43
+ let z = v(() => T.map((e) => ({
24
44
  value: e.id,
25
45
  label: e.title,
26
46
  content: null
27
- })), [T]), { containerRef: z, measurementRef: B, visible: V } = p(R, L?.id ?? null, !0, "Open artifacts", 2, !1), H = T.filter((e) => !V || V.includes(e.id)), U = T.length - H.length, W = () => {
28
- k(), L?.returnFocusRef?.current?.focus();
29
- }, G = (e) => {
47
+ })), [T]), { containerRef: B, measurementRef: V, visible: H } = p(z, R?.id ?? null, !0, "Open artifacts", 2, !1), U = T.filter((e) => !H || H.includes(e.id)), W = T.length - U.length, G = () => {
48
+ k(), R?.returnFocusRef?.current?.focus();
49
+ }, K = (e) => {
30
50
  let t = T.findIndex((t) => t.id === e), n = T.at(t + 1) ?? (t > 0 ? T.at(t - 1) : void 0);
31
- O(e), n ? L?.id === e && (D(n.id), requestAnimationFrame(() => {
32
- (Array.from(z.current?.querySelectorAll("[role=\"tab\"]") ?? []).find((e) => e.dataset.artifactId === n.id) ?? I.current)?.focus();
33
- })) : W();
51
+ O(e), n ? R?.id === e && (D(n.id), requestAnimationFrame(() => {
52
+ (Array.from(B.current?.querySelectorAll("[role=\"tab\"]") ?? []).find((e) => e.dataset.artifactId === n.id) ?? I.current)?.focus();
53
+ })) : G();
34
54
  };
35
55
  if (g(() => {
36
56
  let e = F.current, t = (t) => {
37
- t.key === "Escape" && !t.defaultPrevented && t.target instanceof Node && e?.contains(t.target) && (t.preventDefault(), t.stopPropagation(), k(), L?.returnFocusRef?.current?.focus());
57
+ t.key === "Escape" && !t.defaultPrevented && t.target instanceof Node && e?.contains(t.target) && (t.preventDefault(), t.stopPropagation(), k(), R?.returnFocusRef?.current?.focus());
38
58
  };
39
59
  return document.addEventListener("keydown", t), () => {
40
60
  document.removeEventListener("keydown", t);
41
61
  };
42
- }, [L, k]), !L) return null;
43
- let K = T.indexOf(L), q = `${P}-tab-${String(K)}`, J = `${P}-body`;
62
+ }, [R, k]), !R) return null;
63
+ let q = T.indexOf(R), J = `${P}-tab-${String(q)}`, Y = `${P}-body`;
44
64
  return /* @__PURE__ */ S("section", {
45
65
  "aria-label": w,
46
66
  ref: F,
67
+ onPointerDownCapture: () => {
68
+ L.current = !0;
69
+ },
70
+ onKeyDownCapture: () => {
71
+ L.current = !1;
72
+ },
47
73
  className: h("pf:relative pf:flex pf:min-w-0 pf:max-w-full pf:font-body", N),
48
74
  style: { width: A === "docked" ? M?.value ?? 640 : "100%" },
49
75
  children: [A === "docked" && M && /* @__PURE__ */ x(f, {
@@ -51,7 +77,7 @@ function w({ label: w, items: T, value: E, onValueChange: D, onCloseTab: O, onCl
51
77
  label: `Resize ${w}`,
52
78
  variant: "edge",
53
79
  edge: "start",
54
- controls: J
80
+ controls: Y
55
81
  }), /* @__PURE__ */ S("div", {
56
82
  className: "pf:flex pf:min-w-0 pf:flex-1 pf:flex-col pf:overflow-hidden pf:rounded-xl pf:border-[0.5px] pf:border-solid pf:border-soft-pearl-300 pf:bg-background",
57
83
  children: [
@@ -61,36 +87,36 @@ function w({ label: w, items: T, value: E, onValueChange: D, onCloseTab: O, onCl
61
87
  A === "chat-panel" && /* @__PURE__ */ x(n, {
62
88
  size: "sm",
63
89
  label: "Back to chat",
64
- onClick: W,
90
+ onClick: G,
65
91
  children: /* @__PURE__ */ x(l, {})
66
92
  }),
67
93
  /* @__PURE__ */ S("div", {
68
94
  className: "pf:relative pf:min-w-0 pf:flex-1",
69
95
  children: [/* @__PURE__ */ S("div", {
70
- ref: z,
96
+ ref: B,
71
97
  role: "tablist",
72
98
  "aria-label": "Open artifacts",
73
99
  className: "pf:flex pf:min-w-0 pf:items-center pf:gap-xxs pf:overflow-hidden",
74
- children: [H.map((e) => /* @__PURE__ */ S("div", {
75
- className: h(C, "pf:group/artifact", L.id === e.id && "pf:bg-soft-pearl-200"),
100
+ children: [U.map((e) => /* @__PURE__ */ S("div", {
101
+ className: h(C, "pf:group/artifact", R.id === e.id && "pf:bg-soft-pearl-200"),
76
102
  children: [/* @__PURE__ */ S("button", {
77
103
  type: "button",
78
104
  role: "tab",
79
105
  id: `${P}-tab-${String(T.indexOf(e))}`,
80
106
  "data-artifact-id": e.id,
81
- "aria-selected": L.id === e.id,
82
- "aria-controls": J,
83
- tabIndex: L.id === e.id ? 0 : -1,
107
+ "aria-selected": R.id === e.id,
108
+ "aria-controls": Y,
109
+ tabIndex: R.id === e.id ? 0 : -1,
84
110
  onClick: () => {
85
111
  D(e.id);
86
112
  },
87
113
  onKeyDown: (t) => {
88
114
  if (t.key === "Delete") {
89
- t.preventDefault(), G(e.id);
115
+ t.preventDefault(), K(e.id);
90
116
  return;
91
117
  }
92
- let n = H.indexOf(e), r = getComputedStyle(t.currentTarget).direction === "rtl" ? -1 : 1, i = t.key === "ArrowRight" ? r : t.key === "ArrowLeft" ? -r : 0, a = t.key === "Home" ? H[0] : t.key === "End" ? H.at(-1) : i ? H[(n + i + H.length) % H.length] : void 0;
93
- a && (t.preventDefault(), D(a.id), (z.current?.querySelectorAll("[role=\"tab\"]"))?.[H.indexOf(a)].focus());
118
+ let n = U.indexOf(e), r = getComputedStyle(t.currentTarget).direction === "rtl" ? -1 : 1, i = t.key === "ArrowRight" ? r : t.key === "ArrowLeft" ? -r : 0, a = t.key === "Home" ? U[0] : t.key === "End" ? U.at(-1) : i ? U[(n + i + U.length) % U.length] : void 0;
119
+ a && (t.preventDefault(), D(a.id), (B.current?.querySelectorAll("[role=\"tab\"]"))?.[U.indexOf(a)].focus());
94
120
  },
95
121
  title: e.title,
96
122
  className: "pf:flex pf:min-w-0 pf:items-center pf:gap-xs pf:border-0 pf:bg-transparent pf:p-0 pf:text-inherit pf:font-body pf:text-label-12-strong pf:cursor-pointer pf:focus-visible:outline-2 pf:focus-visible:outline-blue-700",
@@ -102,19 +128,19 @@ function w({ label: w, items: T, value: E, onValueChange: D, onCloseTab: O, onCl
102
128
  size: "xs",
103
129
  label: `Close ${e.title}`,
104
130
  onClick: () => {
105
- G(e.id);
131
+ K(e.id);
106
132
  },
107
- className: h(L.id !== e.id && "pf:[@media(hover:hover)]:opacity-0 pf:group-hover/artifact:opacity-100 pf:group-focus-within/artifact:opacity-100"),
133
+ className: h(R.id !== e.id && "pf:[@media(hover:hover)]:opacity-0 pf:group-hover/artifact:opacity-100 pf:group-focus-within/artifact:opacity-100"),
108
134
  children: /* @__PURE__ */ x(a, { size: 12 })
109
135
  })]
110
- }, e.id)), U > 0 && /* @__PURE__ */ x(s, {
136
+ }, e.id)), W > 0 && /* @__PURE__ */ x(s, {
111
137
  menu: { groups: [{
112
138
  id: "artifacts",
113
139
  items: T.map((t) => ({
114
140
  type: "action",
115
141
  id: t.id,
116
142
  label: t.title,
117
- leadingIcon: L.id === t.id ? /* @__PURE__ */ x(e, {}) : void 0,
143
+ leadingIcon: R.id === t.id ? /* @__PURE__ */ x(e, {}) : void 0,
118
144
  onClick: () => {
119
145
  D(t.id);
120
146
  }
@@ -123,12 +149,12 @@ function w({ label: w, items: T, value: E, onValueChange: D, onCloseTab: O, onCl
123
149
  trigger: /* @__PURE__ */ S(t, {
124
150
  size: "sm",
125
151
  variant: "tertiary",
126
- "aria-label": `${String(U)} more artifacts; show all`,
127
- children: ["+", U]
152
+ "aria-label": `${String(W)} more artifacts; show all`,
153
+ children: ["+", W]
128
154
  })
129
155
  })]
130
156
  }), /* @__PURE__ */ S("div", {
131
- ref: B,
157
+ ref: V,
132
158
  "aria-hidden": "true",
133
159
  className: "pf:pointer-events-none pf:invisible pf:absolute pf:top-0 pf:start-0 pf:flex pf:w-max pf:gap-xxs",
134
160
  children: [T.map((e) => /* @__PURE__ */ S("div", {
@@ -158,7 +184,7 @@ function w({ label: w, items: T, value: E, onValueChange: D, onCloseTab: O, onCl
158
184
  A !== "chat-panel" && /* @__PURE__ */ x(n, {
159
185
  size: "sm",
160
186
  label: "Close artifact panel",
161
- onClick: W,
187
+ onClick: G,
162
188
  children: /* @__PURE__ */ x(a, {})
163
189
  })
164
190
  ]
@@ -168,41 +194,41 @@ function w({ label: w, items: T, value: E, onValueChange: D, onCloseTab: O, onCl
168
194
  children: [
169
195
  /* @__PURE__ */ x("div", {
170
196
  className: "pf:min-w-0 pf:flex-1 pf:text-copy-12 pf:text-soft-pearl-800 pf:wrap-anywhere",
171
- children: L.meta
197
+ children: R.meta
172
198
  }),
173
- L.versionConfig && /* @__PURE__ */ x(s, {
199
+ R.versionConfig && /* @__PURE__ */ x(s, {
174
200
  trigger: /* @__PURE__ */ x(t, {
175
201
  size: "sm",
176
202
  variant: "tertiary",
177
- children: L.versionConfig.items.find((e) => e.id === L.versionConfig?.value)?.label ?? "Version"
203
+ children: R.versionConfig.items.find((e) => e.id === R.versionConfig?.value)?.label ?? "Version"
178
204
  }),
179
205
  menu: { groups: [{
180
206
  id: "versions",
181
- items: L.versionConfig.items.map((t) => ({
207
+ items: R.versionConfig.items.map((t) => ({
182
208
  type: "action",
183
209
  id: t.id,
184
210
  label: t.label,
185
- leadingIcon: t.id === L.versionConfig?.value ? /* @__PURE__ */ x(e, {}) : void 0,
186
- onClick: () => L.versionConfig?.onValueChange(t.id)
211
+ leadingIcon: t.id === R.versionConfig?.value ? /* @__PURE__ */ x(e, {}) : void 0,
212
+ onClick: () => R.versionConfig?.onValueChange(t.id)
187
213
  }))
188
214
  }] }
189
215
  }),
190
- L.actionConfig?.onDownload && /* @__PURE__ */ x(t, {
216
+ R.actionConfig?.onDownload && /* @__PURE__ */ x(t, {
191
217
  size: "sm",
192
218
  variant: "secondary",
193
- onClick: L.actionConfig.onDownload,
194
- disabled: L.stateConfig !== void 0 && L.stateConfig.status !== "ready",
219
+ onClick: R.actionConfig.onDownload,
220
+ disabled: R.stateConfig !== void 0 && R.stateConfig.status !== "ready",
195
221
  children: "Download"
196
222
  }),
197
- L.actionConfig?.onCopy && /* @__PURE__ */ x(n, {
223
+ R.actionConfig?.onCopy && /* @__PURE__ */ x(n, {
198
224
  size: "sm",
199
225
  label: "Copy artifact",
200
- onClick: L.actionConfig.onCopy,
201
- disabled: L.stateConfig !== void 0 && L.stateConfig.status !== "ready",
226
+ onClick: R.actionConfig.onCopy,
227
+ disabled: R.stateConfig !== void 0 && R.stateConfig.status !== "ready",
202
228
  children: /* @__PURE__ */ x(r, {})
203
229
  }),
204
- L.actionConfig?.menu && /* @__PURE__ */ x(s, {
205
- menu: L.actionConfig.menu,
230
+ R.actionConfig?.menu && /* @__PURE__ */ x(s, {
231
+ menu: R.actionConfig.menu,
206
232
  trigger: /* @__PURE__ */ x(n, {
207
233
  size: "sm",
208
234
  label: "Artifact actions",
@@ -213,16 +239,16 @@ function w({ label: w, items: T, value: E, onValueChange: D, onCloseTab: O, onCl
213
239
  }),
214
240
  /* @__PURE__ */ x("div", {
215
241
  ref: I,
216
- id: J,
242
+ id: Y,
217
243
  role: "tabpanel",
218
- "aria-labelledby": H.includes(L) ? q : void 0,
219
- "aria-label": H.includes(L) ? void 0 : L.title,
220
- "aria-busy": L.stateConfig?.status === "loading" || L.stateConfig?.status === "generating" || void 0,
244
+ "aria-labelledby": U.includes(R) ? J : void 0,
245
+ "aria-label": U.includes(R) ? void 0 : R.title,
246
+ "aria-busy": R.stateConfig?.status === "loading" || R.stateConfig?.status === "generating" || void 0,
221
247
  tabIndex: 0,
222
248
  className: "pf:min-w-0 pf:flex-1 pf:overflow-auto pf:overscroll-contain pf:p-2xl pf:focus-visible:outline-2 pf:focus-visible:-outline-offset-2 pf:focus-visible:outline-blue-700",
223
- children: L.stateConfig?.status === "loading" ? /* @__PURE__ */ S("div", {
249
+ children: R.stateConfig?.status === "loading" ? /* @__PURE__ */ S("div", {
224
250
  role: "status",
225
- "aria-label": L.stateConfig.label ?? "Loading artifact",
251
+ "aria-label": R.stateConfig.label ?? "Loading artifact",
226
252
  className: "pf:flex pf:flex-col pf:gap-lg",
227
253
  children: [
228
254
  /* @__PURE__ */ x(o, { width: "40%" }),
@@ -235,26 +261,26 @@ function w({ label: w, items: T, value: E, onValueChange: D, onCloseTab: O, onCl
235
261
  /* @__PURE__ */ x(o, { width: "85%" }),
236
262
  /* @__PURE__ */ x(o, { width: "70%" })
237
263
  ]
238
- }) : L.stateConfig?.status === "failed" ? /* @__PURE__ */ x("div", {
264
+ }) : R.stateConfig?.status === "failed" ? /* @__PURE__ */ x("div", {
239
265
  role: "status",
240
266
  className: "pf:flex pf:min-h-[240px] pf:h-full pf:items-center pf:justify-center",
241
267
  children: /* @__PURE__ */ x(c, {
242
268
  kind: "error",
243
269
  title: "Couldn’t load this artifact",
244
- description: L.stateConfig.message,
270
+ description: R.stateConfig.message,
245
271
  primaryAction: {
246
272
  label: "Retry",
247
- onClick: L.stateConfig.onRetry
273
+ onClick: R.stateConfig.onRetry
248
274
  }
249
275
  })
250
- }) : /* @__PURE__ */ S(b, { children: [L.stateConfig?.status === "generating" && /* @__PURE__ */ S("div", {
276
+ }) : /* @__PURE__ */ S(b, { children: [R.stateConfig?.status === "generating" && /* @__PURE__ */ S("div", {
251
277
  role: "status",
252
278
  className: "pf:flex pf:items-center pf:gap-sm pf:mb-md pf:text-copy-12",
253
279
  children: [/* @__PURE__ */ x(i, {
254
280
  value: null,
255
281
  label: "Generating artifact"
256
- }), L.stateConfig.label ?? "Generating…"]
257
- }), L.content] })
282
+ }), R.stateConfig.label ?? "Generating…"]
283
+ }), R.content] })
258
284
  })
259
285
  ]
260
286
  })]
@@ -1,7 +1,3 @@
1
1
  import type { AttachmentProps } from './attachment-types.js';
2
- /** ATTACH-01: Figma569:26294. 28px pill, radius6, hairline; original filename, max240.
3
- * ATTACH-02: Failed uploads persist with a red border/status icon; clicking retries.
4
- * ATTACH-03: Removal is a separate control, available while uploading; host owns cancellation.
5
- * ATTACH-04: Uploaded inputs are attachments; agent-generated outputs are artifacts.
6
- */
7
- export declare const Attachment: ({ item, layout, onDownload, saveConfig, onPreview, onRetry, onRemove, previewConfig, className, }: AttachmentProps) => import("react/jsx-runtime").JSX.Element;
2
+ /** A host preview callback takes precedence; otherwise use the shared preview dialog. */
3
+ export declare function Attachment(props: AttachmentProps): import("react/jsx-runtime").JSX.Element;
@@ -4,73 +4,96 @@ import { ProgressRing as t } from "../status-icons/ProgressRing.js";
4
4
  import { XCloseIcon as n } from "../icons/XCloseIcon.js";
5
5
  import { Popover as r } from "../popover/Popover.js";
6
6
  import { StatusFailedIcon as i } from "../status-icons/StatusFailedIcon.js";
7
- import { FileTypeHelper as a } from "../file-types/file-type-helper.js";
8
- import { attachmentBodyClass as o, attachmentShellClass as s } from "./attachment-class-names.js";
9
- import { AttachmentCard as c } from "./AttachmentCard.js";
10
- import l from "clsx";
11
- import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
7
+ import { Dialog as a } from "../dialog/Dialog.js";
8
+ import { FileTypeHelper as o } from "../file-types/file-type-helper.js";
9
+ import { safeHref as s } from "../inline-reference/safe-href.js";
10
+ import { attachmentBodyClass as c, attachmentShellClass as l } from "./attachment-class-names.js";
11
+ import { AttachmentCard as u } from "./AttachmentCard.js";
12
+ import d from "clsx";
13
+ import { useState as f } from "react";
14
+ import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
12
15
  //#region src/components/attachment/Attachment.tsx
13
- var p = ({ item: p, layout: m = "pill", onDownload: h, saveConfig: g, onPreview: _, onRetry: v, onRemove: y, previewConfig: b, className: x }) => {
14
- if (m === "card") return /* @__PURE__ */ d(c, {
15
- item: p,
16
+ var g = ({ item: a, layout: s = "pill", onDownload: f, saveConfig: g, onPreview: _, onRetry: v, onRemove: y, previewConfig: b, className: x }) => {
17
+ if (s === "card") return /* @__PURE__ */ m(u, {
18
+ item: a,
16
19
  onPreview: _,
17
20
  onRetry: v,
18
21
  onRemove: y,
19
- onDownload: h,
22
+ onDownload: f,
20
23
  saveConfig: g,
21
- className: x
24
+ className: x,
25
+ previewConfig: b
22
26
  });
23
- let S = p.upload?.status ?? "ready", C = S === "failed", w = C ? v : S === "ready" ? _ : void 0, T = /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d("span", {
27
+ let S = a.upload?.status ?? "ready", C = S === "failed", w = C ? v : S === "ready" ? _ : void 0, T = /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m("span", {
24
28
  className: "pf:flex pf:shrink-0 pf:size-xl pf:items-center pf:justify-center",
25
- children: p.upload?.status === "uploading" ? /* @__PURE__ */ d(t, {
26
- value: p.upload.progress,
27
- label: `Uploading ${p.filename}`
28
- }) : C ? /* @__PURE__ */ d(i, { size: 16 }) : /* @__PURE__ */ d(e, {
29
+ children: a.upload?.status === "uploading" ? /* @__PURE__ */ m(t, {
30
+ value: a.upload.progress,
31
+ label: `Uploading ${a.filename}`
32
+ }) : C ? /* @__PURE__ */ m(i, { size: 16 }) : /* @__PURE__ */ m(e, {
29
33
  size: 16,
30
- kind: p.kind === "folder" ? "folder" : p.kind === "image" || p.mediaType?.startsWith("image/") ? "image" : a.fromFilename(p.filename)
34
+ kind: a.kind === "folder" ? "folder" : a.kind === "image" || a.mediaType?.startsWith("image/") ? "image" : o.fromFilename(a.filename)
31
35
  })
32
- }), /* @__PURE__ */ d("span", {
36
+ }), /* @__PURE__ */ m("span", {
33
37
  className: "pf:min-w-0 pf:truncate",
34
- children: p.filename
35
- })] }), E = w || S === "ready" && b ? /* @__PURE__ */ d("button", {
38
+ children: a.filename
39
+ })] }), E = w || S === "ready" && b ? /* @__PURE__ */ m("button", {
36
40
  type: "button",
37
- className: l(o, "pf:cursor-pointer"),
38
- "aria-label": `${C ? "Retry" : "Preview"} ${p.filename}`,
39
- onClick: () => w?.(p),
41
+ className: d(c, "pf:cursor-pointer"),
42
+ "aria-label": `${C ? "Retry" : "Preview"} ${a.filename}`,
43
+ onClick: () => w?.(a),
40
44
  children: T
41
- }) : /* @__PURE__ */ d("span", {
42
- className: o,
45
+ }) : /* @__PURE__ */ m("span", {
46
+ className: c,
43
47
  children: T
44
48
  });
45
- return /* @__PURE__ */ f("span", {
49
+ return /* @__PURE__ */ h("span", {
46
50
  "data-pf-attachment": "",
47
51
  "data-status": S,
48
- className: l(s, C ? "pf:border pf:border-red-300 pf:text-red-800" : "pf:border-[0.5px] pf:border-soft-pearl-300", S === "uploading" ? "pf:text-soft-pearl-800" : !C && "pf:text-soft-pearl-1000", x),
49
- title: p.upload?.status === "failed" ? `${p.filename}: ${p.upload.error}` : p.filename,
52
+ className: d(l, C ? "pf:border pf:border-red-300 pf:text-red-800" : "pf:border-[0.5px] pf:border-soft-pearl-300", S === "uploading" ? "pf:text-soft-pearl-800" : !C && "pf:text-soft-pearl-1000", x),
50
53
  children: [
51
- S === "ready" && b ? /* @__PURE__ */ d(r, {
54
+ S === "ready" && b ? /* @__PURE__ */ m(r, {
52
55
  mode: "preview",
53
- title: p.filename,
56
+ title: a.filename,
54
57
  trigger: E,
55
58
  loadingConfig: { isLoading: b.isLoading ?? !1 },
56
59
  children: b.content
57
60
  }) : E,
58
- p.upload?.status === "failed" && /* @__PURE__ */ d("span", {
61
+ a.upload?.status === "failed" && /* @__PURE__ */ m("span", {
59
62
  className: "pf:sr-only",
60
63
  role: "status",
61
- children: p.upload.error
64
+ children: a.upload.error
62
65
  }),
63
- y && /* @__PURE__ */ d("button", {
66
+ y && /* @__PURE__ */ m("button", {
64
67
  type: "button",
65
68
  className: "pf:flex pf:shrink-0 pf:size-xl pf:items-center pf:justify-center pf:rounded-xs pf:border-0 pf:bg-transparent pf:p-0 pf:text-soft-pearl-800 pf:cursor-pointer pf:hover:text-soft-pearl-1000 pf:focus-visible:outline-2 pf:focus-visible:outline-blue-700",
66
- "aria-label": `Remove ${p.filename}`,
69
+ "aria-label": `Remove ${a.filename}`,
67
70
  onClick: () => {
68
- y(p);
71
+ y(a);
69
72
  },
70
- children: /* @__PURE__ */ d(n, { size: 16 })
73
+ children: /* @__PURE__ */ m(n, { size: 16 })
71
74
  })
72
75
  ]
73
76
  });
74
77
  };
78
+ function _(e) {
79
+ let [t, n] = f(!1), r = s(e.item.url), i = e.item.kind === "image" || e.item.mediaType?.startsWith("image/"), o = e.previewConfig ?? (r && i ? { content: /* @__PURE__ */ m("img", {
80
+ src: r,
81
+ alt: e.item.filename,
82
+ className: "pf:block pf:max-w-full pf:max-h-[60dvh] pf:object-contain pf:mx-auto"
83
+ }) } : void 0);
84
+ return /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(g, {
85
+ ...e,
86
+ previewConfig: o,
87
+ onPreview: e.onPreview ?? (o ? () => {
88
+ n(!0);
89
+ } : void 0)
90
+ }), /* @__PURE__ */ m(a, {
91
+ open: t,
92
+ onOpenChange: n,
93
+ title: e.item.filename,
94
+ size: "lg",
95
+ children: o?.content
96
+ })] });
97
+ }
75
98
  //#endregion
76
- export { p as Attachment };
99
+ export { _ as Attachment };
@@ -1,3 +1,3 @@
1
1
  import type { AttachmentProps } from './attachment-types.js';
2
2
  /** ATTACH-05: Figma1445:98012/98094. Card attachments retain real names and separate saved/download actions. */
3
- export declare function AttachmentCard({ item, onPreview, onRetry, onRemove, onDownload, saveConfig, className, }: AttachmentProps): import("react/jsx-runtime").JSX.Element;
3
+ export declare function AttachmentCard({ item, onPreview, onRetry, onRemove, onDownload, saveConfig, className, previewConfig, }: AttachmentProps): import("react/jsx-runtime").JSX.Element;