@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,14 +1,43 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { type
|
|
3
|
-
|
|
4
|
-
export
|
|
1
|
+
import { type ReactElement, type ReactNode } from 'react';
|
|
2
|
+
import { type MenuPopupProps, type MenuSize } from './Menu.js';
|
|
3
|
+
import { type MenuAction, type MenuEntry, type MenuSearch } from './MenuEntries.js';
|
|
4
|
+
export interface ActionMenuProps {
|
|
5
5
|
items: MenuEntry[];
|
|
6
|
-
/** Names the trigger, which usually shows only an icon, and labels its tooltip.
|
|
6
|
+
/** Names the trigger, which usually shows only an icon, and labels its tooltip. With
|
|
7
|
+
* `trigger`, it names the menu instead. */
|
|
7
8
|
label: string;
|
|
8
9
|
search?: MenuSearch | undefined;
|
|
9
10
|
align?: 'start' | 'center' | 'end';
|
|
10
|
-
/**
|
|
11
|
+
/** Where the menu opens from the trigger, such as `top` for one near the window's bottom. */
|
|
12
|
+
side?: MenuPopupProps['side'];
|
|
13
|
+
/** Styles the built-in trigger; without it the trigger is a ghost icon button. */
|
|
11
14
|
triggerClassName?: string | undefined;
|
|
12
|
-
/** The trigger's content. */
|
|
13
|
-
children
|
|
14
|
-
|
|
15
|
+
/** The built-in trigger's content. */
|
|
16
|
+
children?: ReactNode;
|
|
17
|
+
/** The whole trigger in place of the built-in one, such as a button with visible text and
|
|
18
|
+
* a chevron, or an avatar and name. It receives the trigger's props and ref, so it must
|
|
19
|
+
* pass them to its element. */
|
|
20
|
+
trigger?: ReactElement | undefined;
|
|
21
|
+
/** Shows `label` on hover. On by default for the built-in trigger, which shows only an
|
|
22
|
+
* icon, and off with `trigger`, whose text would repeat it. Hidden while the menu is open. */
|
|
23
|
+
tooltip?: boolean | undefined;
|
|
24
|
+
/** The trigger can't open the menu, such as while there is nothing to act on. */
|
|
25
|
+
disabled?: boolean | undefined;
|
|
26
|
+
/** On the popup, such as a wider floor: `min-w-64`. */
|
|
27
|
+
popupClassName?: string | undefined;
|
|
28
|
+
/** At least as wide as the trigger, as a switcher under a wide button is. */
|
|
29
|
+
matchTriggerWidth?: boolean | undefined;
|
|
30
|
+
/** Lines above the rows that aren't choices, such as who is signed in. */
|
|
31
|
+
header?: ReactNode;
|
|
32
|
+
/** One action pinned under the rows, ruled off and always in view, such as "See all". */
|
|
33
|
+
footer?: MenuAction | undefined;
|
|
34
|
+
/** Shown in place of the rows when there are none, such as "No connected resources". */
|
|
35
|
+
empty?: string | undefined;
|
|
36
|
+
/** `sm` rows for a compact toolbar whose own text is 12px. */
|
|
37
|
+
size?: MenuSize | undefined;
|
|
38
|
+
/** As `MenuPopup`'s: classes on the menu and its submenus, such as token overrides. */
|
|
39
|
+
themeClassName?: string | undefined;
|
|
40
|
+
onOpenChange?: ((open: boolean) => void) | undefined;
|
|
41
|
+
}
|
|
42
|
+
/** A trigger that opens a menu, such as a header's "New" or "…" button. */
|
|
43
|
+
export declare function ActionMenu({ items, label, search, align, side, triggerClassName, children, trigger, tooltip, disabled, popupClassName, matchTriggerWidth, header, footer, empty, size, themeClassName, onOpenChange, }: ActionMenuProps): import("react").JSX.Element;
|
|
@@ -1,34 +1,60 @@
|
|
|
1
|
+
import { cx } from "../cx.js";
|
|
1
2
|
import { buttonClasses } from "./buttonClasses.js";
|
|
3
|
+
import { EmptyState } from "./EmptyState.js";
|
|
2
4
|
import { MenuPopup } from "./Menu.js";
|
|
3
5
|
import { Tooltip } from "./Tooltip.js";
|
|
4
|
-
import { MenuEntries, MenuFilter } from "./MenuEntries.js";
|
|
6
|
+
import { ActionRow, MenuEntries, MenuFilter } from "./MenuEntries.js";
|
|
5
7
|
import { Menu } from "@base-ui/react/menu";
|
|
8
|
+
import { useState } from "react";
|
|
6
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
10
|
//#region src/components/ActionMenu.tsx
|
|
8
11
|
/** A trigger that opens a menu, such as a header's "New" or "…" button. */
|
|
9
|
-
function ActionMenu({ items, label, search, align, triggerClassName, children }) {
|
|
12
|
+
function ActionMenu({ items, label, search, align, side, triggerClassName, children, trigger, tooltip = trigger === void 0, disabled = false, popupClassName, matchTriggerWidth = false, header, footer, empty, size, themeClassName, onOpenChange }) {
|
|
13
|
+
const [open, setOpen] = useState(false);
|
|
14
|
+
const button = trigger ? /* @__PURE__ */ jsx(Menu.Trigger, {
|
|
15
|
+
render: trigger,
|
|
16
|
+
disabled
|
|
17
|
+
}) : /* @__PURE__ */ jsx(Menu.Trigger, {
|
|
18
|
+
"aria-label": label,
|
|
19
|
+
disabled,
|
|
20
|
+
className: triggerClassName ?? buttonClasses({
|
|
21
|
+
variant: "ghost",
|
|
22
|
+
size: "sm",
|
|
23
|
+
iconOnly: true
|
|
24
|
+
}),
|
|
25
|
+
children
|
|
26
|
+
});
|
|
10
27
|
return /* @__PURE__ */ jsx(MenuFilter, {
|
|
11
28
|
search,
|
|
12
|
-
children: (query) => /* @__PURE__ */ jsxs(Menu.Root, {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
children: (query) => /* @__PURE__ */ jsxs(Menu.Root, {
|
|
30
|
+
onOpenChange: (next) => {
|
|
31
|
+
setOpen(next);
|
|
32
|
+
onOpenChange?.(next);
|
|
33
|
+
},
|
|
34
|
+
children: [tooltip ? /* @__PURE__ */ jsx(Tooltip, {
|
|
35
|
+
content: label,
|
|
36
|
+
disabled: open,
|
|
37
|
+
children: button
|
|
38
|
+
}) : button, /* @__PURE__ */ jsx(MenuPopup, {
|
|
39
|
+
align,
|
|
40
|
+
side,
|
|
41
|
+
size,
|
|
42
|
+
themeClassName,
|
|
43
|
+
matchAnchorWidth: matchTriggerWidth,
|
|
44
|
+
label: trigger ? label : void 0,
|
|
45
|
+
header,
|
|
46
|
+
footer: footer && /* @__PURE__ */ jsx(ActionRow, { action: footer }),
|
|
47
|
+
className: cx("min-w-52", popupClassName),
|
|
48
|
+
children: items.length === 0 && empty ? /* @__PURE__ */ jsx(EmptyState, {
|
|
49
|
+
variant: "bare",
|
|
50
|
+
title: empty
|
|
51
|
+
}) : /* @__PURE__ */ jsx(MenuEntries, {
|
|
52
|
+
entries: items,
|
|
53
|
+
search,
|
|
54
|
+
query
|
|
55
|
+
})
|
|
56
|
+
})]
|
|
57
|
+
})
|
|
32
58
|
});
|
|
33
59
|
}
|
|
34
60
|
//#endregion
|
|
@@ -1,20 +1,80 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
1
2
|
export type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
|
|
2
3
|
export type AvatarStatus = 'online' | 'offline' | 'busy' | 'away';
|
|
4
|
+
/** Who an avatar stands for. An agent's avatar is a rounded square, so its shape, and not only
|
|
5
|
+
* its color, tells it from a person's. */
|
|
6
|
+
export type AvatarKind = 'person' | 'agent';
|
|
7
|
+
export type AvatarShape = 'circle' | 'square';
|
|
3
8
|
export interface AvatarProps {
|
|
4
9
|
/** Image URL. Until it loads, or when it fails, the initials of `name` show. */
|
|
5
10
|
src?: string | null | undefined;
|
|
6
11
|
name?: string | undefined;
|
|
12
|
+
/** A person (a circle, the default) or an agent (a rounded square). Under UIProvider's
|
|
13
|
+
* `avatarColoring="kind"` it also picks the fill: `--avatar-person` or `--avatar-agent`. */
|
|
14
|
+
kind?: AvatarKind | undefined;
|
|
15
|
+
/** Overrides the shape `kind` gives, such as a square for an organization. */
|
|
16
|
+
shape?: AvatarShape | undefined;
|
|
7
17
|
/** Picks the fallback's color from the theme's categorical palette, so the same key gets the
|
|
8
18
|
* same color everywhere. Defaults to `name`; pass a stable id when names can repeat or
|
|
9
|
-
* change, or `null` for the accent fill whatever the name. Without either, the accent fills it.
|
|
19
|
+
* change, or `null` for the accent fill whatever the name. Without either, the accent fills it.
|
|
20
|
+
* Ignored under `avatarColoring="kind"`. */
|
|
10
21
|
colorKey?: string | null | undefined;
|
|
22
|
+
/** Classes for the initials' fill and text in place of the palette's or the kind's, such as a
|
|
23
|
+
* neutral fill for something that is neither a person nor an agent. */
|
|
24
|
+
colorClassName?: string | undefined;
|
|
25
|
+
/** Defaults to the group's size inside an `AvatarGroup`, else `md`. */
|
|
11
26
|
size?: AvatarSize | undefined;
|
|
12
27
|
status?: AvatarStatus | undefined;
|
|
28
|
+
/** Hides it from assistive technology, for an avatar beside the name it shows, which a
|
|
29
|
+
* screen reader would otherwise read twice. */
|
|
30
|
+
decorative?: boolean | undefined;
|
|
31
|
+
/** Names it on hover: `true` shows the name, with the presence when it has a status dot, and
|
|
32
|
+
* anything else shows that instead, such as what the person is doing. */
|
|
33
|
+
tooltip?: boolean | ReactNode;
|
|
34
|
+
/** On the avatar's shape, rounded as it is, so a ring or a shadow follows the circle or the
|
|
35
|
+
* square: its margin, ring or hover effect. */
|
|
13
36
|
className?: string | undefined;
|
|
14
37
|
}
|
|
38
|
+
export interface AvatarInitialsOptions {
|
|
39
|
+
/** Two letters for a one-word name ("maya" reads "MA"), splitting a handle on `_` and `-`
|
|
40
|
+
* too and leaving out an email's domain. Default false: one letter, "M". */
|
|
41
|
+
twoLetters?: boolean | undefined;
|
|
42
|
+
}
|
|
15
43
|
/** Up to two initials: the first and last word of a name split on spaces and dots. */
|
|
16
|
-
export declare function avatarInitials(name: string | undefined): string;
|
|
17
|
-
/** A person's picture, or their initials while it loads or when it fails. It is
|
|
18
|
-
* one image to assistive technology, named for
|
|
19
|
-
*
|
|
20
|
-
|
|
44
|
+
export declare function avatarInitials(name: string | undefined, { twoLetters }?: AvatarInitialsOptions): string;
|
|
45
|
+
/** A person's or an agent's picture, or their initials while it loads or when it fails. It is
|
|
46
|
+
* one image to assistive technology, named for them, whichever shows, and their presence when
|
|
47
|
+
* it has a status dot, unless it is `decorative`.
|
|
48
|
+
*
|
|
49
|
+
* Without a picture the fill follows UIProvider's `avatarColoring`: by name from the
|
|
50
|
+
* categorical palette (the default), or by kind, where people share `--avatar-person` (with
|
|
51
|
+
* `--avatar-person-text`) and agents `--avatar-agent` (with `--avatar-agent-text`, and the
|
|
52
|
+
* edge `--avatar-agent-ring`). */
|
|
53
|
+
export declare function Avatar({ src, name, kind, shape, colorKey, colorClassName, size: sizeProp, status, decorative, tooltip, className, }: AvatarProps): import("react").JSX.Element;
|
|
54
|
+
export interface AvatarGroupProps {
|
|
55
|
+
/** Avatars, each possibly wrapped, such as in a hover card. Each child counts as one. */
|
|
56
|
+
children: ReactNode;
|
|
57
|
+
/** Shows at most this many; the rest become a "+N" chip. */
|
|
58
|
+
max?: number | undefined;
|
|
59
|
+
/** How many there are in all, when the children are already a slice of them: the chip counts
|
|
60
|
+
* the rest. Defaults to the number of children. */
|
|
61
|
+
total?: number | undefined;
|
|
62
|
+
/** Shows the "+N" chip for those left out. Default true; false for a stack whose count is
|
|
63
|
+
* printed beside it. */
|
|
64
|
+
showOverflow?: boolean | undefined;
|
|
65
|
+
/** Every avatar's size, and the chip's. Default `sm`. */
|
|
66
|
+
size?: AvatarSize | undefined;
|
|
67
|
+
/** Rings each avatar in the color behind the stack, so overlapping faces read apart. Default
|
|
68
|
+
* true. */
|
|
69
|
+
ring?: boolean | undefined;
|
|
70
|
+
/** The ring's color, a CSS color: the surface the stack sits on. Defaults to the panel's. One
|
|
71
|
+
* avatar can set its own, such as a highlight, by setting `--avatar-ring` in its `className`. */
|
|
72
|
+
ringColor?: string | undefined;
|
|
73
|
+
/** The group's accessible name, such as "3 people here". */
|
|
74
|
+
label?: string | undefined;
|
|
75
|
+
className?: string | undefined;
|
|
76
|
+
}
|
|
77
|
+
/** Overlapping avatars, such as a task's assignees or who is here, with a "+N" chip for the
|
|
78
|
+
* rest. Each avatar inside takes the group's size and a ring in the color behind it, which
|
|
79
|
+
* follows its shape, round or square. */
|
|
80
|
+
export declare function AvatarGroup({ children, max, total, showOverflow, size, ring, ringColor, label, className, }: AvatarGroupProps): import("react").JSX.Element;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
|
-
import {
|
|
2
|
+
import { Tooltip } from "./Tooltip.js";
|
|
3
|
+
import { useAvatarColoring, useLocale, useStrings } from "./Provider.js";
|
|
3
4
|
import { categoryClasses } from "./category.js";
|
|
5
|
+
import { Children, createContext, use, useMemo } from "react";
|
|
4
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
7
|
import { Avatar } from "@base-ui/react/avatar";
|
|
6
8
|
//#region src/components/Avatar.tsx
|
|
@@ -12,6 +14,23 @@ var SIZE_CLASSES = {
|
|
|
12
14
|
xl: "size-12 text-lg",
|
|
13
15
|
"2xl": "size-16 text-xl"
|
|
14
16
|
};
|
|
17
|
+
var KIND_TEXT_CLASSES = {
|
|
18
|
+
xs: "text-[8px]",
|
|
19
|
+
md: "text-[11px]"
|
|
20
|
+
};
|
|
21
|
+
var SQUARE_CLASSES = {
|
|
22
|
+
xs: "rounded-[5px]",
|
|
23
|
+
sm: "rounded-[5px]",
|
|
24
|
+
md: "rounded-[5px]",
|
|
25
|
+
lg: "rounded-lg",
|
|
26
|
+
xl: "rounded-[10px]",
|
|
27
|
+
"2xl": "rounded-xl"
|
|
28
|
+
};
|
|
29
|
+
var KIND_CLASSES = {
|
|
30
|
+
person: "bg-(--avatar-person,color-mix(in_oklab,var(--theme-info)_12%,var(--theme-panel-bg))) text-(--avatar-person-text,var(--theme-info-text))",
|
|
31
|
+
agent: "bg-(--avatar-agent,var(--theme-category-2)) text-(--avatar-agent-text,var(--theme-category-2-text))"
|
|
32
|
+
};
|
|
33
|
+
var AGENT_EDGE = "after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:content-[''] after:inset-ring after:inset-ring-(--avatar-agent-ring,color-mix(in_oklab,var(--avatar-agent-text,var(--theme-category-2-text))_40%,transparent))";
|
|
15
34
|
var STATUS_CLASSES = {
|
|
16
35
|
online: "bg-(--theme-success)",
|
|
17
36
|
offline: "bg-(--theme-muted-text-color)",
|
|
@@ -19,44 +38,71 @@ var STATUS_CLASSES = {
|
|
|
19
38
|
away: "bg-(--theme-warning)"
|
|
20
39
|
};
|
|
21
40
|
var graphemes = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : void 0;
|
|
41
|
+
function leadingCharacters(text, count) {
|
|
42
|
+
if (!text) return "";
|
|
43
|
+
const out = [];
|
|
44
|
+
for (const part of graphemes ? Array.from(graphemes.segment(text), (s) => s.segment) : text) {
|
|
45
|
+
if (out.length === count) break;
|
|
46
|
+
out.push(part);
|
|
47
|
+
}
|
|
48
|
+
return out.join("");
|
|
49
|
+
}
|
|
22
50
|
function firstCharacter(text) {
|
|
23
|
-
|
|
24
|
-
if (graphemes) return graphemes.segment(text)[Symbol.iterator]().next().value?.segment;
|
|
25
|
-
return Array.from(text)[0];
|
|
51
|
+
return leadingCharacters(text, 1) || void 0;
|
|
26
52
|
}
|
|
27
53
|
/** Up to two initials: the first and last word of a name split on spaces and dots. */
|
|
28
|
-
function avatarInitials(name) {
|
|
29
|
-
|
|
54
|
+
function avatarInitials(name, { twoLetters = false } = {}) {
|
|
55
|
+
let text = (name ?? "").trim();
|
|
56
|
+
if (twoLetters && /^[^\s@]+@\S+$/.test(text)) text = text.slice(0, text.indexOf("@"));
|
|
57
|
+
const parts = text.split(twoLetters ? /[\s.@_-]+/ : /[\s.]+/).filter(Boolean);
|
|
30
58
|
const first = firstCharacter(parts[0]);
|
|
31
59
|
const last = firstCharacter(parts.at(-1));
|
|
32
60
|
if (parts.length >= 2 && first && last) return (first + last).toUpperCase();
|
|
61
|
+
if (twoLetters && parts.length === 1) return leadingCharacters(parts[0], 2).toUpperCase();
|
|
33
62
|
return first?.toUpperCase() || "?";
|
|
34
63
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*
|
|
38
|
-
|
|
64
|
+
var AvatarGroupContext = createContext(null);
|
|
65
|
+
/** A person's or an agent's picture, or their initials while it loads or when it fails. It is
|
|
66
|
+
* one image to assistive technology, named for them, whichever shows, and their presence when
|
|
67
|
+
* it has a status dot, unless it is `decorative`.
|
|
68
|
+
*
|
|
69
|
+
* Without a picture the fill follows UIProvider's `avatarColoring`: by name from the
|
|
70
|
+
* categorical palette (the default), or by kind, where people share `--avatar-person` (with
|
|
71
|
+
* `--avatar-person-text`) and agents `--avatar-agent` (with `--avatar-agent-text`, and the
|
|
72
|
+
* edge `--avatar-agent-ring`). */
|
|
73
|
+
function Avatar$1({ src, name, kind = "person", shape = kind === "agent" ? "square" : "circle", colorKey, colorClassName, size: sizeProp, status, decorative = false, tooltip = false, className }) {
|
|
39
74
|
const { common } = useStrings();
|
|
75
|
+
const byKind = useAvatarColoring() === "kind";
|
|
76
|
+
const group = use(AvatarGroupContext);
|
|
77
|
+
const size = sizeProp ?? group?.size ?? "md";
|
|
40
78
|
const who = name || common.userAvatar;
|
|
79
|
+
const named = status ? common.withPresence(who, common.presence[status]) : who;
|
|
41
80
|
const colorBy = colorKey === void 0 ? name?.trim() : colorKey;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
81
|
+
const initials = avatarInitials(name, { twoLetters: byKind });
|
|
82
|
+
const radius = shape === "square" ? SQUARE_CLASSES[size] : "rounded-full";
|
|
83
|
+
const fill = colorClassName ?? (byKind ? KIND_CLASSES[kind] : colorBy ? categoryClasses(colorBy) : "bg-gradient-to-br from-[var(--gradient-start,var(--theme-accent))] to-[var(--gradient-mid,var(--theme-link))] text-(--theme-accent-text)");
|
|
84
|
+
const avatar = /* @__PURE__ */ jsxs("span", {
|
|
85
|
+
...decorative ? { "aria-hidden": true } : {
|
|
86
|
+
role: "img",
|
|
87
|
+
"aria-label": named
|
|
88
|
+
},
|
|
89
|
+
"data-shape": shape,
|
|
90
|
+
className: cx("relative inline-flex shrink-0", radius, group?.ring && "ring-2 ring-(--avatar-ring)", className),
|
|
46
91
|
children: [/* @__PURE__ */ jsxs(Avatar.Root, {
|
|
47
|
-
className: cx("relative inline-flex items-center justify-center overflow-hidden
|
|
92
|
+
className: cx("relative inline-flex items-center justify-center overflow-hidden select-none", byKind ? "font-semibold" : "font-medium", radius, SIZE_CLASSES[size], byKind && KIND_TEXT_CLASSES[size], byKind && kind === "agent" && !colorClassName && AGENT_EDGE),
|
|
48
93
|
children: [src && /* @__PURE__ */ jsx(Avatar.Image, {
|
|
49
94
|
src,
|
|
50
95
|
alt: "",
|
|
51
96
|
loading: "lazy",
|
|
97
|
+
decoding: "async",
|
|
52
98
|
keepMounted: true,
|
|
53
99
|
className: "absolute inset-0 size-full object-cover data-error:hidden data-loading:invisible"
|
|
54
100
|
}, src), /* @__PURE__ */ jsx(Avatar.Fallback, {
|
|
55
101
|
"aria-hidden": "true",
|
|
56
|
-
className: cx("flex size-full items-center justify-center",
|
|
102
|
+
className: cx("flex size-full items-center justify-center", fill),
|
|
57
103
|
children: /* @__PURE__ */ jsx("span", {
|
|
58
104
|
className: "leading-none [text-box:trim-both_cap_alphabetic]",
|
|
59
|
-
children: size === "xs" ? firstCharacter(
|
|
105
|
+
children: size === "xs" && !byKind ? firstCharacter(initials) : initials
|
|
60
106
|
})
|
|
61
107
|
})]
|
|
62
108
|
}), status && /* @__PURE__ */ jsx("span", {
|
|
@@ -64,6 +110,72 @@ function Avatar$1({ src, name, colorKey, size = "md", status, className }) {
|
|
|
64
110
|
className: cx("absolute right-0 bottom-0 block rounded-full ring-2 ring-(--theme-app-bg)", STATUS_CLASSES[status], size === "xs" || size === "sm" ? "size-1.5" : size === "md" ? "size-2" : "size-2.5")
|
|
65
111
|
})]
|
|
66
112
|
});
|
|
113
|
+
if (tooltip === false || tooltip === null || tooltip === void 0) return avatar;
|
|
114
|
+
return /* @__PURE__ */ jsx(Tooltip, {
|
|
115
|
+
content: tooltip === true ? named : tooltip,
|
|
116
|
+
children: avatar
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
var OVERLAP_CLASSES = {
|
|
120
|
+
xs: "-space-x-px",
|
|
121
|
+
sm: "-space-x-0.5",
|
|
122
|
+
md: "-space-x-1",
|
|
123
|
+
lg: "-space-x-1.5",
|
|
124
|
+
xl: "-space-x-1.5",
|
|
125
|
+
"2xl": "-space-x-1.5"
|
|
126
|
+
};
|
|
127
|
+
var CHIP_SIZE_CLASSES = {
|
|
128
|
+
xs: "h-4 min-w-4 px-0.5 text-[8px]",
|
|
129
|
+
sm: "h-5 min-w-5 px-1 text-[9px]",
|
|
130
|
+
md: "h-7 min-w-7 px-1 text-[11px]",
|
|
131
|
+
lg: "h-10 min-w-10 px-1.5 text-sm",
|
|
132
|
+
xl: "h-12 min-w-12 px-2 text-base",
|
|
133
|
+
"2xl": "h-16 min-w-16 px-2 text-lg"
|
|
134
|
+
};
|
|
135
|
+
var numberFormats = /* @__PURE__ */ new Map();
|
|
136
|
+
function formatNumber(n, locale) {
|
|
137
|
+
let format = numberFormats.get(locale);
|
|
138
|
+
if (!format) {
|
|
139
|
+
format = new Intl.NumberFormat(locale);
|
|
140
|
+
numberFormats.set(locale, format);
|
|
141
|
+
}
|
|
142
|
+
return format.format(n);
|
|
143
|
+
}
|
|
144
|
+
/** Overlapping avatars, such as a task's assignees or who is here, with a "+N" chip for the
|
|
145
|
+
* rest. Each avatar inside takes the group's size and a ring in the color behind it, which
|
|
146
|
+
* follows its shape, round or square. */
|
|
147
|
+
function AvatarGroup({ children, max, total, showOverflow = true, size = "sm", ring = true, ringColor, label, className }) {
|
|
148
|
+
const { common } = useStrings();
|
|
149
|
+
const locale = useLocale();
|
|
150
|
+
const items = Children.toArray(children);
|
|
151
|
+
const shown = max === void 0 ? items : items.slice(0, Math.max(0, max));
|
|
152
|
+
const rest = Math.max(0, (total ?? items.length) - shown.length);
|
|
153
|
+
const context = useMemo(() => ({
|
|
154
|
+
size,
|
|
155
|
+
ring
|
|
156
|
+
}), [size, ring]);
|
|
157
|
+
return /* @__PURE__ */ jsx(AvatarGroupContext, {
|
|
158
|
+
value: context,
|
|
159
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
160
|
+
...label ? {
|
|
161
|
+
role: "group",
|
|
162
|
+
"aria-label": label
|
|
163
|
+
} : {},
|
|
164
|
+
style: { "--avatar-ring": ringColor ?? "var(--theme-panel-bg)" },
|
|
165
|
+
className: cx("inline-flex shrink-0 items-center", OVERLAP_CLASSES[size], className),
|
|
166
|
+
children: [shown, showOverflow && rest > 0 && /* @__PURE__ */ jsxs("span", {
|
|
167
|
+
className: cx("relative inline-flex shrink-0 items-center justify-center rounded-full bg-(--theme-muted-panel-bg) font-medium text-(--theme-muted-text-color) tabular-nums select-none", CHIP_SIZE_CLASSES[size], ring && "ring-2 ring-(--avatar-ring)"),
|
|
168
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
169
|
+
"aria-hidden": "true",
|
|
170
|
+
className: "leading-none [text-box:trim-both_cap_alphabetic]",
|
|
171
|
+
children: ["+", formatNumber(rest, locale)]
|
|
172
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
173
|
+
className: "sr-only",
|
|
174
|
+
children: common.moreCount(rest)
|
|
175
|
+
})]
|
|
176
|
+
})]
|
|
177
|
+
})
|
|
178
|
+
});
|
|
67
179
|
}
|
|
68
180
|
//#endregion
|
|
69
|
-
export { Avatar$1 as Avatar, avatarInitials };
|
|
181
|
+
export { Avatar$1 as Avatar, AvatarGroup, avatarInitials };
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
1
2
|
/** One step of the trail to the current page. */
|
|
2
3
|
export interface Breadcrumb {
|
|
3
4
|
/** Empty while the name is still loading: the trail shows a placeholder. */
|
|
4
5
|
label: string;
|
|
5
6
|
href?: string | undefined;
|
|
7
|
+
/** Before the label, such as the section a page belongs to; also beside
|
|
8
|
+
* the crumb's row once it folds into the "…" menu. */
|
|
9
|
+
icon?: ReactNode;
|
|
6
10
|
}
|
|
7
11
|
export interface BreadcrumbsProps {
|
|
8
12
|
/** The trail, ending with where the reader is. A crumb with an empty label,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
2
|
import { buttonClasses } from "./buttonClasses.js";
|
|
3
3
|
import { ChevronRightIcon, MoreIcon } from "../icons.js";
|
|
4
|
-
import { keyedByContent } from "./keys.js";
|
|
5
4
|
import { Tooltip } from "./Tooltip.js";
|
|
6
5
|
import { useStrings } from "./Provider.js";
|
|
7
6
|
import { AppLink } from "./AppLink.js";
|
|
7
|
+
import { keyedByContent } from "./keys.js";
|
|
8
8
|
import { ActionMenu } from "./ActionMenu.js";
|
|
9
9
|
import { Skeleton } from "./Skeleton.js";
|
|
10
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
10
|
import { useLayoutEffect, useState } from "react";
|
|
11
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
12
12
|
//#region src/components/Breadcrumbs.tsx
|
|
13
13
|
/**
|
|
14
14
|
* The trail to where the reader is, as a list in a `nav` landmark. A trail too
|
|
@@ -29,16 +29,20 @@ function Breadcrumbs({ crumbs, onSelect, current = "page", heading = false, labe
|
|
|
29
29
|
const Last = heading ? "h1" : "span";
|
|
30
30
|
const menuItem = (crumb, index) => {
|
|
31
31
|
const name = crumb.label || common.loading;
|
|
32
|
+
const icon = crumb.icon;
|
|
32
33
|
if (crumb.href) return {
|
|
33
34
|
label: name,
|
|
35
|
+
icon,
|
|
34
36
|
href: crumb.href
|
|
35
37
|
};
|
|
36
38
|
if (onSelect) return {
|
|
37
39
|
label: name,
|
|
40
|
+
icon,
|
|
38
41
|
onClick: () => onSelect(crumb, index)
|
|
39
42
|
};
|
|
40
43
|
return {
|
|
41
44
|
label: name,
|
|
45
|
+
icon,
|
|
42
46
|
disabled: true,
|
|
43
47
|
onClick: () => {}
|
|
44
48
|
};
|
|
@@ -73,16 +77,16 @@ function Breadcrumbs({ crumbs, onSelect, current = "page", heading = false, labe
|
|
|
73
77
|
overflowOnly: true,
|
|
74
78
|
children: crumb.href ? /* @__PURE__ */ jsx(AppLink, {
|
|
75
79
|
href: crumb.href,
|
|
76
|
-
className: cx(crumbText, crumbLink, "max-w-48"),
|
|
77
|
-
children: crumb
|
|
80
|
+
className: cx(crumbText, crumbLink, crumb.icon && withIcon, "max-w-48"),
|
|
81
|
+
children: /* @__PURE__ */ jsx(CrumbLabel, { crumb })
|
|
78
82
|
}) : onSelect ? /* @__PURE__ */ jsx("button", {
|
|
79
83
|
type: "button",
|
|
80
84
|
onClick: () => onSelect(crumb, index),
|
|
81
|
-
className: cx(crumbText, crumbLink, "max-w-48 cursor-pointer text-start"),
|
|
82
|
-
children: crumb
|
|
85
|
+
className: cx(crumbText, crumbLink, crumb.icon && withIcon, "max-w-48 cursor-pointer text-start"),
|
|
86
|
+
children: /* @__PURE__ */ jsx(CrumbLabel, { crumb })
|
|
83
87
|
}) : /* @__PURE__ */ jsx("span", {
|
|
84
|
-
className: cx(crumbText, "max-w-48"),
|
|
85
|
-
children: crumb
|
|
88
|
+
className: cx(crumbText, crumb.icon && withIcon, "max-w-48"),
|
|
89
|
+
children: /* @__PURE__ */ jsx(CrumbLabel, { crumb })
|
|
86
90
|
})
|
|
87
91
|
}), /* @__PURE__ */ jsx(Separator, {})]
|
|
88
92
|
}, key);
|
|
@@ -98,8 +102,8 @@ function Breadcrumbs({ crumbs, onSelect, current = "page", heading = false, labe
|
|
|
98
102
|
overflowOnly: true,
|
|
99
103
|
children: /* @__PURE__ */ jsx(Last, {
|
|
100
104
|
"aria-current": current,
|
|
101
|
-
className: "m-0 block truncate text-[13px] font-medium leading-none text-(--theme-app)",
|
|
102
|
-
children: last
|
|
105
|
+
className: cx("m-0 block truncate text-[13px] font-medium leading-none text-(--theme-app)", last.icon && withIcon),
|
|
106
|
+
children: /* @__PURE__ */ jsx(CrumbLabel, { crumb: last })
|
|
103
107
|
})
|
|
104
108
|
})
|
|
105
109
|
})
|
|
@@ -122,6 +126,18 @@ function Breadcrumbs({ crumbs, onSelect, current = "page", heading = false, labe
|
|
|
122
126
|
});
|
|
123
127
|
}
|
|
124
128
|
var crumbText = "block truncate text-(--theme-muted-text-color)";
|
|
129
|
+
var withIcon = "flex items-center gap-1";
|
|
130
|
+
function CrumbLabel({ crumb }) {
|
|
131
|
+
if (!crumb.icon) return crumb.label;
|
|
132
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
133
|
+
"aria-hidden": "true",
|
|
134
|
+
className: "inline-flex shrink-0 [&_svg]:size-3.5",
|
|
135
|
+
children: crumb.icon
|
|
136
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
137
|
+
className: "min-w-0 truncate",
|
|
138
|
+
children: crumb.label
|
|
139
|
+
})] });
|
|
140
|
+
}
|
|
125
141
|
var crumbLink = "rounded-sm transition-colors hover:text-(--theme-app) focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-(--theme-link)";
|
|
126
142
|
function Separator() {
|
|
127
143
|
return /* @__PURE__ */ jsx(ChevronRightIcon, { className: "size-3 shrink-0 text-(--theme-muted-text-color) opacity-60 rtl:rotate-180" });
|
|
@@ -6,8 +6,9 @@ interface ButtonOwnProps extends ButtonStyle {
|
|
|
6
6
|
className?: string | undefined;
|
|
7
7
|
/** Before the label. */
|
|
8
8
|
icon?: ReactNode;
|
|
9
|
-
/** Busy with what it started: a spinner takes the icon's place,
|
|
10
|
-
*
|
|
9
|
+
/** Busy with what it started: a spinner takes the icon's place, or without an
|
|
10
|
+
* icon sits over the label, so the button keeps its width. It can't be
|
|
11
|
+
* pressed again until done. */
|
|
11
12
|
loading?: boolean | undefined;
|
|
12
13
|
}
|
|
13
14
|
/** A button, or with `href` a link that looks like one: navigation stays a
|
|
@@ -15,7 +15,17 @@ function Button$1({ variant, size = "md", iconOnly, icon, loading = false, class
|
|
|
15
15
|
size,
|
|
16
16
|
iconOnly
|
|
17
17
|
}), className);
|
|
18
|
-
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
18
|
+
const content = loading && !icon ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
19
|
+
className: "inline-flex items-center gap-1.5 opacity-0",
|
|
20
|
+
children
|
|
21
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
22
|
+
className: "absolute inset-0 flex items-center justify-center",
|
|
23
|
+
children: /* @__PURE__ */ jsx(Loader, {
|
|
24
|
+
inline: true,
|
|
25
|
+
decorative: true,
|
|
26
|
+
size: "1em"
|
|
27
|
+
})
|
|
28
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [loading ? /* @__PURE__ */ jsx(Loader, {
|
|
19
29
|
inline: true,
|
|
20
30
|
decorative: true,
|
|
21
31
|
size: "1em"
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import { type Tone } from './tone.js';
|
|
3
|
-
/** A callout's tone: `default` for a plain note, or a
|
|
4
|
-
|
|
3
|
+
/** A callout's tone: `default` for a plain note, a status, or `muted` for a quiet
|
|
4
|
+
* note that something is read-only, such as a page only admins can change. */
|
|
5
|
+
export type CalloutTone = Extract<Tone, 'default' | 'info' | 'success' | 'warning' | 'error' | 'muted'>;
|
|
5
6
|
export interface CalloutProps {
|
|
6
7
|
tone?: CalloutTone | undefined;
|
|
7
8
|
/** A bold first line that says what happened; the children explain it. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
|
-
import { CloseIcon, ErrorIcon, InfoIcon, SuccessIcon, WarningIcon } from "../icons.js";
|
|
2
|
+
import { CloseIcon, ErrorIcon, InfoIcon, LockIcon, SuccessIcon, WarningIcon } from "../icons.js";
|
|
3
3
|
import { toneIcon, toneSurface } from "./tone.js";
|
|
4
4
|
import { useStrings } from "./Provider.js";
|
|
5
5
|
import { IconButton } from "./IconButton.js";
|
|
@@ -10,7 +10,8 @@ var toneIcons = {
|
|
|
10
10
|
info: InfoIcon,
|
|
11
11
|
success: SuccessIcon,
|
|
12
12
|
warning: WarningIcon,
|
|
13
|
-
error: ErrorIcon
|
|
13
|
+
error: ErrorIcon,
|
|
14
|
+
muted: LockIcon
|
|
14
15
|
};
|
|
15
16
|
/** A message set into the page in a status's tone: guidance, a warning, an error
|
|
16
17
|
* or a success, and what to do about it. For a passing notice that floats over
|