@parallelworks/ui 0.40.1 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/dist/ai/adapter/memoryStore.js +7 -0
- package/dist/ai/adapter/mock/mockAdapter.js +52 -17
- package/dist/ai/adapter/openai/createOpenAIStream.js +1 -1
- package/dist/ai/adapter/openai/index.d.ts +1 -1
- package/dist/ai/adapter/openai/sse.d.ts +8 -2
- package/dist/ai/adapter/openai/sse.js +40 -4
- package/dist/ai/adapter/openai/wire.d.ts +6 -0
- package/dist/ai/components/AllocationSelector.d.ts +3 -4
- package/dist/ai/components/AllocationSelector.js +37 -33
- package/dist/ai/components/AttachmentManager.js +7 -7
- package/dist/ai/components/AttachmentUpload.js +5 -5
- package/dist/ai/components/BranchNavigator.js +1 -1
- package/dist/ai/components/ChatEmptyState.js +2 -2
- package/dist/ai/components/ChatInput.js +10 -8
- package/dist/ai/components/ChatLayout.js +4 -5
- package/dist/ai/components/ChatMessage.js +12 -12
- package/dist/ai/components/ChatMessageList.js +9 -9
- package/dist/ai/components/ChatSidebar.js +8 -9
- package/dist/ai/components/ChatThread.js +4 -4
- package/dist/ai/components/ComposerChrome.d.ts +2 -2
- package/dist/ai/components/ComposerChrome.js +3 -6
- package/dist/ai/components/DragOverlay.js +2 -2
- package/dist/ai/components/ModelSelector.d.ts +5 -3
- package/dist/ai/components/ModelSelector.js +102 -339
- package/dist/ai/components/PastedText.js +11 -11
- package/dist/ai/components/ProviderIssueBanner.d.ts +2 -0
- package/dist/ai/components/ProviderIssueBanner.js +34 -16
- package/dist/ai/components/Reasoning.js +4 -4
- package/dist/ai/components/ShareDialog.js +43 -35
- package/dist/ai/components/SlashMenu.d.ts +12 -2
- package/dist/ai/components/SlashMenu.js +29 -13
- package/dist/ai/components/agent/ActivityLine.js +3 -3
- package/dist/ai/components/agent/AgentMessageParts.js +20 -20
- package/dist/ai/components/agent/PermissionPicker.js +13 -11
- package/dist/ai/components/conversationActions.d.ts +4 -6
- package/dist/ai/components/conversationActions.js +9 -13
- package/dist/ai/core/ChatProvider.js +4 -4
- package/dist/ai/core/config.js +1 -1
- package/dist/ai/core/parts.d.ts +5 -0
- package/dist/ai/core/parts.js +28 -1
- package/dist/ai/core/providerIssues.d.ts +7 -0
- package/dist/ai/core/providerIssues.js +9 -1
- package/dist/ai/core/useKeyboardShortcuts.d.ts +4 -0
- package/dist/ai/core/useKeyboardShortcuts.js +8 -2
- package/dist/ai/index.d.ts +0 -1
- package/dist/ai/index.js +1 -2
- package/dist/ai/strings.d.ts +19 -0
- package/dist/ai/strings.js +18 -1
- package/dist/ai/ui/Avatar.js +5 -5
- package/dist/ai/ui/ConversationSidebar.d.ts +0 -1
- package/dist/ai/ui/ConversationSidebar.js +6 -7
- package/dist/ai/ui/Markdown.js +3 -3
- package/dist/ai/ui/Notice.js +6 -6
- package/dist/ai/ui/chip.d.ts +4 -0
- package/dist/ai/ui/chip.js +8 -0
- package/dist/ai/ui/sidebar.d.ts +6 -5
- package/dist/ai/ui/sidebar.js +39 -43
- package/dist/components/ActionMenu.d.ts +13 -0
- package/dist/components/ActionMenu.js +30 -0
- package/dist/components/Avatar.js +6 -6
- package/dist/components/Breadcrumbs.js +1 -1
- package/dist/components/Button.js +10 -10
- package/dist/components/Callout.js +2 -2
- package/dist/components/Card.js +3 -3
- package/dist/components/Combobox.d.ts +66 -0
- package/dist/components/Combobox.js +393 -0
- package/dist/components/ConfirmModal.js +11 -11
- package/dist/components/ContextMenu.d.ts +23 -0
- package/dist/components/ContextMenu.js +89 -0
- package/dist/components/CopyToClipboard.js +2 -2
- package/dist/components/CreateModal.d.ts +17 -36
- package/dist/components/CreateModal.js +97 -259
- package/dist/components/DescriptionList.js +8 -8
- package/dist/components/Filter.js +2 -2
- package/dist/components/FilterPill.js +2 -2
- package/dist/components/HoverCard.d.ts +14 -0
- package/dist/components/HoverCard.js +33 -0
- package/dist/components/IconButton.d.ts +5 -5
- package/dist/components/IconButton.js +18 -22
- package/dist/components/InfoTip.d.ts +15 -0
- package/dist/components/InfoTip.js +60 -0
- package/dist/components/Input.js +5 -5
- package/dist/components/LetterBadge.js +2 -2
- package/dist/components/Loader.js +3 -3
- package/dist/components/Markdown.js +1 -1
- package/dist/components/MarkdownImpl.js +2 -2
- package/dist/components/Menu.d.ts +33 -0
- package/dist/components/Menu.js +86 -0
- package/dist/components/MenuEntries.d.ts +56 -0
- package/dist/components/MenuEntries.js +123 -0
- package/dist/components/Modal.d.ts +29 -0
- package/dist/components/Modal.js +47 -0
- package/dist/components/Overview.js +11 -10
- package/dist/components/PageHeader.d.ts +10 -16
- package/dist/components/PageHeader.js +69 -95
- package/dist/components/Pagination.js +5 -5
- package/dist/components/Provider.d.ts +5 -11
- package/dist/components/Provider.js +11 -14
- package/dist/components/Radio.d.ts +8 -0
- package/dist/components/Radio.js +16 -0
- package/dist/components/SectionHeader.js +2 -2
- package/dist/components/SegmentedControl.d.ts +6 -5
- package/dist/components/SegmentedControl.js +34 -30
- package/dist/components/Select.d.ts +27 -0
- package/dist/components/Select.js +78 -0
- package/dist/components/SettingModeOption.d.ts +5 -8
- package/dist/components/SettingModeOption.js +10 -12
- package/dist/components/SettingRow.js +4 -4
- package/dist/components/SettingsCard.js +4 -4
- package/dist/components/SettingsGroup.js +2 -2
- package/dist/components/Sort.js +1 -1
- package/dist/components/StatusBadge.js +7 -7
- package/dist/components/StatusIcons.js +4 -4
- package/dist/components/Switch.d.ts +22 -0
- package/dist/components/Switch.js +28 -0
- package/dist/components/Table.js +11 -11
- package/dist/components/Tooltip.d.ts +24 -20
- package/dist/components/Tooltip.js +58 -76
- package/dist/components/floating.d.ts +14 -0
- package/dist/components/floating.js +21 -0
- package/dist/components/search.d.ts +2 -0
- package/dist/components/search.js +14 -0
- package/dist/editor/Editor.js +1 -1
- package/dist/editor/EditorField.js +16 -21
- package/dist/editor/FormCodePanel.js +19 -19
- package/dist/editor/Monaco.js +3 -3
- package/dist/file-explorer/FileExplorer.js +77 -81
- package/dist/file-explorer/FileExplorerContext.js +2 -2
- package/dist/file-explorer/FilePreview/CodePreviewEditor.js +1 -1
- package/dist/file-explorer/FilePreview/Inline.js +1 -1
- package/dist/file-explorer/FilePreview/StreamedBadge.js +5 -6
- package/dist/file-explorer/FilePreview/Viewer.js +8 -8
- package/dist/file-explorer/FilePreview/index.d.ts +1 -1
- package/dist/file-explorer/FilePreview/index.js +49 -83
- package/dist/file-explorer/FileRow.d.ts +4 -3
- package/dist/file-explorer/FileRow.js +32 -38
- package/dist/file-explorer/FileRowsWindow.d.ts +3 -2
- package/dist/file-explorer/FileRowsWindow.js +4 -4
- package/dist/file-explorer/FileTable.d.ts +3 -2
- package/dist/file-explorer/FileTable.js +3 -3
- package/dist/file-explorer/LoadMoreRow.js +1 -1
- package/dist/file-explorer/TreeView.js +11 -16
- package/dist/file-explorer/helpers.js +11 -12
- package/dist/file-explorer/toasts.js +11 -11
- package/dist/form/FieldGroup.d.ts +11 -0
- package/dist/form/FieldGroup.js +36 -0
- package/dist/form/FieldWrapper.js +4 -4
- package/dist/form/Fields/BooleanField.js +23 -33
- package/dist/form/Fields/CheckboxGroupField.d.ts +1 -1
- package/dist/form/Fields/CheckboxGroupField.js +9 -13
- package/dist/form/Fields/ColorField.d.ts +1 -2
- package/dist/form/Fields/ColorField.js +6 -11
- package/dist/form/Fields/DropdownField.d.ts +3 -13
- package/dist/form/Fields/DropdownField.js +40 -27
- package/dist/form/Fields/DurationField.d.ts +1 -2
- package/dist/form/Fields/DurationField.js +25 -32
- package/dist/form/Fields/LabelField.js +2 -2
- package/dist/form/Fields/MultiDropdownField.d.ts +6 -12
- package/dist/form/Fields/MultiDropdownField.js +31 -22
- package/dist/form/Fields/NumberField.d.ts +1 -1
- package/dist/form/Fields/NumberField.js +65 -35
- package/dist/form/Fields/ObjectField.d.ts +1 -1
- package/dist/form/Fields/ObjectField.js +12 -43
- package/dist/form/Fields/RadioField.d.ts +1 -1
- package/dist/form/Fields/RadioField.js +30 -41
- package/dist/form/Fields/RangeField.d.ts +1 -2
- package/dist/form/Fields/RangeField.js +23 -16
- package/dist/form/Fields/StringField.d.ts +1 -2
- package/dist/form/Fields/StringField.js +58 -26
- package/dist/form/Fields/TextAreaField.js +12 -10
- package/dist/form/Form.d.ts +30 -48
- package/dist/form/Form.js +306 -412
- package/dist/form/FormLayout.js +9 -9
- package/dist/form/Wizard/WizardContainer.d.ts +1 -4
- package/dist/form/Wizard/WizardContainer.js +40 -56
- package/dist/form/Wizard/WizardNavigation.js +1 -1
- package/dist/form/Wizard/WizardStepContent.d.ts +1 -5
- package/dist/form/Wizard/WizardStepContent.js +11 -16
- package/dist/form/Wizard/WizardStepIndicator.js +6 -6
- package/dist/form/Wizard/types.d.ts +0 -14
- package/dist/form/fieldRegistry.d.ts +1 -1
- package/dist/form/fieldRegistry.js +6 -6
- package/dist/form/formEditing.js +1 -1
- package/dist/form/index.d.ts +5 -4
- package/dist/form/index.js +6 -7
- package/dist/form/types/fieldComponentTypes.d.ts +8 -10
- package/dist/form/useChoiceField.d.ts +20 -0
- package/dist/form/useChoiceField.js +49 -0
- package/dist/form/useFieldValue.d.ts +7 -0
- package/dist/form/useFieldValue.js +20 -0
- package/dist/form/useParsedOpts.d.ts +3 -1
- package/dist/form/useParsedOpts.js +12 -17
- package/dist/form/utils/dependentOptions.d.ts +8 -4
- package/dist/form/utils/dependentOptions.js +25 -17
- package/dist/form/utils/fieldItems.d.ts +10 -0
- package/dist/form/utils/fieldItems.js +11 -0
- package/dist/form/utils/fieldPath.d.ts +10 -0
- package/dist/form/utils/fieldPath.js +20 -0
- package/dist/form/utils/shareEqual.d.ts +6 -0
- package/dist/form/utils/shareEqual.js +38 -0
- package/dist/graph/AnnotationBanner.js +8 -8
- package/dist/graph/Collapse.d.ts +1 -0
- package/dist/graph/Collapse.js +6 -27
- package/dist/graph/Connectors.js +5 -5
- package/dist/graph/DependencyGraph.js +20 -19
- package/dist/graph/GraphEditor.js +30 -41
- package/dist/graph/GraphEditorDialogs.js +17 -17
- package/dist/graph/GraphNode.js +1 -1
- package/dist/graph/InputDialog.js +19 -22
- package/dist/graph/InputsEditor.js +58 -66
- package/dist/graph/JobSummary.js +42 -39
- package/dist/graph/MatrixGroup.js +1 -1
- package/dist/graph/ProblemsButton.js +18 -19
- package/dist/graph/Reveal.js +1 -1
- package/dist/graph/ShortcutsButton.js +15 -18
- package/dist/graph/SuggestionInput.d.ts +5 -10
- package/dist/graph/SuggestionInput.js +14 -18
- package/dist/graph/ToolbarPopover.d.ts +11 -6
- package/dist/graph/ToolbarPopover.js +35 -67
- package/dist/graph/TreeView.js +24 -37
- package/dist/graph/WorkflowSettingsDialog.js +4 -4
- package/dist/graph/editorChrome.js +13 -12
- package/dist/graph/editorFields.js +29 -29
- package/dist/graph/editorPrimitives.d.ts +1 -1
- package/dist/graph/editorPrimitives.js +10 -7
- package/dist/graph/editorRows.js +103 -97
- package/dist/graph/fieldProblems.js +2 -2
- package/dist/graph/graphEditorState.d.ts +4 -3
- package/dist/graph/inputRefs.js +9 -9
- package/dist/graph/settingsViews.js +6 -7
- package/dist/graph/stepWith.js +6 -6
- package/dist/index.d.ts +14 -15
- package/dist/index.js +15 -14
- package/dist/list/ActionToolbar.d.ts +6 -14
- package/dist/list/ActionToolbar.js +48 -96
- package/dist/list/ListPage.d.ts +6 -12
- package/dist/list/ListPage.js +46 -29
- package/dist/list/ListPager.js +4 -4
- package/dist/list/ListTable.js +5 -5
- package/dist/list/ListViewControls.d.ts +5 -4
- package/dist/list/ListViewControls.js +177 -267
- package/dist/list/UserHoverCard.d.ts +3 -17
- package/dist/list/UserHoverCard.js +21 -45
- package/dist/list/index.d.ts +3 -4
- package/dist/list/index.js +3 -4
- package/dist/list/listSearch.js +12 -11
- package/dist/list/rowMenu.d.ts +63 -0
- package/dist/list/rowMenu.js +134 -0
- package/dist/logviewer/LogViewer.js +26 -26
- package/dist/styles.css +1 -1
- package/package.json +7 -13
- package/dist/ai/ui/Dropdown.d.ts +0 -31
- package/dist/ai/ui/Dropdown.js +0 -110
- package/dist/components/AddMenu.d.ts +0 -18
- package/dist/components/AddMenu.js +0 -46
- package/dist/components/BareModal.d.ts +0 -17
- package/dist/components/BareModal.js +0 -77
- package/dist/components/CollapsiblePanel.d.ts +0 -27
- package/dist/components/CollapsiblePanel.js +0 -77
- package/dist/components/Dropdown.d.ts +0 -28
- package/dist/components/Dropdown.js +0 -355
- package/dist/components/Listbox.d.ts +0 -21
- package/dist/components/Listbox.js +0 -119
- package/dist/components/MultiSelect.d.ts +0 -22
- package/dist/components/MultiSelect.js +0 -168
- package/dist/components/SwitchToggle.d.ts +0 -15
- package/dist/components/SwitchToggle.js +0 -57
- package/dist/components/SwitchToggleSmall.d.ts +0 -6
- package/dist/components/SwitchToggleSmall.js +0 -14
- package/dist/components/Toggle.d.ts +0 -6
- package/dist/components/Toggle.js +0 -20
- package/dist/components/dropdownUtils.d.ts +0 -37
- package/dist/components/dropdownUtils.js +0 -99
- package/dist/form/SpecialTypes/DropdownWrapper.d.ts +0 -25
- package/dist/form/SpecialTypes/DropdownWrapper.js +0 -28
- package/dist/form/SpecialTypes/FormikCustomDropdown.d.ts +0 -51
- package/dist/form/SpecialTypes/FormikCustomDropdown.js +0 -119
- package/dist/form/SpecialTypes/FormikCustomInput.d.ts +0 -19
- package/dist/form/SpecialTypes/FormikCustomInput.js +0 -121
- package/dist/form/SpecialTypes/FormikMultiSelectDropdown.d.ts +0 -13
- package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +0 -31
- package/dist/form/SpecialTypes/FormikNumericInput.d.ts +0 -9
- package/dist/form/SpecialTypes/FormikNumericInput.js +0 -60
- package/dist/form/SpecialTypes/index.d.ts +0 -3
- package/dist/list/HoverCard.d.ts +0 -24
- package/dist/list/HoverCard.js +0 -73
- package/dist/list/RowContextMenu.d.ts +0 -127
- package/dist/list/RowContextMenu.js +0 -515
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { MenuPopup } from "./Menu.js";
|
|
2
|
+
import { MenuEntries, MenuFilter } from "./MenuEntries.js";
|
|
3
|
+
import { Menu } from "@base-ui/react/menu";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { useCallback, useRef, useState } from "react";
|
|
6
|
+
//#region src/components/ContextMenu.tsx
|
|
7
|
+
function pointRect(x, y) {
|
|
8
|
+
return {
|
|
9
|
+
x,
|
|
10
|
+
y,
|
|
11
|
+
left: x,
|
|
12
|
+
top: y,
|
|
13
|
+
right: x,
|
|
14
|
+
bottom: y,
|
|
15
|
+
width: 0,
|
|
16
|
+
height: 0
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function toAnchor(at) {
|
|
20
|
+
if (at instanceof Element) return at;
|
|
21
|
+
const { clientX, clientY } = at;
|
|
22
|
+
const on = at.currentTarget instanceof Element ? at.currentTarget : null;
|
|
23
|
+
if (!on) return { getBoundingClientRect: () => pointRect(clientX, clientY) };
|
|
24
|
+
const start = on.getBoundingClientRect();
|
|
25
|
+
const dx = clientX - start.left;
|
|
26
|
+
const dy = clientY - start.top;
|
|
27
|
+
return {
|
|
28
|
+
contextElement: on,
|
|
29
|
+
getBoundingClientRect: () => {
|
|
30
|
+
const now = on.getBoundingClientRect();
|
|
31
|
+
return pointRect(now.left + dx, now.top + dy);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* One menu that any number of rows, buttons or a canvas open with their own
|
|
37
|
+
* items, so a long list holds a single menu rather than one per row. Render
|
|
38
|
+
* `contextMenu` once.
|
|
39
|
+
*/
|
|
40
|
+
function useContextMenu() {
|
|
41
|
+
const [opened, setOpened] = useState(null);
|
|
42
|
+
const [open, setOpen] = useState(false);
|
|
43
|
+
const owner = useRef(null);
|
|
44
|
+
const release = useCallback(() => {
|
|
45
|
+
const was = owner.current;
|
|
46
|
+
owner.current = null;
|
|
47
|
+
was?.onClose?.();
|
|
48
|
+
}, []);
|
|
49
|
+
const openMenu = useCallback((at, items, options) => {
|
|
50
|
+
if (items.length === 0) return;
|
|
51
|
+
release();
|
|
52
|
+
const next = {
|
|
53
|
+
...options,
|
|
54
|
+
anchor: toAnchor(at),
|
|
55
|
+
items
|
|
56
|
+
};
|
|
57
|
+
owner.current = next;
|
|
58
|
+
setOpened(next);
|
|
59
|
+
setOpen(true);
|
|
60
|
+
}, [release]);
|
|
61
|
+
const onOpenChange = useCallback((next) => {
|
|
62
|
+
if (!next) setOpen(false);
|
|
63
|
+
}, []);
|
|
64
|
+
const onOpenChangeComplete = useCallback((next) => {
|
|
65
|
+
if (!next) release();
|
|
66
|
+
}, [release]);
|
|
67
|
+
return {
|
|
68
|
+
openMenu,
|
|
69
|
+
contextMenu: opened && /* @__PURE__ */ jsx(MenuFilter, {
|
|
70
|
+
search: opened.search,
|
|
71
|
+
children: (query) => /* @__PURE__ */ jsx(Menu.Root, {
|
|
72
|
+
open,
|
|
73
|
+
onOpenChange,
|
|
74
|
+
onOpenChangeComplete,
|
|
75
|
+
modal: false,
|
|
76
|
+
children: /* @__PURE__ */ jsx(MenuPopup, {
|
|
77
|
+
anchor: opened.anchor,
|
|
78
|
+
children: /* @__PURE__ */ jsx(MenuEntries, {
|
|
79
|
+
entries: opened.items,
|
|
80
|
+
search: opened.search,
|
|
81
|
+
query
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
}, opened.search ? "search" : "plain")
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export { useContextMenu };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { useNotify, useStrings } from "./Provider.js";
|
|
2
1
|
import { FaCheck } from "../icons/fa/FaCheck.js";
|
|
3
2
|
import { FaEye } from "../icons/fa/FaEye.js";
|
|
4
3
|
import { FaEyeSlash } from "../icons/fa/FaEyeSlash.js";
|
|
5
4
|
import { FiCopy } from "../icons/fi/FiCopy.js";
|
|
6
5
|
import { HiOutlineClipboardCopy } from "../icons/hi/HiOutlineClipboardCopy.js";
|
|
7
|
-
import {
|
|
6
|
+
import { useNotify, useStrings } from "./Provider.js";
|
|
8
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { useState } from "react";
|
|
9
9
|
//#region src/components/CopyToClipboard.tsx
|
|
10
10
|
function CopyToClipboard({ as = "div", text, className, children, showIcon = true }) {
|
|
11
11
|
const notify = useNotify();
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { InputHTMLAttributes, ReactNode, TextareaHTMLAttributes } from 'react';
|
|
2
|
-
import { type
|
|
2
|
+
import { type ComboboxItems } from './Combobox.js';
|
|
3
|
+
import type { MenuEntry } from './MenuEntries.js';
|
|
3
4
|
interface CreateModalProps {
|
|
4
5
|
open: boolean;
|
|
5
6
|
onClose: () => void;
|
|
6
7
|
typeIcon?: ReactNode;
|
|
7
8
|
typeLabel: string;
|
|
8
9
|
/** Makes the type chip a dropdown to switch between sibling form types. */
|
|
9
|
-
typeMenu?:
|
|
10
|
+
typeMenu?: MenuEntry[] | undefined;
|
|
10
11
|
namePlaceholder: string;
|
|
11
12
|
hideName?: boolean;
|
|
12
13
|
initialName?: string | undefined;
|
|
@@ -48,58 +49,38 @@ export declare function CreateModalTextarea({ label, tooltip, rows, ...props }:
|
|
|
48
49
|
/** Help text surfaced via an info icon next to the label. */
|
|
49
50
|
tooltip?: string | undefined;
|
|
50
51
|
}): import("react").JSX.Element;
|
|
51
|
-
/** Labeled input
|
|
52
|
-
export declare function CreateModalAutocompleteField({ label, tooltip, value,
|
|
52
|
+
/** Labeled input with suggestions; any text is allowed. */
|
|
53
|
+
export declare function CreateModalAutocompleteField({ label, tooltip, value, onValueChange, items, placeholder, }: {
|
|
53
54
|
label: string;
|
|
54
55
|
/** Help text surfaced via an info icon next to the label. */
|
|
55
56
|
tooltip?: string;
|
|
56
57
|
value: string;
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
onValueChange: (value: string) => void;
|
|
59
|
+
/** Suggestions, filtered by what's typed. */
|
|
60
|
+
items: string[];
|
|
59
61
|
placeholder?: string;
|
|
60
62
|
}): import("react").JSX.Element;
|
|
61
63
|
/** Compact property pill with an on/off switch. */
|
|
62
|
-
export declare function CreateModalSwitch({ label, checked,
|
|
64
|
+
export declare function CreateModalSwitch({ label, checked, onCheckedChange, tooltip, }: {
|
|
63
65
|
label: string;
|
|
64
66
|
checked: boolean;
|
|
65
|
-
|
|
67
|
+
onCheckedChange: (checked: boolean) => void;
|
|
66
68
|
/** Help text surfaced on hover (explains what the toggle does). */
|
|
67
69
|
tooltip?: string;
|
|
68
70
|
}): import("react").JSX.Element;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
/** Small leading icon (e.g. the resource's provider icon). */
|
|
73
|
-
icon?: ReactNode;
|
|
74
|
-
/** Category header to group this option under in the dropdown. */
|
|
75
|
-
group?: string;
|
|
76
|
-
/** Hidden behind the group's toggle row until the group is expanded. */
|
|
77
|
-
collapsible?: boolean;
|
|
78
|
-
/** Always listed regardless of the typed filter (e.g. a trailing "Create new…" action). */
|
|
79
|
-
pinned?: boolean;
|
|
80
|
-
/** Muted second line under the label (e.g. the allocation a group bills to). */
|
|
81
|
-
description?: string;
|
|
82
|
-
/** Listed but not selectable (e.g. a group whose allocation is exhausted). */
|
|
83
|
-
disabled?: boolean;
|
|
84
|
-
}
|
|
85
|
-
/** Callers gating collapse on list size must use this same threshold so
|
|
86
|
-
* collapsed rows always come with a filter to find them. */
|
|
87
|
-
export declare const CREATE_MODAL_SELECT_FILTER_THRESHOLD = 8;
|
|
88
|
-
/** Compact property pill with a dropdown of options. Options may carry leading
|
|
89
|
-
* icons and group headers (e.g. Clusters vs Kubernetes). */
|
|
90
|
-
export declare function CreateModalSelect({ label, icon, value, options, onChange, disabled, disabledHint, tooltip, collapsedLabel, }: {
|
|
71
|
+
/** Compact property pill that picks one value from a searchable list. Items may carry
|
|
72
|
+
* icons, descriptions and group headings (e.g. Clusters vs Kubernetes). */
|
|
73
|
+
export declare function CreateModalSelect({ label, icon, value, items, onValueChange, disabled, disabledReason, tooltip, }: {
|
|
91
74
|
label: string;
|
|
92
75
|
icon?: ReactNode;
|
|
93
76
|
value?: string | undefined;
|
|
94
|
-
|
|
95
|
-
|
|
77
|
+
items: ComboboxItems<string>;
|
|
78
|
+
onValueChange: (value: string) => void;
|
|
96
79
|
/** Gray the pill out (e.g. while a prerequisite pill is unset). */
|
|
97
80
|
disabled?: boolean;
|
|
98
|
-
/**
|
|
99
|
-
|
|
81
|
+
/** Why the pill is disabled, shown in place of the tooltip (e.g. the prerequisite). */
|
|
82
|
+
disabledReason?: string | undefined;
|
|
100
83
|
/** Help text surfaced on hover (explains what the pill selects). */
|
|
101
84
|
tooltip?: string;
|
|
102
|
-
/** Label for the toggle row hiding a group's collapsible options. */
|
|
103
|
-
collapsedLabel?: (count: number) => string;
|
|
104
85
|
}): import("react").JSX.Element;
|
|
105
86
|
export {};
|
|
@@ -1,40 +1,21 @@
|
|
|
1
|
-
import { useStrings } from "./Provider.js";
|
|
2
1
|
import { FaChevronDown } from "../icons/fa/FaChevronDown.js";
|
|
3
|
-
import { HiQuestionMarkCircle } from "../icons/hi/HiQuestionMarkCircle.js";
|
|
4
2
|
import { IoHeart } from "../icons/io5/IoHeart.js";
|
|
5
3
|
import { IoHeartOutline } from "../icons/io5/IoHeartOutline.js";
|
|
6
4
|
import { LuChevronRight } from "../icons/lu/LuChevronRight.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
5
|
+
import { Tooltip } from "./Tooltip.js";
|
|
6
|
+
import { useStrings } from "./Provider.js";
|
|
7
|
+
import { ActionMenu } from "./ActionMenu.js";
|
|
8
|
+
import { Autocomplete, Combobox } from "./Combobox.js";
|
|
10
9
|
import { ghostButtonClasses } from "./ghostButton.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
import { Fragment
|
|
10
|
+
import { Modal } from "./Modal.js";
|
|
11
|
+
import { InfoTip } from "./InfoTip.js";
|
|
12
|
+
import { Switch } from "./Switch.js";
|
|
13
|
+
import { clsx } from "clsx";
|
|
14
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
+
import { useEffect, useId, useRef, useState } from "react";
|
|
16
|
+
import { Button } from "@base-ui/react/button";
|
|
17
|
+
import { Toggle } from "@base-ui/react/toggle";
|
|
16
18
|
//#region src/components/CreateModal.tsx
|
|
17
|
-
/** Small info icon that surfaces field help via the global tooltip. */
|
|
18
|
-
function FieldHelp({ tooltip }) {
|
|
19
|
-
if (!tooltip) return null;
|
|
20
|
-
return /* @__PURE__ */ jsx("span", {
|
|
21
|
-
"data-tooltip-id": TOOLTIP_ID,
|
|
22
|
-
"data-tooltip-content": tooltip,
|
|
23
|
-
className: "inline-flex cursor-help text-(--theme-muted-text-color)",
|
|
24
|
-
children: /* @__PURE__ */ jsx(HiQuestionMarkCircle, { className: "w-3 h-3" })
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
/** Anchors the tooltip on a non-focusable span so it opens on hover but not when focus returns to the button after its menu/toggle closes (which would leave it stuck). */
|
|
28
|
-
function PillTooltip({ content, className, children }) {
|
|
29
|
-
return /* @__PURE__ */ jsx("span", {
|
|
30
|
-
...content ? {
|
|
31
|
-
"data-tooltip-id": TOOLTIP_ID,
|
|
32
|
-
"data-tooltip-content": content
|
|
33
|
-
} : {},
|
|
34
|
-
className: cx("inline-flex items-center gap-1.5", className),
|
|
35
|
-
children
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
19
|
/** Submits on Enter in the name field or ⌘/Ctrl+Enter from anywhere in the panel. */
|
|
39
20
|
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 }) {
|
|
40
21
|
const t = useStrings().modal;
|
|
@@ -59,13 +40,6 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
|
|
|
59
40
|
setFavorite(false);
|
|
60
41
|
setNameTouched(false);
|
|
61
42
|
setInteracted(false);
|
|
62
|
-
requestAnimationFrame(() => {
|
|
63
|
-
const input = nameRef.current;
|
|
64
|
-
const dialog = input?.closest("[role=\"dialog\"]");
|
|
65
|
-
const active = document.activeElement;
|
|
66
|
-
if (dialog?.contains(active) && active !== dialog) return;
|
|
67
|
-
input?.focus();
|
|
68
|
-
});
|
|
69
43
|
}
|
|
70
44
|
}, [open, initialName]);
|
|
71
45
|
const nameError = name.trim() ? validateName?.(name.trim()) ?? null : null;
|
|
@@ -95,16 +69,17 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
|
|
|
95
69
|
}
|
|
96
70
|
if (close) onClose();
|
|
97
71
|
};
|
|
98
|
-
return /* @__PURE__ */ jsxs(
|
|
72
|
+
return /* @__PURE__ */ jsxs(Modal, {
|
|
99
73
|
open,
|
|
100
74
|
onClose,
|
|
101
|
-
|
|
102
|
-
className:
|
|
103
|
-
|
|
104
|
-
|
|
75
|
+
"aria-label": `${submitText}: ${typeLabel}`,
|
|
76
|
+
className: "w-[560px] max-w-full flex flex-col max-h-full",
|
|
77
|
+
dismissible: !isDirty,
|
|
78
|
+
initialFocus: () => nameRef.current ?? true,
|
|
79
|
+
onKeyDown: (e) => {
|
|
105
80
|
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) handleSubmit();
|
|
106
81
|
},
|
|
107
|
-
|
|
82
|
+
onMouseDown: (e) => {
|
|
108
83
|
if (e.target instanceof Element && !e.target.closest("input, textarea, button, a, select, label, code, pre, .select-all")) e.preventDefault();
|
|
109
84
|
},
|
|
110
85
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
@@ -114,11 +89,10 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
|
|
|
114
89
|
/* @__PURE__ */ jsxs("div", {
|
|
115
90
|
className: "px-4 pt-4",
|
|
116
91
|
children: [
|
|
117
|
-
typeMenu && typeMenu.length > 0 ? /* @__PURE__ */ jsxs(
|
|
92
|
+
typeMenu && typeMenu.length > 0 ? /* @__PURE__ */ jsxs(ActionMenu, {
|
|
118
93
|
items: typeMenu,
|
|
119
94
|
label: typeLabel,
|
|
120
|
-
|
|
121
|
-
buttonClassName: "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)",
|
|
95
|
+
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)",
|
|
122
96
|
children: [
|
|
123
97
|
typeIcon,
|
|
124
98
|
typeLabel,
|
|
@@ -128,7 +102,7 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
|
|
|
128
102
|
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)",
|
|
129
103
|
children: [typeIcon, typeLabel]
|
|
130
104
|
}),
|
|
131
|
-
hideName ? /* @__PURE__ */ jsx("div", { className: "mt-3" }) : /* @__PURE__ */ jsxs(Fragment
|
|
105
|
+
hideName ? /* @__PURE__ */ jsx("div", { className: "mt-3" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
132
106
|
/* @__PURE__ */ jsx("input", {
|
|
133
107
|
ref: nameRef,
|
|
134
108
|
type: "text",
|
|
@@ -153,7 +127,7 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
|
|
|
153
127
|
placeholder: namePlaceholder,
|
|
154
128
|
"aria-label": namePlaceholder,
|
|
155
129
|
onAnimationEnd: () => setNameFlash(false),
|
|
156
|
-
className:
|
|
130
|
+
className: clsx("mt-2 -mb-1 -mx-1.5 w-[calc(100%+0.75rem)] rounded-md border-0 px-1.5 py-1 bg-transparent shadow-none text-lg font-medium text-(--theme-app) placeholder:text-(--theme-muted-text-color) focus:outline-none", nameFlash && "animate-field-flash", nameMissing ? "ring-1 ring-(--theme-error)" : "focus:ring-0")
|
|
157
131
|
}),
|
|
158
132
|
nameError && /* @__PURE__ */ jsx("p", {
|
|
159
133
|
className: "mt-1 text-xs text-(--theme-error)",
|
|
@@ -187,7 +161,7 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
|
|
|
187
161
|
type: "button",
|
|
188
162
|
onClick: () => setAdvancedOpen((o) => !o),
|
|
189
163
|
className: "inline-flex items-center gap-1 text-xs font-medium text-(--theme-muted-text-color) hover:text-(--theme-app) transition-colors",
|
|
190
|
-
children: [/* @__PURE__ */ jsx(LuChevronRight, { className:
|
|
164
|
+
children: [/* @__PURE__ */ jsx(LuChevronRight, { className: clsx("w-3 h-3 transition-transform", advancedOpen && "rotate-90") }), t.advanced]
|
|
191
165
|
}), advancedOpen && /* @__PURE__ */ jsx("div", {
|
|
192
166
|
className: "mt-2",
|
|
193
167
|
children: advanced
|
|
@@ -196,16 +170,13 @@ function CreateModal({ open, onClose, typeIcon, typeLabel, typeMenu, namePlaceho
|
|
|
196
170
|
]
|
|
197
171
|
}), /* @__PURE__ */ jsxs("div", {
|
|
198
172
|
className: "shrink-0 flex items-center justify-between gap-2 px-4 py-3",
|
|
199
|
-
children: [showFavorite ? /* @__PURE__ */ jsx(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
children: /* @__PURE__ */ jsxs(PillTooltip, {
|
|
207
|
-
content: favorite ? t.favoriteHintOn : t.favoriteHintOff,
|
|
208
|
-
className: "px-2.5",
|
|
173
|
+
children: [showFavorite ? /* @__PURE__ */ jsx(Tooltip, {
|
|
174
|
+
content: favorite ? t.favoriteHintOn : t.favoriteHintOff,
|
|
175
|
+
children: /* @__PURE__ */ jsxs(Toggle, {
|
|
176
|
+
pressed: favorite,
|
|
177
|
+
onPressedChange: setFavorite,
|
|
178
|
+
"aria-label": t.favorite,
|
|
179
|
+
className: clsx("inline-flex h-8 items-center gap-1.5 px-2.5 rounded-md text-sm font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-(--theme-focus-ring)", favorite ? "text-(--theme-favorite) bg-(--theme-favorite-muted)" : "text-(--theme-muted-text-color) hover:text-(--theme-app) hover:bg-(--theme-muted-panel-bg)"),
|
|
209
180
|
children: [favorite ? /* @__PURE__ */ jsx(IoHeart, { className: "w-4 h-4 scale-110 transition-transform" }) : /* @__PURE__ */ jsx(IoHeartOutline, { className: "w-4 h-4 transition-transform" }), favorite ? t.favorited : t.favorite]
|
|
210
181
|
})
|
|
211
182
|
}) : /* @__PURE__ */ jsx("span", {}), /* @__PURE__ */ jsxs("div", {
|
|
@@ -233,8 +204,8 @@ function CreateModalField({ label, tooltip, ...props }) {
|
|
|
233
204
|
return /* @__PURE__ */ jsxs("label", {
|
|
234
205
|
className: "block mb-3",
|
|
235
206
|
children: [/* @__PURE__ */ jsxs("span", {
|
|
236
|
-
className:
|
|
237
|
-
children: [label, /* @__PURE__ */ jsx(
|
|
207
|
+
className: clsx(fieldLabelClasses, "flex items-center gap-1"),
|
|
208
|
+
children: [label, /* @__PURE__ */ jsx(InfoTip, { text: tooltip ?? "" })]
|
|
238
209
|
}), /* @__PURE__ */ jsx("input", {
|
|
239
210
|
type: "text",
|
|
240
211
|
autoComplete: "off",
|
|
@@ -249,235 +220,102 @@ function CreateModalTextarea({ label, tooltip, rows = 4, ...props }) {
|
|
|
249
220
|
return /* @__PURE__ */ jsxs("label", {
|
|
250
221
|
className: "block mb-3",
|
|
251
222
|
children: [/* @__PURE__ */ jsxs("span", {
|
|
252
|
-
className:
|
|
253
|
-
children: [label, /* @__PURE__ */ jsx(
|
|
223
|
+
className: clsx(fieldLabelClasses, "flex items-center gap-1"),
|
|
224
|
+
children: [label, /* @__PURE__ */ jsx(InfoTip, { text: tooltip ?? "" })]
|
|
254
225
|
}), /* @__PURE__ */ jsx("textarea", {
|
|
255
226
|
autoComplete: "off",
|
|
256
227
|
"data-1p-ignore": true,
|
|
257
228
|
rows,
|
|
258
229
|
...props,
|
|
259
|
-
className:
|
|
230
|
+
className: clsx(fieldInputClasses, "h-auto py-2 font-mono text-xs leading-relaxed resize-y")
|
|
260
231
|
})]
|
|
261
232
|
});
|
|
262
233
|
}
|
|
263
|
-
/** Labeled input
|
|
264
|
-
function CreateModalAutocompleteField({ label, tooltip, value,
|
|
265
|
-
const
|
|
266
|
-
const filtered = query ? options.filter((option) => option.toLowerCase().includes(query)) : options;
|
|
234
|
+
/** Labeled input with suggestions; any text is allowed. */
|
|
235
|
+
function CreateModalAutocompleteField({ label, tooltip, value, onValueChange, items, placeholder }) {
|
|
236
|
+
const id = useId();
|
|
267
237
|
return /* @__PURE__ */ jsxs("div", {
|
|
268
238
|
className: "mb-3",
|
|
269
|
-
children: [/* @__PURE__ */ jsxs("
|
|
270
|
-
className:
|
|
271
|
-
children: [
|
|
272
|
-
|
|
239
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
240
|
+
className: clsx(fieldLabelClasses, "flex items-center gap-1"),
|
|
241
|
+
children: [/* @__PURE__ */ jsx("label", {
|
|
242
|
+
htmlFor: id,
|
|
243
|
+
children: label
|
|
244
|
+
}), tooltip && /* @__PURE__ */ jsx(InfoTip, { text: tooltip })]
|
|
245
|
+
}), /* @__PURE__ */ jsx(Autocomplete, {
|
|
246
|
+
id,
|
|
247
|
+
items,
|
|
273
248
|
value,
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
children: [/* @__PURE__ */ jsx(ComboboxInput, {
|
|
277
|
-
autoComplete: "off",
|
|
278
|
-
"data-1p-ignore": true,
|
|
279
|
-
"aria-label": label,
|
|
280
|
-
placeholder,
|
|
281
|
-
displayValue: (current) => current ?? "",
|
|
282
|
-
onChange: (e) => onChange(e.target.value),
|
|
283
|
-
className: fieldInputClasses
|
|
284
|
-
}), filtered.length > 0 && /* @__PURE__ */ jsx(ComboboxOptions, {
|
|
285
|
-
anchor: "bottom start",
|
|
286
|
-
className: "z-[9999] mt-1 w-(--input-width) [--anchor-max-height:14rem] overflow-auto rounded-lg border border-(--theme-border) bg-(--theme-app-bg) py-1 shadow-lg focus:outline-none",
|
|
287
|
-
children: filtered.map((option) => /* @__PURE__ */ jsx(ComboboxOption, {
|
|
288
|
-
value: option,
|
|
289
|
-
className: "px-3 py-1.5 text-[13px] text-(--theme-app) data-[focus]:bg-(--theme-muted-panel-bg) cursor-pointer",
|
|
290
|
-
children: option
|
|
291
|
-
}, option))
|
|
292
|
-
})]
|
|
249
|
+
onValueChange,
|
|
250
|
+
placeholder
|
|
293
251
|
})]
|
|
294
252
|
});
|
|
295
253
|
}
|
|
254
|
+
var pillClasses = "inline-flex h-7 items-center gap-1.5 rounded-md border border-(--theme-border) px-2 text-xs font-medium transition-colors";
|
|
296
255
|
/** Compact property pill with an on/off switch. */
|
|
297
|
-
function CreateModalSwitch({ label, checked,
|
|
298
|
-
return /* @__PURE__ */ jsx(
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
className: "px-2",
|
|
307
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
308
|
-
className: cx("relative inline-flex h-3.5 w-6 shrink-0 rounded-full transition-colors", checked ? "bg-(--theme-element)" : "bg-(--theme-border)"),
|
|
309
|
-
children: /* @__PURE__ */ jsx("span", { className: cx("absolute top-0.5 left-0.5 h-2.5 w-2.5 rounded-full bg-white shadow-sm transition-transform", checked && "translate-x-2.5") })
|
|
256
|
+
function CreateModalSwitch({ label, checked, onCheckedChange, tooltip }) {
|
|
257
|
+
return /* @__PURE__ */ jsx(Tooltip, {
|
|
258
|
+
content: tooltip,
|
|
259
|
+
children: /* @__PURE__ */ jsxs("label", {
|
|
260
|
+
className: clsx(pillClasses, "cursor-pointer hover:bg-(--theme-muted-panel-bg)", checked ? "text-(--theme-app)" : "text-(--theme-muted-text-color)"),
|
|
261
|
+
children: [/* @__PURE__ */ jsx(Switch, {
|
|
262
|
+
size: "sm",
|
|
263
|
+
checked,
|
|
264
|
+
onCheckedChange
|
|
310
265
|
}), label]
|
|
311
266
|
})
|
|
312
267
|
});
|
|
313
268
|
}
|
|
314
|
-
/**
|
|
315
|
-
*
|
|
316
|
-
|
|
317
|
-
function collapseToggleRow(group, count, collapse) {
|
|
318
|
-
const expanded = collapse.expanded.has(group);
|
|
319
|
-
return /* @__PURE__ */ jsxs("button", {
|
|
320
|
-
type: "button",
|
|
321
|
-
"aria-expanded": expanded,
|
|
322
|
-
onMouseDown: (e) => e.preventDefault(),
|
|
323
|
-
onClick: () => collapse.onToggle(group),
|
|
324
|
-
className: "flex w-full items-center gap-1.5 px-3 py-1.5 text-[13px] text-(--theme-muted-text-color) hover:text-(--theme-app) cursor-pointer",
|
|
325
|
-
children: [/* @__PURE__ */ jsx(expanded ? FaChevronDown : LuChevronRight, { className: "w-3 h-3" }), collapse.label(count)]
|
|
326
|
-
}, `toggle-${group}`);
|
|
327
|
-
}
|
|
328
|
-
function collapsibleCountsByGroup(options) {
|
|
329
|
-
const counts = /* @__PURE__ */ new Map();
|
|
330
|
-
for (const o of options) if (o.collapsible && o.group) counts.set(o.group, (counts.get(o.group) ?? 0) + 1);
|
|
331
|
-
return counts;
|
|
332
|
-
}
|
|
333
|
-
function pushToggleRowOnce(nodes, toggledGroups, group, count, collapse) {
|
|
334
|
-
if (!toggledGroups.has(group)) {
|
|
335
|
-
toggledGroups.add(group);
|
|
336
|
-
nodes.push(collapseToggleRow(group, count, collapse));
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
function buildOptionNodes(options, query, onChange, collapse) {
|
|
340
|
-
const trimmed = query.trim();
|
|
341
|
-
const q = trimmed.toLowerCase().replace(/-/g, "");
|
|
342
|
-
const filtered = q ? options.filter((o) => o.pinned || filterOption({
|
|
343
|
-
label: o.label,
|
|
344
|
-
value: o.value,
|
|
345
|
-
secondaryValue: o.group
|
|
346
|
-
}, trimmed)) : options;
|
|
347
|
-
const collapsibleCounts = !q && collapse ? collapsibleCountsByGroup(filtered) : /* @__PURE__ */ new Map();
|
|
348
|
-
const nodes = [];
|
|
349
|
-
let lastGroup;
|
|
350
|
-
const toggledGroups = /* @__PURE__ */ new Set();
|
|
351
|
-
for (const option of filtered) {
|
|
352
|
-
const { group } = option;
|
|
353
|
-
if (group && group !== lastGroup) {
|
|
354
|
-
lastGroup = group;
|
|
355
|
-
nodes.push(/* @__PURE__ */ jsx("div", {
|
|
356
|
-
className: "px-3 pt-2 pb-1 text-[10px] font-semibold uppercase tracking-wide text-(--theme-muted-text-color)",
|
|
357
|
-
children: group
|
|
358
|
-
}, `group-${group}`));
|
|
359
|
-
}
|
|
360
|
-
if (!q && collapse && option.collapsible && group) {
|
|
361
|
-
pushToggleRowOnce(nodes, toggledGroups, group, collapsibleCounts.get(group) ?? 0, collapse);
|
|
362
|
-
if (!collapse.expanded.has(group)) continue;
|
|
363
|
-
}
|
|
364
|
-
nodes.push(/* @__PURE__ */ jsx(MenuItem, {
|
|
365
|
-
disabled: option.disabled ?? false,
|
|
366
|
-
children: /* @__PURE__ */ jsxs("button", {
|
|
367
|
-
type: "button",
|
|
368
|
-
disabled: option.disabled,
|
|
369
|
-
"aria-disabled": option.disabled,
|
|
370
|
-
"aria-label": option.description ? option.label : void 0,
|
|
371
|
-
"aria-description": option.description,
|
|
372
|
-
onClick: () => onChange(option.value),
|
|
373
|
-
className: cx("flex w-full items-center gap-2 px-3 py-1.5 text-left text-[13px] data-[focus]:bg-(--theme-muted-panel-bg)", option.disabled ? "cursor-not-allowed text-(--theme-muted-text-color)" : "cursor-pointer text-(--theme-app)", option.pinned && "mt-1 border-t border-(--theme-border) pt-2 font-medium"),
|
|
374
|
-
children: [option.icon, option.description ? /* @__PURE__ */ jsxs("span", {
|
|
375
|
-
className: "flex min-w-0 flex-col",
|
|
376
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
377
|
-
className: "truncate",
|
|
378
|
-
children: option.label
|
|
379
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
380
|
-
className: "truncate text-[11px] font-normal text-(--theme-muted-text-color)",
|
|
381
|
-
children: option.description
|
|
382
|
-
})]
|
|
383
|
-
}) : option.label]
|
|
384
|
-
})
|
|
385
|
-
}, option.value));
|
|
386
|
-
}
|
|
387
|
-
return nodes;
|
|
388
|
-
}
|
|
389
|
-
function CreateModalSelectPanel({ open, options, label, value, collapsedLabel, onChange }) {
|
|
269
|
+
/** Compact property pill that picks one value from a searchable list. Items may carry
|
|
270
|
+
* icons, descriptions and group headings (e.g. Clusters vs Kubernetes). */
|
|
271
|
+
function CreateModalSelect({ label, icon, value, items, onValueChange, disabled = false, disabledReason, tooltip }) {
|
|
390
272
|
const t = useStrings().modal;
|
|
391
|
-
const
|
|
392
|
-
const inputRef = useRef(null);
|
|
393
|
-
const showFilter = options.length > 8;
|
|
394
|
-
const selectedGroup = options.find((o) => o.value === value)?.group;
|
|
395
|
-
const initialExpandedGroups = useCallback(() => new Set(selectedGroup ? [selectedGroup] : []), [selectedGroup]);
|
|
396
|
-
const [expandedGroups, setExpandedGroups] = useState(initialExpandedGroups);
|
|
397
|
-
useEffect(() => {
|
|
398
|
-
if (!open) {
|
|
399
|
-
setQuery("");
|
|
400
|
-
setExpandedGroups(initialExpandedGroups());
|
|
401
|
-
}
|
|
402
|
-
}, [open, initialExpandedGroups]);
|
|
403
|
-
useEffect(() => {
|
|
404
|
-
if (!open || !showFilter) return;
|
|
405
|
-
const raf = requestAnimationFrame(() => inputRef.current?.focus());
|
|
406
|
-
return () => cancelAnimationFrame(raf);
|
|
407
|
-
}, [open, showFilter]);
|
|
408
|
-
const rendered = buildOptionNodes(options, query, onChange, collapsedLabel ? {
|
|
409
|
-
expanded: expandedGroups,
|
|
410
|
-
onToggle: (group) => setExpandedGroups((prev) => toggleSetMember(prev, group)),
|
|
411
|
-
label: collapsedLabel
|
|
412
|
-
} : void 0);
|
|
413
|
-
return /* @__PURE__ */ jsxs(MenuItems, {
|
|
414
|
-
anchor: "bottom start",
|
|
415
|
-
className: "z-[9999] mt-1 flex min-w-44 max-w-[min(28rem,calc(100vw-2rem))] max-h-64 flex-col [--anchor-max-height:16rem] overflow-hidden rounded-lg border border-(--theme-border) bg-(--theme-app-bg) shadow-lg focus:outline-none",
|
|
416
|
-
children: [showFilter && /* @__PURE__ */ jsx("div", {
|
|
417
|
-
className: "shrink-0 bg-(--theme-app-bg) px-1.5 pt-1 pb-1.5 border-b border-(--theme-border)",
|
|
418
|
-
children: /* @__PURE__ */ jsx("input", {
|
|
419
|
-
ref: inputRef,
|
|
420
|
-
type: "text",
|
|
421
|
-
autoComplete: "off",
|
|
422
|
-
"data-1p-ignore": true,
|
|
423
|
-
"aria-label": label,
|
|
424
|
-
placeholder: t.filter,
|
|
425
|
-
value: query,
|
|
426
|
-
onChange: (e) => setQuery(e.target.value),
|
|
427
|
-
onKeyDown: (e) => {
|
|
428
|
-
if (e.key !== "Escape") e.stopPropagation();
|
|
429
|
-
},
|
|
430
|
-
className: "w-full h-7 px-2 rounded-md border border-(--theme-border) bg-(--theme-input-bg) text-[13px] text-(--theme-app) placeholder:text-(--theme-muted-text-color) focus:outline-none focus:border-(--theme-element)"
|
|
431
|
-
})
|
|
432
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
433
|
-
className: "min-h-0 flex-1 overflow-y-auto py-1",
|
|
434
|
-
children: rendered.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
435
|
-
className: "px-3 py-1.5 text-[13px] text-(--theme-muted-text-color)",
|
|
436
|
-
children: t.noOptions
|
|
437
|
-
}) : rendered
|
|
438
|
-
})]
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
/** Compact property pill with a dropdown of options. Options may carry leading
|
|
442
|
-
* icons and group headers (e.g. Clusters vs Kubernetes). */
|
|
443
|
-
function CreateModalSelect({ label, icon, value, options, onChange, disabled = false, disabledHint, tooltip, collapsedLabel }) {
|
|
444
|
-
const selected = options.find((o) => o.value === value);
|
|
273
|
+
const selected = leafItems(items).find((item) => item.value === value);
|
|
445
274
|
const selectedLabel = selected?.label ?? (value || void 0);
|
|
446
|
-
const pillContent = /* @__PURE__ */ jsxs(Fragment
|
|
275
|
+
const pillContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
447
276
|
selected?.icon ?? icon,
|
|
448
|
-
selectedLabel ? /* @__PURE__ */ jsxs(Fragment
|
|
277
|
+
selectedLabel ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
449
278
|
className: "font-normal text-(--theme-muted-text-color)",
|
|
450
279
|
children: label
|
|
451
280
|
}), selectedLabel] }) : label,
|
|
452
281
|
/* @__PURE__ */ jsx(FaChevronDown, { className: "w-3 h-3 opacity-60" })
|
|
453
282
|
] });
|
|
454
|
-
if (disabled) return /* @__PURE__ */ jsx(
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
className: "px-2",
|
|
283
|
+
if (disabled) return /* @__PURE__ */ jsx(Tooltip, {
|
|
284
|
+
content: disabledReason ?? tooltip,
|
|
285
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
286
|
+
disabled: true,
|
|
287
|
+
focusableWhenDisabled: true,
|
|
288
|
+
"aria-label": label,
|
|
289
|
+
className: clsx(pillClasses, "opacity-50 cursor-not-allowed text-(--theme-muted-text-color)"),
|
|
462
290
|
children: pillContent
|
|
463
291
|
})
|
|
464
292
|
});
|
|
465
|
-
return /* @__PURE__ */ jsx(
|
|
293
|
+
return /* @__PURE__ */ jsx(Combobox, {
|
|
294
|
+
items,
|
|
295
|
+
value: value ?? null,
|
|
296
|
+
onValueChange: (next) => {
|
|
297
|
+
if (next !== null) onValueChange(next);
|
|
298
|
+
},
|
|
299
|
+
itemToStringLabel: (next) => next,
|
|
466
300
|
"aria-label": label,
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
301
|
+
placeholder: t.filter,
|
|
302
|
+
triggerTooltip: tooltip,
|
|
303
|
+
trigger: /* @__PURE__ */ jsx("button", {
|
|
304
|
+
type: "button",
|
|
305
|
+
className: clsx(pillClasses, "cursor-pointer hover:bg-(--theme-muted-panel-bg)", selectedLabel ? "text-(--theme-app)" : "text-(--theme-muted-text-color)"),
|
|
471
306
|
children: pillContent
|
|
472
307
|
})
|
|
473
|
-
})
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
function leafItems(items) {
|
|
311
|
+
return items.flatMap((node) => {
|
|
312
|
+
if (typeof node === "string") return [{
|
|
313
|
+
value: node,
|
|
314
|
+
label: node
|
|
315
|
+
}];
|
|
316
|
+
if ("items" in node) return leafItems(node.items);
|
|
317
|
+
return [node];
|
|
318
|
+
});
|
|
481
319
|
}
|
|
482
320
|
//#endregion
|
|
483
|
-
export {
|
|
321
|
+
export { CreateModal, CreateModalAutocompleteField, CreateModalField, CreateModalSelect, CreateModalSwitch, CreateModalTextarea };
|