@parallelworks/ui 0.77.0 → 0.79.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -6
- package/dist/access/AccessDrawer.d.ts +49 -7
- package/dist/access/AccessDrawer.js +243 -38
- package/dist/access/AccessList.d.ts +19 -1
- package/dist/access/AccessList.js +220 -9
- package/dist/access/GrantView.d.ts +3 -1
- package/dist/access/GrantView.js +17 -4
- package/dist/access/PrincipalPicker.js +5 -5
- package/dist/access/focus.js +1 -1
- package/dist/access/index.d.ts +2 -2
- package/dist/access/index.js +2 -2
- package/dist/access/strings.d.ts +25 -1
- package/dist/access/strings.js +27 -3
- package/dist/access/types.d.ts +26 -0
- package/dist/ai/components/AllocationSelector.js +1 -1
- package/dist/ai/components/AttachmentManager.js +5 -5
- package/dist/ai/components/AttachmentUpload.js +2 -2
- package/dist/ai/components/BranchNavigator.js +1 -1
- package/dist/ai/components/ChatActivity.js +1 -1
- package/dist/ai/components/ChatEmptyState.js +3 -3
- package/dist/ai/components/ChatInput.js +3 -5
- package/dist/ai/components/ChatLayout.js +1 -1
- package/dist/ai/components/ChatMessage.js +1 -1
- package/dist/ai/components/ChatMessageList.js +23 -8
- package/dist/ai/components/ChatSidebar.js +3 -3
- package/dist/ai/components/ChatThread.js +4 -4
- package/dist/ai/components/ComposerAddMenu.js +9 -20
- package/dist/ai/components/ModelSelector.js +3 -3
- package/dist/ai/components/PastedText.js +5 -5
- package/dist/ai/components/SessionView.js +1 -1
- package/dist/ai/components/ShareDialog.js +3 -3
- package/dist/ai/components/SlashMenu.d.ts +31 -4
- package/dist/ai/components/SlashMenu.js +36 -63
- package/dist/ai/components/agent/ActivityLine.js +1 -1
- package/dist/ai/components/agent/AgentMessageParts.js +13 -13
- package/dist/ai/components/conversationActions.js +3 -3
- package/dist/ai/core/ChatProvider.js +1 -1
- package/dist/ai/core/config.js +1 -1
- package/dist/ai/ui/ConversationSidebar.js +3 -3
- package/dist/ai/ui/sidebar.js +3 -3
- package/dist/assets/yaml.worker-DOBV2lND.js +884 -0
- package/dist/components/ActionMenu.d.ts +38 -9
- package/dist/components/ActionMenu.js +48 -22
- package/dist/components/Avatar.d.ts +66 -6
- package/dist/components/Avatar.js +130 -18
- package/dist/components/Breadcrumbs.d.ts +4 -0
- package/dist/components/Breadcrumbs.js +26 -10
- package/dist/components/Button.d.ts +3 -2
- package/dist/components/Button.js +11 -1
- package/dist/components/Callout.d.ts +3 -2
- package/dist/components/Callout.js +3 -2
- package/dist/components/Card.d.ts +33 -9
- package/dist/components/Card.js +24 -8
- package/dist/components/Checkbox.d.ts +3 -1
- package/dist/components/Checkbox.js +4 -2
- package/dist/components/ColorInput.js +1 -1
- package/dist/components/Combobox.d.ts +23 -0
- package/dist/components/Combobox.js +252 -86
- package/dist/components/ConfirmModal.d.ts +28 -2
- package/dist/components/ConfirmModal.js +100 -15
- package/dist/components/ContextMenu.d.ts +29 -2
- package/dist/components/ContextMenu.js +60 -8
- package/dist/components/CopyButton.d.ts +21 -8
- package/dist/components/CopyButton.js +29 -9
- package/dist/components/CreateModal.d.ts +20 -4
- package/dist/components/CreateModal.js +28 -17
- package/dist/components/DatePicker.d.ts +31 -1
- package/dist/components/DatePicker.js +178 -47
- package/dist/components/DescriptionList.d.ts +13 -3
- package/dist/components/DescriptionList.js +43 -11
- package/dist/components/Disclosure.d.ts +10 -2
- package/dist/components/Disclosure.js +18 -7
- package/dist/components/Drawer.js +5 -5
- package/dist/components/EmptyState.d.ts +12 -4
- package/dist/components/EmptyState.js +18 -10
- package/dist/components/ErrorPage.d.ts +40 -0
- package/dist/components/ErrorPage.js +101 -0
- package/dist/components/ExternalLink.d.ts +4 -1
- package/dist/components/ExternalLink.js +4 -5
- package/dist/components/Field.d.ts +21 -6
- package/dist/components/Field.js +32 -16
- package/dist/components/FileButton.d.ts +19 -0
- package/dist/components/FileButton.js +32 -0
- package/dist/components/HoverCard.d.ts +26 -6
- package/dist/components/HoverCard.js +11 -5
- package/dist/components/IconButton.js +4 -2
- package/dist/components/InfoTip.js +3 -3
- package/dist/components/Input.d.ts +33 -3
- package/dist/components/Input.js +149 -14
- package/dist/components/Kbd.d.ts +40 -0
- package/dist/components/Kbd.js +168 -0
- package/dist/components/Listbox.d.ts +103 -0
- package/dist/components/Listbox.js +190 -0
- package/dist/components/Loader.d.ts +8 -2
- package/dist/components/Loader.js +16 -1
- package/dist/components/Markdown.js +1 -1
- package/dist/components/MarkdownImpl.js +1 -1
- package/dist/components/Menu.d.ts +20 -2
- package/dist/components/Menu.js +48 -19
- package/dist/components/MenuEntries.d.ts +41 -4
- package/dist/components/MenuEntries.js +266 -39
- package/dist/components/Meter.d.ts +50 -11
- package/dist/components/Meter.js +71 -21
- package/dist/components/Modal.d.ts +9 -3
- package/dist/components/Modal.js +68 -29
- package/dist/components/OneTimeCodeInput.js +1 -1
- package/dist/components/PageHeader.js +111 -7
- package/dist/components/PageHeaderAction.d.ts +8 -3
- package/dist/components/PageHeaderAction.js +122 -34
- package/dist/components/Pagination.d.ts +13 -1
- package/dist/components/Pagination.js +90 -19
- package/dist/components/Popover.d.ts +16 -2
- package/dist/components/Popover.js +20 -21
- package/dist/components/Provider.d.ts +172 -5
- package/dist/components/Provider.js +157 -14
- package/dist/components/RefreshButton.d.ts +13 -6
- package/dist/components/RefreshButton.js +17 -9
- package/dist/components/RunStatusIcon.d.ts +16 -7
- package/dist/components/RunStatusIcon.js +21 -8
- package/dist/components/Section.d.ts +11 -4
- package/dist/components/Section.js +33 -22
- package/dist/components/SegmentedControl.d.ts +16 -3
- package/dist/components/SegmentedControl.js +7 -3
- package/dist/components/Select.d.ts +19 -3
- package/dist/components/Select.js +114 -68
- package/dist/components/SelectionCopy.d.ts +10 -0
- package/dist/components/SelectionCopy.js +105 -0
- package/dist/components/SettingModeOption.js +1 -1
- package/dist/components/SettingsCard.js +1 -1
- package/dist/components/Skeleton.js +1 -1
- package/dist/components/StatusBadge.d.ts +55 -10
- package/dist/components/StatusBadge.js +91 -15
- package/dist/components/StickyBar.js +1 -1
- package/dist/components/Table.d.ts +22 -4
- package/dist/components/Table.js +46 -24
- package/dist/components/Tabs.d.ts +9 -4
- package/dist/components/Tabs.js +9 -4
- package/dist/components/Tag.d.ts +49 -0
- package/dist/components/Tag.js +199 -0
- package/dist/components/ThemeEditor.js +1 -1
- package/dist/components/Toast.js +1 -1
- package/dist/components/ToggleGroup.d.ts +4 -1
- package/dist/components/ToggleGroup.js +30 -13
- package/dist/components/Tooltip.d.ts +9 -3
- package/dist/components/Tooltip.js +55 -39
- package/dist/components/buttonClasses.d.ts +5 -2
- package/dist/components/buttonClasses.js +11 -10
- package/dist/components/chart.d.ts +69 -0
- package/dist/components/chart.js +145 -0
- package/dist/components/comboboxItems.d.ts +7 -1
- package/dist/components/comboboxItems.js +6 -2
- package/dist/components/dismiss.d.ts +5 -1
- package/dist/components/dismiss.js +6 -2
- package/dist/components/floating.d.ts +4 -4
- package/dist/components/floating.js +5 -5
- package/dist/components/headerActionsFit.d.ts +37 -0
- package/dist/components/headerActionsFit.js +81 -0
- package/dist/components/pageHeaderStore.d.ts +3 -0
- package/dist/components/pageHeaderStore.js +3 -0
- package/dist/components/pathBreaks.js +2 -2
- package/dist/components/popupContainer.d.ts +17 -0
- package/dist/components/popupContainer.js +69 -0
- package/dist/components/relativeTime.d.ts +21 -10
- package/dist/components/relativeTime.js +50 -22
- package/dist/components/segmented.d.ts +18 -4
- package/dist/components/segmented.js +48 -6
- package/dist/components/typedDate.d.ts +5 -0
- package/dist/components/typedDate.js +50 -0
- package/dist/components/useClosingValue.d.ts +4 -0
- package/dist/components/useClosingValue.js +12 -0
- package/dist/components/useCopy.d.ts +6 -0
- package/dist/components/useCopy.js +3 -3
- package/dist/components/useNarrow.d.ts +2 -0
- package/dist/components/useNarrow.js +16 -0
- package/dist/editor/Editor.js +1 -1
- package/dist/editor/FormCodePanel.js +1 -1
- package/dist/editor/Monaco.js +1 -1
- package/dist/editor/workers.js +1 -1
- package/dist/file-explorer/FileExplorer.js +16 -15
- package/dist/file-explorer/FileExplorerContext.js +2 -2
- package/dist/file-explorer/FilePreview/Viewer.js +3 -3
- package/dist/file-explorer/FilePreview/index.js +2 -2
- package/dist/file-explorer/FileRowsWindow.js +3 -3
- package/dist/file-explorer/FileTable.js +1 -1
- package/dist/file-explorer/LoadMoreRow.js +1 -1
- package/dist/file-explorer/TreeView.js +5 -5
- package/dist/file-explorer/helpers.js +2 -2
- package/dist/file-explorer/toasts.js +2 -2
- package/dist/form/Fields/CheckboxGroupField.js +1 -1
- package/dist/form/Fields/DropdownField.js +1 -1
- package/dist/form/Fields/DurationField.js +2 -2
- package/dist/form/Fields/MultiDropdownField.js +1 -1
- package/dist/form/Fields/NumberField.js +1 -1
- package/dist/form/Fields/ObjectField.js +1 -1
- package/dist/form/Fields/RangeField.js +1 -1
- package/dist/form/Fields/StringField.js +1 -1
- package/dist/form/Form.js +3 -3
- package/dist/form/FormLayout.js +1 -1
- package/dist/form/Wizard/WizardContainer.js +1 -1
- package/dist/form/Wizard/WizardNavigation.js +1 -1
- package/dist/form/Wizard/WizardStepContent.js +1 -1
- package/dist/form/fieldRegistry.js +1 -1
- package/dist/form/formEditing.js +1 -1
- package/dist/format.d.ts +17 -7
- package/dist/format.js +39 -16
- package/dist/graph/AnnotationBanner.js +2 -2
- package/dist/graph/Connectors.js +5 -5
- package/dist/graph/DependencyGraph.js +10 -9
- package/dist/graph/GraphEditor.js +4 -4
- package/dist/graph/GraphEditorDialogs.js +13 -12
- package/dist/graph/GraphNode.js +1 -1
- package/dist/graph/InputDialog.js +5 -5
- package/dist/graph/InputsEditor.js +10 -9
- package/dist/graph/MatrixGroup.js +2 -2
- package/dist/graph/ProblemPageLink.d.ts +9 -0
- package/dist/graph/ProblemPageLink.js +21 -0
- package/dist/graph/ProblemsButton.js +26 -16
- package/dist/graph/Reveal.js +1 -1
- package/dist/graph/RunWarningsList.js +21 -12
- package/dist/graph/ShortcutsButton.js +25 -8
- package/dist/graph/StepSummaries.js +1 -1
- package/dist/graph/TreeView.js +2 -2
- package/dist/graph/WorkflowSettingsDialog.js +3 -3
- package/dist/graph/editorApi.d.ts +10 -0
- package/dist/graph/editorFields.js +3 -3
- package/dist/graph/editorPrimitives.js +1 -1
- package/dist/graph/editorRows.js +8 -6
- package/dist/graph/editorStrings.d.ts +1 -0
- package/dist/graph/editorStrings.js +1 -0
- package/dist/graph/fieldProblems.js +2 -2
- package/dist/graph/inputRefs.js +7 -6
- package/dist/graph/runWarnings.d.ts +12 -1
- package/dist/graph/stepWith.js +2 -2
- package/dist/index.d.ts +30 -21
- package/dist/index.js +20 -12
- package/dist/list/ActionToolbar.d.ts +4 -0
- package/dist/list/ActionToolbar.js +35 -12
- package/dist/list/ListFilterBar.d.ts +42 -0
- package/dist/list/ListFilterBar.js +789 -0
- package/dist/list/ListPage.d.ts +42 -4
- package/dist/list/ListPage.js +56 -22
- package/dist/list/ListTable.d.ts +27 -3
- package/dist/list/ListTable.js +48 -23
- package/dist/list/ListToolbar.d.ts +31 -0
- package/dist/list/ListToolbar.js +43 -0
- package/dist/list/ListViewControls.d.ts +8 -4
- package/dist/list/ListViewControls.js +22 -14
- package/dist/list/UserHoverCard.d.ts +8 -2
- package/dist/list/UserHoverCard.js +26 -13
- package/dist/list/filterModel.d.ts +122 -0
- package/dist/list/filterModel.js +308 -0
- package/dist/list/index.d.ts +6 -2
- package/dist/list/index.js +6 -2
- package/dist/list/listSearch.d.ts +1 -1
- package/dist/list/listSearch.js +8 -4
- package/dist/list/listView.d.ts +24 -2
- package/dist/list/listView.js +47 -45
- package/dist/list/rowMenu.d.ts +10 -5
- package/dist/list/rowMenu.js +17 -7
- package/dist/list/useListFilters.d.ts +68 -0
- package/dist/list/useListFilters.js +252 -0
- package/dist/logviewer/LogViewer.js +4 -4
- package/dist/styles/theme.css +94 -0
- package/dist/styles.css +1 -1
- package/package.json +11 -11
- package/dist/assets/yaml.worker-k9AdOqzf.js +0 -1441
- package/dist/components/fullscreen.d.ts +0 -4
- package/dist/components/fullscreen.js +0 -18
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
|
-
import {
|
|
2
|
+
import { EmptyState } from "./EmptyState.js";
|
|
3
|
+
import { CheckIcon, ChevronLeftIcon, ChevronRightIcon, ExternalLinkIcon } from "../icons.js";
|
|
4
|
+
import { MenuCheckboxItem, MenuGroupLabel, MenuItem, MenuLinkItem, MenuPopup, MenuSeparator, MenuSubmenuTrigger } from "./Menu.js";
|
|
3
5
|
import { isDev } from "../dev.js";
|
|
4
|
-
import { keyedByContent } from "./keys.js";
|
|
5
6
|
import { Tooltip } from "./Tooltip.js";
|
|
7
|
+
import { useStrings } from "./Provider.js";
|
|
6
8
|
import { AppLink } from "./AppLink.js";
|
|
7
|
-
import {
|
|
9
|
+
import { keyedByContent } from "./keys.js";
|
|
8
10
|
import { useQueryMatch } from "./search.js";
|
|
9
11
|
import { useCopy } from "./useCopy.js";
|
|
12
|
+
import { useNarrow } from "./useNarrow.js";
|
|
10
13
|
import { Menu } from "@base-ui/react/menu";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
14
|
+
import { createContext, use, useCallback, useLayoutEffect, useRef, useState } from "react";
|
|
15
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
13
16
|
//#region src/components/MenuEntries.tsx
|
|
14
17
|
var menuDivider = { divider: true };
|
|
15
18
|
var isMenuDivider = (entry) => "divider" in entry;
|
|
16
|
-
var
|
|
19
|
+
var isMenuGroup = (entry) => "group" in entry;
|
|
20
|
+
var isMenuSubmenu = (entry) => "items" in entry && !("group" in entry);
|
|
17
21
|
/** Gives a menu root its search's filter; `children` renders the root with the query. */
|
|
18
22
|
function MenuFilter({ search, children }) {
|
|
19
23
|
const [query, setQuery] = useState("");
|
|
@@ -26,13 +30,99 @@ function MenuFilter({ search, children }) {
|
|
|
26
30
|
children: children(query)
|
|
27
31
|
});
|
|
28
32
|
}
|
|
33
|
+
var DrillContext = createContext(null);
|
|
29
34
|
/** A menu's rows, with its search field when it has one. */
|
|
30
35
|
function MenuEntries({ entries, search, query = "" }) {
|
|
36
|
+
const narrow = useNarrow();
|
|
37
|
+
const [drilled, setDrilled] = useState();
|
|
38
|
+
const [returnTo, setReturnTo] = useState();
|
|
39
|
+
useLayoutEffect(() => {
|
|
40
|
+
if (!returnTo) return;
|
|
41
|
+
const { label, popup } = returnTo;
|
|
42
|
+
const frame = requestAnimationFrame(() => {
|
|
43
|
+
for (const row of popup?.querySelectorAll("[data-drill]") ?? []) if (row.getAttribute("data-drill") === label) row.focus();
|
|
44
|
+
setReturnTo(void 0);
|
|
45
|
+
});
|
|
46
|
+
return () => cancelAnimationFrame(frame);
|
|
47
|
+
}, [returnTo]);
|
|
48
|
+
if (narrow && drilled) {
|
|
49
|
+
const back = () => {
|
|
50
|
+
setReturnTo({
|
|
51
|
+
label: drilled.submenu.label,
|
|
52
|
+
popup: drilled.popup
|
|
53
|
+
});
|
|
54
|
+
setDrilled(void 0);
|
|
55
|
+
};
|
|
56
|
+
return /* @__PURE__ */ jsx(DrilledSubmenu, {
|
|
57
|
+
submenu: drilled.submenu,
|
|
58
|
+
onBack: back
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return /* @__PURE__ */ jsx(DrillContext, {
|
|
62
|
+
value: narrow ? (submenu, row) => setDrilled({
|
|
63
|
+
submenu,
|
|
64
|
+
popup: row.closest("[role=\"menu\"]")
|
|
65
|
+
}) : null,
|
|
66
|
+
children: /* @__PURE__ */ jsx(SearchedEntries, {
|
|
67
|
+
entries,
|
|
68
|
+
search,
|
|
69
|
+
query
|
|
70
|
+
})
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** A submenu opened in its parent's place: a row back to the parent, then its rows. */
|
|
74
|
+
function DrilledSubmenu({ submenu, onBack }) {
|
|
75
|
+
const t = useStrings().common;
|
|
76
|
+
const backRef = useRef(null);
|
|
77
|
+
useLayoutEffect(() => {
|
|
78
|
+
const frame = requestAnimationFrame(() => backRef.current?.focus());
|
|
79
|
+
return () => cancelAnimationFrame(frame);
|
|
80
|
+
}, []);
|
|
81
|
+
const onKeyDown = (e) => {
|
|
82
|
+
if (e.key === "ArrowLeft" && !(e.target instanceof HTMLInputElement)) {
|
|
83
|
+
e.preventDefault();
|
|
84
|
+
onBack();
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
88
|
+
role: "none",
|
|
89
|
+
className: "contents",
|
|
90
|
+
onKeyDown,
|
|
91
|
+
children: [
|
|
92
|
+
/* @__PURE__ */ jsx(MenuItem, {
|
|
93
|
+
ref: backRef,
|
|
94
|
+
closeOnClick: false,
|
|
95
|
+
onClick: onBack,
|
|
96
|
+
className: "font-medium",
|
|
97
|
+
children: /* @__PURE__ */ jsx(RowContent, {
|
|
98
|
+
icon: /* @__PURE__ */ jsx(ChevronLeftIcon, {
|
|
99
|
+
"aria-hidden": "true",
|
|
100
|
+
className: "size-3 opacity-60"
|
|
101
|
+
}),
|
|
102
|
+
label: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
|
|
103
|
+
className: "sr-only",
|
|
104
|
+
children: [t.back, ": "]
|
|
105
|
+
}), submenu.label] })
|
|
106
|
+
})
|
|
107
|
+
}),
|
|
108
|
+
/* @__PURE__ */ jsx(MenuSeparator, {}),
|
|
109
|
+
/* @__PURE__ */ jsx(MenuFilter, {
|
|
110
|
+
search: submenu.search,
|
|
111
|
+
children: (query) => /* @__PURE__ */ jsx(MenuEntries, {
|
|
112
|
+
entries: submenu.items,
|
|
113
|
+
search: submenu.search,
|
|
114
|
+
query
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
]
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function SearchedEntries({ entries, search, query }) {
|
|
31
121
|
const matches = useQueryMatch();
|
|
32
122
|
if (!search) return /* @__PURE__ */ jsx(EntryRows, { entries });
|
|
33
123
|
const needle = query.trim();
|
|
34
|
-
const shown = needle ? searchMatches(entries, (a) => matches(needle, a.label, a.keywords)) : entries;
|
|
35
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
124
|
+
const shown = needle ? searchMatches(entries, (a) => matches(needle, a.label, a.description, a.keywords), (submenu) => matches(needle, submenu.label, submenu.keywords)) : entries;
|
|
125
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
36
126
|
/* @__PURE__ */ jsx("div", {
|
|
37
127
|
className: "sticky top-0 z-[1] bg-(--theme-app-bg) px-1 pt-0.5 pb-1",
|
|
38
128
|
children: /* @__PURE__ */ jsx(Menu.Input, {
|
|
@@ -48,29 +138,131 @@ function MenuEntries({ entries, search, query = "" }) {
|
|
|
48
138
|
})
|
|
49
139
|
] });
|
|
50
140
|
}
|
|
51
|
-
function searchMatches(entries, match) {
|
|
141
|
+
function searchMatches(entries, match, matchSubmenu) {
|
|
52
142
|
const found = /* @__PURE__ */ new Map();
|
|
53
|
-
const walk = (list) => {
|
|
54
|
-
for (const entry of list)
|
|
55
|
-
|
|
143
|
+
const walk = (list, all) => {
|
|
144
|
+
for (const entry of list) {
|
|
145
|
+
if (isMenuDivider(entry)) continue;
|
|
146
|
+
if (isMenuGroup(entry)) walk(entry.items, all);
|
|
147
|
+
else if (isMenuSubmenu(entry)) {
|
|
148
|
+
if (!entry.disabled) walk(entry.items, all || matchSubmenu(entry));
|
|
149
|
+
} else if (!found.has(entry.label) && (all || match(entry))) found.set(entry.label, entry);
|
|
150
|
+
}
|
|
56
151
|
};
|
|
57
|
-
walk(entries);
|
|
152
|
+
walk(entries, false);
|
|
58
153
|
return [...found.values()];
|
|
59
154
|
}
|
|
155
|
+
var entryKey = (entry) => isMenuDivider(entry) ? "divider" : isMenuGroup(entry) ? `group:${entry.group}` : entry.label;
|
|
60
156
|
function EntryRows({ entries }) {
|
|
61
|
-
return keyedByContent(entries, (
|
|
157
|
+
return keyedByContent(entries, entryKey).map(({ key, item }) => isMenuDivider(item) ? /* @__PURE__ */ jsx(MenuSeparator, {}, key) : isMenuGroup(item) ? /* @__PURE__ */ jsxs(Menu.Group, { children: [/* @__PURE__ */ jsx(MenuGroupLabel, { children: item.group }), /* @__PURE__ */ jsx(EntryRows, { entries: item.items })] }, key) : isMenuSubmenu(item) ? /* @__PURE__ */ jsx(SubmenuRow, { submenu: item }, key) : /* @__PURE__ */ jsx(ActionRow, { action: item }, key));
|
|
158
|
+
}
|
|
159
|
+
/** A key as `aria-keyshortcuts` spells it: `⌘K` reads Meta+K, `⇧P` Shift+P. */
|
|
160
|
+
function ariaKeyShortcut(shortcut) {
|
|
161
|
+
if (!shortcut) return;
|
|
162
|
+
const names = {
|
|
163
|
+
"⌘": "Meta",
|
|
164
|
+
"⌃": "Control",
|
|
165
|
+
"⌥": "Alt",
|
|
166
|
+
"⇧": "Shift"
|
|
167
|
+
};
|
|
168
|
+
const parts = [];
|
|
169
|
+
let rest = shortcut.replace(/\s+/g, "");
|
|
170
|
+
while (rest.length > 1 && names[rest[0] ?? ""]) {
|
|
171
|
+
parts.push(names[rest[0] ?? ""] ?? "");
|
|
172
|
+
rest = rest.slice(1);
|
|
173
|
+
}
|
|
174
|
+
for (const part of rest.split("+").filter(Boolean)) parts.push(part.length === 1 ? part.toUpperCase() : part);
|
|
175
|
+
return parts.join("+");
|
|
176
|
+
}
|
|
177
|
+
/** A detail at the row's end, held to the first line's height so it sits beside the label
|
|
178
|
+
* even when a description adds a second. */
|
|
179
|
+
function RowEnd({ children, className }) {
|
|
180
|
+
return /* @__PURE__ */ jsx("span", {
|
|
181
|
+
"aria-hidden": "true",
|
|
182
|
+
className: cx("flex h-5 shrink-0 items-center in-data-[size=sm]:h-4", className),
|
|
183
|
+
children
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
var shortcutClassName = "ps-3 text-xs text-(--theme-muted-text-color) tabular-nums in-data-[size=sm]:text-[11px]";
|
|
187
|
+
/** A row's icon, label, second line and end details, laid out alike in every kind of row. */
|
|
188
|
+
function RowContent({ icon, label, description, end }) {
|
|
189
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
190
|
+
icon !== void 0 && icon !== null && /* @__PURE__ */ jsx("span", {
|
|
191
|
+
className: "flex h-5 min-w-4 shrink-0 items-center justify-center in-data-[size=sm]:h-4",
|
|
192
|
+
children: icon
|
|
193
|
+
}),
|
|
194
|
+
/* @__PURE__ */ jsxs("span", {
|
|
195
|
+
className: "flex min-w-0 flex-1 flex-col",
|
|
196
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
197
|
+
className: "wrap-break-word",
|
|
198
|
+
children: label
|
|
199
|
+
}), description && /* @__PURE__ */ jsx("span", {
|
|
200
|
+
className: "text-xs text-(--theme-muted-text-color) in-data-[size=sm]:text-[11px]",
|
|
201
|
+
children: description
|
|
202
|
+
})]
|
|
203
|
+
}),
|
|
204
|
+
end
|
|
205
|
+
] });
|
|
62
206
|
}
|
|
63
207
|
function SubmenuRow({ submenu }) {
|
|
208
|
+
const reason = submenu.disabled ? submenu.disabledReason : void 0;
|
|
209
|
+
const drill = use(DrillContext);
|
|
210
|
+
if (drill) return /* @__PURE__ */ jsx(MenuItem, {
|
|
211
|
+
closeOnClick: false,
|
|
212
|
+
disabled: submenu.disabled,
|
|
213
|
+
"data-drill": submenu.label,
|
|
214
|
+
"aria-haspopup": "menu",
|
|
215
|
+
"aria-keyshortcuts": ariaKeyShortcut(submenu.shortcut),
|
|
216
|
+
onClick: (e) => drill(submenu, e.currentTarget),
|
|
217
|
+
onKeyDown: (e) => {
|
|
218
|
+
if (e.key === "ArrowRight") {
|
|
219
|
+
e.preventDefault();
|
|
220
|
+
drill(submenu, e.currentTarget);
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
children: /* @__PURE__ */ jsx(RowContent, {
|
|
224
|
+
icon: submenu.icon,
|
|
225
|
+
label: /* @__PURE__ */ jsxs(Fragment$1, { children: [submenu.label, reason && /* @__PURE__ */ jsxs("span", {
|
|
226
|
+
className: "sr-only",
|
|
227
|
+
children: [". ", reason]
|
|
228
|
+
})] }),
|
|
229
|
+
end: /* @__PURE__ */ jsxs(Fragment$1, { children: [submenu.shortcut && /* @__PURE__ */ jsx(RowEnd, {
|
|
230
|
+
className: shortcutClassName,
|
|
231
|
+
children: submenu.shortcut
|
|
232
|
+
}), /* @__PURE__ */ jsx(RowEnd, { children: /* @__PURE__ */ jsx(ChevronRightIcon, { className: "size-3 opacity-60" }) })] })
|
|
233
|
+
})
|
|
234
|
+
});
|
|
64
235
|
return /* @__PURE__ */ jsx(MenuFilter, {
|
|
65
236
|
search: submenu.search,
|
|
66
|
-
children: (query) => /* @__PURE__ */ jsxs(Menu.SubmenuRoot, {
|
|
67
|
-
|
|
68
|
-
children: /* @__PURE__ */ jsx(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
237
|
+
children: (query) => /* @__PURE__ */ jsxs(Menu.SubmenuRoot, {
|
|
238
|
+
disabled: submenu.disabled,
|
|
239
|
+
children: [/* @__PURE__ */ jsx(Tooltip, {
|
|
240
|
+
content: reason,
|
|
241
|
+
side: "right",
|
|
242
|
+
children: /* @__PURE__ */ jsx(MenuSubmenuTrigger, {
|
|
243
|
+
disabled: submenu.disabled,
|
|
244
|
+
"aria-keyshortcuts": ariaKeyShortcut(submenu.shortcut),
|
|
245
|
+
children: /* @__PURE__ */ jsx(RowContent, {
|
|
246
|
+
icon: submenu.icon,
|
|
247
|
+
label: /* @__PURE__ */ jsxs(Fragment$1, { children: [submenu.label, reason && /* @__PURE__ */ jsxs("span", {
|
|
248
|
+
className: "sr-only",
|
|
249
|
+
children: [". ", reason]
|
|
250
|
+
})] }),
|
|
251
|
+
end: submenu.shortcut && /* @__PURE__ */ jsx(RowEnd, {
|
|
252
|
+
className: shortcutClassName,
|
|
253
|
+
children: submenu.shortcut
|
|
254
|
+
})
|
|
255
|
+
})
|
|
256
|
+
})
|
|
257
|
+
}), /* @__PURE__ */ jsx(MenuPopup, {
|
|
258
|
+
side: "inline-end",
|
|
259
|
+
children: /* @__PURE__ */ jsx(MenuEntries, {
|
|
260
|
+
entries: submenu.items,
|
|
261
|
+
search: submenu.search,
|
|
262
|
+
query
|
|
263
|
+
})
|
|
264
|
+
})]
|
|
265
|
+
})
|
|
74
266
|
});
|
|
75
267
|
}
|
|
76
268
|
var destructiveClassName = "text-(--theme-error-text) data-highlighted:text-(--theme-error-text)";
|
|
@@ -92,42 +284,77 @@ function useRunAction() {
|
|
|
92
284
|
else action.onClick?.();
|
|
93
285
|
}, [copy]);
|
|
94
286
|
}
|
|
287
|
+
/** One action as a menu row: a link, an on/off choice, or a plain item. */
|
|
95
288
|
function ActionRow({ action }) {
|
|
96
289
|
warnIfInert(action, "MenuEntries");
|
|
97
290
|
const runAction = useRunAction();
|
|
98
|
-
const className = cx(action.destructive && destructiveClassName);
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
target: action.target
|
|
291
|
+
const className = cx(action.description && "items-start", action.destructive && destructiveClassName, action.current && "font-medium");
|
|
292
|
+
const keyshortcuts = ariaKeyShortcut(action.shortcut);
|
|
293
|
+
const end = (trailing) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
294
|
+
action.badge !== void 0 && action.badge !== null && action.badge !== false && /* @__PURE__ */ jsx(RowEnd, {
|
|
295
|
+
className: "ps-2",
|
|
296
|
+
children: action.badge
|
|
105
297
|
}),
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
298
|
+
action.shortcut && /* @__PURE__ */ jsx(RowEnd, {
|
|
299
|
+
className: shortcutClassName,
|
|
300
|
+
children: action.shortcut
|
|
301
|
+
}),
|
|
302
|
+
trailing
|
|
303
|
+
] });
|
|
304
|
+
if (action.href && !action.disabled) {
|
|
305
|
+
const newTab = action.target === "_blank";
|
|
306
|
+
return /* @__PURE__ */ jsx(MenuLinkItem, {
|
|
307
|
+
render: /* @__PURE__ */ jsx(AppLink, {
|
|
308
|
+
href: action.href,
|
|
309
|
+
reloadDocument: action.reloadDocument,
|
|
310
|
+
target: action.target,
|
|
311
|
+
"aria-current": action.current ? "page" : void 0
|
|
312
|
+
}),
|
|
313
|
+
"aria-keyshortcuts": keyshortcuts,
|
|
314
|
+
className,
|
|
315
|
+
children: /* @__PURE__ */ jsx(RowContent, {
|
|
316
|
+
icon: action.icon,
|
|
317
|
+
label: action.label,
|
|
318
|
+
description: action.description,
|
|
319
|
+
end: end(action.current ? /* @__PURE__ */ jsx(RowEnd, {
|
|
320
|
+
className: "ps-2",
|
|
321
|
+
children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-3.5 opacity-80" })
|
|
322
|
+
}) : newTab ? /* @__PURE__ */ jsx(RowEnd, {
|
|
323
|
+
className: "ps-2 text-(--theme-muted-text-color)",
|
|
324
|
+
children: /* @__PURE__ */ jsx(ExternalLinkIcon, { className: "size-3" })
|
|
325
|
+
}) : void 0)
|
|
326
|
+
})
|
|
327
|
+
});
|
|
328
|
+
}
|
|
109
329
|
const run = () => runAction(action);
|
|
110
330
|
const reason = action.disabled ? action.disabledReason : void 0;
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
children: [
|
|
114
|
-
|
|
331
|
+
const content = (trailing) => /* @__PURE__ */ jsx(RowContent, {
|
|
332
|
+
icon: action.icon,
|
|
333
|
+
label: /* @__PURE__ */ jsxs(Fragment$1, { children: [action.label, reason && /* @__PURE__ */ jsxs("span", {
|
|
334
|
+
className: "sr-only",
|
|
335
|
+
children: [". ", reason]
|
|
336
|
+
})] }),
|
|
337
|
+
description: action.description,
|
|
338
|
+
end: end(trailing)
|
|
339
|
+
});
|
|
115
340
|
return /* @__PURE__ */ jsx(Tooltip, {
|
|
116
341
|
content: reason,
|
|
117
342
|
side: "right",
|
|
118
343
|
children: action.checked === void 0 ? /* @__PURE__ */ jsx(MenuItem, {
|
|
119
344
|
disabled: action.disabled,
|
|
120
345
|
onClick: run,
|
|
346
|
+
"aria-keyshortcuts": keyshortcuts,
|
|
121
347
|
className,
|
|
122
|
-
children:
|
|
348
|
+
children: content()
|
|
123
349
|
}) : /* @__PURE__ */ jsx(MenuCheckboxItem, {
|
|
124
350
|
checked: action.checked,
|
|
125
351
|
onCheckedChange: run,
|
|
126
352
|
disabled: action.disabled,
|
|
353
|
+
"aria-keyshortcuts": keyshortcuts,
|
|
127
354
|
className,
|
|
128
|
-
children:
|
|
355
|
+
children: content()
|
|
129
356
|
})
|
|
130
357
|
});
|
|
131
358
|
}
|
|
132
359
|
//#endregion
|
|
133
|
-
export { MenuEntries, MenuFilter, isMenuDivider, isMenuSubmenu, menuDivider, useRunAction, warnIfInert };
|
|
360
|
+
export { ActionRow, MenuEntries, MenuFilter, ariaKeyShortcut, isMenuDivider, isMenuGroup, isMenuSubmenu, menuDivider, useRunAction, warnIfInert };
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
/** A bar's color: the theme's accent, a status, or muted for something stopped. */
|
|
3
|
-
export type BarTone = 'accent' | 'success' | 'warning' | 'error' | 'muted';
|
|
4
|
-
declare const
|
|
3
|
+
export type BarTone = 'accent' | 'info' | 'success' | 'warning' | 'error' | 'muted';
|
|
4
|
+
declare const trackHeight: {
|
|
5
5
|
readonly sm: 'h-1';
|
|
6
6
|
readonly md: 'h-1.5';
|
|
7
7
|
readonly lg: 'h-2';
|
|
8
8
|
};
|
|
9
|
-
export type BarSize = keyof typeof
|
|
9
|
+
export type BarSize = keyof typeof trackHeight;
|
|
10
|
+
/** Where a bar's value shows: `beside` its label, over the bar on `tooltip` when
|
|
11
|
+
* room is short, at the bar's `end` on the same row (so a column of bars lines up),
|
|
12
|
+
* or `none`. */
|
|
13
|
+
export type BarValuePlacement = 'beside' | 'tooltip' | 'end' | 'none';
|
|
10
14
|
interface BarProps {
|
|
11
15
|
/** Shown above the bar, which it names. */
|
|
12
16
|
label?: ReactNode;
|
|
@@ -15,15 +19,20 @@ interface BarProps {
|
|
|
15
19
|
/** Shown under the bar, such as the amounts behind it. */
|
|
16
20
|
detail?: ReactNode;
|
|
17
21
|
size?: BarSize;
|
|
22
|
+
/** On the track, such as a fixed `w-24` so bars in a column line up whatever
|
|
23
|
+
* the value beside them reads. */
|
|
24
|
+
trackClassName?: string | undefined;
|
|
25
|
+
/** The locale the value is written in; the browser's own without it. */
|
|
26
|
+
locale?: string | undefined;
|
|
18
27
|
className?: string;
|
|
19
28
|
}
|
|
20
29
|
/** The tone for `value` against a warning and an error level, for a measure
|
|
21
|
-
* that's worse the higher it reads. */
|
|
22
|
-
export declare function levelTone(value: number, warnAt: number, errorAt: number): BarTone;
|
|
30
|
+
* that's worse the higher it reads; `okTone` below the warning. */
|
|
31
|
+
export declare function levelTone(value: number, warnAt: number, errorAt: number, okTone?: BarTone): BarTone;
|
|
23
32
|
/** How full something is, such as storage used or a quota spent: a reading,
|
|
24
|
-
* not a task under way (that's `ProgressBar`). The bar
|
|
25
|
-
* as it passes `warnAt` and `errorAt`; `tone` overrides that. */
|
|
26
|
-
export declare function Meter({ value, min, max, warnAt, errorAt, tone, format, showValue, label, 'aria-label': ariaLabel, detail, size, className, }: BarProps & {
|
|
33
|
+
* not a task under way (that's `ProgressBar`). The bar is blue, then turns
|
|
34
|
+
* amber, then red, as it passes `warnAt` and `errorAt`; `tone` overrides that. */
|
|
35
|
+
export declare function Meter({ value, min, max, warnAt, errorAt, tone, okTone, format, showValue, valueText, getAriaValueText, minFill, locale, label, 'aria-label': ariaLabel, detail, size, trackClassName, className, }: BarProps & {
|
|
27
36
|
value: number;
|
|
28
37
|
min?: number;
|
|
29
38
|
max?: number;
|
|
@@ -31,18 +40,48 @@ export declare function Meter({ value, min, max, warnAt, errorAt, tone, format,
|
|
|
31
40
|
warnAt?: number;
|
|
32
41
|
errorAt?: number;
|
|
33
42
|
tone?: BarTone;
|
|
43
|
+
/** The tone below `warnAt`. Info by default, so the bar reads the same in every
|
|
44
|
+
* host whatever its accent. */
|
|
45
|
+
okTone?: BarTone | undefined;
|
|
34
46
|
/** How the value itself reads; without it, as a percentage of the range. */
|
|
35
47
|
format?: Intl.NumberFormatOptions;
|
|
36
|
-
|
|
37
|
-
|
|
48
|
+
showValue?: BarValuePlacement;
|
|
49
|
+
/** The value as shown, from its formatted text, such as "45% used". */
|
|
50
|
+
valueText?: ((formatted: string, value: number) => ReactNode) | undefined;
|
|
51
|
+
/** The value as read by assistive technology, such as "82%, near limit", for a
|
|
52
|
+
* level the bar's color alone shows. */
|
|
53
|
+
getAriaValueText?: ((formatted: string, value: number) => string) | undefined;
|
|
54
|
+
/** The narrowest the fill draws for a value above `min`, as a percent of the
|
|
55
|
+
* track, so a small reading still shows. */
|
|
56
|
+
minFill?: number | undefined;
|
|
38
57
|
}): import("react").JSX.Element;
|
|
58
|
+
/** A further stretch of a progress bar, drawn after its value, such as work
|
|
59
|
+
* started but not yet done. */
|
|
60
|
+
export interface ProgressSegment {
|
|
61
|
+
/** In the same units as the bar's `max`. */
|
|
62
|
+
value: number;
|
|
63
|
+
tone?: BarTone | undefined;
|
|
64
|
+
/** At 60% strength, for a stretch that's less settled than the one before it. */
|
|
65
|
+
subtle?: boolean | undefined;
|
|
66
|
+
}
|
|
39
67
|
/** How far a task has come, such as an upload, out of `max`; `null` while
|
|
40
68
|
* that's not known. Name it with `label` or `aria-label`. */
|
|
41
|
-
export declare function ProgressBar({ value, max, tone, status, label, 'aria-label': ariaLabel, detail, size, className, }: BarProps & {
|
|
69
|
+
export declare function ProgressBar({ value, max, tone, segments, status, format, showValue, valueText, getAriaValueText, locale, label, 'aria-label': ariaLabel, detail, size, trackClassName, className, }: BarProps & {
|
|
42
70
|
value: number | null;
|
|
43
71
|
max?: number;
|
|
44
72
|
tone?: BarTone;
|
|
73
|
+
/** Further stretches after `value`, in one bar, such as started work after done
|
|
74
|
+
* work. `value` alone is what the bar reads as to assistive technology. */
|
|
75
|
+
segments?: ReadonlyArray<ProgressSegment> | undefined;
|
|
45
76
|
/** Beside the label in place of the percentage, such as "Completed". */
|
|
46
77
|
status?: ReactNode;
|
|
78
|
+
/** How the value itself reads; without it, as a percentage of `max`. */
|
|
79
|
+
format?: Intl.NumberFormatOptions | undefined;
|
|
80
|
+
/** `beside` the label, at the bar's `end` on the same row, or `none`. */
|
|
81
|
+
showValue?: Exclude<BarValuePlacement, 'tooltip'> | undefined;
|
|
82
|
+
/** The value as shown, from its formatted text, such as "3 of 8 done, 38%". */
|
|
83
|
+
valueText?: ((formatted: string | null, value: number | null) => ReactNode) | undefined;
|
|
84
|
+
/** The value as read by assistive technology. */
|
|
85
|
+
getAriaValueText?: ((formatted: string | null, value: number | null) => string) | undefined;
|
|
47
86
|
}): import("react").JSX.Element;
|
|
48
87
|
export {};
|
package/dist/components/Meter.js
CHANGED
|
@@ -7,39 +7,56 @@ import { Progress } from "@base-ui/react/progress";
|
|
|
7
7
|
//#region src/components/Meter.tsx
|
|
8
8
|
var fillClassName = {
|
|
9
9
|
accent: "bg-(--theme-accent)",
|
|
10
|
+
info: toneFill.info,
|
|
10
11
|
success: toneFill.success,
|
|
11
12
|
warning: toneFill.warning,
|
|
12
13
|
error: toneFill.error,
|
|
13
14
|
muted: toneFill.muted
|
|
14
15
|
};
|
|
15
|
-
var
|
|
16
|
+
var trackHeight = {
|
|
16
17
|
sm: "h-1",
|
|
17
18
|
md: "h-1.5",
|
|
18
19
|
lg: "h-2"
|
|
19
20
|
};
|
|
20
21
|
var labelRowClassName = "mb-1 flex items-baseline justify-between gap-2 text-[13px]";
|
|
21
22
|
var detailClassName = "mt-1 text-[11px] tabular-nums text-(--theme-muted-text-color)";
|
|
23
|
+
var endRowClassName = "flex items-center gap-2";
|
|
24
|
+
var endValueClassName = "shrink-0 text-xs tabular-nums text-(--theme-muted-text-color)";
|
|
25
|
+
var trackBaseClassName = "w-full overflow-hidden rounded-full bg-(--theme-border)";
|
|
26
|
+
function trackClasses(size, end, own) {
|
|
27
|
+
return cx(trackBaseClassName, trackHeight[size], end && (own ? "shrink-0" : "min-w-0 flex-1"), own);
|
|
28
|
+
}
|
|
22
29
|
/** The tone for `value` against a warning and an error level, for a measure
|
|
23
|
-
* that's worse the higher it reads. */
|
|
24
|
-
function levelTone(value, warnAt, errorAt) {
|
|
25
|
-
return value >= errorAt ? "error" : value >= warnAt ? "warning" :
|
|
30
|
+
* that's worse the higher it reads; `okTone` below the warning. */
|
|
31
|
+
function levelTone(value, warnAt, errorAt, okTone = "info") {
|
|
32
|
+
return value >= errorAt ? "error" : value >= warnAt ? "warning" : okTone;
|
|
26
33
|
}
|
|
27
34
|
/** How full something is, such as storage used or a quota spent: a reading,
|
|
28
|
-
* not a task under way (that's `ProgressBar`). The bar
|
|
29
|
-
* as it passes `warnAt` and `errorAt`; `tone` overrides that. */
|
|
30
|
-
function Meter$1({ value, min = 0, max = 100, warnAt = 80, errorAt = 90, tone, format, showValue = "beside", label, "aria-label": ariaLabel, detail, size = "md", className }) {
|
|
35
|
+
* not a task under way (that's `ProgressBar`). The bar is blue, then turns
|
|
36
|
+
* amber, then red, as it passes `warnAt` and `errorAt`; `tone` overrides that. */
|
|
37
|
+
function Meter$1({ value, min = 0, max = 100, warnAt = 80, errorAt = 90, tone, okTone = "info", format, showValue = "beside", valueText, getAriaValueText, minFill = 0, locale, label, "aria-label": ariaLabel, detail, size = "md", trackClassName, className }) {
|
|
31
38
|
const clamped = Math.min(Math.max(value, min), max);
|
|
32
|
-
const fill = fillClassName[tone ?? levelTone(clamped, warnAt, errorAt)];
|
|
33
|
-
const
|
|
39
|
+
const fill = fillClassName[tone ?? levelTone(clamped, warnAt, errorAt, okTone)];
|
|
40
|
+
const end = showValue === "end";
|
|
41
|
+
const shownValue = /* @__PURE__ */ jsx(Meter.Value, {
|
|
42
|
+
className: end ? endValueClassName : "shrink-0 font-medium tabular-nums theme-text",
|
|
43
|
+
children: valueText
|
|
44
|
+
});
|
|
34
45
|
const track = /* @__PURE__ */ jsx(Meter.Track, {
|
|
35
|
-
className:
|
|
36
|
-
children: /* @__PURE__ */ jsx(Meter.Indicator, {
|
|
46
|
+
className: trackClasses(size, end, trackClassName),
|
|
47
|
+
children: /* @__PURE__ */ jsx(Meter.Indicator, {
|
|
48
|
+
className: cx("h-full rounded-full transition-[width] duration-300 motion-reduce:transition-none", fill),
|
|
49
|
+
style: minFill > 0 && clamped > min ? { minWidth: `${minFill}%` } : void 0
|
|
50
|
+
})
|
|
37
51
|
});
|
|
52
|
+
const share = formatShare(clamped, min, max, format, locale);
|
|
38
53
|
return /* @__PURE__ */ jsxs(Meter.Root, {
|
|
39
54
|
value: clamped,
|
|
40
55
|
min,
|
|
41
56
|
max,
|
|
42
57
|
format,
|
|
58
|
+
locale,
|
|
59
|
+
getAriaValueText,
|
|
43
60
|
"aria-label": ariaLabel,
|
|
44
61
|
className: cx("min-w-0", className),
|
|
45
62
|
children: [
|
|
@@ -51,8 +68,11 @@ function Meter$1({ value, min = 0, max = 100, warnAt = 80, errorAt = 90, tone, f
|
|
|
51
68
|
}), showValue === "beside" && shownValue]
|
|
52
69
|
}),
|
|
53
70
|
showValue === "tooltip" ? /* @__PURE__ */ jsx(Tooltip, {
|
|
54
|
-
content:
|
|
71
|
+
content: valueText ? valueText(share, clamped) : share,
|
|
55
72
|
children: track
|
|
73
|
+
}) : end ? /* @__PURE__ */ jsxs("div", {
|
|
74
|
+
className: endRowClassName,
|
|
75
|
+
children: [track, shownValue]
|
|
56
76
|
}) : track,
|
|
57
77
|
detail !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
58
78
|
className: detailClassName,
|
|
@@ -61,29 +81,46 @@ function Meter$1({ value, min = 0, max = 100, warnAt = 80, errorAt = 90, tone, f
|
|
|
61
81
|
]
|
|
62
82
|
});
|
|
63
83
|
}
|
|
64
|
-
function formatShare(value, min, max, format) {
|
|
65
|
-
return format ? new Intl.NumberFormat(
|
|
84
|
+
function formatShare(value, min, max, format, locale) {
|
|
85
|
+
return format ? new Intl.NumberFormat(locale, format).format(value) : new Intl.NumberFormat(locale, { style: "percent" }).format((value - min) / (max - min || 1));
|
|
66
86
|
}
|
|
67
87
|
/** How far a task has come, such as an upload, out of `max`; `null` while
|
|
68
88
|
* that's not known. Name it with `label` or `aria-label`. */
|
|
69
|
-
function ProgressBar({ value, max = 100, tone = "accent", status, label, "aria-label": ariaLabel, detail, size = "md", className }) {
|
|
89
|
+
function ProgressBar({ value, max = 100, tone = "accent", segments, status, format, showValue = "beside", valueText, getAriaValueText, locale, label, "aria-label": ariaLabel, detail, size = "md", trackClassName, className }) {
|
|
90
|
+
const end = showValue === "end";
|
|
91
|
+
const shownValue = status ?? (showValue === "none" ? null : /* @__PURE__ */ jsx(Progress.Value, {
|
|
92
|
+
className: end ? endValueClassName : "shrink-0 tabular-nums theme-muted-text",
|
|
93
|
+
children: valueText
|
|
94
|
+
}));
|
|
95
|
+
const stacked = value !== null && segments !== void 0 && segments.length > 0;
|
|
96
|
+
const track = /* @__PURE__ */ jsxs(Progress.Track, {
|
|
97
|
+
className: cx(trackClasses(size, end, trackClassName), stacked && "flex"),
|
|
98
|
+
children: [/* @__PURE__ */ jsx(Progress.Indicator, { className: cx("h-full transition-[width] duration-300 motion-reduce:transition-none", "data-indeterminate:w-1/3 data-indeterminate:animate-pulse", stacked ? "shrink-0" : "rounded-full", fillClassName[tone]) }), stacked && /* @__PURE__ */ jsx(Segments, {
|
|
99
|
+
segments,
|
|
100
|
+
from: value,
|
|
101
|
+
max
|
|
102
|
+
})]
|
|
103
|
+
});
|
|
70
104
|
return /* @__PURE__ */ jsxs(Progress.Root, {
|
|
71
105
|
value,
|
|
72
106
|
max,
|
|
107
|
+
format,
|
|
108
|
+
locale,
|
|
109
|
+
getAriaValueText,
|
|
73
110
|
"aria-label": ariaLabel,
|
|
74
111
|
className: cx("min-w-0", className),
|
|
75
112
|
children: [
|
|
76
|
-
(label !== void 0 || status !== void 0) && /* @__PURE__ */ jsxs("div", {
|
|
113
|
+
(label !== void 0 || !end && status !== void 0) && /* @__PURE__ */ jsxs("div", {
|
|
77
114
|
className: labelRowClassName,
|
|
78
115
|
children: [/* @__PURE__ */ jsx(Progress.Label, {
|
|
79
116
|
className: "min-w-0 truncate theme-muted-text",
|
|
80
117
|
children: label
|
|
81
|
-
}),
|
|
82
|
-
}),
|
|
83
|
-
/* @__PURE__ */ jsx(Progress.Track, {
|
|
84
|
-
className: cx("w-full overflow-hidden rounded-full bg-(--theme-border)", trackClassName[size]),
|
|
85
|
-
children: /* @__PURE__ */ jsx(Progress.Indicator, { className: cx("h-full rounded-full transition-[width] duration-300 motion-reduce:transition-none", "data-indeterminate:w-1/3 data-indeterminate:animate-pulse", fillClassName[tone]) })
|
|
118
|
+
}), !end && shownValue]
|
|
86
119
|
}),
|
|
120
|
+
end ? /* @__PURE__ */ jsxs("div", {
|
|
121
|
+
className: endRowClassName,
|
|
122
|
+
children: [track, shownValue]
|
|
123
|
+
}) : track,
|
|
87
124
|
detail !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
88
125
|
className: detailClassName,
|
|
89
126
|
children: detail
|
|
@@ -91,5 +128,18 @@ function ProgressBar({ value, max = 100, tone = "accent", status, label, "aria-l
|
|
|
91
128
|
]
|
|
92
129
|
});
|
|
93
130
|
}
|
|
131
|
+
function Segments({ segments, from, max }) {
|
|
132
|
+
let used = Math.min(Math.max(from, 0), max);
|
|
133
|
+
return segments.map((segment, index) => {
|
|
134
|
+
const width = Math.min(Math.max(segment.value, 0), max - used);
|
|
135
|
+
used += width;
|
|
136
|
+
return /* @__PURE__ */ jsx("div", {
|
|
137
|
+
"aria-hidden": "true",
|
|
138
|
+
"data-segment": "",
|
|
139
|
+
className: cx("h-full shrink-0 transition-[width] duration-300 motion-reduce:transition-none", fillClassName[segment.tone ?? "accent"], segment.subtle && "opacity-60"),
|
|
140
|
+
style: { width: `${width / (max || 1) * 100}%` }
|
|
141
|
+
}, index);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
94
144
|
//#endregion
|
|
95
145
|
export { Meter$1 as Meter, ProgressBar, levelTone };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Dialog } from '@base-ui/react/dialog';
|
|
2
|
-
import type
|
|
2
|
+
import { type FormEvent, type ReactNode } from 'react';
|
|
3
3
|
/** The panel a modal draws by default; pass `panel={false}` to paint your own. */
|
|
4
4
|
export declare const modalPanelClassName = "rounded-xl border border-(--theme-border) bg-(--theme-app-bg) text-(--theme-app) shadow-2xl";
|
|
5
5
|
/** Names the modal for assistive technology; renders an `<h2>`. */
|
|
@@ -13,7 +13,7 @@ declare const sizeClasses: {
|
|
|
13
13
|
readonly xl: 'w-[672px]';
|
|
14
14
|
};
|
|
15
15
|
export type ModalSize = keyof typeof sizeClasses;
|
|
16
|
-
export interface ModalProps extends Omit<Dialog.Popup.Props, 'className' | 'children' | 'render' | 'title'> {
|
|
16
|
+
export interface ModalProps extends Omit<Dialog.Popup.Props, 'className' | 'children' | 'render' | 'title' | 'onSubmit'> {
|
|
17
17
|
open: boolean;
|
|
18
18
|
onClose: () => void;
|
|
19
19
|
/** The header's heading, which names the modal. Without one, name it with
|
|
@@ -39,6 +39,12 @@ export interface ModalProps extends Omit<Dialog.Popup.Props, 'className' | 'chil
|
|
|
39
39
|
panel?: boolean;
|
|
40
40
|
/** The backdrop's dimming, for a modal that needs a darker or blurred stage. */
|
|
41
41
|
backdropClassName?: string;
|
|
42
|
+
/** Adds a close button at the header's end, for a modal whose footer doesn't close it,
|
|
43
|
+
* such as one that only shows something. It needs no title. */
|
|
44
|
+
closeButton?: boolean | undefined;
|
|
45
|
+
/** Makes the header, body and footer one form, so a `type="submit"` button in the footer
|
|
46
|
+
* submits it, as Enter in a field does. The page never reloads: its default is prevented. */
|
|
47
|
+
onSubmit?: ((event: FormEvent<HTMLFormElement>) => void) | undefined;
|
|
42
48
|
/** On the panel. */
|
|
43
49
|
className?: string;
|
|
44
50
|
/** The body. With a title or a footer it sits padded between them and scrolls
|
|
@@ -49,5 +55,5 @@ export interface ModalProps extends Omit<Dialog.Popup.Props, 'className' | 'chil
|
|
|
49
55
|
* and focus returns to where it was on close. Give it a `title`, a `description`
|
|
50
56
|
* and a `footer` for the standard layout, as a Drawer has, or lay out the whole
|
|
51
57
|
* panel with the children. */
|
|
52
|
-
export declare function Modal({ open, onClose, title, description, footer, size, alert, dismissible, align, panel, backdropClassName, className, children, ...popupProps }: ModalProps): import("react").JSX.Element;
|
|
58
|
+
export declare function Modal({ open, onClose, title, description, footer, size, alert, dismissible, align, panel, backdropClassName, closeButton, onSubmit, className, children, initialFocus, ...popupProps }: ModalProps): import("react").JSX.Element;
|
|
53
59
|
export {};
|