@parallelworks/ui 0.77.0 → 0.79.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 (268) hide show
  1. package/README.md +42 -6
  2. package/dist/access/AccessDrawer.d.ts +49 -7
  3. package/dist/access/AccessDrawer.js +243 -38
  4. package/dist/access/AccessList.d.ts +19 -1
  5. package/dist/access/AccessList.js +220 -9
  6. package/dist/access/GrantView.d.ts +3 -1
  7. package/dist/access/GrantView.js +17 -4
  8. package/dist/access/PrincipalPicker.js +5 -5
  9. package/dist/access/focus.js +1 -1
  10. package/dist/access/index.d.ts +2 -2
  11. package/dist/access/index.js +2 -2
  12. package/dist/access/strings.d.ts +25 -1
  13. package/dist/access/strings.js +27 -3
  14. package/dist/access/types.d.ts +26 -0
  15. package/dist/ai/components/AllocationSelector.js +1 -1
  16. package/dist/ai/components/AttachmentManager.js +5 -5
  17. package/dist/ai/components/AttachmentUpload.js +2 -2
  18. package/dist/ai/components/BranchNavigator.js +1 -1
  19. package/dist/ai/components/ChatActivity.js +1 -1
  20. package/dist/ai/components/ChatEmptyState.js +3 -3
  21. package/dist/ai/components/ChatInput.js +3 -5
  22. package/dist/ai/components/ChatLayout.js +1 -1
  23. package/dist/ai/components/ChatMessage.js +1 -1
  24. package/dist/ai/components/ChatMessageList.js +23 -8
  25. package/dist/ai/components/ChatSidebar.js +3 -3
  26. package/dist/ai/components/ChatThread.js +4 -4
  27. package/dist/ai/components/ComposerAddMenu.js +9 -20
  28. package/dist/ai/components/ModelSelector.js +3 -3
  29. package/dist/ai/components/PastedText.js +5 -5
  30. package/dist/ai/components/SessionView.js +1 -1
  31. package/dist/ai/components/ShareDialog.js +3 -3
  32. package/dist/ai/components/SlashMenu.d.ts +31 -4
  33. package/dist/ai/components/SlashMenu.js +36 -63
  34. package/dist/ai/components/agent/ActivityLine.js +1 -1
  35. package/dist/ai/components/agent/AgentMessageParts.js +13 -13
  36. package/dist/ai/components/conversationActions.js +3 -3
  37. package/dist/ai/core/ChatProvider.js +1 -1
  38. package/dist/ai/core/config.js +1 -1
  39. package/dist/ai/ui/ConversationSidebar.js +3 -3
  40. package/dist/ai/ui/sidebar.js +3 -3
  41. package/dist/assets/yaml.worker-DOBV2lND.js +884 -0
  42. package/dist/components/ActionMenu.d.ts +38 -9
  43. package/dist/components/ActionMenu.js +48 -22
  44. package/dist/components/Avatar.d.ts +66 -6
  45. package/dist/components/Avatar.js +130 -18
  46. package/dist/components/Breadcrumbs.d.ts +4 -0
  47. package/dist/components/Breadcrumbs.js +26 -10
  48. package/dist/components/Button.d.ts +3 -2
  49. package/dist/components/Button.js +11 -1
  50. package/dist/components/Callout.d.ts +3 -2
  51. package/dist/components/Callout.js +3 -2
  52. package/dist/components/Card.d.ts +33 -9
  53. package/dist/components/Card.js +24 -8
  54. package/dist/components/Checkbox.d.ts +3 -1
  55. package/dist/components/Checkbox.js +4 -2
  56. package/dist/components/ColorInput.js +1 -1
  57. package/dist/components/Combobox.d.ts +23 -0
  58. package/dist/components/Combobox.js +252 -86
  59. package/dist/components/ConfirmModal.d.ts +28 -2
  60. package/dist/components/ConfirmModal.js +100 -15
  61. package/dist/components/ContextMenu.d.ts +29 -2
  62. package/dist/components/ContextMenu.js +60 -8
  63. package/dist/components/CopyButton.d.ts +21 -8
  64. package/dist/components/CopyButton.js +29 -9
  65. package/dist/components/CreateModal.d.ts +20 -4
  66. package/dist/components/CreateModal.js +28 -17
  67. package/dist/components/DatePicker.d.ts +31 -1
  68. package/dist/components/DatePicker.js +178 -47
  69. package/dist/components/DescriptionList.d.ts +13 -3
  70. package/dist/components/DescriptionList.js +43 -11
  71. package/dist/components/Disclosure.d.ts +10 -2
  72. package/dist/components/Disclosure.js +18 -7
  73. package/dist/components/Drawer.js +5 -5
  74. package/dist/components/EmptyState.d.ts +12 -4
  75. package/dist/components/EmptyState.js +18 -10
  76. package/dist/components/ErrorPage.d.ts +40 -0
  77. package/dist/components/ErrorPage.js +101 -0
  78. package/dist/components/ExternalLink.d.ts +4 -1
  79. package/dist/components/ExternalLink.js +4 -5
  80. package/dist/components/Field.d.ts +21 -6
  81. package/dist/components/Field.js +32 -16
  82. package/dist/components/FileButton.d.ts +19 -0
  83. package/dist/components/FileButton.js +32 -0
  84. package/dist/components/HoverCard.d.ts +26 -6
  85. package/dist/components/HoverCard.js +11 -5
  86. package/dist/components/IconButton.js +4 -2
  87. package/dist/components/InfoTip.js +3 -3
  88. package/dist/components/Input.d.ts +33 -3
  89. package/dist/components/Input.js +149 -14
  90. package/dist/components/Kbd.d.ts +40 -0
  91. package/dist/components/Kbd.js +168 -0
  92. package/dist/components/Listbox.d.ts +103 -0
  93. package/dist/components/Listbox.js +190 -0
  94. package/dist/components/Loader.d.ts +8 -2
  95. package/dist/components/Loader.js +16 -1
  96. package/dist/components/Markdown.js +1 -1
  97. package/dist/components/MarkdownImpl.js +1 -1
  98. package/dist/components/Menu.d.ts +20 -2
  99. package/dist/components/Menu.js +48 -19
  100. package/dist/components/MenuEntries.d.ts +41 -4
  101. package/dist/components/MenuEntries.js +266 -39
  102. package/dist/components/Meter.d.ts +50 -11
  103. package/dist/components/Meter.js +71 -21
  104. package/dist/components/Modal.d.ts +9 -3
  105. package/dist/components/Modal.js +68 -29
  106. package/dist/components/OneTimeCodeInput.js +1 -1
  107. package/dist/components/PageHeader.js +111 -7
  108. package/dist/components/PageHeaderAction.d.ts +8 -3
  109. package/dist/components/PageHeaderAction.js +122 -34
  110. package/dist/components/Pagination.d.ts +13 -1
  111. package/dist/components/Pagination.js +90 -19
  112. package/dist/components/Popover.d.ts +16 -2
  113. package/dist/components/Popover.js +20 -21
  114. package/dist/components/Provider.d.ts +172 -5
  115. package/dist/components/Provider.js +157 -14
  116. package/dist/components/RefreshButton.d.ts +13 -6
  117. package/dist/components/RefreshButton.js +17 -9
  118. package/dist/components/RunStatusIcon.d.ts +16 -7
  119. package/dist/components/RunStatusIcon.js +21 -8
  120. package/dist/components/Section.d.ts +11 -4
  121. package/dist/components/Section.js +33 -22
  122. package/dist/components/SegmentedControl.d.ts +16 -3
  123. package/dist/components/SegmentedControl.js +7 -3
  124. package/dist/components/Select.d.ts +19 -3
  125. package/dist/components/Select.js +114 -68
  126. package/dist/components/SelectionCopy.d.ts +10 -0
  127. package/dist/components/SelectionCopy.js +105 -0
  128. package/dist/components/SettingModeOption.js +1 -1
  129. package/dist/components/SettingsCard.js +1 -1
  130. package/dist/components/Skeleton.js +1 -1
  131. package/dist/components/StatusBadge.d.ts +55 -10
  132. package/dist/components/StatusBadge.js +91 -15
  133. package/dist/components/StickyBar.js +1 -1
  134. package/dist/components/Table.d.ts +22 -4
  135. package/dist/components/Table.js +46 -24
  136. package/dist/components/Tabs.d.ts +9 -4
  137. package/dist/components/Tabs.js +9 -4
  138. package/dist/components/Tag.d.ts +49 -0
  139. package/dist/components/Tag.js +199 -0
  140. package/dist/components/ThemeEditor.js +1 -1
  141. package/dist/components/Toast.js +1 -1
  142. package/dist/components/ToggleGroup.d.ts +4 -1
  143. package/dist/components/ToggleGroup.js +30 -13
  144. package/dist/components/Tooltip.d.ts +9 -3
  145. package/dist/components/Tooltip.js +55 -39
  146. package/dist/components/buttonClasses.d.ts +5 -2
  147. package/dist/components/buttonClasses.js +11 -10
  148. package/dist/components/chart.d.ts +69 -0
  149. package/dist/components/chart.js +145 -0
  150. package/dist/components/comboboxItems.d.ts +7 -1
  151. package/dist/components/comboboxItems.js +6 -2
  152. package/dist/components/dismiss.d.ts +5 -1
  153. package/dist/components/dismiss.js +6 -2
  154. package/dist/components/floating.d.ts +4 -4
  155. package/dist/components/floating.js +5 -5
  156. package/dist/components/headerActionsFit.d.ts +37 -0
  157. package/dist/components/headerActionsFit.js +81 -0
  158. package/dist/components/pageHeaderStore.d.ts +3 -0
  159. package/dist/components/pageHeaderStore.js +3 -0
  160. package/dist/components/pathBreaks.js +2 -2
  161. package/dist/components/popupContainer.d.ts +17 -0
  162. package/dist/components/popupContainer.js +69 -0
  163. package/dist/components/relativeTime.d.ts +21 -10
  164. package/dist/components/relativeTime.js +50 -22
  165. package/dist/components/segmented.d.ts +18 -4
  166. package/dist/components/segmented.js +48 -6
  167. package/dist/components/typedDate.d.ts +5 -0
  168. package/dist/components/typedDate.js +50 -0
  169. package/dist/components/useClosingValue.d.ts +4 -0
  170. package/dist/components/useClosingValue.js +12 -0
  171. package/dist/components/useCopy.d.ts +6 -0
  172. package/dist/components/useCopy.js +3 -3
  173. package/dist/components/useNarrow.d.ts +2 -0
  174. package/dist/components/useNarrow.js +16 -0
  175. package/dist/editor/Editor.js +1 -1
  176. package/dist/editor/FormCodePanel.js +1 -1
  177. package/dist/editor/Monaco.js +1 -1
  178. package/dist/editor/workers.js +1 -1
  179. package/dist/file-explorer/FileExplorer.js +16 -15
  180. package/dist/file-explorer/FileExplorerContext.js +2 -2
  181. package/dist/file-explorer/FilePreview/Viewer.js +3 -3
  182. package/dist/file-explorer/FilePreview/index.js +2 -2
  183. package/dist/file-explorer/FileRowsWindow.js +3 -3
  184. package/dist/file-explorer/FileTable.js +1 -1
  185. package/dist/file-explorer/LoadMoreRow.js +1 -1
  186. package/dist/file-explorer/TreeView.js +5 -5
  187. package/dist/file-explorer/helpers.js +2 -2
  188. package/dist/file-explorer/toasts.js +2 -2
  189. package/dist/form/Fields/CheckboxGroupField.js +1 -1
  190. package/dist/form/Fields/DropdownField.js +1 -1
  191. package/dist/form/Fields/DurationField.js +2 -2
  192. package/dist/form/Fields/MultiDropdownField.js +1 -1
  193. package/dist/form/Fields/NumberField.js +1 -1
  194. package/dist/form/Fields/ObjectField.js +1 -1
  195. package/dist/form/Fields/RangeField.js +1 -1
  196. package/dist/form/Fields/StringField.js +1 -1
  197. package/dist/form/Form.js +3 -3
  198. package/dist/form/FormLayout.js +1 -1
  199. package/dist/form/Wizard/WizardContainer.js +1 -1
  200. package/dist/form/Wizard/WizardNavigation.js +1 -1
  201. package/dist/form/Wizard/WizardStepContent.js +1 -1
  202. package/dist/form/fieldRegistry.js +1 -1
  203. package/dist/form/formEditing.js +1 -1
  204. package/dist/format.d.ts +17 -7
  205. package/dist/format.js +39 -16
  206. package/dist/graph/AnnotationBanner.js +2 -2
  207. package/dist/graph/Connectors.js +5 -5
  208. package/dist/graph/DependencyGraph.js +10 -9
  209. package/dist/graph/GraphEditor.js +4 -4
  210. package/dist/graph/GraphEditorDialogs.js +13 -12
  211. package/dist/graph/GraphNode.js +1 -1
  212. package/dist/graph/InputDialog.js +5 -5
  213. package/dist/graph/InputsEditor.js +10 -9
  214. package/dist/graph/MatrixGroup.js +2 -2
  215. package/dist/graph/ProblemPageLink.d.ts +9 -0
  216. package/dist/graph/ProblemPageLink.js +21 -0
  217. package/dist/graph/ProblemsButton.js +26 -16
  218. package/dist/graph/Reveal.js +1 -1
  219. package/dist/graph/RunWarningsList.js +21 -12
  220. package/dist/graph/ShortcutsButton.js +25 -8
  221. package/dist/graph/StepSummaries.js +1 -1
  222. package/dist/graph/TreeView.js +2 -2
  223. package/dist/graph/WorkflowSettingsDialog.js +3 -3
  224. package/dist/graph/editorApi.d.ts +10 -0
  225. package/dist/graph/editorFields.js +3 -3
  226. package/dist/graph/editorPrimitives.js +1 -1
  227. package/dist/graph/editorRows.js +8 -6
  228. package/dist/graph/editorStrings.d.ts +1 -0
  229. package/dist/graph/editorStrings.js +1 -0
  230. package/dist/graph/fieldProblems.js +2 -2
  231. package/dist/graph/inputRefs.js +7 -6
  232. package/dist/graph/runWarnings.d.ts +12 -1
  233. package/dist/graph/stepWith.js +2 -2
  234. package/dist/index.d.ts +30 -21
  235. package/dist/index.js +20 -12
  236. package/dist/list/ActionToolbar.d.ts +4 -0
  237. package/dist/list/ActionToolbar.js +35 -12
  238. package/dist/list/ListFilterBar.d.ts +42 -0
  239. package/dist/list/ListFilterBar.js +789 -0
  240. package/dist/list/ListPage.d.ts +42 -4
  241. package/dist/list/ListPage.js +56 -22
  242. package/dist/list/ListTable.d.ts +27 -3
  243. package/dist/list/ListTable.js +48 -23
  244. package/dist/list/ListToolbar.d.ts +31 -0
  245. package/dist/list/ListToolbar.js +43 -0
  246. package/dist/list/ListViewControls.d.ts +8 -4
  247. package/dist/list/ListViewControls.js +22 -14
  248. package/dist/list/UserHoverCard.d.ts +8 -2
  249. package/dist/list/UserHoverCard.js +26 -13
  250. package/dist/list/filterModel.d.ts +122 -0
  251. package/dist/list/filterModel.js +308 -0
  252. package/dist/list/index.d.ts +6 -2
  253. package/dist/list/index.js +6 -2
  254. package/dist/list/listSearch.d.ts +1 -1
  255. package/dist/list/listSearch.js +8 -4
  256. package/dist/list/listView.d.ts +24 -2
  257. package/dist/list/listView.js +47 -45
  258. package/dist/list/rowMenu.d.ts +10 -5
  259. package/dist/list/rowMenu.js +17 -7
  260. package/dist/list/useListFilters.d.ts +68 -0
  261. package/dist/list/useListFilters.js +252 -0
  262. package/dist/logviewer/LogViewer.js +4 -4
  263. package/dist/styles/theme.css +94 -0
  264. package/dist/styles.css +1 -1
  265. package/package.json +11 -11
  266. package/dist/assets/yaml.worker-k9AdOqzf.js +0 -1441
  267. package/dist/components/fullscreen.d.ts +0 -4
  268. package/dist/components/fullscreen.js +0 -18
