@parallelworks/ui 0.76.0 → 0.78.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 (270) hide show
  1. package/README.md +30 -5
  2. package/dist/access/AccessDrawer.d.ts +28 -7
  3. package/dist/access/AccessDrawer.js +216 -35
  4. package/dist/access/AccessList.d.ts +19 -1
  5. package/dist/access/AccessList.js +220 -9
  6. package/dist/access/GrantView.d.ts +3 -1
  7. package/dist/access/GrantView.js +17 -4
  8. package/dist/access/PrincipalPicker.js +5 -5
  9. package/dist/access/focus.js +1 -1
  10. package/dist/access/index.d.ts +2 -2
  11. package/dist/access/index.js +2 -2
  12. package/dist/access/strings.d.ts +18 -0
  13. package/dist/access/strings.js +20 -2
  14. package/dist/access/types.d.ts +26 -0
  15. package/dist/ai/adapter/types.d.ts +1 -0
  16. package/dist/ai/components/AllocationSelector.js +1 -1
  17. package/dist/ai/components/AttachmentManager.js +5 -5
  18. package/dist/ai/components/AttachmentUpload.js +2 -2
  19. package/dist/ai/components/BranchNavigator.js +1 -1
  20. package/dist/ai/components/ChatActivity.d.ts +2 -0
  21. package/dist/ai/components/ChatActivity.js +31 -0
  22. package/dist/ai/components/ChatEmptyState.js +3 -3
  23. package/dist/ai/components/ChatInput.js +3 -5
  24. package/dist/ai/components/ChatLayout.js +1 -1
  25. package/dist/ai/components/ChatMessage.js +1 -1
  26. package/dist/ai/components/ChatMessageList.js +2 -2
  27. package/dist/ai/components/ChatSidebar.js +3 -3
  28. package/dist/ai/components/ChatThread.js +4 -4
  29. package/dist/ai/components/ComposerAddMenu.js +9 -20
  30. package/dist/ai/components/ModelSelector.js +3 -3
  31. package/dist/ai/components/PastedText.js +5 -5
  32. package/dist/ai/components/SessionView.js +5 -2
  33. package/dist/ai/components/ShareDialog.js +3 -3
  34. package/dist/ai/components/SlashMenu.d.ts +31 -4
  35. package/dist/ai/components/SlashMenu.js +36 -63
  36. package/dist/ai/components/agent/ActivityLine.js +1 -1
  37. package/dist/ai/components/agent/AgentMessageParts.d.ts +1 -1
  38. package/dist/ai/components/agent/AgentMessageParts.js +44 -18
  39. package/dist/ai/components/conversationActions.js +3 -3
  40. package/dist/ai/core/ChatProvider.js +11 -2
  41. package/dist/ai/core/config.d.ts +10 -1
  42. package/dist/ai/core/config.js +1 -1
  43. package/dist/ai/index.d.ts +1 -1
  44. package/dist/ai/strings.d.ts +2 -0
  45. package/dist/ai/strings.js +2 -1
  46. package/dist/ai/types.d.ts +3 -0
  47. package/dist/ai/ui/ConversationSidebar.js +3 -3
  48. package/dist/ai/ui/sidebar.js +3 -3
  49. package/dist/assets/yaml.worker-DOBV2lND.js +884 -0
  50. package/dist/components/ActionMenu.d.ts +38 -9
  51. package/dist/components/ActionMenu.js +48 -22
  52. package/dist/components/Avatar.d.ts +66 -6
  53. package/dist/components/Avatar.js +130 -18
  54. package/dist/components/Breadcrumbs.d.ts +4 -0
  55. package/dist/components/Breadcrumbs.js +26 -10
  56. package/dist/components/Button.d.ts +3 -2
  57. package/dist/components/Button.js +11 -1
  58. package/dist/components/Callout.d.ts +3 -2
  59. package/dist/components/Callout.js +3 -2
  60. package/dist/components/Card.d.ts +33 -9
  61. package/dist/components/Card.js +24 -8
  62. package/dist/components/Checkbox.d.ts +3 -1
  63. package/dist/components/Checkbox.js +4 -2
  64. package/dist/components/ColorInput.js +1 -1
  65. package/dist/components/Combobox.d.ts +23 -0
  66. package/dist/components/Combobox.js +252 -86
  67. package/dist/components/ConfirmModal.d.ts +26 -2
  68. package/dist/components/ConfirmModal.js +81 -15
  69. package/dist/components/ContextMenu.d.ts +29 -2
  70. package/dist/components/ContextMenu.js +60 -8
  71. package/dist/components/CopyButton.d.ts +21 -8
  72. package/dist/components/CopyButton.js +29 -9
  73. package/dist/components/CreateModal.d.ts +16 -4
  74. package/dist/components/CreateModal.js +27 -16
  75. package/dist/components/DatePicker.d.ts +31 -1
  76. package/dist/components/DatePicker.js +178 -47
  77. package/dist/components/DescriptionList.d.ts +13 -3
  78. package/dist/components/DescriptionList.js +43 -11
  79. package/dist/components/Disclosure.d.ts +10 -2
  80. package/dist/components/Disclosure.js +18 -7
  81. package/dist/components/Drawer.js +5 -5
  82. package/dist/components/EmptyState.d.ts +12 -4
  83. package/dist/components/EmptyState.js +18 -10
  84. package/dist/components/ErrorPage.d.ts +40 -0
  85. package/dist/components/ErrorPage.js +101 -0
  86. package/dist/components/ExternalLink.d.ts +4 -1
  87. package/dist/components/ExternalLink.js +4 -5
  88. package/dist/components/Field.d.ts +21 -6
  89. package/dist/components/Field.js +32 -16
  90. package/dist/components/FileButton.d.ts +19 -0
  91. package/dist/components/FileButton.js +32 -0
  92. package/dist/components/HoverCard.d.ts +26 -6
  93. package/dist/components/HoverCard.js +11 -5
  94. package/dist/components/IconButton.js +4 -2
  95. package/dist/components/InfoTip.js +3 -3
  96. package/dist/components/Input.d.ts +33 -3
  97. package/dist/components/Input.js +149 -14
  98. package/dist/components/Kbd.d.ts +40 -0
  99. package/dist/components/Kbd.js +168 -0
  100. package/dist/components/Listbox.d.ts +103 -0
  101. package/dist/components/Listbox.js +190 -0
  102. package/dist/components/Loader.d.ts +8 -2
  103. package/dist/components/Loader.js +16 -1
  104. package/dist/components/Markdown.js +1 -1
  105. package/dist/components/MarkdownImpl.js +1 -1
  106. package/dist/components/Menu.d.ts +20 -2
  107. package/dist/components/Menu.js +48 -19
  108. package/dist/components/MenuEntries.d.ts +38 -2
  109. package/dist/components/MenuEntries.js +266 -39
  110. package/dist/components/Meter.d.ts +50 -11
  111. package/dist/components/Meter.js +71 -21
  112. package/dist/components/Modal.d.ts +9 -3
  113. package/dist/components/Modal.js +68 -29
  114. package/dist/components/OneTimeCodeInput.js +1 -1
  115. package/dist/components/PageHeader.js +111 -7
  116. package/dist/components/PageHeaderAction.d.ts +8 -3
  117. package/dist/components/PageHeaderAction.js +122 -34
  118. package/dist/components/Pagination.d.ts +13 -1
  119. package/dist/components/Pagination.js +90 -19
  120. package/dist/components/Popover.d.ts +13 -2
  121. package/dist/components/Popover.js +20 -21
  122. package/dist/components/Provider.d.ts +140 -3
  123. package/dist/components/Provider.js +142 -12
  124. package/dist/components/RefreshButton.d.ts +13 -6
  125. package/dist/components/RefreshButton.js +17 -9
  126. package/dist/components/RunStatusIcon.d.ts +16 -7
  127. package/dist/components/RunStatusIcon.js +21 -8
  128. package/dist/components/Section.d.ts +11 -4
  129. package/dist/components/Section.js +33 -22
  130. package/dist/components/SegmentedControl.d.ts +16 -3
  131. package/dist/components/SegmentedControl.js +7 -3
  132. package/dist/components/Select.d.ts +19 -3
  133. package/dist/components/Select.js +114 -68
  134. package/dist/components/SelectionCopy.d.ts +10 -0
  135. package/dist/components/SelectionCopy.js +105 -0
  136. package/dist/components/SettingModeOption.js +1 -1
  137. package/dist/components/SettingsCard.js +1 -1
  138. package/dist/components/Skeleton.js +1 -1
  139. package/dist/components/StatusBadge.d.ts +55 -10
  140. package/dist/components/StatusBadge.js +91 -15
  141. package/dist/components/StickyBar.js +1 -1
  142. package/dist/components/Table.d.ts +22 -4
  143. package/dist/components/Table.js +46 -24
  144. package/dist/components/Tabs.d.ts +9 -4
  145. package/dist/components/Tabs.js +9 -4
  146. package/dist/components/Tag.d.ts +49 -0
  147. package/dist/components/Tag.js +199 -0
  148. package/dist/components/ThemeEditor.js +1 -1
  149. package/dist/components/Toast.js +1 -1
  150. package/dist/components/ToggleGroup.d.ts +4 -1
  151. package/dist/components/ToggleGroup.js +30 -13
  152. package/dist/components/Tooltip.d.ts +9 -3
  153. package/dist/components/Tooltip.js +55 -39
  154. package/dist/components/buttonClasses.d.ts +5 -2
  155. package/dist/components/buttonClasses.js +11 -10
  156. package/dist/components/chart.d.ts +69 -0
  157. package/dist/components/chart.js +145 -0
  158. package/dist/components/comboboxItems.d.ts +7 -1
  159. package/dist/components/comboboxItems.js +6 -2
  160. package/dist/components/dismiss.d.ts +5 -1
  161. package/dist/components/dismiss.js +6 -2
  162. package/dist/components/floating.d.ts +4 -4
  163. package/dist/components/floating.js +5 -5
  164. package/dist/components/headerActionsFit.d.ts +37 -0
  165. package/dist/components/headerActionsFit.js +81 -0
  166. package/dist/components/pageHeaderStore.d.ts +3 -0
  167. package/dist/components/pageHeaderStore.js +3 -0
  168. package/dist/components/pathBreaks.js +2 -2
  169. package/dist/components/popupContainer.d.ts +17 -0
  170. package/dist/components/popupContainer.js +69 -0
  171. package/dist/components/relativeTime.d.ts +21 -10
  172. package/dist/components/relativeTime.js +50 -22
  173. package/dist/components/segmented.d.ts +18 -4
  174. package/dist/components/segmented.js +48 -6
  175. package/dist/components/typedDate.d.ts +5 -0
  176. package/dist/components/typedDate.js +50 -0
  177. package/dist/components/useClosingValue.d.ts +4 -0
  178. package/dist/components/useClosingValue.js +12 -0
  179. package/dist/components/useCopy.d.ts +6 -0
  180. package/dist/components/useCopy.js +3 -3
  181. package/dist/components/useNarrow.d.ts +2 -0
  182. package/dist/components/useNarrow.js +16 -0
  183. package/dist/editor/Editor.js +1 -1
  184. package/dist/editor/FormCodePanel.js +1 -1
  185. package/dist/editor/Monaco.js +1 -1
  186. package/dist/editor/workers.js +1 -1
  187. package/dist/file-explorer/FileExplorer.js +16 -15
  188. package/dist/file-explorer/FileExplorerContext.js +2 -2
  189. package/dist/file-explorer/FilePreview/Viewer.js +3 -3
  190. package/dist/file-explorer/FilePreview/index.js +2 -2
  191. package/dist/file-explorer/FileRowsWindow.js +3 -3
  192. package/dist/file-explorer/FileTable.js +1 -1
  193. package/dist/file-explorer/LoadMoreRow.js +1 -1
  194. package/dist/file-explorer/TreeView.js +5 -5
  195. package/dist/file-explorer/helpers.js +2 -2
  196. package/dist/file-explorer/toasts.js +2 -2
  197. package/dist/form/Fields/CheckboxGroupField.js +1 -1
  198. package/dist/form/Fields/DropdownField.js +1 -1
  199. package/dist/form/Fields/DurationField.js +2 -2
  200. package/dist/form/Fields/MultiDropdownField.js +1 -1
  201. package/dist/form/Fields/NumberField.js +1 -1
  202. package/dist/form/Fields/ObjectField.js +1 -1
  203. package/dist/form/Fields/RangeField.js +1 -1
  204. package/dist/form/Fields/StringField.js +1 -1
  205. package/dist/form/Form.js +3 -3
  206. package/dist/form/FormLayout.js +1 -1
  207. package/dist/form/Wizard/WizardContainer.js +1 -1
  208. package/dist/form/Wizard/WizardNavigation.js +1 -1
  209. package/dist/form/Wizard/WizardStepContent.js +1 -1
  210. package/dist/form/fieldRegistry.js +1 -1
  211. package/dist/form/formEditing.js +1 -1
  212. package/dist/format.d.ts +17 -7
  213. package/dist/format.js +39 -16
  214. package/dist/graph/AnnotationBanner.js +2 -2
  215. package/dist/graph/Connectors.js +5 -5
  216. package/dist/graph/DependencyGraph.js +10 -9
  217. package/dist/graph/GraphEditor.js +4 -4
  218. package/dist/graph/GraphEditorDialogs.js +13 -12
  219. package/dist/graph/GraphNode.js +1 -1
  220. package/dist/graph/InputDialog.js +5 -5
  221. package/dist/graph/InputsEditor.js +7 -7
  222. package/dist/graph/MatrixGroup.js +2 -2
  223. package/dist/graph/ProblemsButton.js +3 -3
  224. package/dist/graph/Reveal.js +1 -1
  225. package/dist/graph/RunWarningsList.js +1 -1
  226. package/dist/graph/ShortcutsButton.js +25 -8
  227. package/dist/graph/StepSummaries.js +1 -1
  228. package/dist/graph/TreeView.js +2 -2
  229. package/dist/graph/WorkflowSettingsDialog.js +3 -3
  230. package/dist/graph/editorFields.js +3 -3
  231. package/dist/graph/editorPrimitives.js +1 -1
  232. package/dist/graph/editorRows.js +5 -5
  233. package/dist/graph/fieldProblems.js +2 -2
  234. package/dist/graph/inputRefs.js +7 -6
  235. package/dist/graph/stepWith.js +2 -2
  236. package/dist/index.d.ts +30 -21
  237. package/dist/index.js +20 -12
  238. package/dist/list/ActionToolbar.d.ts +4 -0
  239. package/dist/list/ActionToolbar.js +35 -12
  240. package/dist/list/ListFilterBar.d.ts +42 -0
  241. package/dist/list/ListFilterBar.js +789 -0
  242. package/dist/list/ListPage.d.ts +42 -4
  243. package/dist/list/ListPage.js +56 -22
  244. package/dist/list/ListTable.d.ts +27 -3
  245. package/dist/list/ListTable.js +48 -23
  246. package/dist/list/ListToolbar.d.ts +31 -0
  247. package/dist/list/ListToolbar.js +43 -0
  248. package/dist/list/ListViewControls.d.ts +8 -4
  249. package/dist/list/ListViewControls.js +22 -14
  250. package/dist/list/UserHoverCard.d.ts +8 -2
  251. package/dist/list/UserHoverCard.js +26 -13
  252. package/dist/list/filterModel.d.ts +122 -0
  253. package/dist/list/filterModel.js +308 -0
  254. package/dist/list/index.d.ts +6 -2
  255. package/dist/list/index.js +6 -2
  256. package/dist/list/listSearch.d.ts +1 -1
  257. package/dist/list/listSearch.js +8 -4
  258. package/dist/list/listView.d.ts +24 -2
  259. package/dist/list/listView.js +47 -45
  260. package/dist/list/rowMenu.d.ts +10 -5
  261. package/dist/list/rowMenu.js +17 -7
  262. package/dist/list/useListFilters.d.ts +68 -0
  263. package/dist/list/useListFilters.js +252 -0
  264. package/dist/logviewer/LogViewer.js +4 -4
  265. package/dist/styles/theme.css +94 -0
  266. package/dist/styles.css +1 -1
  267. package/package.json +11 -11
  268. package/dist/assets/yaml.worker-k9AdOqzf.js +0 -1441
  269. package/dist/components/fullscreen.d.ts +0 -4
  270. package/dist/components/fullscreen.js +0 -18
