@parallelworks/ui 0.19.0 → 0.19.1

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 (217) hide show
  1. package/dist/{chunks/memoryStore-CC91S5LP.js → ai/adapter/memoryStore.js} +2 -2
  2. package/dist/ai/adapter/mock/index.js +2 -80
  3. package/dist/ai/adapter/mock/mockAdapter.js +81 -0
  4. package/dist/ai/adapter/openai/createOpenAIStream.js +33 -0
  5. package/dist/ai/adapter/openai/errors.js +37 -0
  6. package/dist/ai/adapter/openai/index.js +5 -333
  7. package/dist/ai/adapter/openai/openaiAdapter.js +54 -0
  8. package/dist/ai/adapter/openai/responses.js +108 -0
  9. package/dist/ai/adapter/openai/sse.js +112 -0
  10. package/dist/{chunks/types-Yy0NrerF.js → ai/adapter/types.js} +1 -1
  11. package/dist/ai/agent/classifier.js +12 -0
  12. package/dist/ai/agent/diff.js +223 -0
  13. package/dist/ai/agent/diffHighlight.js +101 -0
  14. package/dist/ai/agent/permissions.js +29 -0
  15. package/dist/ai/agent/toolfmt.js +383 -0
  16. package/dist/ai/agent/transcript.js +127 -0
  17. package/dist/ai/components/AllocationSelector.js +56 -0
  18. package/dist/ai/components/AttachmentManager.js +144 -0
  19. package/dist/ai/components/AttachmentUpload.js +179 -0
  20. package/dist/ai/components/BlockedGroupBanner.js +29 -0
  21. package/dist/ai/components/BranchNavigator.js +57 -0
  22. package/dist/ai/components/ChatEmptyState.js +171 -0
  23. package/dist/ai/components/ChatInput.js +265 -0
  24. package/dist/ai/components/ChatLayout.js +15 -0
  25. package/dist/ai/components/ChatMessage.js +338 -0
  26. package/dist/ai/components/ChatMessageList.js +301 -0
  27. package/dist/ai/components/ChatSidebar.js +345 -0
  28. package/dist/ai/components/ChatThread.js +198 -0
  29. package/dist/ai/components/ComposerChrome.js +50 -0
  30. package/dist/ai/components/ComposerFrame.js +33 -0
  31. package/dist/ai/components/DragOverlay.js +20 -0
  32. package/dist/ai/components/ModelSelector.js +343 -0
  33. package/dist/ai/components/ShareDialog.js +260 -0
  34. package/dist/ai/components/SlashMenu.js +91 -0
  35. package/dist/ai/components/agent/ActivityLine.js +151 -0
  36. package/dist/ai/components/agent/AgentMessageParts.js +721 -0
  37. package/dist/ai/components/agent/PermissionPicker.js +38 -0
  38. package/dist/ai/components/attachmentKeys.js +10 -0
  39. package/dist/ai/core/ChatProvider.js +848 -0
  40. package/dist/ai/core/KeyboardShortcutsProvider.js +9 -0
  41. package/dist/ai/core/chatReducer.js +223 -0
  42. package/dist/ai/core/config.js +45 -0
  43. package/dist/ai/core/events.js +4 -0
  44. package/dist/ai/core/exportConversation.js +42 -0
  45. package/dist/ai/core/greeting.js +38 -0
  46. package/dist/ai/core/parts.js +84 -0
  47. package/dist/ai/core/useDragDrop.js +36 -0
  48. package/dist/ai/core/useKeyboardShortcuts.js +77 -0
  49. package/dist/ai/core/useSSEStream.js +98 -0
  50. package/dist/ai/index.js +43 -6644
  51. package/dist/ai/strings.js +175 -0
  52. package/dist/ai/ui/Avatar.js +35 -0
  53. package/dist/ai/ui/Dropdown.js +110 -0
  54. package/dist/ai/ui/Markdown.js +79 -0
  55. package/dist/ai/ui/Notice.js +77 -0
  56. package/dist/ai/ui/codeBreaks.js +36 -0
  57. package/dist/ai/ui/prose.js +13 -0
  58. package/dist/ai/ui/sidebar.js +148 -0
  59. package/dist/ai/utils.js +23 -0
  60. package/dist/components/AddMenu.js +46 -0
  61. package/dist/components/Avatar.js +46 -0
  62. package/dist/{chunks/BareModal-BtRiQezg.js → components/BareModal.js} +1 -1
  63. package/dist/components/Breadcrumbs.js +83 -0
  64. package/dist/components/Button.js +83 -0
  65. package/dist/components/Callout.js +23 -0
  66. package/dist/components/Card.js +31 -0
  67. package/dist/components/CollapsiblePanel.js +77 -0
  68. package/dist/{chunks/ConfirmModal-aOR4O1QE.js → components/ConfirmModal.js} +4 -9
  69. package/dist/components/CopyToClipboard.js +81 -0
  70. package/dist/{chunks/Markdown-CM-FenNE.js → components/CreateModal.js} +9 -116
  71. package/dist/components/DescriptionList.js +42 -0
  72. package/dist/components/Dropdown.js +349 -0
  73. package/dist/components/EmptyState.js +27 -0
  74. package/dist/components/Filter.js +32 -0
  75. package/dist/components/FilterPill.js +13 -0
  76. package/dist/components/IconButton.js +34 -0
  77. package/dist/{chunks/Indicator-hBSIxOPK.js → components/Indicator.js} +1 -1
  78. package/dist/components/Input.js +88 -0
  79. package/dist/components/LetterBadge.js +13 -0
  80. package/dist/components/Listbox.js +123 -0
  81. package/dist/{chunks/Loader-BXoXTZGc.js → components/Loader.js} +1 -1
  82. package/dist/components/Markdown.js +15 -0
  83. package/dist/components/MultiSelect.js +171 -0
  84. package/dist/components/Overview.js +39 -0
  85. package/dist/components/PageHeader.js +194 -0
  86. package/dist/components/Pagination.js +35 -0
  87. package/dist/{chunks/Provider-CDYurraE.js → components/Provider.js} +1 -1
  88. package/dist/{chunks/RequiredMark-DfLdYbYZ.js → components/RequiredMark.js} +1 -1
  89. package/dist/components/SectionHeader.js +11 -0
  90. package/dist/components/SettingModeOption.js +30 -0
  91. package/dist/components/SettingRow.js +35 -0
  92. package/dist/components/SettingsCard.js +31 -0
  93. package/dist/components/SettingsGroup.js +17 -0
  94. package/dist/components/Sort.js +42 -0
  95. package/dist/components/StatusBadge.js +63 -0
  96. package/dist/components/SwitchToggle.js +59 -0
  97. package/dist/{chunks/SwitchToggleSmall-FcsaYSTs.js → components/SwitchToggleSmall.js} +1 -1
  98. package/dist/{chunks/Table-DU2MW8xz.js → components/Table.js} +3 -3
  99. package/dist/components/Toggle.js +20 -0
  100. package/dist/{chunks/Tooltip-K5HJr4_p.js → components/Tooltip.js} +2 -27
  101. package/dist/{chunks/StatusBadge-C1Blx_cW.js → components/dropdownUtils.js} +2 -63
  102. package/dist/{chunks/focus-D_iZJTW1.js → components/focus.js} +1 -1
  103. package/dist/components/ghostButton.js +7 -0
  104. package/dist/components/inputClasses.js +4 -0
  105. package/dist/components/keys.js +27 -0
  106. package/dist/components/relativeTime.js +32 -0
  107. package/dist/{chunks/useCssIsDark-DHr05dG2.js → components/useCssIsDark.js} +1 -1
  108. package/dist/{chunks/duration-BOv8Phl8.js → duration.js} +1 -1
  109. package/dist/editor/Editor.js +13 -0
  110. package/dist/editor/EditorField.js +53 -0
  111. package/dist/editor/FormCodePanel.js +173 -0
  112. package/dist/{chunks/Monaco-DJ8MW-Dq.js → editor/Monaco.js} +4 -2
  113. package/dist/editor/index.js +6 -1
  114. package/dist/editor/themes.js +91 -0
  115. package/dist/editor/workers.js +29 -0
  116. package/dist/editor/yaml.js +15 -0
  117. package/dist/file-explorer/FileExplorer.js +1402 -0
  118. package/dist/file-explorer/FileExplorerContext.js +370 -0
  119. package/dist/{chunks/CodePreviewEditor-YqQBz1YL.js → file-explorer/FilePreview/CodePreviewEditor.js} +3 -2
  120. package/dist/file-explorer/FilePreview/Inline.js +45 -0
  121. package/dist/file-explorer/FilePreview/StreamedBadge.js +16 -0
  122. package/dist/file-explorer/FilePreview/Viewer.js +526 -0
  123. package/dist/file-explorer/FilePreview/index.js +266 -0
  124. package/dist/file-explorer/FilePreview/parse.js +63 -0
  125. package/dist/file-explorer/FilePreview/previewCache.js +98 -0
  126. package/dist/file-explorer/FilePreview/previewType.js +151 -0
  127. package/dist/file-explorer/FilePreview/readCappedBytes.js +196 -0
  128. package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +95 -0
  129. package/dist/file-explorer/FilePreview/useObjectText.js +109 -0
  130. package/dist/file-explorer/FilePreview/usePresignedUrl.js +73 -0
  131. package/dist/file-explorer/FileRow.js +165 -0
  132. package/dist/file-explorer/FileRowsWindow.js +92 -0
  133. package/dist/file-explorer/FileTable.js +172 -0
  134. package/dist/file-explorer/FileTableHeaders.js +49 -0
  135. package/dist/file-explorer/LoadMoreRow.js +46 -0
  136. package/dist/file-explorer/TreeView.js +376 -0
  137. package/dist/file-explorer/helpers.js +537 -0
  138. package/dist/file-explorer/index.js +7 -5671
  139. package/dist/file-explorer/lib/batch.js +39 -0
  140. package/dist/file-explorer/lib/errors.js +9 -0
  141. package/dist/file-explorer/lib/paging.js +124 -0
  142. package/dist/file-explorer/lib/utils.js +322 -0
  143. package/dist/file-explorer/toasts.js +400 -0
  144. package/dist/file-explorer/treeRows.js +73 -0
  145. package/dist/file-explorer/useNearEnd.js +27 -0
  146. package/dist/form/FieldWrapper.js +54 -0
  147. package/dist/form/Fields/BooleanField.js +51 -0
  148. package/dist/form/Fields/CheckboxGroupField.js +72 -0
  149. package/dist/form/Fields/ColorField.js +33 -0
  150. package/dist/form/Fields/DropdownField.js +49 -0
  151. package/dist/form/Fields/DurationField.js +130 -0
  152. package/dist/form/Fields/LabelField.js +19 -0
  153. package/dist/form/Fields/MultiDropdownField.js +40 -0
  154. package/dist/form/Fields/NumberField.js +51 -0
  155. package/dist/form/Fields/ObjectField.js +54 -0
  156. package/dist/form/Fields/RadioField.js +49 -0
  157. package/dist/form/Fields/RangeField.js +58 -0
  158. package/dist/form/Fields/ResourceOptionIcon.js +21 -0
  159. package/dist/form/Fields/StepField.js +6 -0
  160. package/dist/form/Fields/StringField.js +37 -0
  161. package/dist/form/Fields/TextAreaField.js +31 -0
  162. package/dist/form/Fields/durationValidity.js +11 -0
  163. package/dist/form/Form.js +643 -0
  164. package/dist/form/SpecialTypes/DropdownWrapper.js +30 -0
  165. package/dist/form/SpecialTypes/FormikCustomDropdown.js +122 -0
  166. package/dist/form/SpecialTypes/FormikCustomInput.js +111 -0
  167. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +31 -0
  168. package/dist/form/SpecialTypes/FormikNumericInput.js +60 -0
  169. package/dist/form/Wizard/WizardContainer.js +138 -0
  170. package/dist/form/Wizard/WizardNavigation.js +92 -0
  171. package/dist/form/Wizard/WizardStepContent.js +35 -0
  172. package/dist/form/Wizard/WizardStepIndicator.js +108 -0
  173. package/dist/form/Wizard/useWizardState.js +118 -0
  174. package/dist/form/Wizard/utils.js +34 -0
  175. package/dist/form/fieldContext.js +26 -0
  176. package/dist/form/fieldRegistry.js +50 -0
  177. package/dist/form/index.js +17 -2321
  178. package/dist/{chunks/FieldWrapper-Cszwg-4B.js → form/lib.js} +2 -97
  179. package/dist/form/useParsedOpts.js +62 -0
  180. package/dist/form/usePrevious.js +11 -0
  181. package/dist/form/utils/checkShowIfObject.js +14 -0
  182. package/dist/form/utils/duration.js +69 -0
  183. package/dist/form/utils/getParentValue.js +23 -0
  184. package/dist/form/utils/getPlaceholder.js +9 -0
  185. package/dist/form/utils/getValueUsingPath.js +23 -0
  186. package/dist/form/utils/secondaryField.js +22 -0
  187. package/dist/graph/AnnotationBanner.js +141 -0
  188. package/dist/graph/Collapse.js +41 -0
  189. package/dist/graph/DependencyGraph.js +1398 -0
  190. package/dist/graph/JobSummary.js +104 -0
  191. package/dist/graph/MatrixGroup.js +107 -0
  192. package/dist/graph/Reveal.js +57 -0
  193. package/dist/graph/TreeView.js +711 -0
  194. package/dist/graph/index.js +1 -2519
  195. package/dist/graph/types.js +6 -0
  196. package/dist/index.js +46 -599
  197. package/dist/list/ActionToolbar.js +184 -0
  198. package/dist/list/HoverCard.js +73 -0
  199. package/dist/list/ListPage.js +145 -0
  200. package/dist/list/ListPager.js +59 -0
  201. package/dist/list/ListTable.js +163 -0
  202. package/dist/list/ListViewControls.js +372 -0
  203. package/dist/list/RowContextMenu.js +350 -0
  204. package/dist/list/UserHoverCard.js +117 -0
  205. package/dist/list/index.js +11 -2
  206. package/dist/list/listSearch.js +137 -0
  207. package/dist/list/listView.js +210 -0
  208. package/dist/list/textEntry.js +10 -0
  209. package/dist/{chunks/logviewer-BTKuQWzw.js → logviewer/LogViewer.js} +4 -82
  210. package/dist/logviewer/index.js +2 -1
  211. package/dist/logviewer/segments.js +80 -0
  212. package/package.json +1 -1
  213. package/dist/chunks/PageHeader-0kG_iypP.js +0 -692
  214. package/dist/chunks/SwitchToggle-DShNdcao.js +0 -758
  215. package/dist/chunks/editor-Dk1rbV75.js +0 -361
  216. package/dist/chunks/list-CJm875m7.js +0 -1418
  217. /package/dist/{chunks/MarkdownImpl-CyeTVvSt.js → components/MarkdownImpl.js} +0 -0