@@ -1,43 +1,74 @@
1
1
  import { useStrings } from "./Provider.js";
2
2
  import { Button } from "./Button.js";
3
+ import { ErrorText } from "./Field.js";
3
4
  import { Modal } from "./Modal.js";
4
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
- import { useRef, useState } from "react";
5
+ import { useCallback, useEffect, useRef, useState } from "react";
6
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
7
  //#region src/components/ConfirmModal.tsx
8
+ /** What the reader types or picks in, which takes focus ahead of the buttons. A checkbox or
9
+ * radio doesn't: a destructive dialog with one still opens on Cancel. Inputs a picker keeps
10
+ * out of the tab order, for its form value, aren't fields. */
11
+ var FIELDS = [
12
+ "input:not([disabled]):not([type=\"hidden\"]):not([type=\"checkbox\"]):not([type=\"radio\"])",
13
+ "select:not([disabled])",
14
+ "textarea:not([disabled])",
15
+ "[role=\"combobox\"]:not([disabled]):not([aria-disabled=\"true\"])",
16
+ "[contenteditable=\"true\"]"
17
+ ].map((field) => `${field}:not([tabindex="-1"]):not([aria-hidden="true"])`).join(", ");
7
18
  /** Asks before an action: its title the question, its description what follows,
8
19
  * and Cancel beside a confirm button named for the action. */