@@ -1,7 +1,11 @@
1
1
  import { cx } from "../cx.js";
2
- import { useFullscreenContainer } from "./fullscreen.js";
2
+ import { CloseIcon } from "../icons.js";
3
+ import { usePopupContainer } from "./popupContainer.js";
4
+ import { useStrings } from "./Provider.js";
5
+ import { IconButton } from "./IconButton.js";
3
6
  import { closeHandler } from "./dismiss.js";
4
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import { useRef } from "react";
8
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
5
9
  import { AlertDialog } from "@base-ui/react/alert-dialog";
6
10
  import { Dialog } from "@base-ui/react/dialog";
7
11
  //#region src/components/Modal.tsx
@@ -17,43 +21,78 @@ var sizeClasses = {
17
21
  lg: "w-[560px]",
18
22
  xl: "w-[672px]"
19
23
  };
24
+ var popupMotion = "transition-[transform,opacity] duration-150 ease-out data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:scale-95 data-ending-style:opacity-0 motion-reduce:data-starting-style:scale-100 motion-reduce:data-ending-style:scale-100";
25
+ var backdropMotion = "transition-opacity duration-150 ease-out data-starting-style:opacity-0 data-ending-style:opacity-0";
26
+ var CONTROLS = "input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]):not([data-modal-close]), a[href], [tabindex]:not([tabindex=\"-1\"]):not([data-modal-close])";
27
+ /** The first control in a panel other than its close button, or the panel itself. */
28
+ function firstControlIn(panel) {
29
+ return panel?.querySelector(CONTROLS) ?? panel ?? true;
30
+ }
20
31
  /** A modal dialog: focus stays inside, the page behind is inert and doesn't scroll,
21
32
  * and focus returns to where it was on close. Give it a `title`, a `description`
22
33
  * and a `footer` for the standard layout, as a Drawer has, or lay out the whole
23
34
  * panel with the children. */
