@parallelworks/ui 0.41.0 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -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 +1 -1
- package/dist/ai/core/config.js +1 -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 +49 -0
- package/dist/components/Combobox.js +405 -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 +19 -38
- package/dist/components/CreateModal.js +116 -267
- 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/comboboxItems.d.ts +24 -0
- package/dist/components/comboboxItems.js +10 -0
- 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/lib.js +3 -2
- package/dist/form/types/fieldComponentTypes.d.ts +8 -10
- package/dist/form/useChoiceField.d.ts +18 -0
- package/dist/form/useChoiceField.js +46 -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 +32 -0
- package/dist/form/utils/fieldItems.js +32 -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 +68 -0
- package/dist/list/rowMenu.js +136 -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
|
@@ -1,34 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { forwardRef } from "react";
|
|
1
|
+
import { Tooltip } from "./Tooltip.js";
|
|
2
|
+
import { clsx } from "clsx";
|
|
4
3
|
import { jsx } from "react/jsx-runtime";
|
|
5
4
|
//#region src/components/IconButton.tsx
|
|
6
|
-
|
|
5
|
+
function IconButton({ icon, label, variant = "default", size = "md", active = false, showTooltip = true, className, ...props }) {
|
|
7
6
|
const sizeClasses = {
|
|
8
7
|
sm: "w-7 h-7 [&_svg]:w-3.5 [&_svg]:h-3.5",
|
|
9
8
|
md: "w-9 h-9 [&_svg]:w-4 [&_svg]:h-4",
|
|
10
9
|
lg: "w-11 h-11 [&_svg]:w-5 [&_svg]:h-5"
|
|
11
10
|
};
|
|
12
11
|
const variantClasses = {
|
|
13
|
-
default:
|
|
14
|
-
ghost:
|
|
15
|
-
primary:
|
|
16
|
-
success:
|
|
12
|
+
default: clsx("bg-[var(--theme-muted-panel-bg)] text-[var(--theme-muted-text-color)]", "hover:bg-[var(--theme-border)] hover:text-[var(--theme-app)]", active && "bg-[var(--theme-element)]/10 text-[var(--theme-element)]"),
|
|
13
|
+
ghost: clsx("bg-transparent text-[var(--theme-muted-text-color)]", "hover:bg-[var(--theme-muted-panel-bg)] hover:text-[var(--theme-app)]", active && "text-[var(--theme-element)]"),
|
|
14
|
+
primary: clsx("bg-[var(--theme-element)] text-white", "hover:bg-[var(--theme-element)]/90", active && "ring-2 ring-[var(--theme-element)]/50"),
|
|
15
|
+
success: clsx("bg-[#22c55e] text-white", "hover:bg-[#22c55e]/90", active && "ring-2 ring-[#22c55e]/50")
|
|
17
16
|
};
|
|
18
|
-
return /* @__PURE__ */ jsx(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
...props,
|
|
29
|
-
children: icon
|
|
17
|
+
return /* @__PURE__ */ jsx(Tooltip, {
|
|
18
|
+
content: label,
|
|
19
|
+
disabled: !showTooltip,
|
|
20
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
21
|
+
type: "button",
|
|
22
|
+
"aria-label": label,
|
|
23
|
+
className: clsx("inline-flex items-center justify-center rounded-lg", "transition-all duration-200 cursor-pointer", "disabled:opacity-50 disabled:cursor-not-allowed", sizeClasses[size], variantClasses[variant], className),
|
|
24
|
+
...props,
|
|
25
|
+
children: icon
|
|
26
|
+
})
|
|
30
27
|
});
|
|
31
|
-
}
|
|
32
|
-
IconButton.displayName = "IconButton";
|
|
28
|
+
}
|
|
33
29
|
//#endregion
|
|
34
30
|
export { IconButton };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { TooltipSide } from './Tooltip.js';
|
|
3
|
+
/** Infotip text can come from untrusted sources (workflow YAML), so all markup is literal text — only `[text](url)` links and newlines are parsed. */
|
|
4
|
+
export declare function formatInfoTipContent(content: string): ReactNode;
|
|
5
|
+
interface InfoTipProps {
|
|
6
|
+
text: string;
|
|
7
|
+
side?: TooltipSide;
|
|
8
|
+
className?: string | undefined;
|
|
9
|
+
/** Replaces the info icon as the trigger, such as a status label the text explains. */
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
/** Extra detail behind an info trigger. A popover that also opens on hover, so
|
|
13
|
+
* touch and screen reader users can reach it and its links. */
|
|
14
|
+
export declare function InfoTip({ text, side, className, children }: InfoTipProps): import("react").JSX.Element | null;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { HiQuestionMarkCircle } from "../icons/hi/HiQuestionMarkCircle.js";
|
|
2
|
+
import { portalContainer, positionerClassName, tipArrowClassName, tipClassName } from "./floating.js";
|
|
3
|
+
import { keyedByContent } from "./keys.js";
|
|
4
|
+
import { useStrings } from "./Provider.js";
|
|
5
|
+
import { clsx } from "clsx";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Fragment as Fragment$1 } from "react";
|
|
8
|
+
import { Popover } from "@base-ui/react/popover";
|
|
9
|
+
//#region src/components/InfoTip.tsx
|
|
10
|
+
var linkRegex = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
|
|
11
|
+
function formatLine(line) {
|
|
12
|
+
const nodes = [];
|
|
13
|
+
let last = 0;
|
|
14
|
+
for (const match of line.matchAll(linkRegex)) {
|
|
15
|
+
if (match.index > last) nodes.push(line.slice(last, match.index));
|
|
16
|
+
nodes.push(/* @__PURE__ */ jsx("a", {
|
|
17
|
+
href: match[2],
|
|
18
|
+
target: "_blank",
|
|
19
|
+
rel: "noopener noreferrer",
|
|
20
|
+
className: "underline",
|
|
21
|
+
children: match[1]
|
|
22
|
+
}, match.index));
|
|
23
|
+
last = match.index + match[0].length;
|
|
24
|
+
}
|
|
25
|
+
if (last < line.length) nodes.push(line.slice(last));
|
|
26
|
+
return nodes;
|
|
27
|
+
}
|
|
28
|
+
/** Infotip text can come from untrusted sources (workflow YAML), so all markup is literal text — only `[text](url)` links and newlines are parsed. */
|
|
29
|
+
function formatInfoTipContent(content) {
|
|
30
|
+
if (!content) return null;
|
|
31
|
+
return keyedByContent(content.split(/<br\s*\/?>|\n/i), (l) => l).map(({ key, item: line }, idx) => /* @__PURE__ */ jsxs(Fragment$1, { children: [idx > 0 && /* @__PURE__ */ jsx("br", {}), formatLine(line)] }, key));
|
|
32
|
+
}
|
|
33
|
+
/** Extra detail behind an info trigger. A popover that also opens on hover, so
|
|
34
|
+
* touch and screen reader users can reach it and its links. */
|
|
35
|
+
function InfoTip({ text, side = "top", className, children }) {
|
|
36
|
+
const t = useStrings().common;
|
|
37
|
+
if (!text) return children ? /* @__PURE__ */ jsx("span", {
|
|
38
|
+
className,
|
|
39
|
+
children
|
|
40
|
+
}) : null;
|
|
41
|
+
return /* @__PURE__ */ jsxs(Popover.Root, { children: [/* @__PURE__ */ jsx(Popover.Trigger, {
|
|
42
|
+
openOnHover: true,
|
|
43
|
+
"aria-label": children ? void 0 : t.moreInfo,
|
|
44
|
+
className: clsx("inline-flex items-center cursor-help", !children && "tooltip", className),
|
|
45
|
+
children: children ?? /* @__PURE__ */ jsx(HiQuestionMarkCircle, { "aria-hidden": "true" })
|
|
46
|
+
}), /* @__PURE__ */ jsx(Popover.Portal, {
|
|
47
|
+
container: portalContainer(),
|
|
48
|
+
children: /* @__PURE__ */ jsx(Popover.Positioner, {
|
|
49
|
+
side,
|
|
50
|
+
sideOffset: 8,
|
|
51
|
+
className: positionerClassName,
|
|
52
|
+
children: /* @__PURE__ */ jsxs(Popover.Popup, {
|
|
53
|
+
className: clsx("max-w-sm text-left", tipClassName),
|
|
54
|
+
children: [/* @__PURE__ */ jsx(Popover.Arrow, { className: tipArrowClassName }), formatInfoTipContent(text)]
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
})] });
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
export { InfoTip, formatInfoTipContent };
|
package/dist/components/Input.js
CHANGED
|
@@ -2,12 +2,12 @@ import { LuEye } from "../icons/lu/LuEye.js";
|
|
|
2
2
|
import { LuEyeOff } from "../icons/lu/LuEyeOff.js";
|
|
3
3
|
import { TbAlertTriangle } from "../icons/tb/TbAlertTriangle.js";
|
|
4
4
|
import { RequiredMark } from "./RequiredMark.js";
|
|
5
|
-
import
|
|
6
|
-
import { forwardRef, useId, useState } from "react";
|
|
5
|
+
import { clsx } from "clsx";
|
|
7
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { forwardRef, useId, useState } from "react";
|
|
8
8
|
//#region src/components/Input.tsx
|
|
9
9
|
/** The box a text field draws, for other controls that should look like one. */
|
|
10
|
-
var fieldBoxClasses =
|
|
10
|
+
var fieldBoxClasses = clsx("w-full py-3 px-4 bg-[var(--theme-muted-panel-bg)] border border-[var(--theme-border)] rounded-lg text-[var(--theme-app)] text-sm transition-all duration-200 box-border", "focus:outline-none focus:border-[var(--theme-element)] focus:shadow-[0_0_0_3px_color-mix(in_srgb,var(--theme-element)_25%,transparent)]", "placeholder:text-[var(--theme-muted-text-color)]");
|
|
11
11
|
function LabelRow({ id, label, hint, required }) {
|
|
12
12
|
const element = /* @__PURE__ */ jsxs("label", {
|
|
13
13
|
className: "text-[0.8125rem] font-medium text-[var(--theme-app)]",
|
|
@@ -70,7 +70,7 @@ var Input = forwardRef(({ label, labelHint, description, error, className = "",
|
|
|
70
70
|
children: [/* @__PURE__ */ jsx("input", {
|
|
71
71
|
ref,
|
|
72
72
|
type: isPassword && showPassword ? "text" : type,
|
|
73
|
-
className:
|
|
73
|
+
className: clsx(fieldBoxClasses, "disabled:bg-[var(--theme-muted-panel-bg)] disabled:text-[var(--theme-muted-text-color)] disabled:cursor-not-allowed disabled:opacity-70", mono && "font-mono text-[0.8125rem]", error && "!border-[#ef4444]", isPassword && "pr-11", className),
|
|
74
74
|
...props,
|
|
75
75
|
id: field.id,
|
|
76
76
|
required,
|
|
@@ -96,7 +96,7 @@ var Textarea = forwardRef(({ label, labelHint, description, error, className = "
|
|
|
96
96
|
}, props.id, props["aria-describedby"], required);
|
|
97
97
|
return field.frame(/* @__PURE__ */ jsx("textarea", {
|
|
98
98
|
ref,
|
|
99
|
-
className:
|
|
99
|
+
className: clsx(fieldBoxClasses, "min-h-[140px] resize-y", mono && "font-mono text-[0.8125rem]", error && "!border-[#ef4444]", className),
|
|
100
100
|
...props,
|
|
101
101
|
id: field.id,
|
|
102
102
|
required,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { clsx } from "clsx";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
//#region src/components/LetterBadge.tsx
|
|
4
4
|
/** A compact letter badge ("AI", "PUB", "SSH") used as a type mark in place of
|
|
5
5
|
* an icon. Size the box and text via className (e.g. "h-5 w-5 text-[8px]"). */
|
|
6
6
|
function LetterBadge({ text, className }) {
|
|
7
7
|
return /* @__PURE__ */ jsx("span", {
|
|
8
|
-
className:
|
|
8
|
+
className: clsx("inline-flex shrink-0 items-center justify-center rounded-[3px] border theme-border font-bold leading-none tracking-tight text-(--theme-app)", className),
|
|
9
9
|
children: text
|
|
10
10
|
});
|
|
11
11
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LoaderIcon } from "./StatusIcons.js";
|
|
2
|
-
import
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
//#region src/components/Loader.tsx
|
|
5
5
|
var RIPPLE_STAGGER_S = .22;
|
|
@@ -15,9 +15,9 @@ function Loader({ size = 48, text, textSize = 12, full = true, color = "", loade
|
|
|
15
15
|
return /* @__PURE__ */ jsxs("div", {
|
|
16
16
|
role: "status",
|
|
17
17
|
"aria-label": text || "Loading",
|
|
18
|
-
className:
|
|
18
|
+
className: clsx(full && "w-full", "flex flex-col flex-wrap justify-center items-center gap-y-1"),
|
|
19
19
|
children: [/* @__PURE__ */ jsx("div", {
|
|
20
|
-
className:
|
|
20
|
+
className: clsx("w-full flex justify-center items-center", loaderColor),
|
|
21
21
|
style: loaderStyle,
|
|
22
22
|
children: variant === "logo" ? /* @__PURE__ */ jsx("svg", {
|
|
23
23
|
viewBox: "0 0 64.29 64.29",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { clsx } from "clsx";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { code } from "@streamdown/code";
|
|
4
4
|
import { math } from "@streamdown/math";
|
|
@@ -21,7 +21,7 @@ function Markdown({ children, isStreaming, controls }) {
|
|
|
21
21
|
shikiTheme,
|
|
22
22
|
components: { a: ({ node, ...props }) => /* @__PURE__ */ jsx("a", {
|
|
23
23
|
...props,
|
|
24
|
-
className:
|
|
24
|
+
className: clsx("link wrap-break-word", props.className),
|
|
25
25
|
target: "_blank",
|
|
26
26
|
rel: "noopener noreferrer"
|
|
27
27
|
}) },
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Menu as BaseMenu } from '@base-ui/react/menu';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
type Styled<Props> = Omit<Props, 'className'> & {
|
|
4
|
+
className?: string | undefined;
|
|
5
|
+
};
|
|
6
|
+
export interface MenuPopupProps {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
className?: string | undefined;
|
|
9
|
+
side?: BaseMenu.Positioner.Props['side'];
|
|
10
|
+
align?: BaseMenu.Positioner.Props['align'];
|
|
11
|
+
/** What it opens against in place of its trigger, such as the point a right-click landed. */
|
|
12
|
+
anchor?: BaseMenu.Positioner.Props['anchor'];
|
|
13
|
+
/** Keeps the popup's children mounted while closed, so state they own survives. */
|
|
14
|
+
keepMounted?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** The portal, positioner and popup every menu needs. */
|
|
17
|
+
export declare function MenuPopup({ children, className, side, align, anchor, keepMounted, }: MenuPopupProps): import("react").JSX.Element;
|
|
18
|
+
export declare function MenuItem({ className, ...props }: Styled<BaseMenu.Item.Props>): import("react").JSX.Element;
|
|
19
|
+
/** A navigation row; give it `render` for a router link. Closes the menu like any item. */
|
|
20
|
+
export declare function MenuLinkItem({ className, ...props }: Styled<BaseMenu.LinkItem.Props>): import("react").JSX.Element;
|
|
21
|
+
/** A choice within a Menu.RadioGroup, checked while it holds the group's value. */
|
|
22
|
+
export declare function MenuRadioItem({ className, children, ...props }: Styled<BaseMenu.RadioItem.Props>): import("react").JSX.Element;
|
|
23
|
+
/** An on/off choice, checked while `checked` holds; it closes the menu like any item. */
|
|
24
|
+
export declare function MenuCheckboxItem({ className, children, ...props }: Styled<BaseMenu.CheckboxItem.Props>): import("react").JSX.Element;
|
|
25
|
+
/** The row that opens a submenu, inside a Menu.SubmenuRoot. */
|
|
26
|
+
export declare function MenuSubmenuTrigger({ className, children, ...props }: Styled<BaseMenu.SubmenuTrigger.Props>): import("react").JSX.Element;
|
|
27
|
+
export declare function MenuSeparator({ className }: {
|
|
28
|
+
className?: string | undefined;
|
|
29
|
+
}): import("react").JSX.Element;
|
|
30
|
+
export declare function MenuGroupLabel({ children }: {
|
|
31
|
+
children: ReactNode;
|
|
32
|
+
}): import("react").JSX.Element;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { FaCheck } from "../icons/fa/FaCheck.js";
|
|
2
|
+
import { LuChevronRight } from "../icons/lu/LuChevronRight.js";
|
|
3
|
+
import { panelClassName, panelItemClassName, portalContainer, positionerClassName } from "./floating.js";
|
|
4
|
+
import { Menu } from "@base-ui/react/menu";
|
|
5
|
+
import { clsx } from "clsx";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/Menu.tsx
|
|
8
|
+
var itemClassName = panelItemClassName;
|
|
9
|
+
/** The portal, positioner and popup every menu needs. */
|
|
10
|
+
function MenuPopup({ children, className, side = "bottom", align = "start", anchor, keepMounted = false }) {
|
|
11
|
+
return /* @__PURE__ */ jsx(Menu.Portal, {
|
|
12
|
+
container: portalContainer(),
|
|
13
|
+
keepMounted,
|
|
14
|
+
children: /* @__PURE__ */ jsx(Menu.Positioner, {
|
|
15
|
+
side,
|
|
16
|
+
align,
|
|
17
|
+
anchor,
|
|
18
|
+
sideOffset: 4,
|
|
19
|
+
className: positionerClassName,
|
|
20
|
+
children: /* @__PURE__ */ jsx(Menu.Popup, {
|
|
21
|
+
className: clsx("min-w-44 max-h-(--available-height) overflow-y-auto py-1", panelClassName, className),
|
|
22
|
+
children
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function MenuItem({ className, ...props }) {
|
|
28
|
+
return /* @__PURE__ */ jsx(Menu.Item, {
|
|
29
|
+
...props,
|
|
30
|
+
className: clsx(itemClassName, className)
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/** A navigation row; give it `render` for a router link. Closes the menu like any item. */
|
|
34
|
+
function MenuLinkItem({ className, ...props }) {
|
|
35
|
+
return /* @__PURE__ */ jsx(Menu.LinkItem, {
|
|
36
|
+
closeOnClick: true,
|
|
37
|
+
...props,
|
|
38
|
+
className: clsx(itemClassName, className)
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/** A choice within a Menu.RadioGroup, checked while it holds the group's value. */
|
|
42
|
+
function MenuRadioItem({ className, children, ...props }) {
|
|
43
|
+
return /* @__PURE__ */ jsxs(Menu.RadioItem, {
|
|
44
|
+
closeOnClick: true,
|
|
45
|
+
...props,
|
|
46
|
+
className: clsx(itemClassName, "pl-2", className),
|
|
47
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
48
|
+
className: "flex w-3.5 shrink-0 justify-center",
|
|
49
|
+
children: /* @__PURE__ */ jsx(Menu.RadioItemIndicator, { children: /* @__PURE__ */ jsx(FaCheck, { className: "size-3" }) })
|
|
50
|
+
}), children]
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** An on/off choice, checked while `checked` holds; it closes the menu like any item. */
|
|
54
|
+
function MenuCheckboxItem({ className, children, ...props }) {
|
|
55
|
+
return /* @__PURE__ */ jsxs(Menu.CheckboxItem, {
|
|
56
|
+
closeOnClick: true,
|
|
57
|
+
...props,
|
|
58
|
+
className: clsx(itemClassName, className),
|
|
59
|
+
children: [children, /* @__PURE__ */ jsx(Menu.CheckboxItemIndicator, {
|
|
60
|
+
className: "ml-auto",
|
|
61
|
+
children: /* @__PURE__ */ jsx(FaCheck, { className: "size-3.5 opacity-80" })
|
|
62
|
+
})]
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/** The row that opens a submenu, inside a Menu.SubmenuRoot. */
|
|
66
|
+
function MenuSubmenuTrigger({ className, children, ...props }) {
|
|
67
|
+
return /* @__PURE__ */ jsxs(Menu.SubmenuTrigger, {
|
|
68
|
+
...props,
|
|
69
|
+
className: clsx(itemClassName, "data-popup-open:bg-(--theme-hover)", className),
|
|
70
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
71
|
+
className: "flex min-w-0 flex-1 items-center gap-2",
|
|
72
|
+
children
|
|
73
|
+
}), /* @__PURE__ */ jsx(LuChevronRight, { className: "size-3 shrink-0 opacity-60" })]
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function MenuSeparator({ className }) {
|
|
77
|
+
return /* @__PURE__ */ jsx(Menu.Separator, { className: clsx("my-1 h-px bg-(--theme-border)", className) });
|
|
78
|
+
}
|
|
79
|
+
function MenuGroupLabel({ children }) {
|
|
80
|
+
return /* @__PURE__ */ jsx(Menu.GroupLabel, {
|
|
81
|
+
className: "px-3 pt-2 pb-1 text-[10px] font-semibold uppercase tracking-wide text-(--theme-muted-text-color)",
|
|
82
|
+
children
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { MenuCheckboxItem, MenuGroupLabel, MenuItem, MenuLinkItem, MenuPopup, MenuRadioItem, MenuSeparator, MenuSubmenuTrigger };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
/** Something a menu row does: navigates with `href`, or runs `onClick`. */
|
|
3
|
+
export interface MenuAction {
|
|
4
|
+
label: string;
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
/** Navigates instead of calling onClick. */
|
|
7
|
+
href?: string | undefined;
|
|
8
|
+
/** Loads the page instead of routing, for paths the host's router doesn't serve. */
|
|
9
|
+
reloadDocument?: boolean | undefined;
|
|
10
|
+
onClick?: (() => void) | undefined;
|
|
11
|
+
disabled?: boolean | undefined;
|
|
12
|
+
/** Why the action is disabled, shown on hover and read with its name. */
|
|
13
|
+
disabledReason?: string | undefined;
|
|
14
|
+
destructive?: boolean | undefined;
|
|
15
|
+
/** Makes the row an on/off choice, checked while true. */
|
|
16
|
+
checked?: boolean | undefined;
|
|
17
|
+
/** Text the row copies to the clipboard, confirmed with a toast naming `label`. */
|
|
18
|
+
copy?: {
|
|
19
|
+
text: string;
|
|
20
|
+
label: string;
|
|
21
|
+
} | undefined;
|
|
22
|
+
/** More text a menu's search matches, beside the label. */
|
|
23
|
+
keywords?: string | undefined;
|
|
24
|
+
}
|
|
25
|
+
/** A row that opens a menu of its own. */
|
|
26
|
+
export interface MenuSubmenu {
|
|
27
|
+
label: string;
|
|
28
|
+
icon?: ReactNode;
|
|
29
|
+
items: MenuEntry[];
|
|
30
|
+
search?: MenuSearch | undefined;
|
|
31
|
+
}
|
|
32
|
+
export interface MenuDivider {
|
|
33
|
+
divider: true;
|
|
34
|
+
}
|
|
35
|
+
export type MenuEntry = MenuAction | MenuSubmenu | MenuDivider;
|
|
36
|
+
export declare const menuDivider: MenuDivider;
|
|
37
|
+
/** A field atop a menu that narrows it, submenus included, to the actions it matches. */
|
|
38
|
+
export interface MenuSearch {
|
|
39
|
+
placeholder: string;
|
|
40
|
+
/** Shown when nothing matches. */
|
|
41
|
+
empty: string;
|
|
42
|
+
}
|
|
43
|
+
export declare const isMenuDivider: (entry: MenuEntry) => entry is MenuDivider;
|
|
44
|
+
export declare const isMenuSubmenu: (entry: MenuEntry) => entry is MenuSubmenu;
|
|
45
|
+
/** Gives a menu root its search's filter; `children` renders the root with the query. */
|
|
46
|
+
export declare function MenuFilter({ search, children, }: {
|
|
47
|
+
search: MenuSearch | undefined;
|
|
48
|
+
children: (query: string) => ReactNode;
|
|
49
|
+
}): string | number | bigint | boolean | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null | undefined;
|
|
50
|
+
/** A menu's rows, with its search field when it has one. */
|
|
51
|
+
export declare function MenuEntries({ entries, search, query, }: {
|
|
52
|
+
entries: MenuEntry[];
|
|
53
|
+
search?: MenuSearch | undefined;
|
|
54
|
+
/** The search's text, from the MenuFilter around the menu's root. */
|
|
55
|
+
query?: string;
|
|
56
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { MenuCheckboxItem, MenuItem, MenuLinkItem, MenuPopup, MenuSeparator, MenuSubmenuTrigger } from "./Menu.js";
|
|
2
|
+
import { safeUrl } from "../safeUrl.js";
|
|
3
|
+
import { keyedByContent } from "./keys.js";
|
|
4
|
+
import { Tooltip } from "./Tooltip.js";
|
|
5
|
+
import { useLink, useNotify, useStrings } from "./Provider.js";
|
|
6
|
+
import { useQueryMatch } from "./search.js";
|
|
7
|
+
import { Menu } from "@base-ui/react/menu";
|
|
8
|
+
import { clsx } from "clsx";
|
|
9
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { useState } from "react";
|
|
11
|
+
//#region src/components/MenuEntries.tsx
|
|
12
|
+
var menuDivider = { divider: true };
|
|
13
|
+
var isMenuDivider = (entry) => "divider" in entry;
|
|
14
|
+
var isMenuSubmenu = (entry) => "items" in entry;
|
|
15
|
+
/** Gives a menu root its search's filter; `children` renders the root with the query. */
|
|
16
|
+
function MenuFilter({ search, children }) {
|
|
17
|
+
const [query, setQuery] = useState("");
|
|
18
|
+
if (!search) return children("");
|
|
19
|
+
return /* @__PURE__ */ jsx(Menu.FilterProvider, {
|
|
20
|
+
filter: null,
|
|
21
|
+
value: query,
|
|
22
|
+
onValueChange: setQuery,
|
|
23
|
+
autoHighlight: true,
|
|
24
|
+
children: children(query)
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/** A menu's rows, with its search field when it has one. */
|
|
28
|
+
function MenuEntries({ entries, search, query = "" }) {
|
|
29
|
+
const matches = useQueryMatch();
|
|
30
|
+
if (!search) return /* @__PURE__ */ jsx(EntryRows, { entries });
|
|
31
|
+
const needle = query.trim();
|
|
32
|
+
const shown = needle ? searchMatches(entries, (a) => matches(needle, a.label, a.keywords)) : entries;
|
|
33
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
34
|
+
/* @__PURE__ */ jsx("div", {
|
|
35
|
+
className: "sticky top-0 z-[1] bg-(--theme-app-bg) px-2 pt-0.5 pb-1",
|
|
36
|
+
children: /* @__PURE__ */ jsx(Menu.Input, {
|
|
37
|
+
"aria-label": search.placeholder,
|
|
38
|
+
placeholder: search.placeholder,
|
|
39
|
+
className: "w-full rounded-md border border-(--theme-border) bg-(--theme-muted-panel-bg) px-2 py-1 text-[13px] text-(--theme-app) outline-none placeholder:text-(--theme-muted-text-color) focus:border-(--theme-element)"
|
|
40
|
+
})
|
|
41
|
+
}),
|
|
42
|
+
/* @__PURE__ */ jsx(Menu.List, { children: /* @__PURE__ */ jsx(EntryRows, { entries: shown }) }),
|
|
43
|
+
needle && shown.length === 0 && /* @__PURE__ */ jsx("div", {
|
|
44
|
+
className: "px-3 py-1.5 text-[13px] text-(--theme-muted-text-color)",
|
|
45
|
+
children: search.empty
|
|
46
|
+
})
|
|
47
|
+
] });
|
|
48
|
+
}
|
|
49
|
+
function searchMatches(entries, match) {
|
|
50
|
+
const found = /* @__PURE__ */ new Map();
|
|
51
|
+
const walk = (list) => {
|
|
52
|
+
for (const entry of list) if (isMenuSubmenu(entry)) walk(entry.items);
|
|
53
|
+
else if (!isMenuDivider(entry) && !found.has(entry.label) && match(entry)) found.set(entry.label, entry);
|
|
54
|
+
};
|
|
55
|
+
walk(entries);
|
|
56
|
+
return [...found.values()];
|
|
57
|
+
}
|
|
58
|
+
function EntryRows({ entries }) {
|
|
59
|
+
return keyedByContent(entries, (entry) => isMenuDivider(entry) ? "divider" : entry.label).map(({ key, item }) => isMenuDivider(item) ? /* @__PURE__ */ jsx(MenuSeparator, {}, key) : isMenuSubmenu(item) ? /* @__PURE__ */ jsx(SubmenuRow, { submenu: item }, key) : /* @__PURE__ */ jsx(ActionRow, { action: item }, key));
|
|
60
|
+
}
|
|
61
|
+
function SubmenuRow({ submenu }) {
|
|
62
|
+
return /* @__PURE__ */ jsx(MenuFilter, {
|
|
63
|
+
search: submenu.search,
|
|
64
|
+
children: (query) => /* @__PURE__ */ jsxs(Menu.SubmenuRoot, { children: [/* @__PURE__ */ jsxs(MenuSubmenuTrigger, { children: [submenu.icon, submenu.label] }), /* @__PURE__ */ jsx(MenuPopup, {
|
|
65
|
+
side: "inline-end",
|
|
66
|
+
children: /* @__PURE__ */ jsx(MenuEntries, {
|
|
67
|
+
entries: submenu.items,
|
|
68
|
+
search: submenu.search,
|
|
69
|
+
query
|
|
70
|
+
})
|
|
71
|
+
})] })
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
var destructiveClassName = "text-(--theme-error) data-highlighted:text-(--theme-error)";
|
|
75
|
+
function ActionRow({ action }) {
|
|
76
|
+
const Link = useLink();
|
|
77
|
+
const copy = useCopy();
|
|
78
|
+
const className = clsx(action.destructive && destructiveClassName);
|
|
79
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [action.icon, action.label] });
|
|
80
|
+
if (action.href && !action.disabled) return action.reloadDocument ? /* @__PURE__ */ jsx(MenuLinkItem, {
|
|
81
|
+
href: safeUrl(action.href),
|
|
82
|
+
className,
|
|
83
|
+
children: content
|
|
84
|
+
}) : /* @__PURE__ */ jsx(MenuLinkItem, {
|
|
85
|
+
render: /* @__PURE__ */ jsx(Link, { href: action.href }),
|
|
86
|
+
className,
|
|
87
|
+
children: content
|
|
88
|
+
});
|
|
89
|
+
const run = () => {
|
|
90
|
+
if (action.copy) copy(action.copy);
|
|
91
|
+
action.onClick?.();
|
|
92
|
+
};
|
|
93
|
+
const reason = action.disabled ? action.disabledReason : void 0;
|
|
94
|
+
const label = /* @__PURE__ */ jsxs(Fragment, { children: [content, reason && /* @__PURE__ */ jsxs("span", {
|
|
95
|
+
className: "sr-only",
|
|
96
|
+
children: [". ", reason]
|
|
97
|
+
})] });
|
|
98
|
+
return /* @__PURE__ */ jsx(Tooltip, {
|
|
99
|
+
content: reason,
|
|
100
|
+
side: "right",
|
|
101
|
+
children: action.checked === void 0 ? /* @__PURE__ */ jsx(MenuItem, {
|
|
102
|
+
disabled: action.disabled,
|
|
103
|
+
onClick: run,
|
|
104
|
+
className,
|
|
105
|
+
children: label
|
|
106
|
+
}) : /* @__PURE__ */ jsx(MenuCheckboxItem, {
|
|
107
|
+
checked: action.checked,
|
|
108
|
+
onCheckedChange: run,
|
|
109
|
+
disabled: action.disabled,
|
|
110
|
+
className,
|
|
111
|
+
children: label
|
|
112
|
+
})
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
function useCopy() {
|
|
116
|
+
const notify = useNotify();
|
|
117
|
+
const { list: t } = useStrings();
|
|
118
|
+
return ({ text, label }) => {
|
|
119
|
+
navigator.clipboard?.writeText(text).then(() => notify.success(t.copied(label)), () => notify.error(t.couldntCopy(label)));
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
//#endregion
|
|
123
|
+
export { MenuEntries, MenuFilter, isMenuDivider, isMenuSubmenu, menuDivider };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Dialog } from '@base-ui/react/dialog';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
/** The panel a modal draws by default; pass `panel={false}` to paint your own. */
|
|
4
|
+
export declare const modalPanelClassName = "rounded-xl border border-(--theme-border) bg-(--theme-app-bg) text-(--theme-app) shadow-2xl";
|
|
5
|
+
/** Names the modal for assistive technology; renders an `<h2>`. */
|
|
6
|
+
export declare const ModalTitle: import("react").ForwardRefExoticComponent<Omit<import("@base-ui/react").DialogTitleProps, "ref"> & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
7
|
+
/** Describes the modal for assistive technology; renders a `<p>`. */
|
|
8
|
+
export declare const ModalDescription: import("react").ForwardRefExoticComponent<Omit<import("@base-ui/react").DialogDescriptionProps, "ref"> & import("react").RefAttributes<HTMLParagraphElement>>;
|
|
9
|
+
export interface ModalProps extends Omit<Dialog.Popup.Props, 'className' | 'children' | 'render'> {
|
|
10
|
+
open: boolean;
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
/** A confirmation the person must answer: it takes the alertdialog role and the
|
|
13
|
+
* backdrop doesn't close it. Escape still cancels while it's dismissible. */
|
|
14
|
+
alert?: boolean | undefined;
|
|
15
|
+
/** False ignores the backdrop and Escape, so typed input isn't lost to a stray
|
|
16
|
+
* click; the modal's own buttons still close it. */
|
|
17
|
+
dismissible?: boolean | undefined;
|
|
18
|
+
/** Where the panel sits: near the top of the window, or in its middle. */
|
|
19
|
+
align?: 'top' | 'center' | undefined;
|
|
20
|
+
/** Draws the default panel surface around `className`. */
|
|
21
|
+
panel?: boolean;
|
|
22
|
+
/** The backdrop's dimming, for a modal that needs a darker or blurred stage. */
|
|
23
|
+
backdropClassName?: string;
|
|
24
|
+
className?: string;
|
|
25
|
+
children: ReactNode;
|
|
26
|
+
}
|
|
27
|
+
/** A modal dialog: focus stays inside, the page behind is inert and doesn't scroll,
|
|
28
|
+
* and focus returns to where it was on close. Name it with `ModalTitle` or `aria-label`. */
|
|
29
|
+
export declare function Modal({ open, onClose, alert, dismissible, align, panel, backdropClassName, className, children, ...popupProps }: ModalProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { portalContainer } from "./floating.js";
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { AlertDialog } from "@base-ui/react/alert-dialog";
|
|
5
|
+
import { Dialog } from "@base-ui/react/dialog";
|
|
6
|
+
//#region src/components/Modal.tsx
|
|
7
|
+
/** The panel a modal draws by default; pass `panel={false}` to paint your own. */
|
|
8
|
+
var modalPanelClassName = "rounded-xl border border-(--theme-border) bg-(--theme-app-bg) text-(--theme-app) shadow-2xl";
|
|
9
|
+
/** Names the modal for assistive technology; renders an `<h2>`. */
|
|
10
|
+
var ModalTitle = Dialog.Title;
|
|
11
|
+
/** Describes the modal for assistive technology; renders a `<p>`. */
|
|
12
|
+
var ModalDescription = Dialog.Description;
|
|
13
|
+
/** A modal dialog: focus stays inside, the page behind is inert and doesn't scroll,
|
|
14
|
+
* and focus returns to where it was on close. Name it with `ModalTitle` or `aria-label`. */
|
|
15
|
+
function Modal({ open, onClose, alert = false, dismissible = true, align = "top", panel = true, backdropClassName = "bg-black/40", className, children, ...popupProps }) {
|
|
16
|
+
const onOpenChange = (next, details) => {
|
|
17
|
+
if (next) return;
|
|
18
|
+
if (!dismissible && details.reason === "escape-key") {
|
|
19
|
+
details.cancel();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
onClose();
|
|
23
|
+
};
|
|
24
|
+
const content = /* @__PURE__ */ jsxs(Dialog.Portal, {
|
|
25
|
+
container: portalContainer(),
|
|
26
|
+
children: [/* @__PURE__ */ jsx(Dialog.Backdrop, { className: clsx("fixed inset-0 z-[9990]", backdropClassName) }), /* @__PURE__ */ jsx(Dialog.Viewport, {
|
|
27
|
+
className: clsx("fixed inset-0 z-[9990] flex justify-center px-4 pb-8", align === "center" ? "items-center" : "items-start pt-[14vh]"),
|
|
28
|
+
children: /* @__PURE__ */ jsx(Dialog.Popup, {
|
|
29
|
+
...popupProps,
|
|
30
|
+
className: clsx(panel && "rounded-xl border border-(--theme-border) bg-(--theme-app-bg) text-(--theme-app) shadow-2xl", "outline-none", className),
|
|
31
|
+
children
|
|
32
|
+
})
|
|
33
|
+
})]
|
|
34
|
+
});
|
|
35
|
+
return alert ? /* @__PURE__ */ jsx(AlertDialog.Root, {
|
|
36
|
+
open,
|
|
37
|
+
onOpenChange,
|
|
38
|
+
children: content
|
|
39
|
+
}) : /* @__PURE__ */ jsx(Dialog.Root, {
|
|
40
|
+
open,
|
|
41
|
+
disablePointerDismissal: !dismissible,
|
|
42
|
+
onOpenChange,
|
|
43
|
+
children: content
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { Modal, ModalDescription, ModalTitle, modalPanelClassName };
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { clsx } from "clsx";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import Skeleton from "react-loading-skeleton";
|
|
4
3
|
//#region src/components/Overview.tsx
|
|
5
4
|
function Overview({ Icon, name, type, children, right, className, loading, iconSize = 75 }) {
|
|
6
5
|
return /* @__PURE__ */ jsxs("div", {
|
|
7
|
-
className:
|
|
6
|
+
className: clsx("flex items-center w-full", className),
|
|
8
7
|
children: [
|
|
9
|
-
loading ? /* @__PURE__ */ jsx(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
loading ? /* @__PURE__ */ jsx("div", {
|
|
9
|
+
className: "shrink-0 animate-pulse rounded-full bg-(--theme-muted-panel-bg)",
|
|
10
|
+
style: {
|
|
11
|
+
width: iconSize,
|
|
12
|
+
height: iconSize
|
|
13
|
+
}
|
|
13
14
|
}) : Icon,
|
|
14
15
|
/* @__PURE__ */ jsx("div", {
|
|
15
16
|
className: "flex flex-col min-w-0 flex-1",
|
|
16
|
-
children: loading ? /* @__PURE__ */
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
children: loading ? /* @__PURE__ */ jsxs("div", {
|
|
18
|
+
className: "space-y-1",
|
|
19
|
+
children: [/* @__PURE__ */ jsx("div", { className: "h-3 animate-pulse rounded bg-(--theme-muted-panel-bg)" }), /* @__PURE__ */ jsx("div", { className: "h-3 animate-pulse rounded bg-(--theme-muted-panel-bg)" })]
|
|
19
20
|
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
20
21
|
/* @__PURE__ */ jsx("div", {
|
|
21
22
|
className: "font-semibold text-xl tracking-tight",
|