9
- function ConfirmModal({ open, onClose, title, description, children, confirmLabel, onConfirm, confirmDisabled = false, destructive = false, align = "top", cancelLabel, closeOnConfirm = true }) {
20
+ function ConfirmModal({ open, onClose, title, description, children, confirmLabel, onConfirm, confirmDisabled = false, destructive = false, align = "top", cancelLabel, closeOnConfirm = true, initialFocus, pending: pendingProp = false, error, size = "md" }) {
10
21
  const { common } = useStrings();
11
- const [pending, setPending] = useState(false);
12
- const running = useRef(false);
22
+ const [running, setRunning] = useState(false);
23
+ const fired = useRef(false);
24
+ const cancelButton = useRef(null);
25
+ const confirmButton = useRef(null);
26
+ const bodyElement = useRef(null);
27
+ useEffect(() => {
28
+ if (open) fired.current = false;
29
+ }, [open]);
30
+ const pending = running || pendingProp;
13
31
  const runConfirm = async () => {
14
- if (running.current) return;
15
- running.current = true;
16
- setPending(true);
32
+ if (fired.current || pendingProp) return;
33
+ fired.current = true;
34
+ setRunning(true);
35
+ let closing = false;
17
36
  try {
18
37
  await onConfirm();
19
- if (closeOnConfirm) onClose();
38
+ closing = closeOnConfirm;
39
+ if (closing) onClose();
20
40
  } finally {
21
- running.current = false;
22
- setPending(false);
41
+ fired.current = closing;
42
+ setRunning(false);
23
43
  }
24
44
  };
45
+ const body = children !== void 0 && children !== null && children !== false ? error ? /* @__PURE__ */ jsxs("div", {
46
+ className: "flex flex-col gap-3",
47
+ children: [children, /* @__PURE__ */ jsx(ErrorText, { children: error })]
48
+ }) : children : error ? /* @__PURE__ */ jsx(ErrorText, { children: error }) : void 0;
25
49
  return /* @__PURE__ */ jsx(Modal, {
26
50
  alert: destructive,
27
51
  open,
28
52
  onClose,
29
53
  align,
30
54
  dismissible: !pending,
31
- size: "md",
55
+ size,
32
56
  title,
33
57
  description,
34
- footer: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Button, {
58
+ initialFocus: () => {
59
+ const button = (initialFocus === "cancel" || initialFocus !== "confirm" && destructive ? cancelButton : confirmButton).current;
60
+ if (initialFocus === "cancel" || initialFocus === "confirm") return button ?? true;
61
+ return bodyElement.current?.querySelector(FIELDS) ?? button ?? true;
62
+ },
63
+ footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Button, {
64
+ ref: cancelButton,
35
65
  variant: "ghost",
36
66
  size: "sm",
37
67
  onClick: onClose,
38
68
  disabled: pending,
39
69
  children: cancelLabel ?? common.cancel
40
70
  }), /* @__PURE__ */ jsx(Button, {
71
+ ref: confirmButton,
41
72
  variant: destructive ? "danger" : "primary",
42
73
  size: "sm",
43
74
  onClick: runConfirm,
@@ -45,8 +76,62 @@ function ConfirmModal({ open, onClose, title, description, children, confirmLabe
45
76
  loading: pending,
46
77
  children: confirmLabel
47
78
  })] }),
48
- children
79
+ children: body !== void 0 && /* @__PURE__ */ jsx("div", {
80
+ ref: bodyElement,
81
+ className: "contents",
82
+ children: body
83
+ })
49
84
  });
50
85
  }
