@parallelworks/ui 0.41.0 → 0.42.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 (280) 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 +66 -0
  58. package/dist/components/Combobox.js +393 -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 +17 -36
  64. package/dist/components/CreateModal.js +97 -259
  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/floating.d.ts +14 -0
  112. package/dist/components/floating.js +21 -0
  113. package/dist/components/search.d.ts +2 -0
  114. package/dist/components/search.js +14 -0
  115. package/dist/editor/Editor.js +1 -1
  116. package/dist/editor/EditorField.js +16 -21
  117. package/dist/editor/FormCodePanel.js +19 -19
  118. package/dist/editor/Monaco.js +3 -3
  119. package/dist/file-explorer/FileExplorer.js +77 -81
  120. package/dist/file-explorer/FileExplorerContext.js +2 -2
  121. package/dist/file-explorer/FilePreview/CodePreviewEditor.js +1 -1
  122. package/dist/file-explorer/FilePreview/Inline.js +1 -1
  123. package/dist/file-explorer/FilePreview/StreamedBadge.js +5 -6
  124. package/dist/file-explorer/FilePreview/Viewer.js +8 -8
  125. package/dist/file-explorer/FilePreview/index.d.ts +1 -1
  126. package/dist/file-explorer/FilePreview/index.js +49 -83
  127. package/dist/file-explorer/FileRow.d.ts +4 -3
  128. package/dist/file-explorer/FileRow.js +32 -38
  129. package/dist/file-explorer/FileRowsWindow.d.ts +3 -2
  130. package/dist/file-explorer/FileRowsWindow.js +4 -4
  131. package/dist/file-explorer/FileTable.d.ts +3 -2
  132. package/dist/file-explorer/FileTable.js +3 -3
  133. package/dist/file-explorer/LoadMoreRow.js +1 -1
  134. package/dist/file-explorer/TreeView.js +11 -16
  135. package/dist/file-explorer/helpers.js +11 -12
  136. package/dist/file-explorer/toasts.js +11 -11
  137. package/dist/form/FieldGroup.d.ts +11 -0
  138. package/dist/form/FieldGroup.js +36 -0
  139. package/dist/form/FieldWrapper.js +4 -4
  140. package/dist/form/Fields/BooleanField.js +23 -33
  141. package/dist/form/Fields/CheckboxGroupField.d.ts +1 -1
  142. package/dist/form/Fields/CheckboxGroupField.js +9 -13
  143. package/dist/form/Fields/ColorField.d.ts +1 -2
  144. package/dist/form/Fields/ColorField.js +6 -11
  145. package/dist/form/Fields/DropdownField.d.ts +3 -13
  146. package/dist/form/Fields/DropdownField.js +40 -27
  147. package/dist/form/Fields/DurationField.d.ts +1 -2
  148. package/dist/form/Fields/DurationField.js +25 -32
  149. package/dist/form/Fields/LabelField.js +2 -2
  150. package/dist/form/Fields/MultiDropdownField.d.ts +6 -12
  151. package/dist/form/Fields/MultiDropdownField.js +31 -22
  152. package/dist/form/Fields/NumberField.d.ts +1 -1
  153. package/dist/form/Fields/NumberField.js +65 -35
  154. package/dist/form/Fields/ObjectField.d.ts +1 -1
  155. package/dist/form/Fields/ObjectField.js +12 -43
  156. package/dist/form/Fields/RadioField.d.ts +1 -1
  157. package/dist/form/Fields/RadioField.js +30 -41
  158. package/dist/form/Fields/RangeField.d.ts +1 -2
  159. package/dist/form/Fields/RangeField.js +23 -16
  160. package/dist/form/Fields/StringField.d.ts +1 -2
  161. package/dist/form/Fields/StringField.js +58 -26
  162. package/dist/form/Fields/TextAreaField.js +12 -10
  163. package/dist/form/Form.d.ts +30 -48
  164. package/dist/form/Form.js +306 -412
  165. package/dist/form/FormLayout.js +9 -9
  166. package/dist/form/Wizard/WizardContainer.d.ts +1 -4
  167. package/dist/form/Wizard/WizardContainer.js +40 -56
  168. package/dist/form/Wizard/WizardNavigation.js +1 -1
  169. package/dist/form/Wizard/WizardStepContent.d.ts +1 -5
  170. package/dist/form/Wizard/WizardStepContent.js +11 -16
  171. package/dist/form/Wizard/WizardStepIndicator.js +6 -6
  172. package/dist/form/Wizard/types.d.ts +0 -14
  173. package/dist/form/fieldRegistry.d.ts +1 -1
  174. package/dist/form/fieldRegistry.js +6 -6
  175. package/dist/form/formEditing.js +1 -1
  176. package/dist/form/index.d.ts +5 -4
  177. package/dist/form/index.js +6 -7
  178. package/dist/form/types/fieldComponentTypes.d.ts +8 -10
  179. package/dist/form/useChoiceField.d.ts +20 -0
  180. package/dist/form/useChoiceField.js +49 -0
  181. package/dist/form/useFieldValue.d.ts +7 -0
  182. package/dist/form/useFieldValue.js +20 -0
  183. package/dist/form/useParsedOpts.d.ts +3 -1
  184. package/dist/form/useParsedOpts.js +12 -17
  185. package/dist/form/utils/dependentOptions.d.ts +8 -4
  186. package/dist/form/utils/dependentOptions.js +25 -17
  187. package/dist/form/utils/fieldItems.d.ts +10 -0
  188. package/dist/form/utils/fieldItems.js +11 -0
  189. package/dist/form/utils/fieldPath.d.ts +10 -0
  190. package/dist/form/utils/fieldPath.js +20 -0
  191. package/dist/form/utils/shareEqual.d.ts +6 -0
  192. package/dist/form/utils/shareEqual.js +38 -0
  193. package/dist/graph/AnnotationBanner.js +8 -8
  194. package/dist/graph/Collapse.d.ts +1 -0
  195. package/dist/graph/Collapse.js +6 -27
  196. package/dist/graph/Connectors.js +5 -5
  197. package/dist/graph/DependencyGraph.js +20 -19
  198. package/dist/graph/GraphEditor.js +30 -41
  199. package/dist/graph/GraphEditorDialogs.js +17 -17
  200. package/dist/graph/GraphNode.js +1 -1
  201. package/dist/graph/InputDialog.js +19 -22
  202. package/dist/graph/InputsEditor.js +58 -66
  203. package/dist/graph/JobSummary.js +42 -39
  204. package/dist/graph/MatrixGroup.js +1 -1
  205. package/dist/graph/ProblemsButton.js +18 -19
  206. package/dist/graph/Reveal.js +1 -1
  207. package/dist/graph/ShortcutsButton.js +15 -18
  208. package/dist/graph/SuggestionInput.d.ts +5 -10
  209. package/dist/graph/SuggestionInput.js +14 -18
  210. package/dist/graph/ToolbarPopover.d.ts +11 -6
  211. package/dist/graph/ToolbarPopover.js +35 -67
  212. package/dist/graph/TreeView.js +24 -37
  213. package/dist/graph/WorkflowSettingsDialog.js +4 -4
  214. package/dist/graph/editorChrome.js +13 -12
  215. package/dist/graph/editorFields.js +29 -29
  216. package/dist/graph/editorPrimitives.d.ts +1 -1
  217. package/dist/graph/editorPrimitives.js +10 -7
  218. package/dist/graph/editorRows.js +103 -97
  219. package/dist/graph/fieldProblems.js +2 -2
  220. package/dist/graph/graphEditorState.d.ts +4 -3
  221. package/dist/graph/inputRefs.js +9 -9
  222. package/dist/graph/settingsViews.js +6 -7
  223. package/dist/graph/stepWith.js +6 -6
  224. package/dist/index.d.ts +14 -15
  225. package/dist/index.js +15 -14
  226. package/dist/list/ActionToolbar.d.ts +6 -14
  227. package/dist/list/ActionToolbar.js +48 -96
  228. package/dist/list/ListPage.d.ts +6 -12
  229. package/dist/list/ListPage.js +46 -29
  230. package/dist/list/ListPager.js +4 -4
  231. package/dist/list/ListTable.js +5 -5
  232. package/dist/list/ListViewControls.d.ts +5 -4
  233. package/dist/list/ListViewControls.js +177 -267
  234. package/dist/list/UserHoverCard.d.ts +3 -17
  235. package/dist/list/UserHoverCard.js +21 -45
  236. package/dist/list/index.d.ts +3 -4
  237. package/dist/list/index.js +3 -4
  238. package/dist/list/listSearch.js +12 -11
  239. package/dist/list/rowMenu.d.ts +63 -0
  240. package/dist/list/rowMenu.js +134 -0
  241. package/dist/logviewer/LogViewer.js +26 -26
  242. package/dist/styles.css +1 -1
  243. package/package.json +7 -13
  244. package/dist/ai/ui/Dropdown.d.ts +0 -31
  245. package/dist/ai/ui/Dropdown.js +0 -110
  246. package/dist/components/AddMenu.d.ts +0 -18
  247. package/dist/components/AddMenu.js +0 -46
  248. package/dist/components/BareModal.d.ts +0 -17
  249. package/dist/components/BareModal.js +0 -77
  250. package/dist/components/CollapsiblePanel.d.ts +0 -27
  251. package/dist/components/CollapsiblePanel.js +0 -77
  252. package/dist/components/Dropdown.d.ts +0 -28
  253. package/dist/components/Dropdown.js +0 -355
  254. package/dist/components/Listbox.d.ts +0 -21
  255. package/dist/components/Listbox.js +0 -119
  256. package/dist/components/MultiSelect.d.ts +0 -22
  257. package/dist/components/MultiSelect.js +0 -168
  258. package/dist/components/SwitchToggle.d.ts +0 -15
  259. package/dist/components/SwitchToggle.js +0 -57
  260. package/dist/components/SwitchToggleSmall.d.ts +0 -6
  261. package/dist/components/SwitchToggleSmall.js +0 -14
  262. package/dist/components/Toggle.d.ts +0 -6
  263. package/dist/components/Toggle.js +0 -20
  264. package/dist/components/dropdownUtils.d.ts +0 -37
  265. package/dist/components/dropdownUtils.js +0 -99
  266. package/dist/form/SpecialTypes/DropdownWrapper.d.ts +0 -25
  267. package/dist/form/SpecialTypes/DropdownWrapper.js +0 -28
  268. package/dist/form/SpecialTypes/FormikCustomDropdown.d.ts +0 -51
  269. package/dist/form/SpecialTypes/FormikCustomDropdown.js +0 -119
  270. package/dist/form/SpecialTypes/FormikCustomInput.d.ts +0 -19
  271. package/dist/form/SpecialTypes/FormikCustomInput.js +0 -121
  272. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.d.ts +0 -13
  273. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +0 -31
  274. package/dist/form/SpecialTypes/FormikNumericInput.d.ts +0 -9
  275. package/dist/form/SpecialTypes/FormikNumericInput.js +0 -60
  276. package/dist/form/SpecialTypes/index.d.ts +0 -3
  277. package/dist/list/HoverCard.d.ts +0 -24
  278. package/dist/list/HoverCard.js +0 -73
  279. package/dist/list/RowContextMenu.d.ts +0 -127
  280. package/dist/list/RowContextMenu.js +0 -515
