@parallelworks/ui 0.51.0 → 0.52.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 (227) hide show
  1. package/README.md +155 -14
  2. package/dist/ai/agent/toolStrings.d.ts +2 -0
  3. package/dist/ai/agent/toolStrings.js +20 -18
  4. package/dist/ai/ai.css +12 -0
  5. package/dist/ai/components/AllocationSelector.js +5 -1
  6. package/dist/ai/components/AttachmentManager.js +51 -42
  7. package/dist/ai/components/AttachmentUpload.d.ts +4 -2
  8. package/dist/ai/components/AttachmentUpload.js +9 -9
  9. package/dist/ai/components/BlockedGroupBanner.js +8 -14
  10. package/dist/ai/components/BranchNavigator.js +11 -12
  11. package/dist/ai/components/ChatEmptyState.js +12 -19
  12. package/dist/ai/components/ChatInput.d.ts +4 -3
  13. package/dist/ai/components/ChatInput.js +27 -13
  14. package/dist/ai/components/ChatMessage.js +45 -121
  15. package/dist/ai/components/ChatMessageList.d.ts +5 -2
  16. package/dist/ai/components/ChatMessageList.js +89 -51
  17. package/dist/ai/components/ChatSidebar.js +11 -7
  18. package/dist/ai/components/ChatThread.js +1 -13
  19. package/dist/ai/components/DragOverlay.js +3 -3
  20. package/dist/ai/components/MessageAttachments.d.ts +10 -0
  21. package/dist/ai/components/MessageAttachments.js +78 -0
  22. package/dist/ai/components/ModelSelector.js +3 -3
  23. package/dist/ai/components/PastedText.js +2 -2
  24. package/dist/ai/components/ProviderIssueBanner.js +19 -23
  25. package/dist/ai/components/ShareDialog.js +2 -2
  26. package/dist/ai/components/agent/ActivityLine.d.ts +0 -2
  27. package/dist/ai/components/agent/ActivityLine.js +8 -51
  28. package/dist/ai/components/agent/AgentMessageParts.js +114 -53
  29. package/dist/ai/core/ChatProvider.d.ts +16 -5
  30. package/dist/ai/core/ChatProvider.js +41 -8
  31. package/dist/ai/core/config.js +4 -3
  32. package/dist/ai/index.d.ts +1 -1
  33. package/dist/ai/index.js +3 -3
  34. package/dist/ai/strings.d.ts +29 -3
  35. package/dist/ai/strings.js +81 -26
  36. package/dist/ai/types.d.ts +4 -0
  37. package/dist/ai/ui/Notice.d.ts +2 -2
  38. package/dist/ai/ui/Notice.js +29 -62
  39. package/dist/ai/ui/sidebar.d.ts +5 -3
  40. package/dist/ai/ui/sidebar.js +21 -9
  41. package/dist/components/ActionMenu.d.ts +1 -0
  42. package/dist/components/ActionMenu.js +6 -1
  43. package/dist/components/AppLink.d.ts +26 -0
  44. package/dist/components/AppLink.js +51 -0
  45. package/dist/components/Avatar.d.ts +2 -1
  46. package/dist/components/Avatar.js +4 -2
  47. package/dist/components/Button.d.ts +15 -5
  48. package/dist/components/Button.js +47 -40
  49. package/dist/components/Callout.d.ts +31 -7
  50. package/dist/components/Callout.js +50 -19
  51. package/dist/components/Card.d.ts +11 -6
  52. package/dist/components/Card.js +14 -8
  53. package/dist/components/Checkbox.js +2 -1
  54. package/dist/components/ColorInput.js +5 -3
  55. package/dist/components/Combobox.js +49 -19
  56. package/dist/components/ConfirmModal.d.ts +19 -8
  57. package/dist/components/ConfirmModal.js +31 -53
  58. package/dist/components/CopyButton.d.ts +38 -0
  59. package/dist/components/CopyButton.js +68 -0
  60. package/dist/components/CreateModal.js +118 -111
  61. package/dist/components/DatePicker.js +12 -8
  62. package/dist/components/DescriptionList.d.ts +25 -5
  63. package/dist/components/DescriptionList.js +56 -22
  64. package/dist/components/Disclosure.js +1 -1
  65. package/dist/components/Drawer.js +10 -16
  66. package/dist/components/Field.d.ts +15 -5
  67. package/dist/components/Field.js +40 -8
  68. package/dist/components/IconButton.d.ts +14 -5
  69. package/dist/components/IconButton.js +25 -14
  70. package/dist/components/InfoTip.d.ts +4 -1
  71. package/dist/components/InfoTip.js +2 -1
  72. package/dist/components/Input.d.ts +14 -8
  73. package/dist/components/Input.js +46 -31
  74. package/dist/components/Loader.js +1 -1
  75. package/dist/components/MenuEntries.d.ts +4 -0
  76. package/dist/components/MenuEntries.js +11 -12
  77. package/dist/components/Meter.js +5 -4
  78. package/dist/components/Modal.d.ts +28 -4
  79. package/dist/components/Modal.js +37 -14
  80. package/dist/components/Overview.d.ts +20 -12
  81. package/dist/components/Overview.js +14 -9
  82. package/dist/components/PageHeader.d.ts +47 -65
  83. package/dist/components/PageHeader.js +275 -153
  84. package/dist/components/PageHeaderAction.d.ts +67 -0
  85. package/dist/components/PageHeaderAction.js +107 -0
  86. package/dist/components/Pagination.js +6 -16
  87. package/dist/components/Popover.js +3 -2
  88. package/dist/components/Provider.d.ts +77 -19
  89. package/dist/components/Provider.js +139 -130
  90. package/dist/components/Radio.js +2 -1
  91. package/dist/components/RefreshButton.js +7 -8
  92. package/dist/components/RequiredMark.js +1 -1
  93. package/dist/components/Section.js +1 -1
  94. package/dist/components/Select.d.ts +4 -9
  95. package/dist/components/Select.js +24 -11
  96. package/dist/components/SettingModeOption.d.ts +1 -1
  97. package/dist/components/SettingModeOption.js +7 -1
  98. package/dist/components/SettingsCard.d.ts +5 -3
  99. package/dist/components/SettingsCard.js +27 -20
  100. package/dist/components/Slider.js +1 -1
  101. package/dist/components/StatusBadge.js +2 -2
  102. package/dist/components/Switch.js +5 -4
  103. package/dist/components/Table.d.ts +30 -20
  104. package/dist/components/Table.js +50 -73
  105. package/dist/components/Tabs.d.ts +3 -7
  106. package/dist/components/Tabs.js +6 -10
  107. package/dist/components/ThemeEditor.js +18 -8
  108. package/dist/components/Toast.d.ts +11 -3
  109. package/dist/components/Toast.js +45 -20
  110. package/dist/components/buttonClasses.js +1 -1
  111. package/dist/components/comboboxItems.d.ts +4 -0
  112. package/dist/components/comboboxItems.js +6 -1
  113. package/dist/components/dismiss.d.ts +12 -0
  114. package/dist/components/dismiss.js +19 -0
  115. package/dist/components/fieldBox.d.ts +4 -0
  116. package/dist/components/fieldBox.js +7 -3
  117. package/dist/components/floating.d.ts +3 -3
  118. package/dist/components/floating.js +1 -1
  119. package/dist/components/markdownCodeBreaks.js +3 -4
  120. package/dist/components/pageHeaderStore.d.ts +41 -0
  121. package/dist/components/pageHeaderStore.js +67 -0
  122. package/dist/components/pathBreaks.d.ts +8 -0
  123. package/dist/components/pathBreaks.js +28 -0
  124. package/dist/components/segmented.js +1 -1
  125. package/dist/components/shortcutKey.d.ts +2 -1
  126. package/dist/components/shortcutKey.js +19 -2
  127. package/dist/components/splitter.js +1 -1
  128. package/dist/components/useCssIsDark.js +40 -18
  129. package/dist/components/useTheme.js +9 -10
  130. package/dist/dev.d.ts +9 -0
  131. package/dist/dev.js +14 -0
  132. package/dist/editor/Editor.d.ts +3 -2
  133. package/dist/editor/Editor.js +11 -2
  134. package/dist/editor/EditorField.d.ts +2 -1
  135. package/dist/editor/EditorField.js +11 -29
  136. package/dist/editor/FormCodePanel.d.ts +7 -3
  137. package/dist/editor/FormCodePanel.js +14 -7
  138. package/dist/editor/Monaco.d.ts +14 -5
  139. package/dist/editor/Monaco.js +163 -112
  140. package/dist/editor/index.d.ts +5 -5
  141. package/dist/editor/index.js +3 -3
  142. package/dist/editor/themes.d.ts +8 -5
  143. package/dist/editor/themes.js +58 -30
  144. package/dist/editor/yaml.d.ts +6 -2
  145. package/dist/editor/yaml.js +11 -2
  146. package/dist/file-explorer/FileExplorer.js +143 -124
  147. package/dist/file-explorer/FileExplorerContext.js +1 -1
  148. package/dist/file-explorer/FilePreview/StreamedBadge.js +3 -1
  149. package/dist/file-explorer/FilePreview/Viewer.js +2 -2
  150. package/dist/file-explorer/FilePreview/index.js +4 -4
  151. package/dist/file-explorer/FileRow.js +1 -1
  152. package/dist/file-explorer/FileRowsWindow.js +34 -3
  153. package/dist/file-explorer/FileTable.js +3 -1
  154. package/dist/file-explorer/TreeView.js +37 -14
  155. package/dist/file-explorer/helpers.d.ts +2 -1
  156. package/dist/file-explorer/helpers.js +21 -20
  157. package/dist/file-explorer/toasts.js +27 -19
  158. package/dist/file-explorer/treeRows.d.ts +6 -0
  159. package/dist/file-explorer/treeRows.js +19 -1
  160. package/dist/file-explorer/useNearEnd.js +3 -6
  161. package/dist/form/Fields/CheckboxGroupField.js +12 -5
  162. package/dist/form/Fields/DurationField.js +1 -1
  163. package/dist/form/Fields/LabelField.js +1 -1
  164. package/dist/form/Fields/ObjectField.d.ts +1 -1
  165. package/dist/form/Fields/ObjectField.js +3 -2
  166. package/dist/form/Fields/StringField.js +16 -29
  167. package/dist/form/Fields/TextAreaField.js +3 -4
  168. package/dist/form/Form.js +3 -8
  169. package/dist/form/Wizard/WizardNavigation.js +0 -3
  170. package/dist/form/Wizard/utils.js +1 -1
  171. package/dist/form/fieldFrame.d.ts +1 -1
  172. package/dist/form/fieldFrame.js +2 -2
  173. package/dist/form/types/fieldComponentTypes.d.ts +2 -1
  174. package/dist/graph/AnnotationBanner.d.ts +1 -2
  175. package/dist/graph/AnnotationBanner.js +30 -32
  176. package/dist/graph/Connectors.js +4 -1
  177. package/dist/graph/DependencyGraph.js +2 -2
  178. package/dist/graph/GraphEditor.js +11 -9
  179. package/dist/graph/GraphEditorDialogs.js +1 -1
  180. package/dist/graph/GraphNode.js +7 -4
  181. package/dist/graph/InputDialog.js +1 -1
  182. package/dist/graph/InputsEditor.js +14 -11
  183. package/dist/graph/MatrixGroup.js +9 -3
  184. package/dist/graph/Reveal.js +18 -10
  185. package/dist/graph/ShortcutsButton.d.ts +11 -2
  186. package/dist/graph/ShortcutsButton.js +14 -3
  187. package/dist/graph/TreeView.js +35 -18
  188. package/dist/graph/WorkflowSettingsDialog.js +1 -1
  189. package/dist/graph/editorFields.js +1 -1
  190. package/dist/graph/editorRows.js +16 -10
  191. package/dist/graph/editorStrings.d.ts +7 -0
  192. package/dist/graph/editorStrings.js +8 -1
  193. package/dist/graph/inputRefs.js +1 -1
  194. package/dist/graph/settingsViews.js +11 -18
  195. package/dist/graph/stepWith.js +1 -1
  196. package/dist/icons.d.ts +2 -0
  197. package/dist/icons.js +4 -2
  198. package/dist/index.d.ts +12 -12
  199. package/dist/index.js +16 -16
  200. package/dist/list/ActionToolbar.d.ts +42 -6
  201. package/dist/list/ActionToolbar.js +297 -101
  202. package/dist/list/ListPage.d.ts +15 -23
  203. package/dist/list/ListPage.js +42 -43
  204. package/dist/list/ListTable.d.ts +32 -7
  205. package/dist/list/ListTable.js +48 -12
  206. package/dist/list/ListViewControls.js +1 -1
  207. package/dist/list/UserHoverCard.js +7 -15
  208. package/dist/list/index.d.ts +2 -2
  209. package/dist/list/index.js +2 -2
  210. package/dist/list/listSearch.js +12 -10
  211. package/dist/list/listView.d.ts +10 -1
  212. package/dist/list/listView.js +15 -1
  213. package/dist/logviewer/LogViewer.d.ts +4 -2
  214. package/dist/logviewer/LogViewer.js +87 -69
  215. package/dist/logviewer/logviewer.css +3 -2
  216. package/dist/reducedMotion.d.ts +5 -0
  217. package/dist/reducedMotion.js +20 -0
  218. package/dist/safeUrl.d.ts +1 -1
  219. package/dist/safeUrl.js +4 -2
  220. package/dist/styles.css +1 -1
  221. package/package.json +1 -1
  222. package/dist/components/Breadcrumbs.d.ts +0 -37
  223. package/dist/components/Breadcrumbs.js +0 -90
  224. package/dist/components/CopyToClipboard.d.ts +0 -17
  225. package/dist/components/CopyToClipboard.js +0 -66
  226. package/dist/components/Sort.d.ts +0 -9
  227. package/dist/components/Sort.js +0 -42