24
- function Modal({ open, onClose, title, description, footer, size, alert = false, dismissible = true, align = "top", panel = true, backdropClassName = "bg-black/40", className, children, ...popupProps }) {
25
- const fullscreen = useFullscreenContainer();
35
+ function Modal({ open, onClose, title, description, footer, size, alert = false, dismissible = true, align = "top", panel = true, backdropClassName = "bg-black/40", closeButton = false, onSubmit, className, children, initialFocus, ...popupProps }) {
36
+ const portal = usePopupContainer();
37
+ const { common } = useStrings();
38
+ const panelElement = useRef(null);
26
39
  const onOpenChange = closeHandler(dismissible, onClose);
27
- const header = title !== void 0 || description !== void 0;
40
+ const titled = title !== void 0 || description !== void 0;
41
+ const header = titled || closeButton;
28
42
  const body = children !== void 0 && children !== null && children !== false;
29
- const laidOut = header || footer !== void 0;
43
+ const laidOut = header || footer !== void 0 || onSubmit !== void 0;
44
+ const sections = /* @__PURE__ */ jsxs(Fragment$1, { children: [
45
+ header && /* @__PURE__ */ jsxs("div", {
46
+ className: cx("flex shrink-0 items-start gap-3 px-4 pt-4", !body && "pb-4"),
47
+ children: [titled && /* @__PURE__ */ jsxs("div", {
48
+ className: "min-w-0 flex-1",
49
+ children: [title !== void 0 && /* @__PURE__ */ jsx(ModalTitle, {
50
+ className: "m-0 text-lg font-semibold wrap-break-word",
51
+ children: title
52
+ }), description !== void 0 && /* @__PURE__ */ jsx(ModalDescription, {
53
+ className: "m-0 mt-1.5 text-sm text-(--theme-muted-text-color)",
54
+ children: description
55
+ })]
56
+ }), closeButton && /* @__PURE__ */ jsx(Dialog.Close, {
57
+ "data-modal-close": "",
58
+ render: /* @__PURE__ */ jsx(IconButton, {
59
+ icon: /* @__PURE__ */ jsx(CloseIcon, {}),
60
+ label: common.close,
61
+ className: "-me-1.5 ms-auto mt-0"
62
+ })
63
+ })]
64
+ }),
65
+ body && /* @__PURE__ */ jsx("div", {
66
+ className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-4",
67
+ children
68
+ }),
69
+ footer !== void 0 && /* @__PURE__ */ jsx("div", {
70
+ className: "flex shrink-0 items-center justify-end gap-2 border-t border-(--theme-border) px-4 py-3",
71
+ children: footer
72
+ })
73
+ ] });
30
74
  const content = /* @__PURE__ */ jsxs(Dialog.Portal, {
31
- container: fullscreen,
32
- children: [/* @__PURE__ */ jsx(Dialog.Backdrop, { className: cx("fixed inset-0 z-(--layer-modal)", backdropClassName) }), /* @__PURE__ */ jsx(Dialog.Viewport, {
75
+ ...portal,
76
+ children: [/* @__PURE__ */ jsx(Dialog.Backdrop, { className: cx("fixed inset-0 z-(--layer-modal)", backdropMotion, backdropClassName) }), /* @__PURE__ */ jsx(Dialog.Viewport, {
33
77
  className: cx("fixed inset-0 z-(--layer-modal) flex justify-center px-4 pt-20 pb-8", align === "center" ? "items-center" : "items-start sm:pt-[max(14vh,5rem)]"),
34
78
  children: /* @__PURE__ */ jsx(Dialog.Popup, {
35
79
  ...popupProps,
36
- className: cx(panel && "rounded-xl border border-(--theme-border) bg-(--theme-app-bg) text-(--theme-app) shadow-2xl", size && [sizeClasses[size], "max-w-full"], laidOut && "flex max-h-full flex-col", "outline-none", className),
37
- children: laidOut ? /* @__PURE__ */ jsxs(Fragment, { children: [
38
- header && /* @__PURE__ */ jsxs("div", {
39
- className: cx("shrink-0 px-4 pt-4", !body && "pb-4"),
40
- children: [title !== void 0 && /* @__PURE__ */ jsx(ModalTitle, {
41
- className: "m-0 text-lg font-semibold",
42
- children: title
43
- }), description !== void 0 && /* @__PURE__ */ jsx(ModalDescription, {
44
- className: "m-0 mt-1.5 text-sm text-(--theme-muted-text-color)",
45
- children: description
46
- })]
47
- }),
48
- body && /* @__PURE__ */ jsx("div", {
49
- className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-4",
50
- children
51
- }),
52
- footer !== void 0 && /* @__PURE__ */ jsx("div", {
53
- className: "flex shrink-0 items-center justify-end gap-2 border-t border-(--theme-border) px-4 py-3",
54
- children: footer
55
- })
56
- ] }) : children
80
+ ref: (element) => {
81
+ panelElement.current = element;
82
+ const forward = popupProps.ref;
83
+ if (typeof forward === "function") forward(element);
84
+ else if (forward) forward.current = element;
85
+ },
86
+ initialFocus: initialFocus ?? (closeButton ? () => firstControlIn(panelElement.current) : void 0),
87
+ className: cx(panel && "rounded-xl border border-(--theme-border) bg-(--theme-app-bg) text-(--theme-app) shadow-2xl", size && [sizeClasses[size], "max-w-full"], laidOut && "flex max-h-full flex-col", "outline-none", popupMotion, className),
88
+ children: !laidOut ? children : onSubmit ? /* @__PURE__ */ jsx("form", {
89
+ className: "flex min-h-0 flex-1 flex-col",
90
+ onSubmit: (event) => {
91
+ event.preventDefault();
92
+ onSubmit(event);
93
+ },
94
+ children: sections
95
+ }) : sections
57
96
  })
58
97
  })]
59
98
  });
@@ -1,8 +1,8 @@
1
1
  import { cx } from "../cx.js";
2
2
  import { useStrings } from "./Provider.js";
3
3
  import { fieldBox } from "./fieldBox.js";
4
- import { jsx, jsxs } from "react/jsx-runtime";
5
4
  import { useId } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
6
  import { OTPField } from "@base-ui/react/otp-field";
7
7
  //#region src/components/OneTimeCodeInput.tsx
8
8
  /**
@@ -1,9 +1,13 @@
1
1
  import { cx } from "../cx.js";
2
- import { useSlots } from "./Provider.js";
2
+ import { buttonClasses } from "./buttonClasses.js";
3
+ import { MoreIcon } from "../icons.js";
4
+ import { useSlots, useStrings } from "./Provider.js";
5
+ import { ActionMenu } from "./ActionMenu.js";
3
6
  import { Breadcrumbs } from "./Breadcrumbs.js";
7
+ import { HeaderActionsFit, HeaderActionsFitContext, overflowingActions } from "./headerActionsFit.js";
4
8
  import { PageHeaderStore } from "./pageHeaderStore.js";
5
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
9
  import { createContext, use, useCallback, useLayoutEffect, useState, useSyncExternalStore } from "react";
10
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
11
  import { createPortal } from "react-dom";
8
12
  //#region src/components/PageHeader.tsx
9
13
  var StoreContext = createContext(null);
@@ -76,9 +80,12 @@ function DeclaredHeader({ store, breadcrumbs, titleActions, actions, toolbar, hi
76
80
  });
77
81
  useLayoutEffect(() => () => store.delete(order), [store, order]);
78
82
  if (!nodes || !client) return null;
79
- return /* @__PURE__ */ jsxs(Fragment, { children: [
83
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
80
84
  fills.titleActions && createPortal(titleActions, nodes.titleActions),
81
- fills.actions && createPortal(actions, nodes.actions),
85
+ fills.actions && createPortal(/* @__PURE__ */ jsx(HeaderActionsFitContext, {
86
+ value: store.actionsFit,
87
+ children: actions
88
+ }), nodes.actions),
82
89
  fills.toolbar && createPortal(toolbar, nodes.toolbar)
83
90
  ] });
84
91
  }
@@ -101,6 +108,7 @@ function PageHeaderBar({ compact = false, persistent = false, className }) {
101
108
  titleActions: header.titleActions.length > 0 && /* @__PURE__ */ jsx(Mounts, { nodes: header.titleActions }),
102
109
  actions: header.actions.length > 0 && /* @__PURE__ */ jsx(Mounts, { nodes: header.actions }),
103
110
  toolbar: header.toolbar.length > 0 && /* @__PURE__ */ jsx(Mounts, { nodes: header.toolbar }),
111
+ fit: store.actionsFit,
104
112
  compact,
105
113
  className
106
114
  });
@@ -129,14 +137,25 @@ function Mount({ node }) {
129
137
  className: "contents"
130
138
  });
131
139
  }
132
- function HeaderLayout({ breadcrumbs, titleActions, actions, toolbar, compact = false, className }) {
140
+ function HeaderLayout({ breadcrumbs, titleActions, actions, toolbar, fit: sharedFit, compact = false, className }) {
133
141
  const { breadcrumbPin, navToggle } = useSlots();
142
+ const { list: t } = useStrings();
143
+ const [ownFit] = useState(() => new HeaderActionsFit());
144
+ const fit = sharedFit ?? ownFit;
145
+ const [row, setRow] = useState(null);
146
+ const [lead, setLead] = useState(null);
147
+ const [end, setEnd] = useState(null);
148
+ useActionsFit(fit, row, lead, end);
149
+ useSyncExternalStore(fit.subscribe, fit.getVersion, fit.getVersion);
150
+ const moved = fit.menu();
134
151
  const hasTrail = breadcrumbs.length > 0;
135
152
  return /* @__PURE__ */ jsxs("div", {
136
153
  className: cx("@container w-full shrink-0 bg-(--theme-app-bg)", className),
137
154
  children: [/* @__PURE__ */ jsxs("div", {
155
+ ref: setRow,
138
156
  className: cx("flex items-center justify-between gap-4 border-b border-(--theme-border) px-4", compact ? "h-8" : "h-12"),
139
157
  children: [/* @__PURE__ */ jsxs("div", {
158
+ ref: setLead,
140
159
  className: "flex min-w-0 flex-1 items-center gap-2",
141
160
  children: [
142
161
  navToggle?.(),
@@ -150,9 +169,22 @@ function HeaderLayout({ breadcrumbs, titleActions, actions, toolbar, compact = f
150
169
  }),
151
170
  hasTrail && breadcrumbPin?.({ crumbs: breadcrumbs })
152
171
  ]
153
- }), present(actions) && /* @__PURE__ */ jsx("div", {
172
+ }), present(actions) && /* @__PURE__ */ jsxs("div", {
173
+ ref: setEnd,
154
174
  className: "flex shrink-0 items-center gap-1",
155
- children: actions
175
+ children: [/* @__PURE__ */ jsx(HeaderActionsFitContext, {
176
+ value: fit,
177
+ children: actions
178
+ }), moved.length > 0 && /* @__PURE__ */ jsx(ActionMenu, {
179
+ items: moved,
180
+ label: t.moreActions,
181
+ triggerClassName: buttonClasses({
182
+ variant: "ghost",
183
+ size: "xs",
184
+ iconOnly: true
185
+ }),
186
+ children: /* @__PURE__ */ jsx(MoreIcon, {})
187
+ })]
156
188
  })]
157
189
  }), present(toolbar) && /* @__PURE__ */ jsx("div", {
158
190
  className: "px-4",
@@ -160,5 +192,77 @@ function HeaderLayout({ breadcrumbs, titleActions, actions, toolbar, compact = f
160
192
  })]
161
193
  });
162
194
  }
195
+ var ROW_GAP = 16;
196
+ var LEAD_GAP = 8;
197
+ var TRAIL_MIN_WIDTH = 160;
198
+ var FOLD_WIDTH = 448;
199
+ /**
200
+ * Fits the actions to the bar. Labels fold to their icons first, by the bar's
201
+ * own container query; when the folded actions still leave the trail too
202
+ * little room, the trailing ones move into a "…" menu at the end, last first,
203
+ * until the rest fit. It measures each action as it shows and remembers its
204
+ * width while it has moved, so the answer doesn't depend on what has moved.
205
+ */
206
+ function useActionsFit(fit, row, lead, end) {
207
+ const [widths] = useState(() => /* @__PURE__ */ new Map());
208
+ useLayoutEffect(() => {
209
+ if (!row || !lead || !end) {
210
+ fit.setOverflow([]);
211
+ return;
212
+ }
213
+ const measure = () => {
214
+ const rowWidth = row.clientWidth;
215
+ if (rowWidth === 0) {
216
+ fit.setOverflow([]);
217
+ return;
218
+ }
219
+ const folded = rowWidth < FOLD_WIDTH;
220
+ const key = (id, fold) => `${fold ? "folded" : "full"}:${id}`;
221
+ const items = [...end.querySelectorAll("[data-header-action]")].map((el) => el.dataset["headerAction"] ?? "");
222
+ for (const el of end.querySelectorAll("[data-header-action]")) {
223
+ const id = el.dataset["headerAction"] ?? "";
224
+ const control = el.firstElementChild;
225
+ if (!fit.isOverflowed(id) && control) widths.set(key(id, folded), control.getBoundingClientRect().width);
226
+ }
227
+ const width = (id) => widths.get(key(id, folded)) ?? widths.get(key(id, !folded)) ?? 0;
228
+ const style = getComputedStyle(row);
229
+ let leadMin = 0;
230
+ let leadItems = 0;
231
+ for (const child of lead.children) {
232
+ const w = child.tagName === "NAV" ? TRAIL_MIN_WIDTH : child.getBoundingClientRect().width;
233
+ if (w > 0) {
234
+ leadMin += w;
235
+ leadItems++;
236
+ }
237
+ }
238
+ leadMin += Math.max(0, leadItems - 1) * LEAD_GAP;
239
+ const room = rowWidth - Number.parseFloat(style.paddingLeft || "0") - Number.parseFloat(style.paddingRight || "0") - leadMin - ROW_GAP;
240
+ fit.setOverflow(overflowingActions(items.map((id) => ({
241
+ id,
242
+ width: width(id)
243
+ })), end.getBoundingClientRect().width, items.filter((id) => fit.isOverflowed(id)), room));
244
+ };
245
+ measure();
246
+ const resize = new ResizeObserver(measure);
247
+ resize.observe(row);
248
+ resize.observe(end);
249
+ const changes = new MutationObserver(measure);
250
+ changes.observe(end, {
251
+ childList: true,
252
+ subtree: true
253
+ });
254
+ changes.observe(lead, { childList: true });
255
+ return () => {
256
+ resize.disconnect();
257
+ changes.disconnect();
258
+ };
259
+ }, [
260
+ fit,
261
+ row,
262
+ lead,
263
+ end,
264
+ widths
265
+ ]);
266
+ }
163
267
  //#endregion
164
268
  export { PageHeader, PageHeaderBar, PageHeaderProvider };
@@ -1,4 +1,4 @@
1
- import type { ComponentType } from 'react';
1
+ import { type ComponentType } from 'react';
2
2
  import type { MenuEntry } from './MenuEntries.js';
3
3
  type Target = {
4
4
  href: string;
@@ -40,6 +40,9 @@ export type PageHeaderActionProps = Target & {
40
40
  destructive?: boolean | undefined;
41
41
  /** A toggle's state, such as a favorite: set, it reads as pressed. Buttons only. */
42
42
  pressed?: boolean | undefined;
43
+ /** Busy with what it started, such as a run starting: a spinner takes the
44
+ * icon's place, and it keeps focus but can't be pressed again until done. */
45
+ loading?: boolean | undefined;
43
46
  };
44
47
  /**
45
48
  * An action in the page header: a link (`href`, `external` for a new tab,
@@ -47,7 +50,7 @@ export type PageHeaderActionProps = Target & {
47
50
  * button (`onClick`) or a menu (`menu`). Labeled actions read in the link
48
51
  * color, so the page's commands stand apart from the trail.
49
52
  */
50
- export declare function PageHeaderAction({ icon: Icon, label, ariaLabel, iconOnly, disabled, disabledReason, tooltip, destructive, pressed, ...target }: PageHeaderActionProps): import("react").JSX.Element;
53
+ export declare function PageHeaderAction({ icon: Icon, label, ariaLabel, iconOnly, disabled, disabledReason, tooltip, destructive, pressed, loading, ...target }: PageHeaderActionProps): import("react").JSX.Element;
51
54
  export type PageHeaderAddButtonProps = Target & {
52
55
  /** The full action, such as "New cluster": the tooltip and accessible name. */
53
56
  label: string;
@@ -55,9 +58,11 @@ export type PageHeaderAddButtonProps = Target & {
55
58
  word?: 'add' | 'create' | undefined;
56
59
  disabled?: boolean | undefined;
57
60
  disabledReason?: string | undefined;
61
+ /** Busy making it: a spinner takes the plus's place, and it can't be pressed again until done. */
62
+ loading?: boolean | undefined;
58
63
  };
59
64
  /** The page's "+ Add" or "+ Create": with `menu`, a chooser of what to make. */
60
- export declare function PageHeaderAddButton({ label, word, disabled, disabledReason, ...target }: PageHeaderAddButtonProps): import("react").JSX.Element;
65
+ export declare function PageHeaderAddButton({ label, word, disabled, disabledReason, loading, ...target }: PageHeaderAddButtonProps): import("react").JSX.Element;
61
66
  /** The "…" menu of actions on the page's subject. Renders nothing without items. */
62
67
  export declare function PageHeaderMenu({ items, label, }: {
63
68
  items: MenuEntry[];
@@ -1,10 +1,13 @@
1
1
  import { cx } from "../cx.js";
2
2
  import { buttonClasses } from "./buttonClasses.js";
3
3
  import { AddIcon, MoreIcon } from "../icons.js";
4
+ import { Loader } from "./Loader.js";
4
5
  import { Tooltip } from "./Tooltip.js";
5
6
  import { useStrings } from "./Provider.js";
6
7
  import { AppLink } from "./AppLink.js";
7
8
  import { ActionMenu } from "./ActionMenu.js";
9
+ import { HeaderActionsFitContext } from "./headerActionsFit.js";
10
+ import { use, useId, useLayoutEffect, useSyncExternalStore } from "react";
8
11
  import { jsx, jsxs } from "react/jsx-runtime";
9
12
  //#region src/components/PageHeaderAction.tsx
10
13
  /**
@@ -13,9 +16,9 @@ import { jsx, jsxs } from "react/jsx-runtime";
13
16
  * focusable (`aria-disabled`, not `disabled`), so its reason is reachable by
14
17
  * keyboard and pointer, where a disabled button would swallow both.
15
18
  */
16
- function HeaderControl({ name, tooltip, disabled, disabledReason, pressed, className, children, href, external, reloadDocument, onClick, menu }) {
19
+ function HeaderControl({ name, tooltip, disabled, disabledReason, loading = false, pressed, className, children, href, external, reloadDocument, onClick, menu }) {
17
20
  const { common } = useStrings();
18
- if (menu && !disabled) return /* @__PURE__ */ jsx(ActionMenu, {
21
+ if (menu && !disabled && !loading) return /* @__PURE__ */ jsx(ActionMenu, {
19
22
  items: menu,
20
23
  label: name,
21
24
  triggerClassName: className,
@@ -28,7 +31,8 @@ function HeaderControl({ name, tooltip, disabled, disabledReason, pressed, class
28
31
  href,
29
32
  reloadDocument,
30
33
  target: external ? "_blank" : void 0,
31
- disabled,
34
+ disabled: disabled || loading,
35
+ "aria-busy": loading || void 0,
32
36
  "aria-label": reason ? `${name}. ${reason}` : external ? `${name} ${common.opensInNewTab}` : name,
33
37
  className,
34
38
  children
@@ -38,9 +42,10 @@ function HeaderControl({ name, tooltip, disabled, disabledReason, pressed, class
38
42
  content: disabled ? disabledReason ?? tooltip : tooltip,
39
43
  children: /* @__PURE__ */ jsx("button", {
40
44
  type: "button",
41
- onClick: disabled ? void 0 : onClick,
45
+ onClick: disabled || loading ? void 0 : onClick,
42
46
  "aria-label": reason ? `${name}. ${reason}` : name,
43
- "aria-disabled": disabled || void 0,
47
+ "aria-disabled": disabled || loading || void 0,
48
+ "aria-busy": loading || void 0,
44
49
  "aria-pressed": pressed,
45
50
  className,
46
51
  children
@@ -53,43 +58,126 @@ function HeaderControl({ name, tooltip, disabled, disabledReason, pressed, class
53
58
  * button (`onClick`) or a menu (`menu`). Labeled actions read in the link
54
59
  * color, so the page's commands stand apart from the trail.
55
60
  */
56
- function PageHeaderAction({ icon: Icon, label, ariaLabel, iconOnly = false, disabled = false, disabledReason, tooltip, destructive = false, pressed, ...target }) {
61
+ function PageHeaderAction({ icon: Icon, label, ariaLabel, iconOnly = false, disabled = false, disabledReason, tooltip, destructive = false, pressed, loading = false, ...target }) {
57
62
  const tone = destructive ? "*:text-(--theme-error-text)" : iconOnly ? void 0 : "*:text-(--theme-link)";
58
- return /* @__PURE__ */ jsxs(HeaderControl, {
59
- ...target,
60
- name: ariaLabel ?? label,
61
- tooltip: tooltip ?? label,
63
+ const icon = loading ? /* @__PURE__ */ jsx(Loader, {
64
+ inline: true,
65
+ decorative: true,
66
+ size: "1em"
67
+ }) : /* @__PURE__ */ jsx(Icon, {});
68
+ return /* @__PURE__ */ jsx(Fitted, {
69
+ entry: menuRow({
70
+ label: ariaLabel ?? label,
71
+ icon,
72
+ disabled: disabled || loading,
73
+ disabledReason,
74
+ destructive,
75
+ pressed,
76
+ target
77
+ }),
78
+ children: /* @__PURE__ */ jsxs(HeaderControl, {
79
+ ...target,
80
+ name: ariaLabel ?? label,
81
+ tooltip: tooltip ?? label,
82
+ disabled,
83
+ disabledReason,
84
+ loading,
85
+ pressed,
86
+ className: cx(buttonClasses({
87
+ variant: "ghost",
88
+ size: "xs",
89
+ iconOnly
90
+ }), tone),
91
+ children: [icon, !iconOnly && /* @__PURE__ */ jsx("span", {
92
+ className: "@max-md:sr-only",
93
+ children: label
94
+ })]
95
+ })
96
+ });
97
+ }
98
+ /** An action as a row of the header's "…" menu, for when the bar has no room for it. */
99
+ function menuRow({ label, icon, disabled, disabledReason, destructive, pressed, target }) {
100
+ const shared = {
101
+ label,
102
+ icon,
62
103
  disabled,
63
104
  disabledReason,
64
- pressed,
65
- className: cx(buttonClasses({
66
- variant: "ghost",
67
- size: "xs",
68
- iconOnly
69
- }), tone),
70
- children: [/* @__PURE__ */ jsx(Icon, {}), !iconOnly && /* @__PURE__ */ jsx("span", {
71
- className: "@max-md:sr-only",
72
- children: label
73
- })]
105
+ destructive
106
+ };
107
+ if (target.menu) return disabled ? {
108
+ ...shared,
109
+ onClick: () => {}
110
+ } : {
111
+ label,
112
+ icon,
113
+ items: target.menu
114
+ };
115
+ if (target.href) return {
116
+ ...shared,
117
+ href: target.href,
118
+ reloadDocument: target.reloadDocument,
119
+ target: target.external ? "_blank" : void 0
120
+ };
121
+ return {
122
+ ...shared,
123
+ onClick: target.onClick ?? (() => {}),
124
+ checked: pressed
125
+ };
126
+ }
127
+ /**
128
+ * Lets an action in the header's `actions` move into the bar's "…" menu when
129
+ * the bar runs out of room: it registers its menu row, and hides while it has
130
+ * moved. Anywhere else, such as among the title actions, it is the action alone.
131
+ */
132
+ function Fitted({ entry, children }) {
133
+ const fit = use(HeaderActionsFitContext);
134
+ const id = useId();
135
+ useLayoutEffect(() => {
136
+ fit?.register(id, entry);
137
+ });
138
+ useLayoutEffect(() => fit ? () => fit.unregister(id) : void 0, [fit, id]);
139
+ const moved = useSyncExternalStore(fit?.subscribe ?? subscribeNever, () => fit?.isOverflowed(id) ?? false, () => false);
140
+ if (!fit) return children;
141
+ return /* @__PURE__ */ jsx("span", {
142
+ "data-header-action": id,
143
+ hidden: moved,
144
+ className: moved ? void 0 : "contents",
145
+ children
74
146
  });
75
147
  }
148
+ var subscribeNever = () => () => {};
76
149
  /** The page's "+ Add" or "+ Create": with `menu`, a chooser of what to make. */
77
- function PageHeaderAddButton({ label, word = "add", disabled = false, disabledReason, ...target }) {
150
+ function PageHeaderAddButton({ label, word = "add", disabled = false, disabledReason, loading = false, ...target }) {
78
151
  const { common } = useStrings();
79
- return /* @__PURE__ */ jsxs(HeaderControl, {
80
- ...target,
81
- name: label,
82
- tooltip: label,
83
- disabled,
84
- disabledReason,
85
- className: buttonClasses({
86
- variant: "outline",
87
- size: "xs"
152
+ const icon = loading ? /* @__PURE__ */ jsx(Loader, {
153
+ inline: true,
154
+ decorative: true,
155
+ size: "1em"
156
+ }) : /* @__PURE__ */ jsx(AddIcon, {});
157
+ return /* @__PURE__ */ jsx(Fitted, {
158
+ entry: menuRow({
159
+ label,
160
+ icon,
161
+ disabled: disabled || loading,
162
+ disabledReason,
163
+ target
88
164
  }),
89
- children: [/* @__PURE__ */ jsx(AddIcon, {}), /* @__PURE__ */ jsx("span", {
90
- className: "@max-md:sr-only",
91
- children: word === "create" ? common.create : common.add
92
- })]
165
+ children: /* @__PURE__ */ jsxs(HeaderControl, {
166
+ ...target,
167
+ name: label,
168
+ tooltip: label,
169
+ disabled,
170
+ disabledReason,
171
+ loading,
172
+ className: buttonClasses({
173
+ variant: "outline",
174
+ size: "xs"
175
+ }),
176
+ children: [icon, /* @__PURE__ */ jsx("span", {
177
+ className: "@max-md:sr-only",
178
+ children: word === "create" ? common.create : common.add
179
+ })]
180
+ })
93
181
  });
94
182
  }
95
183
  /** The "…" menu of actions on the page's subject. Renders nothing without items. */
@@ -20,9 +20,21 @@ export interface PaginationProps {
20
20
  onPageSizeChange?: ((size: number) => void) | undefined;
21
21
  /** Replaces "1–50 of 200", such as with the time range a page covers. */
22
22
  summary?: ReactNode;
23
+ /** Numbers the pages between previous and next, for a list a reader jumps
24
+ * around in, such as a catalog: the first and last, and a window around
25
+ * the current one, with gaps between. `max` is how many steps show at
26
+ * most, gaps included (7 by default, 5 at least). Needs a `total`; hidden
27
+ * on a phone-width screen, where previous and next remain. */
28
+ pageNumbers?: boolean | {
29
+ max?: number | undefined;
30
+ } | undefined;
23
31
  className?: string | undefined;
24
32
  }
33
+ /** The pages to number, counting from 0, with `null` for a gap: all of them
34
+ * when they fit in `max` steps, and otherwise the first and last around a
35
+ * window on the current one, `max` steps in all. */
36
+ export declare function pageSteps(page: number, count: number, max?: number): (number | null)[];
25
37
  /** Steps through a list a page at a time: where the page sits in the list,
26
38
  * previous and next, and optionally how many rows a page holds. Renders
27
39
  * nothing when everything fits on one page. */
28
- export declare function Pagination({ page, pageSize, total, hasNext, onPageChange, pageHref, pageSizes, onPageSizeChange, summary, className, }: PaginationProps): import("react").JSX.Element | null;
40
+ export declare function Pagination({ page, pageSize, total, hasNext, onPageChange, pageHref, pageSizes, onPageSizeChange, summary, pageNumbers, className, }: PaginationProps): import("react").JSX.Element | null;