@parallelworks/ui 0.41.0 → 0.43.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 (283) hide show
  1. package/README.md +25 -0
  2. package/dist/ai/components/AllocationSelector.d.ts +3 -4
  3. package/dist/ai/components/AllocationSelector.js +37 -33
  4. package/dist/ai/components/AttachmentManager.js +7 -7
  5. package/dist/ai/components/AttachmentUpload.js +5 -5
  6. package/dist/ai/components/BranchNavigator.js +1 -1
  7. package/dist/ai/components/ChatEmptyState.js +2 -2
  8. package/dist/ai/components/ChatInput.js +10 -8
  9. package/dist/ai/components/ChatLayout.js +4 -5
  10. package/dist/ai/components/ChatMessage.js +12 -12
  11. package/dist/ai/components/ChatMessageList.js +9 -9
  12. package/dist/ai/components/ChatSidebar.js +8 -9
  13. package/dist/ai/components/ChatThread.js +4 -4
  14. package/dist/ai/components/ComposerChrome.d.ts +2 -2
  15. package/dist/ai/components/ComposerChrome.js +3 -6
  16. package/dist/ai/components/DragOverlay.js +2 -2
  17. package/dist/ai/components/ModelSelector.d.ts +5 -3
  18. package/dist/ai/components/ModelSelector.js +102 -339
  19. package/dist/ai/components/PastedText.js +11 -11
  20. package/dist/ai/components/ProviderIssueBanner.d.ts +2 -0
  21. package/dist/ai/components/ProviderIssueBanner.js +34 -16
  22. package/dist/ai/components/Reasoning.js +4 -4
  23. package/dist/ai/components/ShareDialog.js +43 -35
  24. package/dist/ai/components/SlashMenu.d.ts +12 -2
  25. package/dist/ai/components/SlashMenu.js +29 -13
  26. package/dist/ai/components/agent/ActivityLine.js +3 -3
  27. package/dist/ai/components/agent/AgentMessageParts.js +20 -20
  28. package/dist/ai/components/agent/PermissionPicker.js +13 -11
  29. package/dist/ai/components/conversationActions.d.ts +4 -6
  30. package/dist/ai/components/conversationActions.js +9 -13
  31. package/dist/ai/core/ChatProvider.js +1 -1
  32. package/dist/ai/core/config.js +1 -1
  33. package/dist/ai/core/providerIssues.d.ts +7 -0
  34. package/dist/ai/core/providerIssues.js +9 -1
  35. package/dist/ai/core/useKeyboardShortcuts.d.ts +4 -0
  36. package/dist/ai/core/useKeyboardShortcuts.js +8 -2
  37. package/dist/ai/index.d.ts +0 -1
  38. package/dist/ai/index.js +1 -2
  39. package/dist/ai/strings.d.ts +19 -0
  40. package/dist/ai/strings.js +18 -1
  41. package/dist/ai/ui/Avatar.js +5 -5
  42. package/dist/ai/ui/ConversationSidebar.d.ts +0 -1
  43. package/dist/ai/ui/ConversationSidebar.js +6 -7
  44. package/dist/ai/ui/Markdown.js +3 -3
  45. package/dist/ai/ui/Notice.js +6 -6
  46. package/dist/ai/ui/chip.d.ts +4 -0
  47. package/dist/ai/ui/chip.js +8 -0
  48. package/dist/ai/ui/sidebar.d.ts +6 -5
  49. package/dist/ai/ui/sidebar.js +39 -43
  50. package/dist/components/ActionMenu.d.ts +13 -0
  51. package/dist/components/ActionMenu.js +30 -0
  52. package/dist/components/Avatar.js +6 -6
  53. package/dist/components/Breadcrumbs.js +1 -1
  54. package/dist/components/Button.js +10 -10
  55. package/dist/components/Callout.js +2 -2
  56. package/dist/components/Card.js +3 -3
  57. package/dist/components/Combobox.d.ts +49 -0
  58. package/dist/components/Combobox.js +405 -0
  59. package/dist/components/ConfirmModal.js +11 -11
  60. package/dist/components/ContextMenu.d.ts +23 -0
  61. package/dist/components/ContextMenu.js +89 -0
  62. package/dist/components/CopyToClipboard.js +2 -2
  63. package/dist/components/CreateModal.d.ts +19 -38
  64. package/dist/components/CreateModal.js +116 -267
  65. package/dist/components/DescriptionList.js +8 -8
  66. package/dist/components/Filter.js +2 -2
  67. package/dist/components/FilterPill.js +2 -2
  68. package/dist/components/HoverCard.d.ts +14 -0
  69. package/dist/components/HoverCard.js +33 -0
  70. package/dist/components/IconButton.d.ts +5 -5
  71. package/dist/components/IconButton.js +18 -22
  72. package/dist/components/InfoTip.d.ts +15 -0
  73. package/dist/components/InfoTip.js +60 -0
  74. package/dist/components/Input.js +5 -5
  75. package/dist/components/LetterBadge.js +2 -2
  76. package/dist/components/Loader.js +3 -3
  77. package/dist/components/Markdown.js +1 -1
  78. package/dist/components/MarkdownImpl.js +2 -2
  79. package/dist/components/Menu.d.ts +33 -0
  80. package/dist/components/Menu.js +86 -0
  81. package/dist/components/MenuEntries.d.ts +56 -0
  82. package/dist/components/MenuEntries.js +123 -0
  83. package/dist/components/Modal.d.ts +29 -0
  84. package/dist/components/Modal.js +47 -0
  85. package/dist/components/Overview.js +11 -10
  86. package/dist/components/PageHeader.d.ts +10 -16
  87. package/dist/components/PageHeader.js +69 -95
  88. package/dist/components/Pagination.js +5 -5
  89. package/dist/components/Provider.d.ts +5 -11
  90. package/dist/components/Provider.js +11 -14
  91. package/dist/components/Radio.d.ts +8 -0
  92. package/dist/components/Radio.js +16 -0
  93. package/dist/components/SectionHeader.js +2 -2
  94. package/dist/components/SegmentedControl.d.ts +6 -5
  95. package/dist/components/SegmentedControl.js +34 -30
  96. package/dist/components/Select.d.ts +27 -0
  97. package/dist/components/Select.js +78 -0
  98. package/dist/components/SettingModeOption.d.ts +5 -8
  99. package/dist/components/SettingModeOption.js +10 -12
  100. package/dist/components/SettingRow.js +4 -4
  101. package/dist/components/SettingsCard.js +4 -4
  102. package/dist/components/SettingsGroup.js +2 -2
  103. package/dist/components/Sort.js +1 -1
  104. package/dist/components/StatusBadge.js +7 -7
  105. package/dist/components/StatusIcons.js +4 -4
  106. package/dist/components/Switch.d.ts +22 -0
  107. package/dist/components/Switch.js +28 -0
  108. package/dist/components/Table.js +11 -11
  109. package/dist/components/Tooltip.d.ts +24 -20
  110. package/dist/components/Tooltip.js +58 -76
  111. package/dist/components/comboboxItems.d.ts +24 -0
  112. package/dist/components/comboboxItems.js +10 -0
  113. package/dist/components/floating.d.ts +14 -0
  114. package/dist/components/floating.js +21 -0
  115. package/dist/components/search.d.ts +2 -0
  116. package/dist/components/search.js +14 -0
  117. package/dist/editor/Editor.js +1 -1
  118. package/dist/editor/EditorField.js +16 -21
  119. package/dist/editor/FormCodePanel.js +19 -19
  120. package/dist/editor/Monaco.js +3 -3
  121. package/dist/file-explorer/FileExplorer.js +77 -81
  122. package/dist/file-explorer/FileExplorerContext.js +2 -2
  123. package/dist/file-explorer/FilePreview/CodePreviewEditor.js +1 -1
  124. package/dist/file-explorer/FilePreview/Inline.js +1 -1
  125. package/dist/file-explorer/FilePreview/StreamedBadge.js +5 -6
  126. package/dist/file-explorer/FilePreview/Viewer.js +8 -8
  127. package/dist/file-explorer/FilePreview/index.d.ts +1 -1
  128. package/dist/file-explorer/FilePreview/index.js +49 -83
  129. package/dist/file-explorer/FileRow.d.ts +4 -3
  130. package/dist/file-explorer/FileRow.js +32 -38
  131. package/dist/file-explorer/FileRowsWindow.d.ts +3 -2
  132. package/dist/file-explorer/FileRowsWindow.js +4 -4
  133. package/dist/file-explorer/FileTable.d.ts +3 -2
  134. package/dist/file-explorer/FileTable.js +3 -3
  135. package/dist/file-explorer/LoadMoreRow.js +1 -1
  136. package/dist/file-explorer/TreeView.js +11 -16
  137. package/dist/file-explorer/helpers.js +11 -12
  138. package/dist/file-explorer/toasts.js +11 -11
  139. package/dist/form/FieldGroup.d.ts +11 -0
  140. package/dist/form/FieldGroup.js +36 -0
  141. package/dist/form/FieldWrapper.js +4 -4
  142. package/dist/form/Fields/BooleanField.js +23 -33
  143. package/dist/form/Fields/CheckboxGroupField.d.ts +1 -1
  144. package/dist/form/Fields/CheckboxGroupField.js +9 -13
  145. package/dist/form/Fields/ColorField.d.ts +1 -2
  146. package/dist/form/Fields/ColorField.js +6 -11
  147. package/dist/form/Fields/DropdownField.d.ts +3 -13
  148. package/dist/form/Fields/DropdownField.js +40 -27
  149. package/dist/form/Fields/DurationField.d.ts +1 -2
  150. package/dist/form/Fields/DurationField.js +25 -32
  151. package/dist/form/Fields/LabelField.js +2 -2
  152. package/dist/form/Fields/MultiDropdownField.d.ts +6 -12
  153. package/dist/form/Fields/MultiDropdownField.js +31 -22
  154. package/dist/form/Fields/NumberField.d.ts +1 -1
  155. package/dist/form/Fields/NumberField.js +65 -35
  156. package/dist/form/Fields/ObjectField.d.ts +1 -1
  157. package/dist/form/Fields/ObjectField.js +12 -43
  158. package/dist/form/Fields/RadioField.d.ts +1 -1
  159. package/dist/form/Fields/RadioField.js +30 -41
  160. package/dist/form/Fields/RangeField.d.ts +1 -2
  161. package/dist/form/Fields/RangeField.js +23 -16
  162. package/dist/form/Fields/StringField.d.ts +1 -2
  163. package/dist/form/Fields/StringField.js +58 -26
  164. package/dist/form/Fields/TextAreaField.js +12 -10
  165. package/dist/form/Form.d.ts +30 -48
  166. package/dist/form/Form.js +306 -412
  167. package/dist/form/FormLayout.js +9 -9
  168. package/dist/form/Wizard/WizardContainer.d.ts +1 -4
  169. package/dist/form/Wizard/WizardContainer.js +40 -56
  170. package/dist/form/Wizard/WizardNavigation.js +1 -1
  171. package/dist/form/Wizard/WizardStepContent.d.ts +1 -5
  172. package/dist/form/Wizard/WizardStepContent.js +11 -16
  173. package/dist/form/Wizard/WizardStepIndicator.js +6 -6
  174. package/dist/form/Wizard/types.d.ts +0 -14
  175. package/dist/form/fieldRegistry.d.ts +1 -1
  176. package/dist/form/fieldRegistry.js +6 -6
  177. package/dist/form/formEditing.js +1 -1
  178. package/dist/form/index.d.ts +5 -4
  179. package/dist/form/index.js +6 -7
  180. package/dist/form/lib.js +3 -2
  181. package/dist/form/types/fieldComponentTypes.d.ts +8 -10
  182. package/dist/form/useChoiceField.d.ts +18 -0
  183. package/dist/form/useChoiceField.js +46 -0
  184. package/dist/form/useFieldValue.d.ts +7 -0
  185. package/dist/form/useFieldValue.js +20 -0
  186. package/dist/form/useParsedOpts.d.ts +3 -1
  187. package/dist/form/useParsedOpts.js +12 -17
  188. package/dist/form/utils/dependentOptions.d.ts +8 -4
  189. package/dist/form/utils/dependentOptions.js +25 -17
  190. package/dist/form/utils/fieldItems.d.ts +32 -0
  191. package/dist/form/utils/fieldItems.js +32 -0
  192. package/dist/form/utils/fieldPath.d.ts +10 -0
  193. package/dist/form/utils/fieldPath.js +20 -0
  194. package/dist/form/utils/shareEqual.d.ts +6 -0
  195. package/dist/form/utils/shareEqual.js +38 -0
  196. package/dist/graph/AnnotationBanner.js +8 -8
  197. package/dist/graph/Collapse.d.ts +1 -0
  198. package/dist/graph/Collapse.js +6 -27
  199. package/dist/graph/Connectors.js +5 -5
  200. package/dist/graph/DependencyGraph.js +20 -19
  201. package/dist/graph/GraphEditor.js +30 -41
  202. package/dist/graph/GraphEditorDialogs.js +17 -17
  203. package/dist/graph/GraphNode.js +1 -1
  204. package/dist/graph/InputDialog.js +19 -22
  205. package/dist/graph/InputsEditor.js +58 -66
  206. package/dist/graph/JobSummary.js +42 -39
  207. package/dist/graph/MatrixGroup.js +1 -1
  208. package/dist/graph/ProblemsButton.js +18 -19
  209. package/dist/graph/Reveal.js +1 -1
  210. package/dist/graph/ShortcutsButton.js +15 -18
  211. package/dist/graph/SuggestionInput.d.ts +5 -10
  212. package/dist/graph/SuggestionInput.js +14 -18
  213. package/dist/graph/ToolbarPopover.d.ts +11 -6
  214. package/dist/graph/ToolbarPopover.js +35 -67
  215. package/dist/graph/TreeView.js +24 -37
  216. package/dist/graph/WorkflowSettingsDialog.js +4 -4
  217. package/dist/graph/editorChrome.js +13 -12
  218. package/dist/graph/editorFields.js +29 -29
  219. package/dist/graph/editorPrimitives.d.ts +1 -1
  220. package/dist/graph/editorPrimitives.js +10 -7
  221. package/dist/graph/editorRows.js +103 -97
  222. package/dist/graph/fieldProblems.js +2 -2
  223. package/dist/graph/graphEditorState.d.ts +4 -3
  224. package/dist/graph/inputRefs.js +9 -9
  225. package/dist/graph/settingsViews.js +6 -7
  226. package/dist/graph/stepWith.js +6 -6
  227. package/dist/index.d.ts +14 -15
  228. package/dist/index.js +15 -14
  229. package/dist/list/ActionToolbar.d.ts +6 -14
  230. package/dist/list/ActionToolbar.js +48 -96
  231. package/dist/list/ListPage.d.ts +6 -12
  232. package/dist/list/ListPage.js +46 -29
  233. package/dist/list/ListPager.js +4 -4
  234. package/dist/list/ListTable.js +5 -5
  235. package/dist/list/ListViewControls.d.ts +5 -4
  236. package/dist/list/ListViewControls.js +177 -267
  237. package/dist/list/UserHoverCard.d.ts +3 -17
  238. package/dist/list/UserHoverCard.js +21 -45
  239. package/dist/list/index.d.ts +3 -4
  240. package/dist/list/index.js +3 -4
  241. package/dist/list/listSearch.js +12 -11
  242. package/dist/list/rowMenu.d.ts +68 -0
  243. package/dist/list/rowMenu.js +136 -0
  244. package/dist/logviewer/LogViewer.js +26 -26
  245. package/dist/styles.css +1 -1
  246. package/package.json +7 -13
  247. package/dist/ai/ui/Dropdown.d.ts +0 -31
  248. package/dist/ai/ui/Dropdown.js +0 -110
  249. package/dist/components/AddMenu.d.ts +0 -18
  250. package/dist/components/AddMenu.js +0 -46
  251. package/dist/components/BareModal.d.ts +0 -17
  252. package/dist/components/BareModal.js +0 -77
  253. package/dist/components/CollapsiblePanel.d.ts +0 -27
  254. package/dist/components/CollapsiblePanel.js +0 -77
  255. package/dist/components/Dropdown.d.ts +0 -28
  256. package/dist/components/Dropdown.js +0 -355
  257. package/dist/components/Listbox.d.ts +0 -21
  258. package/dist/components/Listbox.js +0 -119
  259. package/dist/components/MultiSelect.d.ts +0 -22
  260. package/dist/components/MultiSelect.js +0 -168
  261. package/dist/components/SwitchToggle.d.ts +0 -15
  262. package/dist/components/SwitchToggle.js +0 -57
  263. package/dist/components/SwitchToggleSmall.d.ts +0 -6
  264. package/dist/components/SwitchToggleSmall.js +0 -14
  265. package/dist/components/Toggle.d.ts +0 -6
  266. package/dist/components/Toggle.js +0 -20
  267. package/dist/components/dropdownUtils.d.ts +0 -37
  268. package/dist/components/dropdownUtils.js +0 -99
  269. package/dist/form/SpecialTypes/DropdownWrapper.d.ts +0 -25
  270. package/dist/form/SpecialTypes/DropdownWrapper.js +0 -28
  271. package/dist/form/SpecialTypes/FormikCustomDropdown.d.ts +0 -51
  272. package/dist/form/SpecialTypes/FormikCustomDropdown.js +0 -119
  273. package/dist/form/SpecialTypes/FormikCustomInput.d.ts +0 -19
  274. package/dist/form/SpecialTypes/FormikCustomInput.js +0 -121
  275. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.d.ts +0 -13
  276. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +0 -31
  277. package/dist/form/SpecialTypes/FormikNumericInput.d.ts +0 -9
  278. package/dist/form/SpecialTypes/FormikNumericInput.js +0 -60
  279. package/dist/form/SpecialTypes/index.d.ts +0 -3
  280. package/dist/list/HoverCard.d.ts +0 -24
  281. package/dist/list/HoverCard.js +0 -73
  282. package/dist/list/RowContextMenu.d.ts +0 -127
  283. package/dist/list/RowContextMenu.js +0 -515