86
+ /** Asks from anywhere, such as a menu row, without keeping a dialog's state by hand:
87
+ * `const { confirm, dialog } = useConfirm()`, render `dialog` once, then
88
+ * `confirm({ title, confirmLabel, destructive, onConfirm })`. It resolves true once
89
+ * confirmed and `onConfirm` has settled, and false when the reader cancels. */
90
+ function useConfirm() {
91
+ const [request, setRequest] = useState(null);
92
+ const [open, setOpen] = useState(false);
93
+ const [error, setError] = useState(void 0);
94
+ const settle = useRef(null);
95
+ const finish = useCallback((confirmed) => {
96
+ const resolve = settle.current;
97
+ settle.current = null;
98
+ resolve?.(confirmed);
99
+ }, []);
100
+ const confirm = useCallback((next) => {
101
+ finish(false);
102
+ setRequest(next);
103
+ setError(void 0);
104
+ setOpen(true);
105
+ return new Promise((resolve) => {
106
+ settle.current = resolve;
107
+ });
108
+ }, [finish]);
109
+ const close = useCallback(() => {
110
+ setOpen(false);
111
+ finish(false);
112
+ }, [finish]);
113
+ return {
114
+ confirm,
115
+ dialog: request && /* @__PURE__ */ jsx(ConfirmModal, {
116
+ ...request,
117
+ open,
118
+ onClose: close,
119
+ error,
120
+ closeOnConfirm: false,
121
+ onConfirm: async () => {
122
+ if (!settle.current) return;
123
+ setError(void 0);
124
+ try {
125
+ await request.onConfirm();
126
+ } catch (failure) {
127
+ setError(request.errorMessage?.(failure));
128
+ return;
129
+ }
130
+ finish(true);
131
+ if (request.closeOnConfirm !== false) setOpen(false);
132
+ }
133
+ })
134
+ };
135
+ }
51
136
  //#endregion
52
- export { ConfirmModal };
137
+ export { ConfirmModal, useConfirm };
@@ -1,17 +1,44 @@
1
+ import { type ReactNode } from 'react';
1
2
  import { type FloatingAnchor } from './floating.js';
3
+ import { type MenuSize } from './Menu.js';
2
4
  import { type MenuEntry, type MenuSearch } from './MenuEntries.js';
3
5
  export interface OpenMenuOptions {
4
6
  search?: MenuSearch | undefined;
5
7
  /** Called once the menu closes, or another menu replaces it. */
6
8
  onClose?: (() => void) | undefined;
9
+ /** As `MenuPopup`'s: `sm` rows for a compact surface. */
10
+ size?: MenuSize | undefined;
11
+ /** As `MenuPopup`'s: classes on the menu and its submenus, such as a terminal's colors. */
12
+ themeClassName?: string | undefined;
7
13
  }
8
- export type OpenMenu = (at: FloatingAnchor, items: MenuEntry[], options?: OpenMenuOptions) => void;
14
+ /** Where a menu opens: an element, such as the button that opened it, or a pointer event,
15
+ * such as a right-click. An event with Shift held is left to the browser, whose own menu
16
+ * then shows; any other has its default prevented. */
17
+ export type MenuOpener = FloatingAnchor & {
18
+ shiftKey?: boolean;
19
+ preventDefault?: () => void;
20
+ };
21
+ /** Opens a menu of `items` at `at`. Returns false when it opened none: no items, Shift held,
22
+ * or `at` is the element whose menu is open, which it closes instead. */
23
+ export type OpenMenu = (at: MenuOpener, items: MenuEntry[], options?: OpenMenuOptions) => boolean | void;
9
24
  /**
10
25
  * One menu that any number of rows, buttons or a canvas open with their own
11
26
  * items, so a long list holds a single menu rather than one per row. Render
12
- * `contextMenu` once.
27
+ * `contextMenu` once. Most hosts want the one `UIProvider` mounts, through
28
+ * `useOpenMenu`; this is for a menu scoped to one region.
13
29
  */
14
30
  export declare function useContextMenu(): {
15
31
  openMenu: OpenMenu;
16
32
  contextMenu: import("react").JSX.Element | null;
33
+ openedBy: Element | null;
17
34
  };