package/dist/index.js CHANGED
@@ -1,19 +1,22 @@
1
1
  import { cx } from "./cx.js";
2
- import { MenuCheckboxItem, MenuGroupLabel, MenuItem, MenuLinkItem, MenuPopup, MenuRadioItem, MenuSeparator, MenuSubmenuTrigger } from "./components/Menu.js";
3
- import { EmptyState } from "./components/EmptyState.js";
4
2
  import { buttonClasses } from "./components/buttonClasses.js";
3
+ import { MenuCheckboxItem, MenuGroupLabel, MenuItem, MenuLinkItem, MenuPopup, MenuRadioItem, MenuSeparator, MenuSubmenuTrigger } from "./components/Menu.js";
5
4
  import { Loader } from "./components/Loader.js";
6
5
  import { toast } from "./components/Toast.js";
7
6
  import { Tooltip, TooltipProvider } from "./components/Tooltip.js";
8
7
  import { UIProvider, useNavigation, useOptionalWorkflowEngine, usePersistedState, useProvisionCorsRules, useRunFile, useSlots, useStrings, useWorkflowActions, useWorkflowEditing, useWorkflowEngine, useWorkflowEngineLoader } from "./components/Provider.js";
8
+ import { AppLink, isPlainClick } from "./components/AppLink.js";
9
+ import { EmptyState } from "./components/EmptyState.js";
9
10
  import { useCopy } from "./components/useCopy.js";