@@ -0,0 +1,78 @@
1
+ import { FaAngleDown } from "../icons/fa/FaAngleDown.js";
2
+ import { FaCheck } from "../icons/fa/FaCheck.js";
3
+ import { panelClassName, panelItemClassName, portalContainer, positionerClassName } from "./floating.js";
4
+ import { Tooltip } from "./Tooltip.js";
5
+ import { clsx } from "clsx";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { Select } from "@base-ui/react/select";
8
+ //#region src/components/Select.tsx
9
+ var triggerClassName = clsx("flex w-full items-center justify-between gap-2 rounded-md border border-(--theme-border) bg-(--theme-input-bg) py-2 pl-3 pr-2 text-left text-sm text-(--theme-app) cursor-pointer outline-none", "focus-visible:border-(--theme-element) focus-visible:ring-1 focus-visible:ring-(--theme-element)", "aria-invalid:border-(--theme-error) data-disabled:cursor-not-allowed data-disabled:bg-(--theme-input-disabled-bg) data-disabled:text-(--theme-input-disabled-text)");
10
+ /** Picks one value, or several with `multiple`, from a short list. Use
11
+ * Combobox when the list is long enough to need filtering. */
12
+ function Select$1({ items, placeholder, className, "aria-label": ariaLabel, "aria-describedby": describedBy, "aria-invalid": invalid, trigger, triggerTooltip, ...rootProps }) {
13
+ const labelOf = (value) => items.find((item) => Object.is(item.value, value))?.label;
14
+ const triggerProps = {
15
+ "aria-label": ariaLabel,
16
+ "aria-describedby": describedBy,
17
+ "aria-invalid": invalid || void 0
18
+ };
19
+ return /* @__PURE__ */ jsxs(Select.Root, {
20
+ items,
21
+ ...rootProps,
22
+ children: [trigger ? /* @__PURE__ */ jsx(Tooltip, {
23
+ content: triggerTooltip,
24
+ children: /* @__PURE__ */ jsx(Select.Trigger, {
25
+ ...triggerProps,
26
+ render: trigger
27
+ })
28
+ }) : /* @__PURE__ */ jsxs(Select.Trigger, {
29
+ ...triggerProps,
30
+ className: clsx(triggerClassName, className),
31
+ children: [/* @__PURE__ */ jsx(Select.Value, {
32
+ placeholder,
33
+ className: "truncate data-placeholder:text-(--theme-muted-text-color)",
34
+ children: rootProps.multiple ? (values) => values.length > 0 ? values.map(labelOf).join(", ") : placeholder : void 0
35
+ }), /* @__PURE__ */ jsx(Select.Icon, {
36
+ className: "shrink-0 text-(--theme-muted-text-color)",
37
+ children: /* @__PURE__ */ jsx(FaAngleDown, { "aria-hidden": "true" })
38
+ })]
39
+ }), /* @__PURE__ */ jsx(Select.Portal, {
40
+ container: portalContainer(),
41
+ children: /* @__PURE__ */ jsx(Select.Positioner, {
42
+ alignItemWithTrigger: false,
43
+ sideOffset: 4,
44
+ className: positionerClassName,
45
+ children: /* @__PURE__ */ jsx(Select.Popup, {
46
+ className: clsx("min-w-(--anchor-width) max-w-[min(20rem,var(--available-width))]", panelClassName),
47
+ children: /* @__PURE__ */ jsx(Select.List, {
48
+ className: "max-h-[min(15rem,var(--available-height))] overflow-y-auto py-1",
49
+ children: items.map((item) => /* @__PURE__ */ jsxs(Select.Item, {
50
+ value: item.value,
51
+ disabled: item.disabled,
52
+ className: clsx("grid grid-cols-[1rem_1fr]", panelItemClassName),
53
+ children: [
54
+ /* @__PURE__ */ jsx(Select.ItemIndicator, {
55
+ className: "col-start-1",
56
+ children: /* @__PURE__ */ jsx(FaCheck, { className: "size-3.5" })
57
+ }),
58
+ /* @__PURE__ */ jsxs("span", {
59
+ className: "col-start-2 flex min-w-0 items-center gap-2",
60
+ children: [item.icon, /* @__PURE__ */ jsx(Select.ItemText, {
61
+ className: "truncate",
62
+ children: item.label
63
+ })]
64
+ }),
65
+ item.description && /* @__PURE__ */ jsx("span", {
66
+ className: "col-start-2 text-xs text-(--theme-muted-text-color)",
67
+ children: item.description
68
+ })
69
+ ]
70
+ }, String(item.value)))
71
+ })
72
+ })
73
+ })
74
+ })]
75
+ });
76
+ }
77
+ //#endregion
78
+ export { Select$1 as Select };
@@ -1,11 +1,8 @@
1
- /** A labeled + described radio option row, used inside a SettingsCard to pick
2
- * between modes (e.g. default vs custom). Stacked rows share the card's
3
- * dividers via `isFirst`. */
4
- export declare function SettingModeOption({ name, checked, onSelect, label, description, isFirst, disabled, }: {
5
- /** Radio group name; shared across the options of one picker. */
6
- name: string;
7
- checked: boolean;
8
- onSelect: () => void;
1
+ /** A labeled + described choice in a SettingsCard, picking between modes (e.g.
2
+ * default vs custom). Stack them in a `RadioGroup`, which holds the value;
3
+ * stacked rows share the card's dividers via `isFirst`. */
4
+ export declare function SettingModeOption({ value, label, description, isFirst, disabled, }: {
5
+ value: string;
9
6
  label: string;
10
7
  description: string;
11
8
  isFirst?: boolean;
@@ -1,19 +1,17 @@
1
- import cx from "classnames";
1
+ import { Radio } from "./Radio.js";
2
+ import { clsx } from "clsx";
2
3
  import { jsx, jsxs } from "react/jsx-runtime";
3
4
  //#region src/components/SettingModeOption.tsx
4
- /** A labeled + described radio option row, used inside a SettingsCard to pick
5
- * between modes (e.g. default vs custom). Stacked rows share the card's
6
- * dividers via `isFirst`. */
7
- function SettingModeOption({ name, checked, onSelect, label, description, isFirst, disabled }) {
5
+ /** A labeled + described choice in a SettingsCard, picking between modes (e.g.
6
+ * default vs custom). Stack them in a `RadioGroup`, which holds the value;
7
+ * stacked rows share the card's dividers via `isFirst`. */
8
+ function SettingModeOption({ value, label, description, isFirst, disabled }) {
8
9
  return /* @__PURE__ */ jsxs("label", {
9
- className: cx("flex items-start gap-3 px-5 py-4", disabled ? "cursor-default opacity-60" : "cursor-pointer", !isFirst && "border-t theme-border"),
10
- children: [/* @__PURE__ */ jsx("input", {
11
- type: "radio",
12
- name,
13
- checked,
14
- onChange: onSelect,
10
+ className: clsx("flex items-start gap-3 px-5 py-4", disabled ? "cursor-default opacity-60" : "cursor-pointer", !isFirst && "border-t theme-border"),
11
+ children: [/* @__PURE__ */ jsx(Radio, {
12
+ value,
15
13
  disabled,
16
- className: "mt-0.5 w-4 h-4 theme-input shrink-0"
14
+ className: "mt-0.5"
17
15
  }), /* @__PURE__ */ jsxs("div", {
18
16
  className: "min-w-0",
19
17
  children: [/* @__PURE__ */ jsx("div", {
@@ -1,11 +1,11 @@
1
- import cx from "classnames";
1
+ import { clsx } from "clsx";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/components/SettingRow.tsx
4
4
  function SettingRow({ label, htmlFor, helpText, children, isFirst, fill, onClick }) {
5
5
  return /* @__PURE__ */ jsxs("div", {
6
6
  role: "none",
7
7
  onClick,
8
- className: cx("px-5 py-5 grid grid-cols-1 gap-x-8 gap-y-2", fill ? "md:grid-cols-[200px_1fr]" : "md:grid-cols-[1fr_auto]", !isFirst && "border-t theme-border", onClick && "cursor-pointer select-none hover:theme-hover transition-colors"),
8
+ className: clsx("px-5 py-5 grid grid-cols-1 gap-x-8 gap-y-2", fill ? "md:grid-cols-[200px_1fr]" : "md:grid-cols-[1fr_auto]", !isFirst && "border-t theme-border", onClick && "cursor-pointer select-none hover:theme-hover transition-colors"),
9
9
  children: [/* @__PURE__ */ jsxs("div", {
10
10
  className: "flex flex-col gap-y-1",
11
11
  children: [/* @__PURE__ */ jsx("label", {
@@ -17,14 +17,14 @@ function SettingRow({ label, htmlFor, helpText, children, isFirst, fill, onClick
17
17
  children: helpText
18
18
  })]
19
19
  }), /* @__PURE__ */ jsx("div", {
20
- className: cx("min-w-0", !fill && "flex items-center justify-end"),
20
+ className: clsx("min-w-0", !fill && "flex items-center justify-end"),
21
21
  children
22
22
  })]
23
23
  });
24
24
  }
25
25
  function SettingSection({ title, isFirst }) {
26
26
  return /* @__PURE__ */ jsx("div", {
27
- className: cx("px-5 py-3 theme-muted-panel", !isFirst && "border-t theme-border"),
27
+ className: clsx("px-5 py-3 theme-muted-panel", !isFirst && "border-t theme-border"),
28
28
  children: /* @__PURE__ */ jsx("h2", {
29
29
  className: "font-semibold text-sm uppercase tracking-wider theme-muted-text",
30
30
  children: title
@@ -1,4 +1,4 @@
1
- import cx from "classnames";
1
+ import { clsx } from "clsx";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/components/SettingsCard.tsx
4
4
  /**
@@ -8,11 +8,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
8
8
  */
9
9
  function SettingsCard({ title, description, action, actionAlign = "adjacent", overflowVisible, children, className }) {
10
10
  return /* @__PURE__ */ jsxs("section", {
11
- className: cx("mt-10 first:mt-0", className),
11
+ className: clsx("mt-10 first:mt-0", className),
12
12
  children: [(title || action) && /* @__PURE__ */ jsxs("div", {
13
13
  className: "mb-3 px-0.5",
14
14
  children: [/* @__PURE__ */ jsxs("div", {
15
- className: cx("flex items-center gap-1.5", actionAlign === "right" && "justify-between"),
15
+ className: clsx("flex items-center gap-1.5", actionAlign === "right" && "justify-between"),
16
16
  children: [title && /* @__PURE__ */ jsx("h2", {
17
17
  className: "text-[15px] font-semibold theme-text leading-none",
18
18
  children: title
@@ -22,7 +22,7 @@ function SettingsCard({ title, description, action, actionAlign = "adjacent", ov
22
22
  children: description
23
23
  })]
24
24
  }), /* @__PURE__ */ jsx("div", {
25
- className: cx("panel", overflowVisible ? "overflow-visible" : "overflow-hidden"),
25
+ className: clsx("panel", overflowVisible ? "overflow-visible" : "overflow-hidden"),
26
26
  children
27
27
  })]
28
28
  });
@@ -1,9 +1,9 @@
1
- import cx from "classnames";
1
+ import { clsx } from "clsx";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/components/SettingsGroup.tsx
4
4
  function SettingsGroup({ title, children, className }) {
5
5
  return /* @__PURE__ */ jsxs("div", {
6
- className: cx("mt-8 first:mt-0", className),
6
+ className: clsx("mt-8 first:mt-0", className),
7
7
  children: [title && /* @__PURE__ */ jsx("h2", {
8
8
  className: "text-[11px] font-semibold uppercase tracking-wider theme-muted-text mb-2 px-1",
9
9
  children: title
@@ -1,7 +1,7 @@
1
- import { useStrings } from "./Provider.js";
2
1
  import { TiArrowSortedDown } from "../icons/ti/TiArrowSortedDown.js";
3
2
  import { TiArrowSortedUp } from "../icons/ti/TiArrowSortedUp.js";
4
3
  import { TiArrowUnsorted } from "../icons/ti/TiArrowUnsorted.js";
4
+ import { useStrings } from "./Provider.js";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  //#region src/components/Sort.tsx
7
7
  var SortIcon = ({ currentlySorted, currentDirection, name }) => {
@@ -1,4 +1,4 @@
1
- import cx from "classnames";
1
+ import { clsx } from "clsx";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  //#region src/components/StatusBadge.tsx
4
4
  var variantStyles = {
@@ -32,26 +32,26 @@ function statusTextClass(variant) {
32
32
  }
33
33
  function StatusBadge({ children, variant = "default", pulse = false, dot = false, size = "sm", className }) {
34
34
  return /* @__PURE__ */ jsxs("span", {
35
- className: cx("inline-flex items-center gap-1.5 rounded-full border font-medium", size === "sm" && "px-2 py-0.5 text-[10px]", size === "md" && "px-2.5 py-1 text-xs", variantStyles[variant], className),
35
+ className: clsx("inline-flex items-center gap-1.5 rounded-full border font-medium", size === "sm" && "px-2 py-0.5 text-[10px]", size === "md" && "px-2.5 py-1 text-xs", variantStyles[variant], className),
36
36
  children: [
37
37
  pulse && /* @__PURE__ */ jsxs("span", {
38
38
  className: "relative flex h-2 w-2",
39
- children: [/* @__PURE__ */ jsx("span", { className: cx("absolute inline-flex h-full w-full animate-ping rounded-full opacity-75", pulseColors[variant]) }), /* @__PURE__ */ jsx("span", { className: cx("relative inline-flex h-2 w-2 rounded-full", pulseColors[variant]) })]
39
+ children: [/* @__PURE__ */ jsx("span", { className: clsx("absolute inline-flex h-full w-full animate-ping rounded-full opacity-75", pulseColors[variant]) }), /* @__PURE__ */ jsx("span", { className: clsx("relative inline-flex h-2 w-2 rounded-full", pulseColors[variant]) })]
40
40
  }),
41
- dot && !pulse && /* @__PURE__ */ jsx("span", { className: cx("inline-flex h-1.5 w-1.5 rounded-full", pulseColors[variant]) }),
41
+ dot && !pulse && /* @__PURE__ */ jsx("span", { className: clsx("inline-flex h-1.5 w-1.5 rounded-full", pulseColors[variant]) }),
42
42
  children
43
43
  ]
44
44
  });
45
45
  }
46
46
  function StatusDot({ variant = "default", pulse = false, size = 8, className }) {
47
47
  return /* @__PURE__ */ jsxs("span", {
48
- className: cx("relative inline-flex", className),
48
+ className: clsx("relative inline-flex", className),
49
49
  style: {
50
50
  width: size,
51
51
  height: size
52
52
  },
53
- children: [pulse && /* @__PURE__ */ jsx("span", { className: cx("absolute inline-flex h-full w-full animate-ping rounded-full opacity-75", pulseColors[variant]) }), /* @__PURE__ */ jsx("span", {
54
- className: cx("relative inline-flex rounded-full", pulseColors[variant]),
53
+ children: [pulse && /* @__PURE__ */ jsx("span", { className: clsx("absolute inline-flex h-full w-full animate-ping rounded-full opacity-75", pulseColors[variant]) }), /* @__PURE__ */ jsx("span", {
54
+ className: clsx("relative inline-flex rounded-full", pulseColors[variant]),
55
55
  style: {
56
56
  width: size,
57
57
  height: size
@@ -1,18 +1,18 @@
1
1
  import { BiError } from "../icons/bi/BiError.js";
2
2
  import { HiMiniCheckCircle } from "../icons/hi2/HiMiniCheckCircle.js";
3
3
  import { FaCircleNotch } from "../icons/fa/FaCircleNotch.js";
4
- import cx from "classnames";
4
+ import { clsx } from "clsx";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  //#region src/components/StatusIcons.tsx
7
7
  function SuccessCheckmark({ className, colored = true }) {
8
- return /* @__PURE__ */ jsx(HiMiniCheckCircle, { className: cx(colored && "text-green-500", className) });
8
+ return /* @__PURE__ */ jsx(HiMiniCheckCircle, { className: clsx(colored && "text-green-500", className) });
9
9
  }
10
10
  function ErrorCheckmark({ className, colored = true }) {
11
- return /* @__PURE__ */ jsx(BiError, { className: cx(colored && "text-red-400", className) });
11
+ return /* @__PURE__ */ jsx(BiError, { className: clsx(colored && "text-red-400", className) });
12
12
  }
13
13
  function LoaderIcon({ className, ...props }) {
14
14
  return /* @__PURE__ */ jsx(FaCircleNotch, {
15
- className: cx("animate-spin", className),
15
+ className: clsx("animate-spin", className),
16
16
  ...props
17
17
  });
18
18
  }
@@ -0,0 +1,22 @@
1
+ import { Switch as BaseSwitch } from '@base-ui/react/switch';
2
+ declare const sizes: {
3
+ sm: {
4
+ root: string;
5
+ thumb: string;
6
+ };
7
+ md: {
8
+ root: string;
9
+ thumb: string;
10
+ };
11
+ };
12
+ export interface SwitchProps extends Omit<BaseSwitch.Root.Props, 'className' | 'children'> {
13
+ size?: keyof typeof sizes;
14
+ className?: string | undefined;
15
+ }
16
+ /**
17
+ * An on/off control. Name it with an enclosing `<label>`, or `aria-label`. A
18
+ * sibling `<label htmlFor>` needs `nativeButton render={<button />}`, which
19
+ * puts the id on the button the label points at.
20
+ */
21
+ export declare function Switch({ size, className, ...props }: SwitchProps): import("react").JSX.Element;
22
+ export {};
@@ -0,0 +1,28 @@
1
+ import { clsx } from "clsx";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Switch } from "@base-ui/react/switch";
4
+ //#region src/components/Switch.tsx
5
+ var sizes = {
6
+ sm: {
7
+ root: "h-5 w-9",
8
+ thumb: "size-4 data-checked:translate-x-4"
9
+ },
10
+ md: {
11
+ root: "h-6 w-11",
12
+ thumb: "size-5 data-checked:translate-x-5"
13
+ }
14
+ };
15
+ /**
16
+ * An on/off control. Name it with an enclosing `<label>`, or `aria-label`. A
17
+ * sibling `<label htmlFor>` needs `nativeButton render={<button />}`, which
18
+ * puts the id on the button the label points at.
19
+ */
20
+ function Switch$1({ size = "md", className, ...props }) {
21
+ return /* @__PURE__ */ jsx(Switch.Root, {
22
+ ...props,
23
+ className: clsx("inline-flex shrink-0 items-center rounded-full p-0.5 bg-(--theme-border) transition-colors duration-200 cursor-pointer outline-none", "data-checked:bg-(--theme-element)", "focus-visible:ring-2 focus-visible:ring-(--theme-focus-ring) aria-invalid:ring-2 aria-invalid:ring-(--theme-error)", "data-disabled:cursor-not-allowed data-disabled:opacity-50", sizes[size].root, className),
24
+ children: /* @__PURE__ */ jsx(Switch.Thumb, { className: clsx("rounded-full bg-white shadow-sm transition-transform duration-200", sizes[size].thumb) })
25
+ });
26
+ }
27
+ //#endregion
28
+ export { Switch$1 as Switch };
@@ -1,8 +1,8 @@
1
1
  import { useStrings } from "./Provider.js";
2
2
  import Loader from "./Loader.js";
3
- import cx from "classnames";
4
- import React from "react";
3
+ import { clsx } from "clsx";
5
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
+ import React from "react";
6
6
  //#region src/components/Table.tsx
7
7
  function Item({ wrap = false, children, className, colspan = 1, ...tdProps }) {
8
8
  const yPadding = className?.includes("py-") ? "" : "py-4";
@@ -10,7 +10,7 @@ function Item({ wrap = false, children, className, colspan = 1, ...tdProps }) {
10
10
  return /* @__PURE__ */ jsx("td", {
11
11
  ...tdProps,
12
12
  colSpan: colspan,
13
- className: cx(yPadding, xPadding, wrap ? "" : "whitespace-nowrap", className),
13
+ className: clsx(yPadding, xPadding, wrap ? "" : "whitespace-nowrap", className),
14
14
  children
15
15
  });
16
16
  }
@@ -18,7 +18,7 @@ function CompactItem({ wrap = false, children, className, colspan = 1, ...tdProp
18
18
  return /* @__PURE__ */ jsx("td", {
19
19
  ...tdProps,
20
20
  colSpan: colspan,
21
- className: cx("px-2 text-sm font-medium", !wrap && "whitespace-nowrap", className),
21
+ className: clsx("px-2 text-sm font-medium", !wrap && "whitespace-nowrap", className),
22
22
  children
23
23
  });
24
24
  }
@@ -31,7 +31,7 @@ function Header({ children, className, style, colspan = 1, onClick, sort, caps =
31
31
  colSpan: colspan,
32
32
  style,
33
33
  "aria-sort": sort === "unsorted" ? "none" : sort,
34
- className: cx(className, yPadding, xPadding, textAlign, "text-xs font-medium", caps ? "uppercase tracking-wider" : ""),
34
+ className: clsx(className, yPadding, xPadding, textAlign, "text-xs font-medium", caps ? "uppercase tracking-wider" : ""),
35
35
  children: onClick ? /* @__PURE__ */ jsx("button", {
36
36
  type: "button",
37
37
  onClick,
@@ -52,7 +52,7 @@ function Table({ borderless = false, panel = true, className = "", wrapperClassN
52
52
  const hasOverflow = wrapperClassName.split(" ").some((cls) => cls.startsWith("overflow-"));
53
53
  return /* @__PURE__ */ jsx("div", {
54
54
  "aria-busy": isLoading,
55
- className: cx("flex flex-col w-full", !hasOverflow && "overflow-hidden", wrapperClassName),
55
+ className: clsx("flex flex-col w-full", !hasOverflow && "overflow-hidden", wrapperClassName),
56
56
  children: isLoading ? /* @__PURE__ */ jsxs("div", {
57
57
  role: "status",
58
58
  "aria-label": loading,
@@ -62,9 +62,9 @@ function Table({ borderless = false, panel = true, className = "", wrapperClassN
62
62
  children: loading
63
63
  })]
64
64
  }) : /* @__PURE__ */ jsx("div", {
65
- className: cx("align-middle inline-block min-w-full overflow-x-auto", panel && "theme-panel", !borderless && "border theme-border", rounded && "rounded-2xl", roundedBottom && "rounded-b-2xl", roundedTop && "rounded-t-2xl"),
65
+ className: clsx("align-middle inline-block min-w-full overflow-x-auto", panel && "theme-panel", !borderless && "border theme-border", rounded && "rounded-2xl", roundedBottom && "rounded-b-2xl", roundedTop && "rounded-t-2xl"),
66
66
  children: /* @__PURE__ */ jsxs("table", {
67
- className: cx(className, "min-w-full divide-y theme-border"),
67
+ className: clsx(className, "min-w-full divide-y theme-border"),
68
68
  ...tableProps,
69
69
  children: [/* @__PURE__ */ jsx("thead", {
70
70
  className: theadClassName,
@@ -82,11 +82,11 @@ function CompactTable({ wrapperClassName = "", className = "", tbodyClassName =
82
82
  const Headers = getHeaders(ChildrenArr);
83
83
  const hasOverflow = wrapperClassName.split(" ").some((cls) => cls.startsWith("overflow-"));
84
84
  return /* @__PURE__ */ jsx("div", {
85
- className: cx("flex flex-col w-full", !hasOverflow && "overflow-hidden", wrapperClassName),
85
+ className: clsx("flex flex-col w-full", !hasOverflow && "overflow-hidden", wrapperClassName),
86
86
  children: /* @__PURE__ */ jsx("div", {
87
- className: cx("theme-panel inline-block min-w-full align-middle overflow-x-auto", rounded && "rounded-2xl", roundedBottom && "rounded-b-2xl pb-1", roundedTop && "rounded-t-2xl"),
87
+ className: clsx("theme-panel inline-block min-w-full align-middle overflow-x-auto", rounded && "rounded-2xl", roundedBottom && "rounded-b-2xl pb-1", roundedTop && "rounded-t-2xl"),
88
88
  children: /* @__PURE__ */ jsxs("table", {
89
- className: cx("min-w-full divide-y theme-border", className),
89
+ className: clsx("min-w-full divide-y theme-border", className),
90
90
  children: [/* @__PURE__ */ jsx("thead", {
91
91
  className: "theme-muted-panel",
92
92
  children: /* @__PURE__ */ jsx("tr", {
@@ -1,21 +1,25 @@
1
- import { type PlacesType } from 'react-tooltip';
2
- export declare const TOOLTIP_ID = "global-tooltip";
3
- /** Anchor props that reveal `content` only while the text is ellipsized; `measure` picks the clipped descendant when it isn't the anchor. */
4
- export declare function truncationTooltipProps(content: string, measure?: (anchor: HTMLElement) => HTMLElement | null): {
5
- role: 'none';
6
- 'data-tooltip-id': string;
7
- onMouseEnter: (event: React.MouseEvent<HTMLElement>) => void;
8
- };
9
- /** Tooltip text can come from untrusted sources (workflow YAML), so all markup is literal text — only `[text](url)` links and newlines are parsed. */
10
- export declare function formatTooltipContent(content: React.ReactNode): number | bigint | true | import("react").JSX.Element[] | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | Iterable<import("react").ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | null;
11
- /** Singleton rendered at layout root; anchors opt in via data-tooltip-id={TOOLTIP_ID}, data-tooltip-content, and data-tooltip-shortcut. */
12
- export declare function GlobalTooltip(): import("react").JSX.Element;
13
- interface ITooltipInfo {
14
- text: string;
15
- className?: string | undefined;
16
- place?: PlacesType;
17
- children?: React.ReactNode;
18
- tabIndex?: number;
1
+ import { Tooltip as BaseTooltip } from '@base-ui/react/tooltip';
2
+ import { type ReactElement, type ReactNode } from 'react';
3
+ export type TooltipSide = 'top' | 'bottom' | 'left' | 'right';
4
+ /** One popup serves every Tooltip below it, so each anchor costs only a trigger.
5
+ * UIProvider mounts it; nothing else needs to. */
6
+ export declare function TooltipProvider({ children }: {
7
+ children: ReactNode;
8
+ }): import("react").JSX.Element;
9
+ /** Props beyond the tooltip's own go to the anchor, so a Tooltip can be another
10
+ * trigger's render target, such as a popover button with a hint. */
11
+ export interface TooltipProps extends Omit<BaseTooltip.Trigger.Props, 'content' | 'children' | 'render' | 'handle' | 'payload'> {
12
+ /** Nothing to show disables the tooltip. Newlines in a string break lines. */
13
+ content: ReactNode;
14
+ /** The anchor. It receives the trigger's props and ref, so it must pass them to its element. */
15
+ children: ReactElement;
16
+ side?: TooltipSide;
17
+ /** Keys shown beside the content, joined with +, such as ⌘+F. */
18
+ shortcut?: string | undefined;
19
+ disabled?: boolean | undefined;
20
+ /** Opens only while the anchor's text is clipped, such as a truncated label. */
21
+ overflowOnly?: boolean;
19
22
  }
20
- export declare function TooltipInfo({ text, className, children, place, tabIndex, }: ITooltipInfo): import("react").JSX.Element;
21
- export {};
23
+ /** A visual hint for sighted pointer and keyboard users. The anchor still needs
24
+ * its own accessible name; use InfoTip for content everyone must reach. */
25
+ export declare function Tooltip({ content, children, side, shortcut, disabled, overflowOnly, ...anchorProps }: TooltipProps): import("react").JSX.Element;
@@ -1,98 +1,80 @@
1
- import { HiQuestionMarkCircle } from "../icons/hi/HiQuestionMarkCircle.js";
1
+ import { portalContainer, positionerClassName, tipArrowClassName, tipClassName } from "./floating.js";
2
2
  import { keyedByContent } from "./keys.js";
3
- import { Fragment } from "react";
4
3
  import { jsx, jsxs } from "react/jsx-runtime";
5
- import { Tooltip } from "react-tooltip";
4
+ import { Fragment as Fragment$1, createContext, use, useState } from "react";
5
+ import { Tooltip } from "@base-ui/react/tooltip";
6
6
  //#region src/components/Tooltip.tsx
7
- var TOOLTIP_ID = "global-tooltip";
8
- /** Anchor props that reveal `content` only while the text is ellipsized; `measure` picks the clipped descendant when it isn't the anchor. */
9
- function truncationTooltipProps(content, measure) {
10
- return {
11
- role: "none",
12
- "data-tooltip-id": TOOLTIP_ID,
13
- onMouseEnter: (event) => {
14
- const anchor = event.currentTarget;
15
- const measured = measure ? measure(anchor) : anchor;
16
- if (measured && measured.scrollWidth > measured.clientWidth) anchor.setAttribute("data-tooltip-content", content);
17
- else anchor.removeAttribute("data-tooltip-content");
18
- }
19
- };
20
- }
21
- var linkRegex = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
22
- function formatLine(line) {
23
- const nodes = [];
24
- let last = 0;
25
- for (const match of line.matchAll(linkRegex)) {
26
- if (match.index > last) nodes.push(line.slice(last, match.index));
27
- nodes.push(/* @__PURE__ */ jsx("a", {
28
- href: match[2],
29
- target: "_blank",
30
- rel: "noopener noreferrer",
31
- className: "underline",
32
- children: match[1]
33
- }, match.index));
34
- last = match.index + match[0].length;
35
- }
36
- if (last < line.length) nodes.push(line.slice(last));
37
- return nodes;
38
- }
39
- /** Tooltip text can come from untrusted sources (workflow YAML), so all markup is literal text — only `[text](url)` links and newlines are parsed. */
40
- function formatTooltipContent(content) {
41
- if (typeof content !== "string") return content || null;
42
- if (!content) return null;
43
- return keyedByContent(content.split(/<br\s*\/?>|\n/i), (l) => l).map(({ key, item: line }, idx) => /* @__PURE__ */ jsxs(Fragment, { children: [idx > 0 && /* @__PURE__ */ jsx("br", {}), formatLine(line)] }, key));
44
- }
7
+ var TooltipHandleContext = createContext(null);
45
8
  function KbdShortcut({ keys }) {
46
9
  const parts = keys.split("+").map((part) => part.trim()).filter(Boolean);
47
10
  return /* @__PURE__ */ jsx("span", {
48
11
  className: "inline-flex items-center gap-1 align-middle",
49
- children: keyedByContent(parts, (p) => p).map(({ key, item: part }, idx) => /* @__PURE__ */ jsxs(Fragment, { children: [idx > 0 && /* @__PURE__ */ jsx("span", {
12
+ children: keyedByContent(parts, (p) => p).map(({ key, item: part }, idx) => /* @__PURE__ */ jsxs(Fragment$1, { children: [idx > 0 && /* @__PURE__ */ jsx("span", {
50
13
  className: "opacity-60 text-[11px]",
51
14
  children: "+"
52
15
  }), /* @__PURE__ */ jsx("kbd", {
53
- className: "inline-flex items-center justify-center min-w-[18px] h-[18px] px-1 rounded border border-white/30 bg-white/10 font-sans text-[11px] font-semibold leading-none",
16
+ className: "inline-flex items-center justify-center min-w-[18px] h-[18px] px-1 rounded border border-current/30 bg-current/10 font-sans text-[11px] font-semibold leading-none",
54
17
  children: part
55
18
  })] }, key))
56
19
  });
57
20
  }
58
- var globalCloseEvents = { escape: true };
59
- /** Singleton rendered at layout root; anchors opt in via data-tooltip-id={TOOLTIP_ID}, data-tooltip-content, and data-tooltip-shortcut. */
60
- function GlobalTooltip() {
61
- return /* @__PURE__ */ jsx(Tooltip, {
62
- id: TOOLTIP_ID,
63
- className: "max-w-lg break-words config-tips normal-case text-left z-[10000]",
64
- place: "top",
65
- globalCloseEvents,
66
- render: ({ content, activeAnchor }) => {
67
- const body = formatTooltipContent(content);
68
- const shortcut = activeAnchor?.getAttribute("data-tooltip-shortcut");
69
- if (!shortcut) return body;
70
- return /* @__PURE__ */ jsxs("span", {
71
- className: "inline-flex items-center gap-2",
72
- children: [body, /* @__PURE__ */ jsx(KbdShortcut, { keys: shortcut })]
73
- });
74
- }
21
+ function TooltipPopup({ content, shortcut, side }) {
22
+ return /* @__PURE__ */ jsx(Tooltip.Portal, {
23
+ container: portalContainer(),
24
+ children: /* @__PURE__ */ jsx(Tooltip.Positioner, {
25
+ side,
26
+ sideOffset: 8,
27
+ className: positionerClassName,
28
+ children: /* @__PURE__ */ jsxs(Tooltip.Popup, {
29
+ className: `max-w-xs ${tipClassName}`,
30
+ children: [/* @__PURE__ */ jsx(Tooltip.Arrow, { className: tipArrowClassName }), shortcut ? /* @__PURE__ */ jsxs("span", {
31
+ className: "inline-flex items-center gap-2",
32
+ children: [content, /* @__PURE__ */ jsx(KbdShortcut, { keys: shortcut })]
33
+ }) : content]
34
+ })
35
+ })
75
36
  });
76
37
  }
77
- function TooltipInfo({ text, className = "", children, place = "top", tabIndex }) {
78
- const anchorProps = {
79
- "data-tooltip-id": TOOLTIP_ID,
80
- "data-tooltip-content": text,
81
- "data-tooltip-place": place,
82
- className
38
+ /** One popup serves every Tooltip below it, so each anchor costs only a trigger.
39
+ * UIProvider mounts it; nothing else needs to. */
40
+ function TooltipProvider({ children }) {
41
+ const [handle] = useState(() => Tooltip.createHandle());
42
+ return /* @__PURE__ */ jsxs(Tooltip.Provider, { children: [/* @__PURE__ */ jsx(TooltipHandleContext, {
43
+ value: handle,
44
+ children
45
+ }), /* @__PURE__ */ jsx(Tooltip.Root, {
46
+ handle,
47
+ onOpenChange: skipUnclipped,
48
+ children: ({ payload }) => payload && /* @__PURE__ */ jsx(TooltipPopup, { ...payload })
49
+ })] });
50
+ }
51
+ /** An overflowOnly anchor opens only while its text is cut off. */
52
+ function skipUnclipped(open, details) {
53
+ const anchor = details.trigger;
54
+ if (open && anchor instanceof HTMLElement && anchor.hasAttribute("data-overflow-only") && anchor.scrollWidth <= anchor.clientWidth) details.cancel();
55
+ }
56
+ /** A visual hint for sighted pointer and keyboard users. The anchor still needs
57
+ * its own accessible name; use InfoTip for content everyone must reach. */
58
+ function Tooltip$1({ content, children, side = "top", shortcut, disabled = false, overflowOnly = false, ...anchorProps }) {
59
+ const handle = use(TooltipHandleContext);
60
+ const payload = {
61
+ content,
62
+ shortcut,
63
+ side
83
64
  };
84
- if (children || !text) return /* @__PURE__ */ jsx("div", {
65
+ const trigger = /* @__PURE__ */ jsx(Tooltip.Trigger, {
85
66
  ...anchorProps,
86
- tabIndex,
87
- children: children || /* @__PURE__ */ jsx(HiQuestionMarkCircle, { className: "tooltip" })
67
+ handle: handle ?? void 0,
68
+ payload,
69
+ disabled: disabled || !content,
70
+ "data-overflow-only": overflowOnly || void 0,
71
+ render: children
88
72
  });
89
- return /* @__PURE__ */ jsx("div", {
90
- ...anchorProps,
91
- role: "img",
92
- "aria-label": text,
93
- tabIndex: tabIndex ?? 0,
94
- children: /* @__PURE__ */ jsx(HiQuestionMarkCircle, { className: "tooltip" })
73
+ if (handle) return trigger;
74
+ return /* @__PURE__ */ jsxs(Tooltip.Root, {
75
+ onOpenChange: skipUnclipped,
76
+ children: [trigger, /* @__PURE__ */ jsx(TooltipPopup, { ...payload })]
95
77
  });
96
78
  }
97
79
  //#endregion
98
- export { GlobalTooltip, TOOLTIP_ID, TooltipInfo, formatTooltipContent, truncationTooltipProps };
80
+ export { Tooltip$1 as Tooltip, TooltipProvider };
@@ -0,0 +1,14 @@
1
+ /** Popups portal into the host's .ds-root when it has one, so they inherit the
2
+ * design system's CSS variables; undefined lets the portal use document.body. */
3
+ export declare function portalContainer(): HTMLElement | undefined;
4
+ /** Above dialogs and sticky chrome; hidden while its anchor is scrolled out of view. */
5
+ export declare const positionerClassName = "z-[10000] outline-none data-anchor-hidden:invisible";
6
+ /** A panel of choices: a menu, a select's list, a combobox's list. */
7
+ export declare const panelClassName = "rounded-lg border border-(--theme-border) bg-(--theme-app-bg) text-sm text-(--theme-app) shadow-(--theme-shadow-lg) outline-none origin-(--transform-origin) transition-[transform,opacity] duration-100 data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:scale-95 data-ending-style:opacity-0";
8
+ /** A row in a panel. */
9
+ export declare const panelItemClassName = "flex w-full cursor-pointer select-none items-center gap-2 px-3 py-1.5 text-left outline-none data-highlighted:bg-(--theme-hover) data-highlighted:text-(--theme-hover-text) data-disabled:cursor-not-allowed data-disabled:opacity-50";
10
+ /** A tooltip's or infotip's small inverted surface. */
11
+ export declare const tipClassName = "rounded-md bg-(--theme-app) px-2 py-1 text-xs text-(--theme-app-bg) shadow-(--theme-shadow) whitespace-pre-line break-words data-instant:transition-none origin-(--transform-origin) transition-[transform,opacity] duration-100 data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:scale-95 data-ending-style:opacity-0";
12
+ export declare const tipArrowClassName = "size-2 rotate-45 bg-(--theme-app) data-[side=top]:-bottom-1 data-[side=bottom]:-top-1 data-[side=left]:-right-1 data-[side=right]:-left-1";
13
+ /** A hover card's surface; the card sets its own width and padding. */
14
+ export declare const cardClassName = "overflow-hidden rounded-xl border border-(--theme-border) bg-(--theme-panel-bg) text-(--theme-app) shadow-(--theme-shadow-lg) outline-none origin-(--transform-origin) transition-[transform,opacity] duration-100 data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:scale-95 data-ending-style:opacity-0";