35
+ /** The one menu every row, button and canvas below it opens through `useOpenMenu`, so none
36
+ * renders a menu of its own. `UIProvider` mounts it; nothing else needs to. */
37
+ export declare function ContextMenuProvider({ children }: {
38
+ children: ReactNode;
39
+ }): import("react").JSX.Element;
40
+ /** Opens the app's one shared menu: `openMenu(e, items)` from a right-click, or
41
+ * `openMenu(button, items)` under a button, which a second press closes. */
42
+ export declare function useOpenMenu(): OpenMenu;
43
+ /** The element the shared menu is open under, so its button can say it's expanded. */
44
+ export declare function useMenuOpenedBy(): Element | null;
@@ -1,38 +1,60 @@
1
1
  import { toPositionerAnchor } from "./floating.js";
2
2
  import { MenuPopup } from "./Menu.js";
3
+ import { isDev } from "../dev.js";
3
4
  import { MenuEntries, MenuFilter } from "./MenuEntries.js";
4
5
  import { Menu } from "@base-ui/react/menu";
5
- import { jsx } from "react/jsx-runtime";
6
- import { useCallback, useRef, useState } from "react";
6
+ import { createContext, use, useCallback, useRef, useState } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
7
8
  //#region src/components/ContextMenu.tsx
8
9
  /**
9
10
  * One menu that any number of rows, buttons or a canvas open with their own
10
11
  * items, so a long list holds a single menu rather than one per row. Render
11
- * `contextMenu` once.
12
+ * `contextMenu` once. Most hosts want the one `UIProvider` mounts, through
13
+ * `useOpenMenu`; this is for a menu scoped to one region.
12
14
  */
13
15
  function useContextMenu() {
14
16
  const [opened, setOpened] = useState(null);
15
17
  const [open, setOpen] = useState(false);
16
18
  const owner = useRef(null);
19
+ const current = useRef(null);
17
20
  const release = useCallback(() => {
18
21
  const was = owner.current;
19
22
  owner.current = null;
20
23
  was?.onClose?.();
21
24
  }, []);
22
25
  const openMenu = useCallback((at, items, options) => {
23
- if (items.length === 0) return;
26
+ const element = at instanceof Element ? at : null;
27
+ if (!element && at.shiftKey || items.length === 0) return false;
28
+ if (element && current.current?.element === element) {
29
+ current.current = null;
30
+ setOpen(false);
31
+ return false;
32
+ }
33
+ if (!element) at.preventDefault?.();
24
34
  release();
25
35
  const next = {
26
36
  ...options,
27
37
  anchor: toPositionerAnchor(at),
38
+ element,
28
39
  items
29
40
  };
30
41
  owner.current = next;
42
+ current.current = next;
31
43
  setOpened(next);
32
44
  setOpen(true);
45
+ return true;
33
46
  }, [release]);
34
- const onOpenChange = useCallback((next) => {
35
- if (!next) setOpen(false);
47
+ const onOpenChange = useCallback((next, details) => {
48
+ if (next) return;
49
+ const element = current.current?.element;
50
+ const event = details.event;
51
+ const target = details.reason === "focus-out" && event instanceof FocusEvent ? event.relatedTarget : event?.target;
52
+ if ((details.reason === "outside-press" || details.reason === "focus-out") && element && target instanceof Node && element.contains(target)) {
53
+ details.cancel();
54
+ return;
55
+ }
56
+ current.current = null;
57
+ setOpen(false);
36
58
  }, []);
37
59
  const onOpenChangeComplete = useCallback((next) => {
38
60
  if (!next) release();
@@ -48,6 +70,8 @@ function useContextMenu() {
48
70
  modal: false,
49
71
  children: /* @__PURE__ */ jsx(MenuPopup, {
50
72
  anchor: opened.anchor,
73
+ size: opened.size,
74
+ themeClassName: opened.themeClassName,
51
75
  children: /* @__PURE__ */ jsx(MenuEntries, {
52
76
  entries: opened.items,
53
77
  search: opened.search,
@@ -55,8 +79,36 @@ function useContextMenu() {
55
79
  })
56
80
  })
57
81
  })
58
- }, opened.search ? "search" : "plain")
82
+ }, opened.search ? "search" : "plain"),
83
+ openedBy: open ? opened?.element ?? null : null
59
84
  };
60
85
  }
86
+ var OpenMenuContext = createContext(null);
87
+ var OpenedByContext = createContext(null);
88
+ /** The one menu every row, button and canvas below it opens through `useOpenMenu`, so none
89
+ * renders a menu of its own. `UIProvider` mounts it; nothing else needs to. */
90
+ function ContextMenuProvider({ children }) {
91
+ const { openMenu, contextMenu, openedBy } = useContextMenu();
92
+ return /* @__PURE__ */ jsx(OpenMenuContext, {
93
+ value: openMenu,
94
+ children: /* @__PURE__ */ jsxs(OpenedByContext, {
95
+ value: openedBy,
96
+ children: [children, contextMenu]
97
+ })
98
+ });
99
+ }
100
+ var warnNoProvider = () => {
101
+ if (isDev()) console.warn("useOpenMenu: no ContextMenuProvider or UIProvider above, so no menu opens.");
102
+ return false;
103
+ };
104
+ /** Opens the app's one shared menu: `openMenu(e, items)` from a right-click, or
105
+ * `openMenu(button, items)` under a button, which a second press closes. */
106
+ function useOpenMenu() {
107
+ return use(OpenMenuContext) ?? warnNoProvider;
108
+ }
109
+ /** The element the shared menu is open under, so its button can say it's expanded. */
110
+ function useMenuOpenedBy() {
111
+ return use(OpenedByContext);
112
+ }
61
113
  //#endregion
62
- export { useContextMenu };
114
+ export { ContextMenuProvider, useContextMenu, useMenuOpenedBy, useOpenMenu };
@@ -1,4 +1,4 @@
1
- import type { ComponentPropsWithRef, ReactNode } from 'react';
1
+ import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
2
  import { type ButtonSize, type ButtonVariant } from './buttonClasses.js';
3
3
  export interface CopyButtonProps extends Omit<ComponentPropsWithRef<'button'>, 'onClick' | 'children' | 'type'> {
4
4
  variant?: ButtonVariant | undefined;
@@ -14,25 +14,38 @@ export interface CopyButtonProps extends Omit<ComponentPropsWithRef<'button'>, '
14
14
  /** Shows "Copy" (then "Copied") beside the icon, for a copy that is a toolbar's
15
15
  * command rather than a detail beside a value. */
16
16
  showLabel?: boolean | undefined;
17
+ /** A glyph in place of the copy icon, such as a branch for a branch name; the check
18
+ * still shows once it has copied. */
19
+ icon?: ReactNode | undefined;
20
+ /** The whole success toast, in place of "Copied …", as `useCopy` takes it. */
21
+ success?: string | undefined;
22
+ /** The whole failure toast, such as one that says where else to copy it from. */
23
+ failure?: string | undefined;
17
24
  }