@@ -1,7 +1,7 @@
1
1
  import { useStrings } from "./Provider.js";
2
- import cx from "classnames";
3
- import { useState } from "react";
2
+ import { clsx } from "clsx";
4
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { useState } from "react";
5
5
  //#region src/components/Avatar.tsx
6
6
  var SIZE_CLASSES = {
7
7
  xs: "w-4 h-4 text-[9px]",
@@ -30,19 +30,19 @@ function Avatar({ src, name, size = "md", status, className }) {
30
30
  const [erroredUrl, setErroredUrl] = useState(null);
31
31
  const showImage = !!src && erroredUrl !== src;
32
32
  return /* @__PURE__ */ jsxs("div", {
33
- className: cx("relative inline-flex", className),
33
+ className: clsx("relative inline-flex", className),
34
34
  children: [showImage ? /* @__PURE__ */ jsx("img", {
35
35
  src,
36
36
  alt: name || strings.common.userAvatar,
37
37
  loading: "lazy",
38
38
  onError: () => setErroredUrl(src),
39
- className: cx("rounded-full object-cover", SIZE_CLASSES[size])
39
+ className: clsx("rounded-full object-cover", SIZE_CLASSES[size])
40
40
  }) : /* @__PURE__ */ jsx("div", {
41
- className: cx("rounded-full flex items-center justify-center font-medium", "bg-gradient-to-br from-[var(--gradient-start,var(--theme-element))] to-[var(--gradient-mid,var(--theme-link))] text-white", SIZE_CLASSES[size]),
41
+ className: clsx("rounded-full flex items-center justify-center font-medium", "bg-gradient-to-br from-[var(--gradient-start,var(--theme-element))] to-[var(--gradient-mid,var(--theme-link))] text-white", SIZE_CLASSES[size]),
42
42
  children: size === "xs" ? avatarInitials(name).charAt(0) : avatarInitials(name)
43
43
  }), status && /* @__PURE__ */ jsx("span", {
44
44
  "data-testid": "online-indicator",
45
- className: cx("absolute bottom-0 right-0 block rounded-full ring-2 ring-(--theme-app-bg)", STATUS_CLASSES[status], size === "xs" || size === "sm" ? "w-1.5 h-1.5" : "w-2.5 h-2.5")
45
+ className: clsx("absolute bottom-0 right-0 block rounded-full ring-2 ring-(--theme-app-bg)", STATUS_CLASSES[status], size === "xs" || size === "sm" ? "w-1.5 h-1.5" : "w-2.5 h-2.5")
46
46
  })]
47
47
  });
48
48
  }
@@ -1,5 +1,5 @@
1
- import React, { createContext, useContext, useEffect, useLayoutEffect, useMemo } from "react";
2
1
  import { jsx } from "react/jsx-runtime";
2
+ import React, { createContext, useContext, useEffect, useLayoutEffect, useMemo } from "react";
3
3
  //#region src/components/Breadcrumbs.tsx
4
4
  var BreadcrumbContext = createContext({
5
5
  breadcrumbs: [],
@@ -1,9 +1,9 @@
1
- import { useLink } from "./Provider.js";
2
1
  import { FaAngleRight } from "../icons/fa/FaAngleRight.js";
3
2
  import { LoaderIcon } from "./StatusIcons.js";
4
- import cx from "classnames";
3
+ import { useLink } from "./Provider.js";
4
+ import { clsx } from "clsx";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
6
  import { forwardRef } from "react";
6
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
7
  //#region src/components/Button.tsx
8
8
  var Button = forwardRef(({ children, variant = "primary", size = "default", loading, icon, iconPosition = "right", fullWidth = true, className = "", disabled, ...props }, ref) => {
9
9
  const baseClasses = "inline-flex items-center justify-center gap-2 font-semibold rounded-lg transition-all duration-200 cursor-pointer border-none mt-2 disabled:opacity-50 disabled:cursor-not-allowed";
@@ -23,9 +23,9 @@ var Button = forwardRef(({ children, variant = "primary", size = "default", load
23
23
  ref,
24
24
  type: "button",
25
25
  disabled: disabled || loading,
26
- className: cx(baseClasses, variantClasses[variant], sizeClasses[size], widthClass, className),
26
+ className: clsx(baseClasses, variantClasses[variant], sizeClasses[size], widthClass, className),
27
27
  ...props,
28
- children: loading ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(LoaderIcon, { className: "size-[18px]" }), children] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
28
+ children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(LoaderIcon, { className: "size-[18px]" }), children] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
29
29
  icon && iconPosition === "left" && /* @__PURE__ */ jsx("span", {
30
30
  className: "flex items-center",
31
31
  children: icon
@@ -43,7 +43,7 @@ function MethodButton({ icon, label, description, href, loading, disabled, class
43
43
  const Link = useLink();
44
44
  const baseClasses = "flex items-center w-full p-4 bg-[var(--theme-muted-panel-bg)] border border-[var(--theme-border)] rounded-xl text-[var(--theme-app)] text-[0.9375rem] font-medium cursor-pointer transition-all duration-200 no-underline mb-3 last:mb-0 hover:bg-[var(--theme-border)] hover:border-[var(--theme-muted-text-color)] hover:-translate-y-0.5 active:translate-y-0";
45
45
  const disabledClasses = "disabled:opacity-60 disabled:cursor-not-allowed disabled:hover:bg-[var(--ds-muted)] disabled:hover:border-[var(--ds-border)] disabled:hover:translate-y-0";
46
- const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [
46
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
47
47
  icon && /* @__PURE__ */ jsx("span", {
48
48
  className: "size-10 rounded-lg bg-gradient-to-br from-[var(--gradient-start,var(--theme-element))] to-[var(--gradient-mid,var(--theme-link))] flex items-center justify-center shrink-0 mr-4 [&_svg]:size-5 [&_svg]:text-white",
49
49
  children: icon
@@ -63,18 +63,18 @@ function MethodButton({ icon, label, description, href, loading, disabled, class
63
63
  if (href) {
64
64
  if (href.startsWith("/api/") || href.startsWith("http")) return /* @__PURE__ */ jsx("a", {
65
65
  href,
66
- className: cx("group", baseClasses, className),
66
+ className: clsx("group", baseClasses, className),
67
67
  children: content
68
68
  });
69
69
  return /* @__PURE__ */ jsx(Link, {
70
- to: href,
71
- className: cx("group", baseClasses, className),
70
+ href,
71
+ className: clsx("group", baseClasses, className),
72
72
  children: content
73
73
  });
74
74
  }
75
75
  return /* @__PURE__ */ jsx("button", {
76
76
  type: "button",
77
- className: cx("group", baseClasses, disabledClasses, className),
77
+ className: clsx("group", baseClasses, disabledClasses, className),
78
78
  disabled: disabled || loading,
79
79
  ...props,
80
80
  children: content
@@ -1,6 +1,6 @@
1
1
  import { FaInfoCircle } from "../icons/fa/FaInfoCircle.js";
2
2
  import { TbAlertTriangle } from "../icons/tb/TbAlertTriangle.js";
3
- import cx from "classnames";
3
+ import { clsx } from "clsx";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/components/Callout.tsx
6
6
  function CalloutIcon({ type }) {
@@ -9,7 +9,7 @@ function CalloutIcon({ type }) {
9
9
  }
10
10
  function Callout({ type, className = "", children }) {
11
11
  return /* @__PURE__ */ jsx("div", {
12
- className: cx(className, type === "warning" && "bg-orange-100 border-orange-500 text-orange-700", type === "error" && "bg-red-100 border-red-500 text-red-700", type === "info" && "bg-blue-100 border-blue-500 text-blue-700", "border-t-4 rounded-b px-4 py-3 shadow-md my-4"),
12
+ className: clsx(className, type === "warning" && "bg-orange-100 border-orange-500 text-orange-700", type === "error" && "bg-red-100 border-red-500 text-red-700", type === "info" && "bg-blue-100 border-blue-500 text-blue-700", "border-t-4 rounded-b px-4 py-3 shadow-md my-4"),
13
13
  role: "alert",
14
14
  children: /* @__PURE__ */ jsxs("div", {
15
15
  className: "flex",
@@ -1,15 +1,15 @@
1
- import cx from "classnames";
1
+ import { clsx } from "clsx";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/components/Card.tsx
4
4
  function Card({ children, className = "", wide, compact, interactive, authShadow }) {
5
5
  return /* @__PURE__ */ jsx("div", {
6
- className: cx("w-full bg-[var(--theme-card-bg)] backdrop-blur-xl border border-[var(--theme-border)] rounded-2xl", authShadow ? "shadow-[var(--theme-auth-shadow)]" : "shadow-[var(--theme-shadow)]", wide && "max-w-[560px] p-8", compact && "max-w-[400px] p-6", !wide && !compact && "max-w-[520px] p-10", interactive && "ds-card-interactive cursor-pointer", className),
6
+ className: clsx("w-full bg-[var(--theme-card-bg)] backdrop-blur-xl border border-[var(--theme-border)] rounded-2xl", authShadow ? "shadow-[var(--theme-auth-shadow)]" : "shadow-[var(--theme-shadow)]", wide && "max-w-[560px] p-8", compact && "max-w-[400px] p-6", !wide && !compact && "max-w-[520px] p-10", interactive && "ds-card-interactive cursor-pointer", className),
7
7
  children
8
8
  });
9
9
  }
10
10
  function CardHeader({ badge, title, description, className = "", align = "center" }) {
11
11
  return /* @__PURE__ */ jsxs("div", {
12
- className: cx(align === "center" ? "text-center" : "text-left", "mb-6", className),
12
+ className: clsx(align === "center" ? "text-center" : "text-left", "mb-6", className),
13
13
  children: [
14
14
  badge && /* @__PURE__ */ jsx("div", {
15
15
  className: "inline-flex items-center gap-1.5 py-1.5 px-3 text-xs font-medium bg-[var(--theme-muted-panel-bg)] border border-[var(--theme-border)] rounded-full text-[var(--theme-muted-text-color)] mb-4 transition-colors duration-200",
@@ -0,0 +1,49 @@
1
+ import { type ReactElement, type ReactNode } from 'react';
2
+ import { type ComboboxItems } from './comboboxItems.js';
3
+ export type { ComboboxGroup, ComboboxItem, ComboboxItems, ComboboxLeaf, } from './comboboxItems.js';
4
+ interface FieldProps {
5
+ id?: string | undefined;
6
+ placeholder?: string | undefined;
7
+ disabled?: boolean | undefined;
8
+ required?: boolean | undefined;
9
+ 'aria-label'?: string | undefined;
10
+ 'aria-labelledby'?: string | undefined;
11
+ 'aria-describedby'?: string | undefined;
12
+ 'aria-invalid'?: boolean | undefined;
13
+ /** Classes for the field box: border, background, size. */
14
+ className?: string | undefined;
15
+ }
16
+ type SelectionProps<Value> = {
17
+ multiple?: false | undefined;
18
+ value?: Value | null | undefined;
19
+ defaultValue?: Value | null | undefined;
20
+ onValueChange?: ((value: NoInfer<Value> | null) => void) | undefined;
21
+ } | {
22
+ multiple: true;
23
+ value?: readonly Value[] | undefined;
24
+ defaultValue?: readonly Value[] | undefined;
25
+ onValueChange?: ((value: NoInfer<Value>[]) => void) | undefined;
26
+ };
27
+ export type ComboboxProps<Value = string> = FieldProps & SelectionProps<Value> & {
28
+ items: ComboboxItems<Value>;
29
+ /** Matches a value to its item. Defaults to deep equality, so object values can be recreated. */
30
+ isItemEqualToValue?: ((itemValue: Value, value: Value) => boolean) | undefined;
31
+ /** Labels a selected value that no item has, such as a saved choice the list no longer offers. */
32
+ itemToStringLabel?: ((value: Value) => string) | undefined;
33
+ /** Renders the field as this button, with the search input inside the popup, for compact
34
+ * pickers such as a toolbar pill. The button shows the selection itself. */
35
+ trigger?: ReactElement | undefined;
36
+ /** A hint on the trigger button. */
37
+ triggerTooltip?: ReactNode;
38
+ };
39
+ export interface AutocompleteProps extends FieldProps {
40
+ /** Suggestions; any typed text is also a valid value. */
41
+ items: ComboboxItems<string>;
42
+ value?: string | undefined;
43
+ defaultValue?: string | undefined;
44
+ onValueChange?: ((value: string) => void) | undefined;
45
+ }
46
+ /** A pick-from-the-list field: one value, or several with `multiple`. Typing filters the list. */
47
+ export declare function Combobox<Value = string>(props: ComboboxProps<Value>): import("react").JSX.Element;
48
+ /** A free-text field that suggests values as you type. */
49
+ export declare function Autocomplete({ items, value, defaultValue, onValueChange, className, placeholder, disabled, required, id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, 'aria-invalid': ariaInvalid, }: AutocompleteProps): import("react").JSX.Element;
@@ -0,0 +1,405 @@
1
+ import { FaCaretDown } from "../icons/fa/FaCaretDown.js";
2
+ import { FaCheck } from "../icons/fa/FaCheck.js";
3
+ import { FiX } from "../icons/fi/FiX.js";
4
+ import { panelClassName, panelItemClassName, portalContainer, positionerClassName } from "./floating.js";
5
+ import { Tooltip } from "./Tooltip.js";
6
+ import { useStrings } from "./Provider.js";
7
+ import { useQueryMatch } from "./search.js";
8
+ import { isComboboxGroup } from "./comboboxItems.js";
9
+ import { clsx } from "clsx";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
+ import { useCallback, useImperativeHandle, useMemo, useRef, useState } from "react";
12
+ import { Combobox } from "@base-ui/react/combobox";
13
+ import { Autocomplete } from "@base-ui/react/autocomplete";
14
+ import { useVirtualizer } from "@tanstack/react-virtual";
15
+ import { dequal } from "dequal";
16
+ //#region src/components/Combobox.tsx
17
+ function toEntry(item, group) {
18
+ const entry = typeof item === "string" ? {
19
+ value: item,
20
+ label: item
21
+ } : item;
22
+ return group === void 0 ? entry : {
23
+ ...entry,
24
+ group
25
+ };
26
+ }
27
+ /** Base UI takes either flat items or groups, and filters and navigates by the leaf items, so
28
+ * items listed between groups gather into headless groups where they sit. */
29
+ function useEntries(items) {
30
+ return useMemo(() => {
31
+ if (!items.some(isComboboxGroup)) {
32
+ const flat = items.map((item) => toEntry(item));
33
+ return {
34
+ items: flat,
35
+ flat,
36
+ statusGroups: []
37
+ };
38
+ }
39
+ const groups = [];
40
+ for (const item of items) {
41
+ if (isComboboxGroup(item)) {
42
+ groups.push({
43
+ label: item.label,
44
+ icon: item.icon,
45
+ description: item.description,
46
+ items: item.items.map((leaf) => toEntry(leaf, item.label)),
47
+ order: groups.length
48
+ });
49
+ continue;
50
+ }
51
+ const last = groups.at(-1);
52
+ if (last?.headless) last.items.push(toEntry(item));
53
+ else groups.push({
54
+ label: "",
55
+ items: [toEntry(item)],
56
+ order: groups.length,
57
+ headless: true
58
+ });
59
+ }
60
+ return {
61
+ items: groups,
62
+ flat: groups.flatMap((g) => g.items),
63
+ statusGroups: groups.filter((g) => g.items.length === 0)
64
+ };
65
+ }, [items]);
66
+ }
67
+ function useEntryFilter() {
68
+ const match = useQueryMatch();
69
+ return useCallback((entry, query) => match(query, entry.label, typeof entry.value === "string" ? entry.value : void 0, entry.group), [match]);
70
+ }
71
+ var entryLabel = (entry) => entry?.label ?? "";
72
+ var fieldClassName = "theme-input relative flex min-h-8 w-full items-center gap-1 rounded-md border text-sm focus-within:border-(--theme-element) focus-within:ring-1 focus-within:ring-(--theme-element) has-[[aria-invalid=true]]:border-(--theme-error) has-[input:disabled]:cursor-not-allowed has-[input:disabled]:bg-(--theme-input-disabled-bg) has-[input:disabled]:text-(--theme-input-disabled-text)";
73
+ var inputClassName = "h-full min-w-12 flex-1 self-stretch border-0 bg-transparent py-1.5 pl-3 text-inherit outline-none placeholder:text-(--theme-muted-text-color) disabled:cursor-not-allowed";
74
+ var triggerClassName = "flex shrink-0 items-center self-stretch px-2 text-(--theme-muted-text-color) disabled:cursor-not-allowed";
75
+ var popupInputClassName = "theme-input h-7 w-full rounded-md border px-2 text-sm outline-none placeholder:text-(--theme-muted-text-color) focus:border-(--theme-element)";
76
+ /** A pick-from-the-list field: one value, or several with `multiple`. Typing filters the list. */
77
+ function Combobox$1(props) {
78
+ const { items, isItemEqualToValue = dequal, itemToStringLabel = String, className, placeholder, disabled, required, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, trigger, triggerTooltip } = props;
79
+ const entries = useEntries(items);
80
+ const filter = useEntryFilter();
81
+ const strings = useStrings();
82
+ const t = strings.dropdown;
83
+ const list = useRef(null);
84
+ const [inputValue, setInputValue] = useState(null);
85
+ const entryOf = (value) => entries.flat.find((entry) => isItemEqualToValue(entry.value, value)) ?? {
86
+ value,
87
+ label: itemToStringLabel(value)
88
+ };
89
+ const toEntries = (values) => values?.map(entryOf);
90
+ const toSingle = (value) => value === void 0 ? void 0 : value === null ? null : entryOf(value);
91
+ const selected = props.multiple ? void 0 : toSingle(props.value);
92
+ const selectedIcon = selected?.icon && (inputValue === null || inputValue === selected.label) ? selected.icon : null;
93
+ const input = /* @__PURE__ */ jsx(Combobox.Input, {
94
+ id: trigger ? void 0 : id,
95
+ placeholder,
96
+ "aria-label": ariaLabel || void 0,
97
+ "aria-labelledby": ariaLabelledBy,
98
+ "aria-describedby": ariaDescribedBy,
99
+ "aria-invalid": ariaInvalid || void 0,
100
+ autoComplete: "off",
101
+ className: trigger ? popupInputClassName : inputClassName
102
+ });
103
+ const itemRow = (entry, rowProps) => /* @__PURE__ */ jsxs(Combobox.Item, {
104
+ value: entry,
105
+ disabled: entry.disabled,
106
+ ...rowProps.props,
107
+ className: itemClassName,
108
+ children: [/* @__PURE__ */ jsx(ItemContent, { entry }), /* @__PURE__ */ jsx(Combobox.ItemIndicator, {
109
+ className: "ml-auto flex shrink-0 items-center",
110
+ children: /* @__PURE__ */ jsx(FaCheck, { className: "size-3.5" })
111
+ })]
112
+ }, rowProps.key);
113
+ const parts = trigger ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Tooltip, {
114
+ content: triggerTooltip,
115
+ children: /* @__PURE__ */ jsx(Combobox.Trigger, {
116
+ id,
117
+ "aria-label": ariaLabel || void 0,
118
+ "aria-labelledby": ariaLabelledBy,
119
+ "aria-describedby": ariaDescribedBy,
120
+ "aria-invalid": ariaInvalid || void 0,
121
+ render: trigger
122
+ })
123
+ }), /* @__PURE__ */ jsx(ListPopup, {
124
+ listRef: list,
125
+ empty: t.noOptionsFound,
126
+ statusGroups: entries.statusGroups,
127
+ query: inputValue ?? "",
128
+ header: /* @__PURE__ */ jsx("div", {
129
+ className: "border-b border-(--theme-border) p-1.5",
130
+ children: input
131
+ }),
132
+ className: "w-max min-w-(--anchor-width) max-w-[min(28rem,var(--available-width))]",
133
+ renderItem: itemRow
134
+ })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Combobox.InputGroup, {
135
+ "data-testid": "combobox",
136
+ className: clsx(fieldClassName, className),
137
+ children: [props.multiple ? /* @__PURE__ */ jsxs(Combobox.Chips, {
138
+ className: "flex min-w-0 flex-1 flex-wrap items-center gap-1 py-1 pl-1",
139
+ children: [/* @__PURE__ */ jsx(Combobox.Value, { children: (values) => values.map((entry) => /* @__PURE__ */ jsxs(Combobox.Chip, {
140
+ "aria-label": entry.label,
141
+ className: "flex items-center gap-1 rounded bg-(--theme-muted-panel-bg) py-0.5 pr-0.5 pl-1.5 text-xs outline-none data-highlighted:bg-(--theme-hover)",
142
+ children: [entry.label, /* @__PURE__ */ jsx(Combobox.ChipRemove, {
143
+ "aria-label": `${strings.common.remove} ${entry.label}`,
144
+ className: "flex size-4 items-center justify-center rounded hover:bg-(--theme-hover)",
145
+ children: /* @__PURE__ */ jsx(FiX, { className: "size-3" })
146
+ })]
147
+ }, entry.label)) }), input]
148
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [selectedIcon && /* @__PURE__ */ jsx("span", {
149
+ className: "flex shrink-0 items-center pl-3",
150
+ children: selectedIcon
151
+ }), input] }), /* @__PURE__ */ jsx(Combobox.Trigger, {
152
+ "aria-label": t.showOptions,
153
+ "data-testid": "combobox-button",
154
+ className: triggerClassName,
155
+ children: /* @__PURE__ */ jsx(FaCaretDown, { className: "size-3" })
156
+ })]
157
+ }), /* @__PURE__ */ jsx(ListPopup, {
158
+ listRef: list,
159
+ empty: t.noOptionsFound,
160
+ statusGroups: entries.statusGroups,
161
+ query: inputValue ?? "",
162
+ renderItem: itemRow
163
+ })] });
164
+ const root = {
165
+ items: entries.items,
166
+ filter,
167
+ isItemEqualToValue: (a, b) => isItemEqualToValue(a.value, b.value),
168
+ itemToStringLabel: entryLabel,
169
+ onInputValueChange: setInputValue,
170
+ onItemHighlighted: (_, { index, reason }) => list.current?.reveal(index, reason),
171
+ disabled,
172
+ required,
173
+ virtualized: true,
174
+ children: parts
175
+ };
176
+ return props.multiple ? /* @__PURE__ */ jsx(Combobox.Root, {
177
+ ...root,
178
+ multiple: true,
179
+ value: toEntries(props.value),
180
+ defaultValue: toEntries(props.defaultValue),
181
+ onValueChange: (next) => props.onValueChange?.(next.map((entry) => entry.value))
182
+ }) : /* @__PURE__ */ jsx(Combobox.Root, {
183
+ ...root,
184
+ value: selected,
185
+ defaultValue: toSingle(props.defaultValue),
186
+ onValueChange: (next) => props.onValueChange?.(next?.value ?? null)
187
+ });
188
+ }
189
+ /** A free-text field that suggests values as you type. */
190
+ function Autocomplete$1({ items, value, defaultValue, onValueChange, className, placeholder, disabled, required, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid }) {
191
+ const entries = useEntries(items);
192
+ const filter = useEntryFilter();
193
+ const t = useStrings().dropdown;
194
+ const list = useRef(null);
195
+ return /* @__PURE__ */ jsxs(Autocomplete.Root, {
196
+ items: entries.items,
197
+ filter,
198
+ itemToStringValue: (entry) => entry.value,
199
+ value,
200
+ defaultValue,
201
+ onValueChange: (next) => onValueChange?.(next),
202
+ onItemHighlighted: (_, { index, reason }) => list.current?.reveal(index, reason),
203
+ disabled,
204
+ required,
205
+ virtualized: true,
206
+ children: [/* @__PURE__ */ jsxs(Autocomplete.InputGroup, {
207
+ "data-testid": "combobox",
208
+ className: clsx(fieldClassName, className),
209
+ children: [/* @__PURE__ */ jsx(Autocomplete.Input, {
210
+ id,
211
+ placeholder,
212
+ "aria-label": ariaLabel || void 0,
213
+ "aria-labelledby": ariaLabelledBy,
214
+ "aria-describedby": ariaDescribedBy,
215
+ "aria-invalid": ariaInvalid || void 0,
216
+ autoComplete: "off",
217
+ className: inputClassName
218
+ }), entries.flat.length > 0 && /* @__PURE__ */ jsx(Autocomplete.Trigger, {
219
+ "aria-label": t.showOptions,
220
+ "data-testid": "combobox-button",
221
+ className: triggerClassName,
222
+ children: /* @__PURE__ */ jsx(FaCaretDown, { className: "size-3" })
223
+ })]
224
+ }), /* @__PURE__ */ jsx(ListPopup, {
225
+ listRef: list,
226
+ renderItem: (entry, rowProps) => /* @__PURE__ */ jsx(Autocomplete.Item, {
227
+ value: entry,
228
+ disabled: entry.disabled,
229
+ ...rowProps.props,
230
+ className: itemClassName,
231
+ children: /* @__PURE__ */ jsx(ItemContent, { entry })
232
+ }, rowProps.key)
233
+ })]
234
+ });
235
+ }
236
+ var itemClassName = clsx(panelItemClassName, "data-selected:font-medium");
237
+ function ItemContent({ entry }) {
238
+ return /* @__PURE__ */ jsxs(Fragment, { children: [entry.icon && /* @__PURE__ */ jsx("span", {
239
+ className: "flex shrink-0 items-center",
240
+ children: entry.icon
241
+ }), /* @__PURE__ */ jsxs("span", {
242
+ className: "flex min-w-0 flex-col",
243
+ children: [/* @__PURE__ */ jsx(Tooltip, {
244
+ content: entry.label,
245
+ overflowOnly: true,
246
+ children: /* @__PURE__ */ jsx("span", {
247
+ className: "truncate",
248
+ children: entry.label
249
+ })
250
+ }), entry.description && /* @__PURE__ */ jsx("span", {
251
+ className: "text-xs leading-snug text-(--theme-muted-text-color)",
252
+ children: entry.description
253
+ })]
254
+ })] });
255
+ }
256
+ function GroupHeading({ group }) {
257
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
258
+ group.icon && /* @__PURE__ */ jsx("span", {
259
+ className: "flex shrink-0 items-center",
260
+ children: group.icon
261
+ }),
262
+ /* @__PURE__ */ jsx("span", {
263
+ className: "shrink-0 font-semibold",
264
+ children: group.label
265
+ }),
266
+ group.description && /* @__PURE__ */ jsx(Tooltip, {
267
+ content: group.description,
268
+ overflowOnly: true,
269
+ children: /* @__PURE__ */ jsxs("span", {
270
+ className: "min-w-0 truncate",
271
+ children: ["· ", group.description]
272
+ })
273
+ })
274
+ ] });
275
+ }
276
+ /** Portal, positioner and popup shared by Combobox and Autocomplete; both use the same parts. */
277
+ function ListPopup({ listRef, empty, statusGroups = [], query = "", header, className = "w-(--anchor-width) max-w-(--available-width)", renderItem }) {
278
+ return /* @__PURE__ */ jsx(Combobox.Portal, {
279
+ container: portalContainer(),
280
+ children: /* @__PURE__ */ jsx(Combobox.Positioner, {
281
+ align: "start",
282
+ sideOffset: 4,
283
+ className: positionerClassName,
284
+ children: /* @__PURE__ */ jsxs(Combobox.Popup, {
285
+ className: clsx("overflow-hidden", className, panelClassName),
286
+ children: [
287
+ header,
288
+ empty && statusGroups.length === 0 && /* @__PURE__ */ jsx(Combobox.Empty, {
289
+ className: "px-3 py-2 text-(--theme-muted-text-color) empty:hidden",
290
+ children: empty
291
+ }),
292
+ /* @__PURE__ */ jsx(Combobox.List, { children: /* @__PURE__ */ jsx(VirtualList, {
293
+ ref: listRef,
294
+ statusGroups,
295
+ query,
296
+ renderItem
297
+ }) })
298
+ ]
299
+ })
300
+ })
301
+ });
302
+ }
303
+ function toRows(filtered, statusGroups) {
304
+ const nodes = statusGroups.length ? [...filtered, ...statusGroups].sort((a, b) => ("order" in a ? a.order : 0) - ("order" in b ? b.order : 0)) : filtered;
305
+ const rows = [];
306
+ const rowOfItem = [];
307
+ for (const node of nodes) {
308
+ const leaves = "items" in node ? node.items : [node];
309
+ if ("items" in node && !node.headless) rows.push({
310
+ kind: "group",
311
+ group: node
312
+ });
313
+ for (const entry of leaves) {
314
+ rowOfItem.push(rows.length);
315
+ rows.push({
316
+ kind: "item",
317
+ entry,
318
+ index: rowOfItem.length - 1
319
+ });
320
+ }
321
+ }
322
+ return {
323
+ rows,
324
+ rowOfItem
325
+ };
326
+ }
327
+ function VirtualList({ ref, statusGroups, query, renderItem }) {
328
+ const filtered = Combobox.useFilteredItems();
329
+ const match = useQueryMatch();
330
+ const { rows, rowOfItem } = useMemo(() => {
331
+ const q = query.trim();
332
+ const shown = q ? statusGroups.filter((g) => match(q, g.label, g.description)) : statusGroups;
333
+ return toRows(filtered, shown);
334
+ }, [
335
+ filtered,
336
+ statusGroups,
337
+ query,
338
+ match
339
+ ]);
340
+ const scroller = useRef(null);
341
+ const virtualizer = useVirtualizer({
342
+ count: rows.length,
343
+ getScrollElement: () => scroller.current,
344
+ estimateSize: (i) => rows[i]?.kind === "group" ? 28 : 36,
345
+ overscan: 10,
346
+ paddingStart: 4,
347
+ paddingEnd: 4,
348
+ scrollPaddingStart: 4,
349
+ scrollPaddingEnd: 4
350
+ });
351
+ useImperativeHandle(ref, () => ({ reveal(index, reason) {
352
+ const row = index === void 0 ? void 0 : rowOfItem[index];
353
+ if (row === void 0 || reason === "pointer") return;
354
+ queueMicrotask(() => virtualizer.scrollToIndex(row, { align: "auto" }));
355
+ } }), [rowOfItem, virtualizer]);
356
+ const scrollerRef = useCallback((element) => {
357
+ scroller.current = element;
358
+ if (element) virtualizer.measure();
359
+ }, [virtualizer]);
360
+ if (rows.length === 0) return null;
361
+ const total = virtualizer.getTotalSize();
362
+ return /* @__PURE__ */ jsx("div", {
363
+ role: "presentation",
364
+ ref: scrollerRef,
365
+ className: "max-h-[min(15rem,var(--available-height))] overflow-auto overscroll-contain",
366
+ style: { height: total },
367
+ children: /* @__PURE__ */ jsx("div", {
368
+ role: "presentation",
369
+ className: "relative w-full",
370
+ style: { height: total },
371
+ children: virtualizer.getVirtualItems().map((virtual) => {
372
+ const row = rows[virtual.index];
373
+ const style = {
374
+ position: "absolute",
375
+ top: 0,
376
+ left: 0,
377
+ width: "100%",
378
+ transform: `translateY(${virtual.start}px)`
379
+ };
380
+ if (!row) return null;
381
+ if (row.kind === "group") return /* @__PURE__ */ jsx("div", {
382
+ role: "presentation",
383
+ "data-index": virtual.index,
384
+ ref: virtualizer.measureElement,
385
+ style,
386
+ className: "flex items-center gap-1.5 px-3 pt-2 pb-1 text-xs text-(--theme-muted-text-color)",
387
+ children: /* @__PURE__ */ jsx(GroupHeading, { group: row.group })
388
+ }, virtual.key);
389
+ return renderItem(row.entry, {
390
+ key: virtual.key,
391
+ props: {
392
+ index: row.index,
393
+ ref: virtualizer.measureElement,
394
+ "data-index": virtual.index,
395
+ "aria-setsize": rowOfItem.length,
396
+ "aria-posinset": row.index + 1,
397
+ style
398
+ }
399
+ });
400
+ })
401
+ })
402
+ });
403
+ }
404
+ //#endregion
405
+ export { Autocomplete$1 as Autocomplete, Combobox$1 as Combobox };
@@ -1,9 +1,9 @@
1
1
  import { useStrings } from "./Provider.js";
2
- import { BareModal, modalPanelClasses } from "./BareModal.js";
3
2
  import { dangerButtonClasses, ghostButtonClasses, primaryButtonClasses } from "./ghostButton.js";
4
- import cx from "classnames";
5
- import { useCallback, useEffect, useRef, useState } from "react";
3
+ import { Modal, ModalDescription, ModalTitle } from "./Modal.js";
4
+ import { clsx } from "clsx";
6
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { useCallback, useEffect, useRef, useState } from "react";
7
7
  //#region src/components/ConfirmModal.tsx
8
8
  function ConfirmModal({ open, onClose, title, description, children, confirmLabel, onConfirm, confirmDisabled = false, destructive = false, align = "top", cancelLabel, closeOnConfirm = true }) {
9
9
  const strings = useStrings();
@@ -29,21 +29,21 @@ function ConfirmModal({ open, onClose, title, description, children, confirmLabe
29
29
  setPending(false);
30
30
  }
31
31
  }, [onConfirm, closeOnConfirm]);
32
- return /* @__PURE__ */ jsxs(BareModal, {
32
+ return /* @__PURE__ */ jsxs(Modal, {
33
+ alert: destructive,
33
34
  open,
34
35
  onClose,
35
- ariaLabel: title,
36
36
  align,
37
- preventClose: pending,
38
- className: cx(modalPanelClasses, "w-[480px] max-w-full"),
37
+ dismissible: !pending,
38
+ className: "w-[480px] max-w-full",
39
39
  children: [/* @__PURE__ */ jsxs("div", {
40
40
  className: "px-5 pt-5",
41
41
  children: [
42
- /* @__PURE__ */ jsx("h2", {
42
+ /* @__PURE__ */ jsx(ModalTitle, {
43
43
  className: "text-lg font-semibold text-(--theme-app)",
44
44
  children: title
45
45
  }),
46
- description !== null && description !== void 0 && /* @__PURE__ */ jsx("p", {
46
+ description !== null && description !== void 0 && /* @__PURE__ */ jsx(ModalDescription, {
47
47
  className: "mt-1.5 text-sm text-(--theme-muted-text-color)",
48
48
  children: description
49
49
  }),
@@ -58,13 +58,13 @@ function ConfirmModal({ open, onClose, title, description, children, confirmLabe
58
58
  type: "button",
59
59
  onClick: onClose,
60
60
  disabled: pending,
61
- className: cx(ghostButtonClasses, pending && "cursor-wait"),
61
+ className: clsx(ghostButtonClasses, pending && "cursor-wait"),
62
62
  children: cancelLabel ?? strings.modal.cancel
63
63
  }), /* @__PURE__ */ jsx("button", {
64
64
  type: "button",
65
65
  onClick: runConfirm,
66
66
  disabled: confirmDisabled || pending,
67
- className: cx(destructive ? dangerButtonClasses : primaryButtonClasses, "disabled:cursor-not-allowed disabled:opacity-50", pending && "cursor-wait"),
67
+ className: clsx(destructive ? dangerButtonClasses : primaryButtonClasses, "disabled:cursor-not-allowed disabled:opacity-50", pending && "cursor-wait"),
68
68
  children: confirmLabel
69
69
  })]
70
70
  })]