@@ -0,0 +1,372 @@
1
+ import { useStrings } from "../components/Provider.js";
2
+ import { CheckIcon, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, DisplayIcon, FilterIcon } from "../icons.js";
3
+ import { TOOLTIP_ID, TooltipInfo } from "../components/Tooltip.js";
4
+ import { isTextEntryContext } from "./textEntry.js";
5
+ import cx from "classnames";
6
+ import { useCallback, useEffect, useRef, useState } from "react";
7
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
+ import { createPortal } from "react-dom";
9
+ //#region src/list/ListViewControls.tsx
10
+ /** Shared chrome for the toolbar control buttons (Filter, Display, Search) so
11
+ * they read as a consistent button cluster — matched by ListSearchControl. */
12
+ var listControlButtonClasses = "relative flex h-7 w-7 items-center justify-center rounded-md border border-(--theme-border) text-(--theme-muted-text-color) hover:bg-(--theme-muted-panel-bg) hover:text-(--theme-app) transition-colors";
13
+ var FLYOUT = "min-w-44 rounded-lg border border-(--theme-border) bg-(--theme-app-bg) py-1 shadow-lg";
14
+ /** Toggle pill shared by the Display menu's column + pinned-action pickers. */
15
+ function pillClass(on) {
16
+ return cx("whitespace-nowrap rounded-full border px-2.5 py-1 text-[12px] transition-colors", on ? "border-transparent bg-(--theme-muted-panel-bg) text-(--theme-app)" : "border-(--theme-border) text-(--theme-muted-text-color) hover:bg-(--theme-muted-panel-bg) hover:text-(--theme-app)");
17
+ }
18
+ var SECTION_LABEL = "mb-2 text-[11px] font-medium uppercase tracking-wide text-(--theme-muted-text-color)";
19
+ /** Portals into .ds-root so the panel escapes the toolbar's overflow clipping. */
20
+ function AnchoredPopover({ icon, label, active, shortcut, panelClassName, children }) {
21
+ const btnRef = useRef(null);
22
+ const panelRef = useRef(null);
23
+ const [pos, setPos] = useState(null);
24
+ const close = useCallback(() => setPos(null), []);
25
+ const open = useCallback(() => {
26
+ const r = btnRef.current?.getBoundingClientRect();
27
+ if (r) setPos({
28
+ right: Math.max(8, Math.round(window.innerWidth - r.right)),
29
+ top: Math.round(r.bottom) + 4
30
+ });
31
+ }, []);
32
+ useEffect(() => {
33
+ if (!pos) return;
34
+ const onKey = (e) => {
35
+ if (e.key === "Escape") close();
36
+ };
37
+ const onScroll = (e) => {
38
+ if (e.target instanceof Node && panelRef.current?.contains(e.target)) return;
39
+ close();
40
+ };
41
+ window.addEventListener("keydown", onKey);
42
+ window.addEventListener("scroll", onScroll, true);
43
+ window.addEventListener("resize", close);
44
+ return () => {
45
+ window.removeEventListener("keydown", onKey);
46
+ window.removeEventListener("scroll", onScroll, true);
47
+ window.removeEventListener("resize", close);
48
+ };
49
+ }, [pos, close]);
50
+ useEffect(() => {
51
+ if (!shortcut) return;
52
+ const onKey = (e) => {
53
+ if (e.metaKey || e.ctrlKey || e.altKey) return;
54
+ if (e.key.toLowerCase() !== shortcut.toLowerCase()) return;
55
+ if (isTextEntryContext(e.target)) return;
56
+ e.preventDefault();
57
+ open();
58
+ };
59
+ window.addEventListener("keydown", onKey);
60
+ return () => window.removeEventListener("keydown", onKey);
61
+ }, [shortcut, open]);
62
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("button", {
63
+ ref: btnRef,
64
+ type: "button",
65
+ onClick: () => pos ? close() : open(),
66
+ "aria-label": label,
67
+ "data-tooltip-id": TOOLTIP_ID,
68
+ "data-tooltip-content": label,
69
+ "data-tooltip-shortcut": shortcut ? shortcut.toUpperCase() : void 0,
70
+ className: cx(listControlButtonClasses, active && "border-(--theme-link) text-(--theme-app)"),
71
+ children: [icon, active && /* @__PURE__ */ jsx("span", { className: "absolute right-0 top-0 h-1.5 w-1.5 rounded-full bg-(--theme-link)" })]
72
+ }), pos && createPortal(/* @__PURE__ */ jsx("div", {
73
+ role: "none",
74
+ className: "fixed inset-0 z-50",
75
+ onMouseDown: close,
76
+ onContextMenu: (e) => {
77
+ e.preventDefault();
78
+ close();
79
+ },
80
+ children: /* @__PURE__ */ jsx("div", {
81
+ ref: panelRef,
82
+ role: "menu",
83
+ onMouseDown: (e) => e.stopPropagation(),
84
+ className: cx("absolute rounded-lg border border-(--theme-border) bg-(--theme-app-bg) shadow-lg", panelClassName),
85
+ style: {
86
+ right: pos.right,
87
+ top: pos.top
88
+ },
89
+ children
90
+ })
91
+ }), document.querySelector(".ds-root") ?? document.body)] });
92
+ }
93
+ /** Small on/off switch for the Display menu's boolean options. */
94
+ function Switch({ checked, onChange, label }) {
95
+ return /* @__PURE__ */ jsx("button", {
96
+ type: "button",
97
+ role: "switch",
98
+ "aria-checked": checked,
99
+ "aria-label": label,
100
+ onClick: onChange,
101
+ className: cx("relative inline-flex h-4 w-7 shrink-0 items-center rounded-full transition-colors", checked ? "bg-(--theme-link)" : "bg-(--theme-border)"),
102
+ children: /* @__PURE__ */ jsx("span", { className: cx("inline-block h-3 w-3 rounded-full bg-white transition-transform", checked ? "translate-x-3.5" : "translate-x-0.5") })
103
+ });
104
+ }
105
+ function ListDisplayMenu({ view, label }) {
106
+ const t = useStrings().list;
107
+ const toggleable = view.columns.filter((c) => !c.alwaysVisible);
108
+ const hasGrouping = view.groupBys.length > 0;
109
+ const orderDirLabel = view.orderDir === "asc" ? t.ascending : t.descending;
110
+ return /* @__PURE__ */ jsxs(AnchoredPopover, {
111
+ icon: /* @__PURE__ */ jsx(DisplayIcon, { className: "h-3.5 w-3.5" }),
112
+ label: label ?? t.displayOptions,
113
+ panelClassName: "w-72 p-3",
114
+ children: [
115
+ hasGrouping && /* @__PURE__ */ jsxs("div", {
116
+ className: "flex items-center justify-between gap-3",
117
+ children: [/* @__PURE__ */ jsx("span", {
118
+ className: "text-[13px] text-(--theme-app)",
119
+ children: t.grouping
120
+ }), /* @__PURE__ */ jsx(GroupingDropdown, { view })]
121
+ }),
122
+ view.orderBys.length > 0 && /* @__PURE__ */ jsxs("div", {
123
+ className: cx("flex items-center justify-between gap-3", hasGrouping && "mt-2.5"),
124
+ children: [/* @__PURE__ */ jsx("span", {
125
+ className: "text-[13px] text-(--theme-app)",
126
+ children: t.ordering
127
+ }), /* @__PURE__ */ jsxs("div", {
128
+ className: "flex items-center gap-1",
129
+ children: [/* @__PURE__ */ jsx("button", {
130
+ type: "button",
131
+ onClick: view.toggleOrderDir,
132
+ "aria-label": orderDirLabel,
133
+ title: orderDirLabel,
134
+ className: "flex h-7 w-7 items-center justify-center rounded-md border border-(--theme-border) text-(--theme-muted-text-color) hover:bg-(--theme-muted-panel-bg) hover:text-(--theme-app)",
135
+ children: view.orderDir === "asc" ? /* @__PURE__ */ jsx(ChevronUpIcon, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-3 w-3" })
136
+ }), /* @__PURE__ */ jsx(OrderingDropdown, { view })]
137
+ })]
138
+ }),
139
+ /* @__PURE__ */ jsxs("div", {
140
+ className: cx("flex items-center justify-between gap-3", (hasGrouping || view.orderBys.length > 0) && "mt-2.5"),
141
+ children: [/* @__PURE__ */ jsx("span", {
142
+ className: "text-[13px] text-(--theme-app)",
143
+ children: t.columnHeaders
144
+ }), /* @__PURE__ */ jsx(Switch, {
145
+ checked: view.showColumnHeaders,
146
+ onChange: view.toggleColumnHeaders,
147
+ label: t.showColumnHeaders
148
+ })]
149
+ }),
150
+ /* @__PURE__ */ jsxs("div", {
151
+ className: "mt-2.5 flex items-center justify-between gap-3",
152
+ children: [/* @__PURE__ */ jsx("span", {
153
+ className: "text-[13px] text-(--theme-app)",
154
+ children: t.showActions
155
+ }), /* @__PURE__ */ jsx(Switch, {
156
+ checked: view.showActions,
157
+ onChange: view.toggleShowActions,
158
+ label: t.showRowActions
159
+ })]
160
+ }),
161
+ view.showActions && /* @__PURE__ */ jsxs("div", {
162
+ className: "mt-2.5 flex items-center justify-between gap-3 pl-3",
163
+ children: [/* @__PURE__ */ jsx("span", {
164
+ className: "text-[13px] text-(--theme-muted-text-color)",
165
+ children: t.alwaysShowActions
166
+ }), /* @__PURE__ */ jsx(Switch, {
167
+ checked: view.alwaysShowActions,
168
+ onChange: view.toggleAlwaysShowActions,
169
+ label: t.alwaysShowRowActions
170
+ })]
171
+ }),
172
+ toggleable.length > 0 && /* @__PURE__ */ jsxs("div", {
173
+ className: "mt-3 border-t border-(--theme-border) pt-3",
174
+ children: [/* @__PURE__ */ jsx("div", {
175
+ className: SECTION_LABEL,
176
+ children: t.displayProperties
177
+ }), /* @__PURE__ */ jsx("div", {
178
+ className: "flex flex-wrap gap-1.5",
179
+ children: toggleable.map((c) => /* @__PURE__ */ jsx("button", {
180
+ type: "button",
181
+ onClick: () => view.toggleColumn(c.key),
182
+ className: pillClass(view.isVisible(c.key)),
183
+ children: c.label
184
+ }, c.key))
185
+ })]
186
+ }),
187
+ view.showActions && view.actions.length > 0 && /* @__PURE__ */ jsxs("div", {
188
+ className: "mt-3 border-t border-(--theme-border) pt-3",
189
+ children: [/* @__PURE__ */ jsxs("div", {
190
+ className: cx(SECTION_LABEL, "flex items-center gap-1"),
191
+ children: [t.pinnedActions, /* @__PURE__ */ jsx(TooltipInfo, {
192
+ className: "inline-flex",
193
+ text: t.pinnedActionsHelp
194
+ })]
195
+ }), /* @__PURE__ */ jsx("div", {
196
+ className: "flex flex-wrap gap-1.5",
197
+ children: view.actions.map((a) => /* @__PURE__ */ jsx("button", {
198
+ type: "button",
199
+ onClick: () => view.togglePinned(a.key),
200
+ className: pillClass(view.isPinned(a.key)),
201
+ children: a.label
202
+ }, a.key))
203
+ })]
204
+ }),
205
+ !view.isDisplayDefault && /* @__PURE__ */ jsx("div", {
206
+ className: "mt-3 border-t border-(--theme-border) pt-2",
207
+ children: /* @__PURE__ */ jsx("button", {
208
+ type: "button",
209
+ onClick: view.resetDisplay,
210
+ className: "link text-[12px]",
211
+ children: t.reset
212
+ })
213
+ })
214
+ ]
215
+ });
216
+ }
217
+ /** Capture phase: the popover panel stops mousedown propagation, so a
218
+ * bubble-phase listener never sees clicks inside it. */
219
+ function useCloseOnOutsideClick(open, close) {
220
+ const ref = useRef(null);
221
+ useEffect(() => {
222
+ if (!open) return;
223
+ const onDown = (e) => {
224
+ if (e.target instanceof Node && !ref.current?.contains(e.target)) close();
225
+ };
226
+ document.addEventListener("mousedown", onDown, true);
227
+ return () => document.removeEventListener("mousedown", onDown, true);
228
+ }, [open, close]);
229
+ return ref;
230
+ }
231
+ function GroupingDropdown({ view }) {
232
+ const t = useStrings().list;
233
+ const [open, setOpen] = useState(false);
234
+ const ref = useCloseOnOutsideClick(open, useCallback(() => setOpen(false), []));
235
+ const current = view.groupBys.find((g) => g.value === view.groupBy);
236
+ return /* @__PURE__ */ jsxs("div", {
237
+ ref,
238
+ className: "relative",
239
+ children: [/* @__PURE__ */ jsxs("button", {
240
+ type: "button",
241
+ onClick: () => setOpen((o) => !o),
242
+ className: "flex items-center gap-1.5 rounded-md border border-(--theme-border) px-2 py-1 text-[12px] text-(--theme-app) hover:bg-(--theme-muted-panel-bg)",
243
+ children: [current?.label ?? t.none, /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-2.5 w-2.5 opacity-60" })]
244
+ }), open && /* @__PURE__ */ jsx("div", {
245
+ className: cx("absolute right-0 top-full z-20 mt-1", FLYOUT),
246
+ children: view.groupBys.map((g) => /* @__PURE__ */ jsxs("button", {
247
+ type: "button",
248
+ onClick: () => {
249
+ view.setGroupBy(g.value);
250
+ setOpen(false);
251
+ },
252
+ className: cx("flex w-full items-center justify-between gap-3 px-3 py-1.5 text-left text-[13px] hover:bg-(--theme-muted-panel-bg)", view.groupBy === g.value ? "text-(--theme-app)" : "text-(--theme-muted-text-color)"),
253
+ children: [g.label, view.groupBy === g.value && /* @__PURE__ */ jsx(CheckIcon, { className: "h-3 w-3" })]
254
+ }, g.value))
255
+ })]
256
+ });
257
+ }
258
+ function OrderingDropdown({ view }) {
259
+ const t = useStrings().list;
260
+ const [open, setOpen] = useState(false);
261
+ const ref = useCloseOnOutsideClick(open, useCallback(() => setOpen(false), []));
262
+ const current = view.orderBys.find((o) => o.value === view.orderBy);
263
+ return /* @__PURE__ */ jsxs("div", {
264
+ ref,
265
+ className: "relative",
266
+ children: [/* @__PURE__ */ jsxs("button", {
267
+ type: "button",
268
+ onClick: () => setOpen((o) => !o),
269
+ className: "flex items-center gap-1.5 rounded-md border border-(--theme-border) px-2 py-1 text-[12px] text-(--theme-app) hover:bg-(--theme-muted-panel-bg)",
270
+ children: [current?.label ?? t.none, /* @__PURE__ */ jsx(ChevronDownIcon, { className: "h-2.5 w-2.5 opacity-60" })]
271
+ }), open && /* @__PURE__ */ jsx("div", {
272
+ className: cx("absolute right-0 top-full z-20 mt-1", FLYOUT),
273
+ children: view.orderBys.map((o) => /* @__PURE__ */ jsxs("button", {
274
+ type: "button",
275
+ onClick: () => {
276
+ view.setOrderBy(o.value);
277
+ setOpen(false);
278
+ },
279
+ className: cx("flex w-full items-center justify-between gap-3 px-3 py-1.5 text-left text-[13px] hover:bg-(--theme-muted-panel-bg)", view.orderBy === o.value ? "text-(--theme-app)" : "text-(--theme-muted-text-color)"),
280
+ children: [o.label, view.orderBy === o.value && /* @__PURE__ */ jsx(CheckIcon, { className: "h-3 w-3" })]
281
+ }, o.value))
282
+ })]
283
+ });
284
+ }
285
+ function ListFilterMenu({ view, label }) {
286
+ const t = useStrings().list;
287
+ if (view.facets.length === 0) return null;
288
+ return /* @__PURE__ */ jsx(AnchoredPopover, {
289
+ icon: /* @__PURE__ */ jsx(FilterIcon, { className: "h-3.5 w-3.5" }),
290
+ label: label ?? t.filter,
291
+ active: view.activeFilterCount > 0,
292
+ shortcut: "f",
293
+ panelClassName: "w-56 py-1",
294
+ children: /* @__PURE__ */ jsx(FilterMenuBody, { view })
295
+ });
296
+ }
297
+ /** Single-open submenu prevents overlapping; resets on panel remount so Filter opens clean. */
298
+ function FilterMenuBody({ view }) {
299
+ const t = useStrings().list;
300
+ const [openKey, setOpenKey] = useState(null);
301
+ const closeTimer = useRef(void 0);
302
+ const openFacet = (key) => {
303
+ clearTimeout(closeTimer.current);
304
+ setOpenKey(key);
305
+ };
306
+ const scheduleClose = () => {
307
+ closeTimer.current = setTimeout(() => setOpenKey(null), 160);
308
+ };
309
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
310
+ className: "flex items-center justify-between px-3 py-1",
311
+ children: [/* @__PURE__ */ jsx("span", {
312
+ className: "text-[11px] font-medium uppercase tracking-wide text-(--theme-muted-text-color)",
313
+ children: t.filter
314
+ }), view.activeFilterCount > 0 && /* @__PURE__ */ jsx("button", {
315
+ type: "button",
316
+ onClick: view.clearFilters,
317
+ className: "text-[12px] text-(--theme-muted-text-color) hover:text-(--theme-app)",
318
+ children: t.clear
319
+ })]
320
+ }), view.facets.map((facet) => /* @__PURE__ */ jsx(FilterFacetRow, {
321
+ view,
322
+ facet,
323
+ open: openKey === facet.key,
324
+ onEnter: () => openFacet(facet.key),
325
+ onLeave: scheduleClose
326
+ }, facet.key))] });
327
+ }
328
+ function FilterFacetRow({ view, facet, open, onEnter, onLeave }) {
329
+ const selected = view.filters[facet.key] ?? [];
330
+ return /* @__PURE__ */ jsxs("div", {
331
+ className: "relative",
332
+ role: "none",
333
+ onMouseEnter: onEnter,
334
+ onMouseLeave: onLeave,
335
+ onFocus: onEnter,
336
+ onBlur: onLeave,
337
+ children: [/* @__PURE__ */ jsxs("button", {
338
+ type: "button",
339
+ "aria-expanded": open,
340
+ "aria-haspopup": "menu",
341
+ onClick: onEnter,
342
+ className: "flex w-full cursor-default items-center justify-between gap-3 px-3 py-1.5 text-[13px] text-(--theme-app) hover:bg-(--theme-muted-panel-bg)",
343
+ children: [/* @__PURE__ */ jsx("span", { children: facet.label }), /* @__PURE__ */ jsxs("span", {
344
+ className: "flex items-center gap-1.5",
345
+ children: [selected.length > 0 && /* @__PURE__ */ jsx("span", {
346
+ className: "text-[11px] text-(--theme-muted-text-color)",
347
+ children: selected.length
348
+ }), /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 opacity-60" })]
349
+ })]
350
+ }), open && /* @__PURE__ */ jsx("div", {
351
+ className: cx("absolute right-full top-0 z-10 max-h-[70vh] overflow-y-auto", FLYOUT),
352
+ children: facet.options.map((option) => {
353
+ const checked = selected.includes(option.value);
354
+ return /* @__PURE__ */ jsxs("button", {
355
+ type: "button",
356
+ onClick: () => view.setFacetValues(facet.key, checked ? selected.filter((v) => v !== option.value) : [...selected, option.value]),
357
+ className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-[13px] text-(--theme-app) hover:bg-(--theme-muted-panel-bg)",
358
+ children: [
359
+ /* @__PURE__ */ jsx("span", {
360
+ className: "flex h-3.5 w-3.5 shrink-0 items-center justify-center text-(--theme-link)",
361
+ children: checked && /* @__PURE__ */ jsx(CheckIcon, { className: "h-3 w-3" })
362
+ }),
363
+ option.icon,
364
+ option.label
365
+ ]
366
+ }, option.value);
367
+ })
368
+ })]
369
+ });
370
+ }
371
+ //#endregion
372
+ export { ListDisplayMenu, ListFilterMenu, listControlButtonClasses };