18
25
  /** The one copy control: a button that copies its text, turns into a check for a
19
26
  * moment, and says so in a toast, which screen readers announce. */
20
- export declare function CopyButton({ text, label, quiet, showLabel, variant, size, ...props }: CopyButtonProps): import("react").JSX.Element;
27
+ export declare function CopyButton({ text, label, quiet, showLabel, variant, size, icon: glyph, success, failure, ...props }: CopyButtonProps): import("react").JSX.Element;
21
28
  export interface CopyCodeBlockProps {
22
29
  /** What the button copies: the code as the reader would type it. */
23
30
  text: string;
24
31
  /** Names what it copies, as CopyButton's `label` does, such as "install command". */
25
32
  label?: string | undefined;
26
- /** The code as shown, which may be masked or highlighted. */
27
- children: ReactNode;
28
- /** Adds an eye button that shows or hides the value; the caller masks `children`
29
- * while `revealed` is false. */
33
+ /** The code as shown, such as highlighted; `text` by default. A secret's own children
34
+ * must mask it while it is hidden. */
35
+ children?: ReactNode;
36
+ /** Adds an eye button that shows or hides the value. Without `children` the block masks
37
+ * the value itself, with dots that don't give away its length. */
30
38
  secret?: boolean | undefined;
39
+ /** Whether a secret shows. Leave it out for the block to keep its own state, hidden first. */
31
40
  revealed?: boolean | undefined;
41
+ defaultRevealed?: boolean | undefined;
32
42
  onRevealedChange?: ((revealed: boolean) => void) | undefined;
43
+ /** Breaks a long value across lines instead of scrolling it, such as a token. */
44
+ wrap?: boolean | undefined;
33
45
  className?: string | undefined;
34
46
  }
35
47
  /** A block of code, such as a command to run, with a button that copies it. The
36
48
  * buttons show while the pointer is over the block or focus is in it, and always
37
- * where there is no hover to reveal them. */
38
- export declare function CopyCodeBlock({ text, label, children, secret, revealed, onRevealedChange, className, }: CopyCodeBlockProps): import("react").JSX.Element;
49
+ * where there is no hover to reveal them. With `secret` it holds a value shown once,
50
+ * such as a new API key: masked until the eye shows it, and copied either way. */
51
+ export declare function CopyCodeBlock({ text, label, children, secret, revealed: revealedProp, defaultRevealed, onRevealedChange, wrap, className, }: CopyCodeBlockProps): import("react").JSX.Element;
@@ -4,18 +4,21 @@ import { CheckIcon, CopyIcon, EyeIcon, EyeOffIcon } from "../icons.js";
4
4
  import { useStrings } from "./Provider.js";
5
5
  import { useCopy } from "./useCopy.js";
6
6
  import { IconButton } from "./IconButton.js";
7
- import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { useState } from "react";
8
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
9
  //#region src/components/CopyButton.tsx
9
10
  /** The one copy control: a button that copies its text, turns into a check for a
10
11
  * moment, and says so in a toast, which screen readers announce. */