10
11
  import { MenuEntries, MenuFilter, menuDivider } from "./components/MenuEntries.js";
11
12
  import { ActionMenu } from "./components/ActionMenu.js";
12
13
  import { Avatar, avatarInitials } from "./components/Avatar.js";
13
- import { BreadcrumbProvider, useBreadcrumb, useClearBreadcrumbs, useHideBreadcrumbs, useSetBreadcrumbs, useSetDefaultBreadcrumbs } from "./components/Breadcrumbs.js";
14
14
  import { Button, MethodButton } from "./components/Button.js";
15
- import Callout from "./components/Callout.js";
15
+ import { isTextEntryContext, useShortcutKey } from "./components/shortcutKey.js";
16
+ import { IconButton } from "./components/IconButton.js";
17
+ import { Callout } from "./components/Callout.js";
16
18
  import { Card, CardHeader } from "./components/Card.js";
19
+ import { fieldBox } from "./components/fieldBox.js";
17
20
  import { Checkbox, CheckboxGroup } from "./components/Checkbox.js";
18
21
  import { JND, composite, deltaE, parseColor, toHex, toP3 } from "./theme/color.js";
19
22
  import { apcaContrast, contrastRatio, isDarkColor } from "./theme/contrast.js";
@@ -21,26 +24,23 @@ import { CODE_STYLES, DEFAULT_CONTRAST, DEFAULT_PRESET, DEFAULT_THEME, THEME_PRE
21
24
  import { SIDEBAR_TOKENS, THEME_TOKENS, deriveTheme, generateTheme, themeStylesheet } from "./theme/derive.js";
22
25
  import { fitSeed } from "./theme/fit.js";
23
26
  import { applyTheme, prefersWideGamut } from "./theme/index.js";
27
+ import { ExternalLink } from "./components/ExternalLink.js";
28
+ import { Popover, PopoverClose, useClosePopover } from "./components/Popover.js";
29
+ import { InfoTip, formatInfoTipContent } from "./components/InfoTip.js";
24
30
  import { RequiredMark } from "./components/RequiredMark.js";
25
31
  import { ErrorText, Field, FieldOption, FieldValue, RevealToggle, useFieldControl } from "./components/Field.js";
26
- import { fieldBox } from "./components/fieldBox.js";
27
32
  import { Input, Textarea } from "./components/Input.js";
28
33
  import { ColorInput } from "./components/ColorInput.js";
29
34
  import { Autocomplete, Combobox } from "./components/Combobox.js";
30
35
  import { Modal, ModalDescription, ModalTitle, modalPanelClassName } from "./components/Modal.js";
31
36
  import { ConfirmModal } from "./components/ConfirmModal.js";
32
37
  import { useContextMenu } from "./components/ContextMenu.js";
33
- import CopyToClipboard, { CopyCodeBlock } from "./components/CopyToClipboard.js";
38
+ import { CopyButton, CopyCodeBlock } from "./components/CopyButton.js";
34
39
  import { Disclosure, DisclosurePanel } from "./components/Disclosure.js";
35
40
  import { Switch } from "./components/Switch.js";
36
41
  import { CreateModal, CreateModalSelect, CreateModalSwitch } from "./components/CreateModal.js";
37
42
  import { DatePicker } from "./components/DatePicker.js";
38
- import { isTextEntryContext, useShortcutKey } from "./components/shortcutKey.js";
39
- import { IconButton } from "./components/IconButton.js";
40
- import { ExternalLink } from "./components/ExternalLink.js";
41
- import { Popover, PopoverClose, useClosePopover } from "./components/Popover.js";
42
- import { InfoTip, formatInfoTipContent } from "./components/InfoTip.js";
43
- import DescriptionList, { DescriptionListItem } from "./components/DescriptionList.js";
43
+ import DescriptionList, { DescriptionListGroup, DescriptionListItem } from "./components/DescriptionList.js";
44
44
  import { Drawer } from "./components/Drawer.js";
45
45
  import { HoverCard } from "./components/HoverCard.js";
46
46
  import { LetterBadge } from "./components/LetterBadge.js";
@@ -50,7 +50,8 @@ import { NumberInput } from "./components/NumberInput.js";
50
50
  import { OneTimeCodeInput } from "./components/OneTimeCodeInput.js";
51
51
  import { LoadingRegion, Skeleton } from "./components/Skeleton.js";
52
52
  import { Overview } from "./components/Overview.js";
53
- import { BreadcrumbsActionButton, BreadcrumbsRightAction, BreadcrumbsTitleAction, HeaderActionMenu, HeaderAddButton, HeaderEditButton, PageHeader } from "./components/PageHeader.js";
53
+ import { PageHeader, PageHeaderBar, PageHeaderProvider } from "./components/PageHeader.js";
54
+ import { PageHeaderAction, PageHeaderAddButton, PageHeaderMenu } from "./components/PageHeaderAction.js";
54
55
  import { Select } from "./components/Select.js";
55
56
  import { PAGE_SIZES, Pagination } from "./components/Pagination.js";
56
57
  import { Radio, RadioGroup } from "./components/Radio.js";
@@ -64,12 +65,11 @@ import { SegmentedControl } from "./components/SegmentedControl.js";
64
65
  import { SettingModeOption } from "./components/SettingModeOption.js";
65
66
  import { SettingRow, SettingsCard, SettingsHeading } from "./components/SettingsCard.js";
66
67
  import { Slider } from "./components/Slider.js";
67
- import Sort from "./components/Sort.js";
68
68
  import { StatusBadge, StatusDot, statusTextClass } from "./components/StatusBadge.js";
69
- import { CompactTable, Table } from "./components/Table.js";
69
+ import { Table } from "./components/Table.js";
70
70
  import { TabPanel, Tabs } from "./components/Tabs.js";
71
71
  import { ThemeEditor, ThemePreview } from "./components/ThemeEditor.js";
72
72
  import { ToggleGroup } from "./components/ToggleGroup.js";
73
73
  import { useCssIsDark } from "./components/useCssIsDark.js";
74
74
  import { useApplyTheme, useColorMode } from "./components/useTheme.js";
75
- export { ActionMenu, Autocomplete, Avatar, BreadcrumbProvider, BreadcrumbsActionButton, BreadcrumbsRightAction, BreadcrumbsTitleAction, Button, CODE_STYLES, Callout, Card, CardHeader, Checkbox, CheckboxGroup, ColorInput, Combobox, CompactTable, ConfirmModal, CopyCodeBlock, CopyToClipboard, CreateModal, CreateModalSelect, CreateModalSwitch, DEFAULT_CONTRAST, DEFAULT_PRESET, DEFAULT_THEME, DatePicker, DescriptionList, DescriptionListItem, Disclosure, DisclosurePanel, Drawer, Elapsed, EmptyState, ErrorText, ExternalLink, Field, FieldOption, FieldValue, HeaderActionMenu, HeaderAddButton, HeaderEditButton, HoverCard, IconButton, InfoTip, Input, JND, LetterBadge, Loader, LoadingRegion, Markdown, MenuCheckboxItem, MenuEntries, MenuFilter, MenuGroupLabel, MenuItem, MenuLinkItem, MenuPopup, MenuRadioItem, MenuSeparator, MenuSubmenuTrigger, Meter, MethodButton, Modal, ModalDescription, ModalTitle, NumberInput, OneTimeCodeInput, Overview, PAGE_SIZES, PageHeader, Pagination, Popover, PopoverClose, ProgressBar, Radio, RadioGroup, RefreshButton, RelativeTime, RequiredMark, RevealToggle, RunStatusIcon, SIDEBAR_TOKENS, SearchInput, Section, SegmentedControl, Select, SettingModeOption, SettingRow, SettingsCard, SettingsHeading, Skeleton, Slider, Sort, StatusBadge, StatusDot, Switch, THEME_PRESETS, THEME_TOKENS, TabPanel, Table, Tabs, Textarea, ThemeEditor, ThemePreview, ToggleGroup, Tooltip, TooltipProvider, UIProvider, apcaContrast, applyTheme, avatarInitials, buttonClasses, composite, contrastRatio, cx, deltaE, deriveTheme, fieldBox, fitSeed, formatBytes, formatCount, formatDateTime, formatDuration, formatInfoTipContent, formatTimeLeft, generateTheme, isDarkColor, isTextEntryContext, levelTone, menuDivider, modalPanelClassName, modeOf, parseColor, parseTheme, prefersWideGamut, resolveMode, runStatusTone, schemeFor, serializeTheme, statusTextClass, themeStylesheet, toHex, toP3, toast, useApplyTheme, useBreadcrumb, useClearBreadcrumbs, useClock, useClosePopover, useColorMode, useContextMenu, useCopy, useCssIsDark, useElapsed, useFieldControl, useHideBreadcrumbs, useNavigation, useOptionalWorkflowEngine, usePersistedState, useProvisionCorsRules, useRelativeTime, useRunFile, useSetBreadcrumbs, useSetDefaultBreadcrumbs, useShortcutKey, useSlots, useStrings, useWorkflowActions, useWorkflowEditing, useWorkflowEngine, useWorkflowEngineLoader };
75
+ export { ActionMenu, AppLink, Autocomplete, Avatar, Button, CODE_STYLES, Callout, Card, CardHeader, Checkbox, CheckboxGroup, ColorInput, Combobox, ConfirmModal, CopyButton, CopyCodeBlock, CreateModal, CreateModalSelect, CreateModalSwitch, DEFAULT_CONTRAST, DEFAULT_PRESET, DEFAULT_THEME, DatePicker, DescriptionList, DescriptionListGroup, DescriptionListItem, Disclosure, DisclosurePanel, Drawer, Elapsed, EmptyState, ErrorText, ExternalLink, Field, FieldOption, FieldValue, HoverCard, IconButton, InfoTip, Input, JND, LetterBadge, Loader, LoadingRegion, Markdown, MenuCheckboxItem, MenuEntries, MenuFilter, MenuGroupLabel, MenuItem, MenuLinkItem, MenuPopup, MenuRadioItem, MenuSeparator, MenuSubmenuTrigger, Meter, MethodButton, Modal, ModalDescription, ModalTitle, NumberInput, OneTimeCodeInput, Overview, PAGE_SIZES, PageHeader, PageHeaderAction, PageHeaderAddButton, PageHeaderBar, PageHeaderMenu, PageHeaderProvider, Pagination, Popover, PopoverClose, ProgressBar, Radio, RadioGroup, RefreshButton, RelativeTime, RequiredMark, RevealToggle, RunStatusIcon, SIDEBAR_TOKENS, SearchInput, Section, SegmentedControl, Select, SettingModeOption, SettingRow, SettingsCard, SettingsHeading, Skeleton, Slider, StatusBadge, StatusDot, Switch, THEME_PRESETS, THEME_TOKENS, TabPanel, Table, Tabs, Textarea, ThemeEditor, ThemePreview, ToggleGroup, Tooltip, TooltipProvider, UIProvider, apcaContrast, applyTheme, avatarInitials, buttonClasses, composite, contrastRatio, cx, deltaE, deriveTheme, fieldBox, fitSeed, formatBytes, formatCount, formatDateTime, formatDuration, formatInfoTipContent, formatTimeLeft, generateTheme, isDarkColor, isPlainClick, isTextEntryContext, levelTone, menuDivider, modalPanelClassName, modeOf, parseColor, parseTheme, prefersWideGamut, resolveMode, runStatusTone, schemeFor, serializeTheme, statusTextClass, themeStylesheet, toHex, toP3, toast, useApplyTheme, useClock, useClosePopover, useColorMode, useContextMenu, useCopy, useCssIsDark, useElapsed, useFieldControl, useNavigation, useOptionalWorkflowEngine, usePersistedState, useProvisionCorsRules, useRelativeTime, useRunFile, useShortcutKey, useSlots, useStrings, useWorkflowActions, useWorkflowEditing, useWorkflowEngine, useWorkflowEngineLoader };
@@ -3,6 +3,9 @@ import type { RowAction } from './rowMenu.js';
3
3
  export type ToolbarAction = RowAction & {
4
4
  /** A hint on the enabled button. */
5
5
  tooltip?: string | undefined;
6
+ /** The one action the view leads to, filled in the accent. Give it to one
7
+ * action at most: the rest are outlined, so it stands out. */
8
+ primary?: boolean | undefined;
6
9
  hidden?: boolean;
7
10
  };
8
11
  /** A pre-rendered element (e.g. a button component that owns its modal). */
@@ -12,17 +15,50 @@ interface ToolbarElement {
12
15
  hidden?: boolean;
13
16
  }
14
17
  export type ToolbarItem = ToolbarAction | ToolbarElement;
15
- /** A toolbar action as a button: a link with `href`, a toggle with `checked`. */
18
+ /** A toolbar action as a button: a link with `href`, a toggle with `checked`.
19
+ * In an ActionToolbar it is one of its items, reached with the arrow keys. */
16
20
  export declare function ToolbarButton({ action }: {
17
21
  action: ToolbarAction;
18
22
  }): import("react").JSX.Element;
19
- /** Pins a detail-page toolbar just below the sticky breadcrumb strip (top-10 matches the strip's 40px height). */
20
- export declare const stickyToolbarClasses = "sticky top-10 z-(--layer-sticky) bg-(--theme-app-bg)";
21
- /** Action groups left, secondary actions right (collapsing into a `…` menu). */
22
- export declare function ActionToolbar({ groups, right, sticky, }: {
23
+ /** How the toolbar fits its row: the items whose labels fold to their icons,
24
+ * and those moved into the `…` menu, by key. */
25
+ export interface ToolbarFit {
26
+ folded: readonly string[];
27
+ overflow: readonly string[];
28
+ }
29
+ /** An item's widths with its label and folded to its icon. */
30
+ export interface ItemWidth {
31
+ key: string;
32
+ full: number;
33
+ folded: number;
34
+ primary: boolean;
35
+ }
36
+ /**
37
+ * Fits a toolbar to `available` pixels one item at a time, stopping as soon as
38
+ * it fits, so it keeps every label the width allows. Items go lowest priority
39
+ * first: the right-hand ones, then the last group's, and so on, each from the
40
+ * end. First their labels fold to their icons, one by one; then, all folded,
41
+ * they move into the `…` menu in the same order; the primary action never
42
+ * moves, and its label folds only once nothing else is left to try.
43
+ */
44
+ export declare function fitToolbar(groups: ItemWidth[][], right: ItemWidth[], available: number): ToolbarFit;
45
+ /** Pins a toolbar to the top of the page's scroll area while the content scrolls under it. */
46
+ export declare const stickyToolbarClasses = "sticky top-0 z-(--layer-sticky) bg-(--theme-app-bg)";
47
+ /** A view's controls in one WAI-ARIA toolbar: a single tab stop, with the arrow
48
+ * keys moving between its items, the `…` menu and disabled ones included, so
49
+ * their reasons stay reachable. Action groups sit on the left and `right` holds
50
+ * secondary actions at the end. It stays one row: when it runs out of room
51
+ * labels fold to their icons one at a time, then actions move into a `…` menu,
52
+ * the right-hand ones first and the primary action never. Give each action its
53
+ * own icon, since a folded one is known by it, and mark the one action the
54
+ * view leads to `primary`. */
55
+ export declare function ActionToolbar({ groups, right, sticky, label, }: {
23
56
  groups: ToolbarItem[][];
24
57
  right?: ToolbarItem[];
25
- /** Pin below the breadcrumb strip while the page scrolls. Requires the toolbar's parent to span the page content. */
58
+ /** Pins it to the top of the page's scroll area while the page scrolls. */
26
59
  sticky?: boolean;
60
+ /** Names the toolbar for assistive technology, such as "Log controls";
61
+ * defaults to "Actions". */
62
+ label?: string | undefined;
27
63
  }): import("react").JSX.Element;
28
64
  export {};
@@ -1,57 +1,93 @@
1
1
  import { cx } from "../cx.js";
2
- import { MoreIcon } from "../icons.js";
3
- import { MenuPopup } from "../components/Menu.js";
4
2
  import { buttonClasses } from "../components/buttonClasses.js";
3
+ import { MoreIcon } from "../icons.js";
4
+ import { MenuPopup, MenuSeparator } from "../components/Menu.js";
5
5
  import { Tooltip } from "../components/Tooltip.js";
6
- import { useLink, useStrings } from "../components/Provider.js";
6
+ import { useStrings } from "../components/Provider.js";
7
+ import { AppLink } from "../components/AppLink.js";
7
8
  import { MenuEntries, useRunAction, warnIfInert } from "../components/MenuEntries.js";
8
- import { Button } from "../components/Button.js";
9
9
  import { Menu } from "@base-ui/react/menu";
10
10
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
- import { Fragment as Fragment$1, createContext, useContext, useLayoutEffect, useRef, useState } from "react";
11
+ import { Fragment as Fragment$1, cloneElement, createContext, isValidElement, use, useLayoutEffect, useRef, useState } from "react";
12
+ import { Button } from "@base-ui/react/button";
12
13
  import { Toggle } from "@base-ui/react/toggle";
14
+ import { Toolbar } from "@base-ui/react/toolbar";
13
15
  //#region src/list/ActionToolbar.tsx
14
- var OverflowMenuContext = createContext(false);
15
- function ToolbarItemView({ item }) {
16
- if ("element" in item) return /* @__PURE__ */ jsx(Fragment, { children: item.element });
17
- return /* @__PURE__ */ jsx(ToolbarButton, { action: item });
16
+ var PlacementContext = createContext("alone");
17
+ var FoldedContext = createContext(false);
18
+ /** A toolbar button's classes: outlined unless it's the view's one primary
19
+ * action, so the toolbar has a hierarchy; a toggle shows its state by
20
+ * `aria-pressed` instead of a fill. A destructive one reads in the error
21
+ * color, as it does in a menu. */
22
+ function actionClasses(action, iconOnly) {
23
+ const primary = action.primary && action.checked === void 0;
24
+ return cx(buttonClasses({
25
+ variant: primary ? "primary" : "outline",
26
+ size: "sm",
27
+ iconOnly
28
+ }), action.destructive && !primary && "text-(--theme-error-text)");
18
29
  }
19
- /** A toolbar action as a button: a link with `href`, a toggle with `checked`. */
30
+ /** A toolbar action as a button: a link with `href`, a toggle with `checked`.
31
+ * In an ActionToolbar it is one of its items, reached with the arrow keys. */
20
32
  function ToolbarButton({ action }) {
21
- const inOverflowMenu = useContext(OverflowMenuContext);
22
- const Link = useLink();
33
+ const placement = use(PlacementContext);
23
34
  const runAction = useRunAction();
24
- if (inOverflowMenu) return /* @__PURE__ */ jsx(MenuEntries, { entries: [action] });
25
- const className = buttonClasses({
26
- variant: action.checked === false ? "outline" : "primary",
27
- size: "md"
28
- });
29
- const content = /* @__PURE__ */ jsxs(Fragment, { children: [action.icon, action.label] });
35
+ const folded = use(FoldedContext);
36
+ if (placement === "menu") return /* @__PURE__ */ jsx(MenuEntries, { entries: [action] });
30
37
  warnIfInert(action, "ActionToolbar");
38
+ const iconOnly = Boolean(action.icon) && placement === "toolbar" && folded;
39
+ const className = actionClasses(action, iconOnly);
40
+ const reason = action.disabled ? action.disabledReason : void 0;
41
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
42
+ action.icon,
43
+ iconOnly ? /* @__PURE__ */ jsx("span", {
44
+ className: "sr-only",
45
+ children: action.label
46
+ }) : action.label,
47
+ reason && /* @__PURE__ */ jsxs("span", {
48
+ className: "sr-only",
49
+ children: [". ", reason]
50
+ })
51
+ ] });
31
52
  const run = () => runAction(action);
53
+ const inToolbar = placement === "toolbar";
32
54
  let control;
33
- if (action.href && !action.disabled) control = /* @__PURE__ */ jsx(Link, {
34
- href: action.href,
35
- className,
36
- children: content
37
- });
38
- else if (action.checked !== void 0) control = /* @__PURE__ */ jsx(Toggle, {
39
- pressed: action.checked,
40
- onPressedChange: run,
41
- disabled: action.disabled,
42
- className,
43
- children: content
44
- });
45
- else control = /* @__PURE__ */ jsx(Button, {
46
- variant: "primary",
47
- size: "md",
48
- onClick: run,
49
- disabled: action.disabled,
50
- focusableWhenDisabled: true,
51
- children: content
52
- });
55
+ if (action.href) {
56
+ const link = /* @__PURE__ */ jsx(AppLink, {
57
+ href: action.href,
58
+ reloadDocument: action.reloadDocument,
59
+ target: action.target,
60
+ disabled: action.disabled,
61
+ className
62
+ });
63
+ control = inToolbar ? /* @__PURE__ */ jsx(Toolbar.Link, {
64
+ render: link,
65
+ children: content
66
+ }) : cloneElement(link, void 0, content);
67
+ } else if (action.checked !== void 0) {
68
+ const toggle = /* @__PURE__ */ jsx(Toggle, {
69
+ pressed: action.checked,
70
+ onPressedChange: run,
71
+ disabled: action.disabled,
72
+ className
73
+ });
74
+ control = inToolbar ? /* @__PURE__ */ jsx(Toolbar.Button, {
75
+ render: toggle,
76
+ disabled: action.disabled,
77
+ children: content
78
+ }) : cloneElement(toggle, void 0, content);
79
+ } else {
80
+ const Control = inToolbar ? Toolbar.Button : Button;
81
+ control = /* @__PURE__ */ jsx(Control, {
82
+ onClick: run,
83
+ disabled: action.disabled,
84
+ focusableWhenDisabled: true,
85
+ className,
86
+ children: content
87
+ });
88
+ }
53
89
  return /* @__PURE__ */ jsx(Tooltip, {
54
- content: action.disabled ? action.disabledReason : action.tooltip,
90
+ content: reason ?? (iconOnly ? action.tooltip ?? action.label : action.tooltip),
55
91
  side: "bottom",
56
92
  children: control
57
93
  });
@@ -60,11 +96,12 @@ function OverflowMenu({ items }) {
60
96
  const { list: t } = useStrings();
61
97
  return /* @__PURE__ */ jsxs(Menu.Root, { children: [/* @__PURE__ */ jsx(Tooltip, {
62
98
  content: t.moreActions,
63
- children: /* @__PURE__ */ jsx(Menu.Trigger, {
99
+ children: /* @__PURE__ */ jsx(Toolbar.Button, {
100
+ render: /* @__PURE__ */ jsx(Menu.Trigger, {}),
64
101
  "aria-label": t.moreActions,
65
102
  className: buttonClasses({
66
103
  variant: "outline",
67
- size: "md",
104
+ size: "sm",
68
105
  iconOnly: true
69
106
  }),
70
107
  "data-testid": "action-toolbar-menu-button",
@@ -74,80 +111,239 @@ function OverflowMenu({ items }) {
74
111
  keepMounted: true,
75
112
  align: "end",
76
113
  className: "min-w-56",
77
- children: /* @__PURE__ */ jsx(OverflowMenuContext.Provider, {
78
- value: true,
79
- children: items.map((item) => "element" in item ? /* @__PURE__ */ jsx(Fragment$1, { children: item.element }, item.key) : /* @__PURE__ */ jsx(MenuEntries, { entries: [item] }, item.key))
114
+ children: /* @__PURE__ */ jsx(PlacementContext, {
115
+ value: "menu",
116
+ children: items.map((group, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [i > 0 && /* @__PURE__ */ jsx(MenuSeparator, {}), group.map((item) => "element" in item ? /* @__PURE__ */ jsx(Fragment$1, { children: item.element }, item.key) : /* @__PURE__ */ jsx(MenuEntries, { entries: [item] }, item.key))] }, group[0]?.key ?? i))
80
117
  })
81
118
  })] });
82
119
  }
83
- var MENU_BUTTON_WIDTH = 40;
120
+ var FITS_ALL = {
121
+ folded: [],
122
+ overflow: []
123
+ };
124
+ var GROUP_GAP = 10;
84
125
  var ITEM_GAP = 4;
85
- function fitCount(widths, available, gap, menuWidth) {
86
- if (widths.length === 0) return 0;
87
- if (widths.reduce((sum, w) => sum + w, 0) + gap * (widths.length - 1) <= available) return widths.length;
88
- let used = menuWidth;
89
- let count = 0;
90
- for (const w of widths) {
91
- if (used + gap + w > available) break;
92
- used += gap + w;
93
- count++;
126
+ var MENU_BUTTON_WIDTH = 28;
127
+ function rowWidth(groups, right, fit) {
128
+ const hidden = new Set(fit.overflow);
129
+ const folded = new Set(fit.folded);
130
+ const width = (item) => folded.has(item.key) ? item.folded : item.full;
131
+ const run = (items) => items.reduce((sum, item) => sum + width(item), 0) + ITEM_GAP * (items.length - 1);
132
+ const shownGroups = groups.map((group) => group.filter((item) => !hidden.has(item.key))).filter((group) => group.length > 0);
133
+ let total = shownGroups.reduce((sum, group) => sum + run(group), 0);
134
+ total += (shownGroups.length - 1) * 21;
135
+ const shownRight = right.filter((item) => !hidden.has(item.key));
136
+ const end = (shownRight.length > 0 ? run(shownRight) : 0) + (hidden.size > 0 ? MENU_BUTTON_WIDTH + (shownRight.length > 0 ? ITEM_GAP : 0) : 0);
137
+ if (end > 0) total += end + (shownGroups.length > 0 ? GROUP_GAP : 0);
138
+ return Math.max(total, 0);
139
+ }
140
+ /**
141
+ * Fits a toolbar to `available` pixels one item at a time, stopping as soon as
142
+ * it fits, so it keeps every label the width allows. Items go lowest priority
143
+ * first: the right-hand ones, then the last group's, and so on, each from the
144
+ * end. First their labels fold to their icons, one by one; then, all folded,
145
+ * they move into the `…` menu in the same order; the primary action never
146
+ * moves, and its label folds only once nothing else is left to try.
147
+ */
148
+ function fitToolbar(groups, right, available) {
149
+ const fits = (fit) => rowWidth(groups, right, fit) <= available + .5;
150
+ if (fits(FITS_ALL)) return FITS_ALL;
151
+ const byPriority = [...right].reverse().concat(...[...groups].reverse().map((g) => [...g].reverse()));
152
+ const rest = byPriority.filter((item) => !item.primary);
153
+ const folded = [];
154
+ for (const item of rest) {
155
+ if (item.folded >= item.full) continue;
156
+ folded.push(item.key);
157
+ const fit = {
158
+ folded: [...folded],
159
+ overflow: []
160
+ };
161
+ if (fits(fit)) return fit;
94
162
  }
95
- return count;
163
+ const overflow = [];
164
+ for (const item of rest) {
165
+ overflow.push(item.key);
166
+ const fit = {
167
+ folded: [...folded],
168
+ overflow: [...overflow]
169
+ };
170
+ if (fits(fit)) return fit;
171
+ }
172
+ const primary = byPriority.filter((item) => item.primary).map((item) => item.key);
173
+ return {
174
+ folded: [...folded, ...primary],
175
+ overflow
176
+ };
96
177
  }
97
- /** Measures in a layout effect (before paint) so the inline/overflow split never flashes. */
98
- function CollapsibleRight({ items }) {
99
- const wrapRef = useRef(null);
100
- const itemRefs = useRef({});
101
- const widthCache = useRef({});
102
- const [available, setAvailable] = useState(Number.POSITIVE_INFINITY);
103
- const [count, setCount] = useState(items.length);
178
+ var sameFit = (a, b) => a.folded.join("\n") === b.folded.join("\n") && a.overflow.join("\n") === b.overflow.join("\n");
179
+ var isPrimary = (item) => "label" in item && Boolean(item.primary);
180
+ /**
181
+ * Fits the toolbar to its own width. It measures a hidden copy of the actions,
182
+ * each with its label and folded, and caches the widths of element items as
183
+ * they render, so the answer doesn't depend on how the toolbar is folded at the
184
+ * moment and settles within one paint.
185
+ */
186
+ function useToolbarFit(root, copy, groups, right) {
187
+ const [fit, setFit] = useState(FITS_ALL);
188
+ const elementWidths = useRef(/* @__PURE__ */ new Map());
189
+ const measure = useRef(() => {});
190
+ measure.current = () => {
191
+ const available = root?.clientWidth ?? 0;
192
+ if (!root || !copy || available === 0) {
193
+ setFit((prev) => sameFit(prev, FITS_ALL) ? prev : FITS_ALL);
194
+ return;
195
+ }
196
+ const measured = /* @__PURE__ */ new Map();
197
+ for (const el of copy.querySelectorAll("[data-measure]")) {
198
+ const key = el.dataset["measure"] ?? "";
199
+ const widths = measured.get(key) ?? {};
200
+ widths[el.dataset["fold"] === "folded" ? "folded" : "full"] = el.getBoundingClientRect().width;
201
+ measured.set(key, widths);
202
+ }
203
+ for (const el of root.querySelectorAll("[data-toolbar-element]")) {
204
+ const key = el.dataset["toolbarElement"] ?? "";
205
+ const widths = elementWidths.current.get(key) ?? {};
206
+ widths[fit.folded.includes(key) ? "folded" : "full"] = el.getBoundingClientRect().width;
207
+ elementWidths.current.set(key, widths);
208
+ }
209
+ const widthsOf = (item) => {
210
+ const w = ("element" in item ? elementWidths.current : measured).get(item.key) ?? {};
211
+ const full = w.full ?? w.folded ?? 0;
212
+ return {
213
+ key: item.key,
214
+ full,
215
+ folded: w.folded ?? full,
216
+ primary: isPrimary(item)
217
+ };
218
+ };
219
+ const next = fitToolbar(groups.map((g) => g.map(widthsOf)), right.map(widthsOf), available);
220
+ setFit((prev) => sameFit(prev, next) ? prev : next);
221
+ };
222
+ useLayoutEffect(() => measure.current());
104
223
  useLayoutEffect(() => {
105
- const el = wrapRef.current;
106
- if (!el) return;
107
- const update = () => setAvailable(el.clientWidth);
108
- update();
109
- const observer = new ResizeObserver(update);
110
- observer.observe(el);
224
+ if (!root || !copy) return;
225
+ const observer = new ResizeObserver(() => measure.current());
226
+ observer.observe(root);
227
+ observer.observe(copy);
111
228
  return () => observer.disconnect();
112
- }, []);
113
- useLayoutEffect(() => {
114
- for (const key in itemRefs.current) {
115
- const el = itemRefs.current[key];
116
- if (el) widthCache.current[key] = el.offsetWidth;
117
- }
118
- const next = fitCount(items.map((item) => widthCache.current[item.key] ?? 0), available, ITEM_GAP, MENU_BUTTON_WIDTH);
119
- setCount((prev) => prev === next ? prev : next);
229
+ }, [root, copy]);
230
+ return fit;
231
+ }
232
+ /** The hidden copy `useToolbarFit` measures: each action with its label and
233
+ * folded to its icon, styled as its button is. */
234
+ function MeasuringCopy({ items, ref }) {
235
+ return /* @__PURE__ */ jsx("div", {
236
+ "aria-hidden": true,
237
+ inert: true,
238
+ className: "pointer-events-none invisible absolute top-0 left-0 size-0 overflow-hidden",
239
+ children: /* @__PURE__ */ jsx("div", {
240
+ ref,
241
+ className: "flex w-max gap-1",
242
+ children: items.map((item) => "element" in item ? null : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
243
+ "data-measure": item.key,
244
+ "data-fold": "full",
245
+ className: actionClasses(item, false),
246
+ children: [item.icon, item.label]
247
+ }), item.icon && /* @__PURE__ */ jsx("span", {
248
+ "data-measure": item.key,
249
+ "data-fold": "folded",
250
+ className: actionClasses(item, true),
251
+ children: item.icon
252
+ })] }, item.key))
253
+ })
120
254
  });
121
- const visible = items.slice(0, count);
122
- const overflow = items.slice(count);
123
- return /* @__PURE__ */ jsxs("div", {
124
- ref: wrapRef,
125
- className: "flex-1 min-w-0 flex items-center justify-end gap-1",
126
- children: [visible.map((item) => /* @__PURE__ */ jsx("span", {
127
- ref: (el) => {
128
- itemRefs.current[item.key] = el;
129
- },
255
+ }
256
+ function ItemSlot({ item, folded }) {
257
+ return /* @__PURE__ */ jsx(FoldedContext, {
258
+ value: folded,
259
+ children: "element" in item ? /* @__PURE__ */ jsx("span", {
260
+ "data-toolbar-element": item.key,
130
261
  className: "inline-flex shrink-0",
131
- children: /* @__PURE__ */ jsx(ToolbarItemView, { item })
132
- }, item.key)), overflow.length > 0 && /* @__PURE__ */ jsx(OverflowMenu, { items: overflow })]
262
+ children: item.element
263
+ }) : /* @__PURE__ */ jsx(ToolbarButton, { action: item })
133
264
  });
134
265
  }
135
- /** Pins a detail-page toolbar just below the sticky breadcrumb strip (top-10 matches the strip's 40px height). */
136
- var stickyToolbarClasses = "sticky top-10 z-(--layer-sticky) bg-(--theme-app-bg)";
137
- /** Action groups left, secondary actions right (collapsing into a `…` menu). */
138
- function ActionToolbar({ groups, right = [], sticky = false }) {
266
+ /** Pins a toolbar to the top of the page's scroll area while the content scrolls under it. */
267
+ var stickyToolbarClasses = "sticky top-0 z-(--layer-sticky) bg-(--theme-app-bg)";
268
+ /** A view's controls in one WAI-ARIA toolbar: a single tab stop, with the arrow
269
+ * keys moving between its items, the `…` menu and disabled ones included, so
270
+ * their reasons stay reachable. Action groups sit on the left and `right` holds
271
+ * secondary actions at the end. It stays one row: when it runs out of room
272
+ * labels fold to their icons one at a time, then actions move into a `…` menu,
273
+ * the right-hand ones first and the primary action never. Give each action its
274
+ * own icon, since a folded one is known by it, and mark the one action the
275
+ * view leads to `primary`. */
276
+ function ActionToolbar({ groups, right = [], sticky = false, label }) {
277
+ const { common } = useStrings();
278
+ const [root, setRoot] = useState(null);
279
+ const [copy, setCopy] = useState(null);
139
280
  const visibleGroups = groups.map((group) => group.filter((a) => !a.hidden)).filter((group) => group.length > 0);
140
281
  const visibleRight = right.filter((a) => !a.hidden);
141
- return /* @__PURE__ */ jsxs("div", {
142
- className: cx("flex items-center gap-2.5", sticky && cx("sticky top-10 z-(--layer-sticky) bg-(--theme-app-bg)", "py-1.5")),
143
- children: [visibleGroups.length > 0 && /* @__PURE__ */ jsx("div", {
144
- className: "flex items-center gap-2.5 shrink-0",
145
- children: visibleGroups.map((group, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [i > 0 && /* @__PURE__ */ jsx("div", { className: "w-px h-5 bg-(--theme-border)" }), /* @__PURE__ */ jsx("div", {
146
- className: "flex items-center gap-1",
147
- children: group.map((item) => /* @__PURE__ */ jsx(ToolbarItemView, { item }, item.key))
148
- })] }, group[0]?.key ?? i))
149
- }), visibleRight.length > 0 && /* @__PURE__ */ jsx(CollapsibleRight, { items: visibleRight })]
282
+ const all = [...visibleGroups.flat(), ...visibleRight];
283
+ warnIfManyPrimary(all);
284
+ warnIfIconsRepeat(all);
285
+ const fit = useToolbarFit(root, copy, visibleGroups, visibleRight);
286
+ const overflow = new Set(fit.overflow);
287
+ const folded = new Set(fit.folded);
288
+ const shown = (items) => items.filter((item) => !overflow.has(item.key));
289
+ const shownGroups = visibleGroups.map(shown).filter((group) => group.length > 0);
290
+ const shownRight = shown(visibleRight);
291
+ const menu = [...visibleGroups, visibleRight].map((group) => group.filter((item) => overflow.has(item.key))).filter((group) => group.length > 0);
292
+ return /* @__PURE__ */ jsxs(Toolbar.Root, {
293
+ ref: setRoot,
294
+ "aria-label": label ?? common.actions,
295
+ className: cx("relative flex min-w-0 items-center gap-2.5", sticky && cx("sticky top-0 z-(--layer-sticky) bg-(--theme-app-bg)", "py-1.5")),
296
+ children: [/* @__PURE__ */ jsx(MeasuringCopy, {
297
+ ref: setCopy,
298
+ items: all
299
+ }), /* @__PURE__ */ jsxs(PlacementContext, {
300
+ value: "toolbar",
301
+ children: [shownGroups.map((group, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [i > 0 && /* @__PURE__ */ jsx(Toolbar.Separator, {
302
+ orientation: "vertical",
303
+ className: "h-5 w-px shrink-0 bg-(--theme-border)"
304
+ }), /* @__PURE__ */ jsx(Toolbar.Group, {
305
+ className: "flex shrink-0 items-center gap-1",
306
+ children: group.map((item) => /* @__PURE__ */ jsx(ItemSlot, {
307
+ item,
308
+ folded: folded.has(item.key)
309
+ }, item.key))
310
+ })] }, group[0]?.key ?? i)), (shownRight.length > 0 || menu.length > 0) && /* @__PURE__ */ jsxs("div", {
311
+ className: "ml-auto flex shrink-0 items-center gap-1",
312
+ children: [shownRight.map((item) => /* @__PURE__ */ jsx(ItemSlot, {
313
+ item,
314
+ folded: folded.has(item.key)
315
+ }, item.key)), menu.length > 0 && /* @__PURE__ */ jsx(OverflowMenu, { items: menu })]
316
+ })]
317
+ })]
150
318
  });
151
319
  }
320
+ var warnedPrimary = /* @__PURE__ */ new Set();
321
+ /** Warns in development when more than one action is primary: the fill marks
322
+ * the one next step, so two of them mark none. */
323
+ function warnIfManyPrimary(items) {
324
+ if (process.env.NODE_ENV === "production") return;
325
+ const labels = items.flatMap((item) => "label" in item && item.primary ? [item.label] : []);
326
+ const names = labels.map((label) => `"${label}"`).join(", ");
327
+ if (labels.length < 2 || warnedPrimary.has(names)) return;
328
+ warnedPrimary.add(names);
329
+ console.warn(`ActionToolbar: ${names} are all primary; mark one action at most.`);
330
+ }
331
+ var warnedIcons = /* @__PURE__ */ new Set();
332
+ /** Warns in development when two actions share an icon: folded to their icons
333
+ * in a narrow toolbar, they would look the same. */
334
+ function warnIfIconsRepeat(items) {
335
+ if (process.env.NODE_ENV === "production") return;
336
+ const byIcon = /* @__PURE__ */ new Map();
337
+ for (const item of items) {
338
+ if ("element" in item || !isValidElement(item.icon) || typeof item.icon.type === "string") continue;
339
+ byIcon.set(item.icon.type, [...byIcon.get(item.icon.type) ?? [], item.label]);
340
+ }
341
+ for (const labels of byIcon.values()) {
342
+ const names = labels.map((label) => `"${label}"`).join(", ");
343
+ if (labels.length < 2 || warnedIcons.has(names)) continue;
344
+ warnedIcons.add(names);
345
+ console.warn(`ActionToolbar: ${names} share an icon, so they look the same once their labels fold; give each its own.`);
346
+ }
347
+ }
152
348
  //#endregion
153
- export { ActionToolbar, ToolbarButton, stickyToolbarClasses };
349
+ export { ActionToolbar, ToolbarButton, fitToolbar, stickyToolbarClasses };