11
- function CopyButton({ text, label, quiet = false, showLabel = false, variant = showLabel ? "outline" : "ghost", size = "sm", ...props }) {
12
+ function CopyButton({ text, label, quiet = false, showLabel = false, variant = showLabel ? "outline" : "ghost", size = "sm", icon: glyph, success, failure, ...props }) {
12
13
  const { common: t } = useStrings();
13
14
  const { copy, copied } = useCopy();
14
15
  const name = label ? copied ? t.copiedThing(label) : t.copyThing(label) : copied ? t.copied : t.copy;
15
- const icon = copied ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-(--theme-success)" }) : /* @__PURE__ */ jsx(CopyIcon, {});
16
+ const icon = copied ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-(--theme-success)" }) : glyph ?? /* @__PURE__ */ jsx(CopyIcon, {});
16
17
  const onClick = () => void copy(typeof text === "function" ? text() : text, {
17
18
  label,
18
- quiet
19
+ quiet,
20
+ success,
21
+ failure
19
22
  });
20
23
  if (showLabel) return /* @__PURE__ */ jsxs("button", {
21
24
  type: "button",
@@ -37,24 +40,41 @@ function CopyButton({ text, label, quiet = false, showLabel = false, variant = s
37
40
  onClick
38
41
  });
39
42
  }
43
+ var MASK = "•".repeat(24);
40
44
  /** A block of code, such as a command to run, with a button that copies it. The
41
45
  * buttons show while the pointer is over the block or focus is in it, and always
42
- * where there is no hover to reveal them. */
43
- function CopyCodeBlock({ text, label, children, secret = false, revealed = false, onRevealedChange, className }) {
46
+ * where there is no hover to reveal them. With `secret` it holds a value shown once,
47
+ * such as a new API key: masked until the eye shows it, and copied either way. */
48
+ function CopyCodeBlock({ text, label, children, secret = false, revealed: revealedProp, defaultRevealed = false, onRevealedChange, wrap = false, className }) {
44
49
  const { common: t } = useStrings();
50
+ const [ownRevealed, setOwnRevealed] = useState(defaultRevealed);
51
+ const revealed = revealedProp ?? ownRevealed;
52
+ const setRevealed = (next) => {
53
+ setOwnRevealed(next);
54
+ onRevealedChange?.(next);
55
+ };
45
56
  const reveal = "opacity-0 group-hover/code:opacity-100 group-focus-within/code:opacity-100 pointer-coarse:opacity-100";
57
+ let shown = children ?? text;
58
+ if (secret && !revealed && children === void 0) shown = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
59
+ "aria-hidden": "true",
60
+ className: "whitespace-nowrap",
61
+ children: MASK
62
+ }), /* @__PURE__ */ jsx("span", {
63
+ className: "sr-only",
64
+ children: t.hiddenValue
65
+ })] });
46
66
  return /* @__PURE__ */ jsxs("div", {
47
67
  className: cx("group/code relative", className),
48
68
  children: [/* @__PURE__ */ jsx("pre", {
49
- className: cx("m-0 overflow-x-auto rounded-lg border border-(--theme-border) bg-(--theme-muted-panel-bg) p-4 text-left font-mono text-sm text-(--theme-app)", secret ? "pr-20" : "pr-12"),
50
- children
69
+ className: cx("m-0 rounded-lg border border-(--theme-border) bg-(--theme-muted-panel-bg) p-4 text-left font-mono text-sm text-(--theme-app)", wrap ? "whitespace-pre-wrap break-all" : "overflow-x-auto", secret ? "pr-20" : "pr-12"),
70
+ children: shown
51
71
  }), /* @__PURE__ */ jsxs("div", {
52
72
  className: "absolute top-2 right-2 flex items-center gap-1",
53
73
  children: [secret && /* @__PURE__ */ jsx(IconButton, {
54
74
  label: t.showValue,
55
75
  icon: revealed ? /* @__PURE__ */ jsx(EyeIcon, {}) : /* @__PURE__ */ jsx(EyeOffIcon, {}),
56
76
  pressed: revealed,
57
- onClick: () => onRevealedChange?.(!revealed),
77
+ onClick: () => setRevealed(!revealed),
58
78
  className: cx("bg-(--theme-muted-panel-bg)", reveal)
59
79
  }), /* @__PURE__ */ jsx(CopyButton, {
60
80
  text,
@@ -1,6 +1,7 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import { type ComboboxItems } from './comboboxItems.js';
3
- import type { MenuEntry } from './MenuEntries.js';
3
+ import type { MenuEntry, MenuSearch } from './MenuEntries.js';
4
+ import { type ModalSize } from './Modal.js';
4
5
  interface CreateModalProps {
5
6
  open: boolean;
6
7
  onClose: () => void;
@@ -8,11 +9,16 @@ interface CreateModalProps {
8
9
  typeLabel: string;
9
10
  /** Makes the type chip a dropdown to switch between sibling form types. */
10
11
  typeMenu?: MenuEntry[] | undefined;
12
+ /** A search atop the type chip's menu, for a long list such as many teams. */
13
+ typeMenuSearch?: MenuSearch | undefined;
11
14
  namePlaceholder: string;
12
15
  hideName?: boolean;
13
16
  initialName?: string | undefined;
14
17
  showDescription?: boolean;
15
18
  descriptionPlaceholder?: string;
19
+ /** Takes the description's place, such as a rich text editor. Typing in it counts as
20
+ * unsaved input, as the description's does. */
21
+ descriptionField?: ReactNode;
16
22
  submitLabel?: string;
17
23
  submittingLabel?: string;
18
24
  validateName?: ((name: string) => string | null) | undefined;
@@ -34,11 +40,21 @@ interface CreateModalProps {
34
40
  dirty?: boolean;
35
41
  /** Show a favorite toggle in the footer. */
36
42
  showFavorite?: boolean;
37
- /** Resolves true to close the modal, false to keep it open (e.g. on error). */
38
- onSubmit: (name: string, description: string, favorite: boolean) => Promise<boolean>;
43
+ /** Muted text at the footer's start, such as which keys submit. `error` takes its place. */
44
+ footerHint?: ReactNode;
45
+ /** Why the last submit failed, at the footer's start, read out as it appears. */
46
+ error?: ReactNode;
47
+ /** Its width, as `Modal`'s: `xl` for a long body such as a rich text editor. It narrows to
48
+ * fit a small window. */
49
+ size?: ModalSize | undefined;
50
+ /** Resolves true to close the modal, false to keep it open (e.g. on error). `modifier` is
51
+ * true when submitted with ⌘/Ctrl+Enter, so a host can create and then open what it made. */
52
+ onSubmit: (name: string, description: string, favorite: boolean, how: {
53
+ modifier: boolean;
54
+ }) => Promise<boolean>;
39
55
  }
40
56
  /** Submits on Enter in the name field or ⌘/Ctrl+Enter from anywhere in the panel. */
41
- export declare function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceholder, hideName, initialName, showDescription, descriptionPlaceholder, submitLabel, submittingLabel, validateName, sanitizeName, nameHint, children, properties, advanced, submitDisabled, hideSubmit, nameOptional, onNameChange, dirty, showFavorite, onSubmit, }: CreateModalProps): import("react").JSX.Element;
57
+ export declare function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, typeMenuSearch, namePlaceholder, hideName, initialName, showDescription, descriptionPlaceholder, descriptionField, submitLabel, submittingLabel, validateName, sanitizeName, nameHint, children, properties, advanced, submitDisabled, hideSubmit, nameOptional, onNameChange, dirty, showFavorite, footerHint, error, size, onSubmit, }: CreateModalProps): import("react").JSX.Element;
42
58
  /** Compact property pill with an on/off switch. */
43
59
  export declare function CreateModalSwitch({ label, checked, onCheckedChange, tooltip, }: {
44
60
  label: string;
@@ -5,17 +5,18 @@ import { Tooltip } from "./Tooltip.js";
5
5
  import { useStrings } from "./Provider.js";
6
6
  import { ActionMenu } from "./ActionMenu.js";
7
7
  import { Button } from "./Button.js";
8
+ import { ErrorText } from "./Field.js";
8
9
  import { comboboxLeaves } from "./comboboxItems.js";
9
10
  import { Combobox } from "./Combobox.js";
10
11
  import { Modal } from "./Modal.js";
11
12
  import { Disclosure } from "./Disclosure.js";
12
13
  import { Switch } from "./Switch.js";
13
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
14
  import { useId, useRef, useState } from "react";
15
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
15
16
  import { Toggle } from "@base-ui/react/toggle";
16
17
  //#region src/components/CreateModal.tsx
17
18
  /** Submits on Enter in the name field or ⌘/Ctrl+Enter from anywhere in the panel. */
18
- function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceholder, hideName = false, initialName, showDescription = true, descriptionPlaceholder, submitLabel, submittingLabel, validateName, sanitizeName, nameHint, children, properties, advanced, submitDisabled = false, hideSubmit = false, nameOptional = false, onNameChange, dirty = false, showFavorite = false, onSubmit }) {
19
+ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, typeMenuSearch, namePlaceholder, hideName = false, initialName, showDescription = true, descriptionPlaceholder, descriptionField, submitLabel, submittingLabel, validateName, sanitizeName, nameHint, children, properties, advanced, submitDisabled = false, hideSubmit = false, nameOptional = false, onNameChange, dirty = false, showFavorite = false, footerHint, error, size = "lg", onSubmit }) {
19
20
  const t = useStrings().modal;
20
21
  const { common } = useStrings();
21
22
  const submitText = submitLabel ?? common.create;
@@ -54,7 +55,7 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
54
55
  setNameFlash(false);
55
56
  requestAnimationFrame(() => setNameFlash(true));
56
57
  };
57
- const handleSubmit = async () => {
58
+ const handleSubmit = async (modifier = false) => {
58
59
  if (!canSubmit) {
59
60
  if (!hideName && !submitting && (!name.trim() || nameError)) flashName();
60
61
  return;
@@ -62,7 +63,7 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
62
63
  setSubmitting(true);
63
64
  let close = false;
64
65
  try {
65
- close = await onSubmit(name.trim(), description.trim(), favorite);
66
+ close = await onSubmit(name.trim(), description.trim(), favorite, { modifier });
66
67
  } catch (error) {
67
68
  console.error(error);
68
69
  } finally {
@@ -74,19 +75,19 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
74
75
  open,
75
76
  onClose,
76
77
  "aria-label": `${submitText}: ${typeLabel}`,
77
- size: "lg",
78
+ size,
78
79
  dismissible: !isDirty,
79
80
  initialFocus: () => nameRef.current ?? true,
80
81
  onKeyDown: (e) => {
81
- if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) handleSubmit();
82
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) handleSubmit(true);
82
83
  },
83
84
  onMouseDown: (e) => {
84
85
  if (e.target instanceof Element && !e.target.closest("input, textarea, button, a, select, label, code, pre, .select-all")) e.preventDefault();
85
86
  },
86
- footer: /* @__PURE__ */ jsxs(Fragment, { children: [
87
- showFavorite && /* @__PURE__ */ jsx("div", {
88
- className: "me-auto",
89
- children: /* @__PURE__ */ jsx(Tooltip, {
87
+ footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [
88
+ (showFavorite || footerHint || error) && /* @__PURE__ */ jsxs("div", {
89
+ className: "me-auto flex min-w-0 items-center gap-3",
90
+ children: [showFavorite && /* @__PURE__ */ jsx(Tooltip, {
90
91
  content: favorite ? t.favoriteHintOn : t.favoriteHintOff,
91
92
  children: /* @__PURE__ */ jsxs(Toggle, {
92
93
  pressed: favorite,
@@ -98,7 +99,10 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
98
99
  }),
99
100
  children: [favorite ? /* @__PURE__ */ jsx(FavoriteIcon, { className: "text-(--theme-favorite)" }) : /* @__PURE__ */ jsx(FavoriteOutlineIcon, {}), favorite ? t.favorited : t.favorite]
100
101
  })
101
- })
102
+ }), error ? /* @__PURE__ */ jsx(ErrorText, { children: error }) : footerHint && /* @__PURE__ */ jsx("p", {
103
+ className: "m-0 min-w-0 text-xs text-(--theme-muted-text-color)",
104
+ children: footerHint
105
+ })]
102
106
  }),
103
107
  /* @__PURE__ */ jsx(Button, {
104
108
  variant: "ghost",
@@ -109,7 +113,7 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
109
113
  !hideSubmit && /* @__PURE__ */ jsx(Button, {
110
114
  variant: "primary",
111
115
  size: "sm",
112
- onClick: handleSubmit,
116
+ onClick: () => handleSubmit(false),
113
117
  "aria-disabled": !canSubmit,
114
118
  loading: submitting,
115
119
  children: submitting ? submittingText : submitText
@@ -117,11 +121,15 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
117
121
  ] }),
118
122
  children: /* @__PURE__ */ jsxs("div", {
119
123
  onChangeCapture: () => setInteracted(true),
124
+ onInputCapture: (e) => {
125
+ if (e.target instanceof HTMLElement && e.target.isContentEditable) setInteracted(true);
126
+ },
120
127
  children: [
121
128
  /* @__PURE__ */ jsxs("div", { children: [
122
129
  typeMenu && typeMenu.length > 0 ? /* @__PURE__ */ jsxs(ActionMenu, {
123
130
  items: typeMenu,
124
131
  label: typeLabel,
132
+ search: typeMenuSearch,
125
133
  triggerClassName: "inline-flex items-center gap-1.5 px-1.5 py-1 rounded-md bg-(--theme-muted-panel-bg) text-xs font-medium text-(--theme-muted-text-color) transition-colors hover:text-(--theme-app)",
126
134
  children: [
127
135
  typeIcon,
@@ -132,7 +140,7 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
132
140
  className: "inline-flex items-center gap-1.5 px-1.5 py-1 rounded-md bg-(--theme-muted-panel-bg) text-xs font-medium text-(--theme-muted-text-color)",
133
141
  children: [typeIcon, typeLabel]
134
142
  }),
135
- hideName ? /* @__PURE__ */ jsx("div", { className: "mt-3" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
143
+ hideName ? /* @__PURE__ */ jsx("div", { className: "mt-3" }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
136
144
  /* @__PURE__ */ jsx("input", {
137
145
  ref: nameRef,
138
146
  type: "text",
@@ -151,7 +159,7 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
151
159
  if (e.key === "Enter" && !e.nativeEvent.isComposing && !e.metaKey && !e.ctrlKey) {
152
160
  e.preventDefault();
153
161
  e.stopPropagation();
154
- handleSubmit();
162
+ handleSubmit(false);
155
163
  }
156
164
  },
157
165
  placeholder: namePlaceholder,
@@ -172,7 +180,10 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
172
180
  className: "mt-1 text-xs text-(--theme-muted-text-color)",
173
181
  children: hint
174
182
  }),
175
- showDescription ? /* @__PURE__ */ jsx("textarea", {
183
+ showDescription && descriptionField ? /* @__PURE__ */ jsx("div", {
184
+ className: "mt-1.5",
185
+ children: descriptionField
186
+ }) : showDescription ? /* @__PURE__ */ jsx("textarea", {
176
187
  autoComplete: "off",
177
188
  "data-1p-ignore": true,
178
189
  value: description,
@@ -232,9 +243,9 @@ function CreateModalSelect({ label, icon, value, items, onValueChange, disabled
232
243
  label: item
233
244
  } : item).find((item) => item.value === value);
234
245
  const selectedLabel = selected?.label ?? (value || void 0);
235
- const pillContent = /* @__PURE__ */ jsxs(Fragment, { children: [
246
+ const pillContent = /* @__PURE__ */ jsxs(Fragment$1, { children: [
236
247
  selected?.icon ?? icon,
237
- selectedLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
248
+ selectedLabel ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
238
249
  className: "font-normal text-(--theme-muted-text-color)",
239
250
  children: label
240
251
  }), selectedLabel] }) : label,