@parallelworks/ui 0.77.0 → 0.78.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 +30 -5
- package/dist/access/AccessDrawer.d.ts +28 -7
- package/dist/access/AccessDrawer.js +216 -35
- 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 +18 -0
- package/dist/access/strings.js +20 -2
- 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 +2 -2
- 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 +26 -2
- package/dist/components/ConfirmModal.js +81 -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 +16 -4
- package/dist/components/CreateModal.js +27 -16
- 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 +38 -2
- 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 +13 -2
- package/dist/components/Popover.js +20 -21
- package/dist/components/Provider.d.ts +140 -3
- package/dist/components/Provider.js +142 -12
- 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 +7 -7
- package/dist/graph/MatrixGroup.js +2 -2
- package/dist/graph/ProblemsButton.js +3 -3
- package/dist/graph/Reveal.js +1 -1
- package/dist/graph/RunWarningsList.js +1 -1
- 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/editorFields.js +3 -3
- package/dist/graph/editorPrimitives.js +1 -1
- package/dist/graph/editorRows.js +5 -5
- package/dist/graph/fieldProblems.js +2 -2
- package/dist/graph/inputRefs.js +7 -6
- 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
package/dist/components/Modal.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
|
-
import {
|
|
2
|
+
import { CloseIcon } from "../icons.js";
|
|
3
|
+
import { usePopupContainer } from "./popupContainer.js";
|
|
4
|
+
import { useStrings } from "./Provider.js";
|
|
5
|
+
import { IconButton } from "./IconButton.js";
|
|
3
6
|
import { closeHandler } from "./dismiss.js";
|
|
4
|
-
import {
|
|
7
|
+
import { useRef } from "react";
|
|
8
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
5
9
|
import { AlertDialog } from "@base-ui/react/alert-dialog";
|
|
6
10
|
import { Dialog } from "@base-ui/react/dialog";
|
|
7
11
|
//#region src/components/Modal.tsx
|
|
@@ -17,43 +21,78 @@ var sizeClasses = {
|
|
|
17
21
|
lg: "w-[560px]",
|
|
18
22
|
xl: "w-[672px]"
|
|
19
23
|
};
|
|
24
|
+
var popupMotion = "transition-[transform,opacity] duration-150 ease-out data-starting-style:scale-95 data-starting-style:opacity-0 data-ending-style:scale-95 data-ending-style:opacity-0 motion-reduce:data-starting-style:scale-100 motion-reduce:data-ending-style:scale-100";
|
|
25
|
+
var backdropMotion = "transition-opacity duration-150 ease-out data-starting-style:opacity-0 data-ending-style:opacity-0";
|
|
26
|
+
var CONTROLS = "input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]):not([data-modal-close]), a[href], [tabindex]:not([tabindex=\"-1\"]):not([data-modal-close])";
|
|
27
|
+
/** The first control in a panel other than its close button, or the panel itself. */
|
|
28
|
+
function firstControlIn(panel) {
|
|
29
|
+
return panel?.querySelector(CONTROLS) ?? panel ?? true;
|
|
30
|
+
}
|
|
20
31
|
/** A modal dialog: focus stays inside, the page behind is inert and doesn't scroll,
|
|
21
32
|
* and focus returns to where it was on close. Give it a `title`, a `description`
|
|
22
33
|
* and a `footer` for the standard layout, as a Drawer has, or lay out the whole
|
|
23
34
|
* panel with the children. */
|
|
24
|
-
function Modal({ open, onClose, title, description, footer, size, alert = false, dismissible = true, align = "top", panel = true, backdropClassName = "bg-black/40", className, children, ...popupProps }) {
|
|
25
|
-
const
|
|
35
|
+
function Modal({ open, onClose, title, description, footer, size, alert = false, dismissible = true, align = "top", panel = true, backdropClassName = "bg-black/40", closeButton = false, onSubmit, className, children, initialFocus, ...popupProps }) {
|
|
36
|
+
const portal = usePopupContainer();
|
|
37
|
+
const { common } = useStrings();
|
|
38
|
+
const panelElement = useRef(null);
|
|
26
39
|
const onOpenChange = closeHandler(dismissible, onClose);
|
|
27
|
-
const
|
|
40
|
+
const titled = title !== void 0 || description !== void 0;
|
|
41
|
+
const header = titled || closeButton;
|
|
28
42
|
const body = children !== void 0 && children !== null && children !== false;
|
|
29
|
-
const laidOut = header || footer !== void 0;
|
|
43
|
+
const laidOut = header || footer !== void 0 || onSubmit !== void 0;
|
|
44
|
+
const sections = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
45
|
+
header && /* @__PURE__ */ jsxs("div", {
|
|
46
|
+
className: cx("flex shrink-0 items-start gap-3 px-4 pt-4", !body && "pb-4"),
|
|
47
|
+
children: [titled && /* @__PURE__ */ jsxs("div", {
|
|
48
|
+
className: "min-w-0 flex-1",
|
|
49
|
+
children: [title !== void 0 && /* @__PURE__ */ jsx(ModalTitle, {
|
|
50
|
+
className: "m-0 text-lg font-semibold wrap-break-word",
|
|
51
|
+
children: title
|
|
52
|
+
}), description !== void 0 && /* @__PURE__ */ jsx(ModalDescription, {
|
|
53
|
+
className: "m-0 mt-1.5 text-sm text-(--theme-muted-text-color)",
|
|
54
|
+
children: description
|
|
55
|
+
})]
|
|
56
|
+
}), closeButton && /* @__PURE__ */ jsx(Dialog.Close, {
|
|
57
|
+
"data-modal-close": "",
|
|
58
|
+
render: /* @__PURE__ */ jsx(IconButton, {
|
|
59
|
+
icon: /* @__PURE__ */ jsx(CloseIcon, {}),
|
|
60
|
+
label: common.close,
|
|
61
|
+
className: "-me-1.5 ms-auto mt-0"
|
|
62
|
+
})
|
|
63
|
+
})]
|
|
64
|
+
}),
|
|
65
|
+
body && /* @__PURE__ */ jsx("div", {
|
|
66
|
+
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-4",
|
|
67
|
+
children
|
|
68
|
+
}),
|
|
69
|
+
footer !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
70
|
+
className: "flex shrink-0 items-center justify-end gap-2 border-t border-(--theme-border) px-4 py-3",
|
|
71
|
+
children: footer
|
|
72
|
+
})
|
|
73
|
+
] });
|
|
30
74
|
const content = /* @__PURE__ */ jsxs(Dialog.Portal, {
|
|
31
|
-
|
|
32
|
-
children: [/* @__PURE__ */ jsx(Dialog.Backdrop, { className: cx("fixed inset-0 z-(--layer-modal)", backdropClassName) }), /* @__PURE__ */ jsx(Dialog.Viewport, {
|
|
75
|
+
...portal,
|
|
76
|
+
children: [/* @__PURE__ */ jsx(Dialog.Backdrop, { className: cx("fixed inset-0 z-(--layer-modal)", backdropMotion, backdropClassName) }), /* @__PURE__ */ jsx(Dialog.Viewport, {
|
|
33
77
|
className: cx("fixed inset-0 z-(--layer-modal) flex justify-center px-4 pt-20 pb-8", align === "center" ? "items-center" : "items-start sm:pt-[max(14vh,5rem)]"),
|
|
34
78
|
children: /* @__PURE__ */ jsx(Dialog.Popup, {
|
|
35
79
|
...popupProps,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
footer !== void 0 && /* @__PURE__ */ jsx("div", {
|
|
53
|
-
className: "flex shrink-0 items-center justify-end gap-2 border-t border-(--theme-border) px-4 py-3",
|
|
54
|
-
children: footer
|
|
55
|
-
})
|
|
56
|
-
] }) : children
|
|
80
|
+
ref: (element) => {
|
|
81
|
+
panelElement.current = element;
|
|
82
|
+
const forward = popupProps.ref;
|
|
83
|
+
if (typeof forward === "function") forward(element);
|
|
84
|
+
else if (forward) forward.current = element;
|
|
85
|
+
},
|
|
86
|
+
initialFocus: initialFocus ?? (closeButton ? () => firstControlIn(panelElement.current) : void 0),
|
|
87
|
+
className: cx(panel && "rounded-xl border border-(--theme-border) bg-(--theme-app-bg) text-(--theme-app) shadow-2xl", size && [sizeClasses[size], "max-w-full"], laidOut && "flex max-h-full flex-col", "outline-none", popupMotion, className),
|
|
88
|
+
children: !laidOut ? children : onSubmit ? /* @__PURE__ */ jsx("form", {
|
|
89
|
+
className: "flex min-h-0 flex-1 flex-col",
|
|
90
|
+
onSubmit: (event) => {
|
|
91
|
+
event.preventDefault();
|
|
92
|
+
onSubmit(event);
|
|
93
|
+
},
|
|
94
|
+
children: sections
|
|
95
|
+
}) : sections
|
|
57
96
|
})
|
|
58
97
|
})]
|
|
59
98
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
2
|
import { useStrings } from "./Provider.js";
|
|
3
3
|
import { fieldBox } from "./fieldBox.js";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
4
|
import { useId } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { OTPField } from "@base-ui/react/otp-field";
|
|
7
7
|
//#region src/components/OneTimeCodeInput.tsx
|
|
8
8
|
/**
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
|
-
import {
|
|
2
|
+
import { buttonClasses } from "./buttonClasses.js";
|
|
3
|
+
import { MoreIcon } from "../icons.js";
|
|
4
|
+
import { useSlots, useStrings } from "./Provider.js";
|
|
5
|
+
import { ActionMenu } from "./ActionMenu.js";
|
|
3
6
|
import { Breadcrumbs } from "./Breadcrumbs.js";
|
|
7
|
+
import { HeaderActionsFit, HeaderActionsFitContext, overflowingActions } from "./headerActionsFit.js";
|
|
4
8
|
import { PageHeaderStore } from "./pageHeaderStore.js";
|
|
5
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
9
|
import { createContext, use, useCallback, useLayoutEffect, useState, useSyncExternalStore } from "react";
|
|
10
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
11
|
import { createPortal } from "react-dom";
|
|
8
12
|
//#region src/components/PageHeader.tsx
|
|
9
13
|
var StoreContext = createContext(null);
|
|
@@ -76,9 +80,12 @@ function DeclaredHeader({ store, breadcrumbs, titleActions, actions, toolbar, hi
|
|
|
76
80
|
});
|
|
77
81
|
useLayoutEffect(() => () => store.delete(order), [store, order]);
|
|
78
82
|
if (!nodes || !client) return null;
|
|
79
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
83
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
80
84
|
fills.titleActions && createPortal(titleActions, nodes.titleActions),
|
|
81
|
-
fills.actions && createPortal(
|
|
85
|
+
fills.actions && createPortal(/* @__PURE__ */ jsx(HeaderActionsFitContext, {
|
|
86
|
+
value: store.actionsFit,
|
|
87
|
+
children: actions
|
|
88
|
+
}), nodes.actions),
|
|
82
89
|
fills.toolbar && createPortal(toolbar, nodes.toolbar)
|
|
83
90
|
] });
|
|
84
91
|
}
|
|
@@ -101,6 +108,7 @@ function PageHeaderBar({ compact = false, persistent = false, className }) {
|
|
|
101
108
|
titleActions: header.titleActions.length > 0 && /* @__PURE__ */ jsx(Mounts, { nodes: header.titleActions }),
|
|
102
109
|
actions: header.actions.length > 0 && /* @__PURE__ */ jsx(Mounts, { nodes: header.actions }),
|
|
103
110
|
toolbar: header.toolbar.length > 0 && /* @__PURE__ */ jsx(Mounts, { nodes: header.toolbar }),
|
|
111
|
+
fit: store.actionsFit,
|
|
104
112
|
compact,
|
|
105
113
|
className
|
|
106
114
|
});
|
|
@@ -129,14 +137,25 @@ function Mount({ node }) {
|
|
|
129
137
|
className: "contents"
|
|
130
138
|
});
|
|
131
139
|
}
|
|
132
|
-
function HeaderLayout({ breadcrumbs, titleActions, actions, toolbar, compact = false, className }) {
|
|
140
|
+
function HeaderLayout({ breadcrumbs, titleActions, actions, toolbar, fit: sharedFit, compact = false, className }) {
|
|
133
141
|
const { breadcrumbPin, navToggle } = useSlots();
|
|
142
|
+
const { list: t } = useStrings();
|
|
143
|
+
const [ownFit] = useState(() => new HeaderActionsFit());
|
|
144
|
+
const fit = sharedFit ?? ownFit;
|
|
145
|
+
const [row, setRow] = useState(null);
|
|
146
|
+
const [lead, setLead] = useState(null);
|
|
147
|
+
const [end, setEnd] = useState(null);
|
|
148
|
+
useActionsFit(fit, row, lead, end);
|
|
149
|
+
useSyncExternalStore(fit.subscribe, fit.getVersion, fit.getVersion);
|
|
150
|
+
const moved = fit.menu();
|
|
134
151
|
const hasTrail = breadcrumbs.length > 0;
|
|
135
152
|
return /* @__PURE__ */ jsxs("div", {
|
|
136
153
|
className: cx("@container w-full shrink-0 bg-(--theme-app-bg)", className),
|
|
137
154
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
155
|
+
ref: setRow,
|
|
138
156
|
className: cx("flex items-center justify-between gap-4 border-b border-(--theme-border) px-4", compact ? "h-8" : "h-12"),
|
|
139
157
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
158
|
+
ref: setLead,
|
|
140
159
|
className: "flex min-w-0 flex-1 items-center gap-2",
|
|
141
160
|
children: [
|
|
142
161
|
navToggle?.(),
|
|
@@ -150,9 +169,22 @@ function HeaderLayout({ breadcrumbs, titleActions, actions, toolbar, compact = f
|
|
|
150
169
|
}),
|
|
151
170
|
hasTrail && breadcrumbPin?.({ crumbs: breadcrumbs })
|
|
152
171
|
]
|
|
153
|
-
}), present(actions) && /* @__PURE__ */
|
|
172
|
+
}), present(actions) && /* @__PURE__ */ jsxs("div", {
|
|
173
|
+
ref: setEnd,
|
|
154
174
|
className: "flex shrink-0 items-center gap-1",
|
|
155
|
-
children:
|
|
175
|
+
children: [/* @__PURE__ */ jsx(HeaderActionsFitContext, {
|
|
176
|
+
value: fit,
|
|
177
|
+
children: actions
|
|
178
|
+
}), moved.length > 0 && /* @__PURE__ */ jsx(ActionMenu, {
|
|
179
|
+
items: moved,
|
|
180
|
+
label: t.moreActions,
|
|
181
|
+
triggerClassName: buttonClasses({
|
|
182
|
+
variant: "ghost",
|
|
183
|
+
size: "xs",
|
|
184
|
+
iconOnly: true
|
|
185
|
+
}),
|
|
186
|
+
children: /* @__PURE__ */ jsx(MoreIcon, {})
|
|
187
|
+
})]
|
|
156
188
|
})]
|
|
157
189
|
}), present(toolbar) && /* @__PURE__ */ jsx("div", {
|
|
158
190
|
className: "px-4",
|
|
@@ -160,5 +192,77 @@ function HeaderLayout({ breadcrumbs, titleActions, actions, toolbar, compact = f
|
|
|
160
192
|
})]
|
|
161
193
|
});
|
|
162
194
|
}
|
|
195
|
+
var ROW_GAP = 16;
|
|
196
|
+
var LEAD_GAP = 8;
|
|
197
|
+
var TRAIL_MIN_WIDTH = 160;
|
|
198
|
+
var FOLD_WIDTH = 448;
|
|
199
|
+
/**
|
|
200
|
+
* Fits the actions to the bar. Labels fold to their icons first, by the bar's
|
|
201
|
+
* own container query; when the folded actions still leave the trail too
|
|
202
|
+
* little room, the trailing ones move into a "…" menu at the end, last first,
|
|
203
|
+
* until the rest fit. It measures each action as it shows and remembers its
|
|
204
|
+
* width while it has moved, so the answer doesn't depend on what has moved.
|
|
205
|
+
*/
|
|
206
|
+
function useActionsFit(fit, row, lead, end) {
|
|
207
|
+
const [widths] = useState(() => /* @__PURE__ */ new Map());
|
|
208
|
+
useLayoutEffect(() => {
|
|
209
|
+
if (!row || !lead || !end) {
|
|
210
|
+
fit.setOverflow([]);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const measure = () => {
|
|
214
|
+
const rowWidth = row.clientWidth;
|
|
215
|
+
if (rowWidth === 0) {
|
|
216
|
+
fit.setOverflow([]);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const folded = rowWidth < FOLD_WIDTH;
|
|
220
|
+
const key = (id, fold) => `${fold ? "folded" : "full"}:${id}`;
|
|
221
|
+
const items = [...end.querySelectorAll("[data-header-action]")].map((el) => el.dataset["headerAction"] ?? "");
|
|
222
|
+
for (const el of end.querySelectorAll("[data-header-action]")) {
|
|
223
|
+
const id = el.dataset["headerAction"] ?? "";
|
|
224
|
+
const control = el.firstElementChild;
|
|
225
|
+
if (!fit.isOverflowed(id) && control) widths.set(key(id, folded), control.getBoundingClientRect().width);
|
|
226
|
+
}
|
|
227
|
+
const width = (id) => widths.get(key(id, folded)) ?? widths.get(key(id, !folded)) ?? 0;
|
|
228
|
+
const style = getComputedStyle(row);
|
|
229
|
+
let leadMin = 0;
|
|
230
|
+
let leadItems = 0;
|
|
231
|
+
for (const child of lead.children) {
|
|
232
|
+
const w = child.tagName === "NAV" ? TRAIL_MIN_WIDTH : child.getBoundingClientRect().width;
|
|
233
|
+
if (w > 0) {
|
|
234
|
+
leadMin += w;
|
|
235
|
+
leadItems++;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
leadMin += Math.max(0, leadItems - 1) * LEAD_GAP;
|
|
239
|
+
const room = rowWidth - Number.parseFloat(style.paddingLeft || "0") - Number.parseFloat(style.paddingRight || "0") - leadMin - ROW_GAP;
|
|
240
|
+
fit.setOverflow(overflowingActions(items.map((id) => ({
|
|
241
|
+
id,
|
|
242
|
+
width: width(id)
|
|
243
|
+
})), end.getBoundingClientRect().width, items.filter((id) => fit.isOverflowed(id)), room));
|
|
244
|
+
};
|
|
245
|
+
measure();
|
|
246
|
+
const resize = new ResizeObserver(measure);
|
|
247
|
+
resize.observe(row);
|
|
248
|
+
resize.observe(end);
|
|
249
|
+
const changes = new MutationObserver(measure);
|
|
250
|
+
changes.observe(end, {
|
|
251
|
+
childList: true,
|
|
252
|
+
subtree: true
|
|
253
|
+
});
|
|
254
|
+
changes.observe(lead, { childList: true });
|
|
255
|
+
return () => {
|
|
256
|
+
resize.disconnect();
|
|
257
|
+
changes.disconnect();
|
|
258
|
+
};
|
|
259
|
+
}, [
|
|
260
|
+
fit,
|
|
261
|
+
row,
|
|
262
|
+
lead,
|
|
263
|
+
end,
|
|
264
|
+
widths
|
|
265
|
+
]);
|
|
266
|
+
}
|
|
163
267
|
//#endregion
|
|
164
268
|
export { PageHeader, PageHeaderBar, PageHeaderProvider };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ComponentType } from 'react';
|
|
2
2
|
import type { MenuEntry } from './MenuEntries.js';
|
|
3
3
|
type Target = {
|
|
4
4
|
href: string;
|
|
@@ -40,6 +40,9 @@ export type PageHeaderActionProps = Target & {
|
|
|
40
40
|
destructive?: boolean | undefined;
|
|
41
41
|
/** A toggle's state, such as a favorite: set, it reads as pressed. Buttons only. */
|
|
42
42
|
pressed?: boolean | undefined;
|
|
43
|
+
/** Busy with what it started, such as a run starting: a spinner takes the
|
|
44
|
+
* icon's place, and it keeps focus but can't be pressed again until done. */
|
|
45
|
+
loading?: boolean | undefined;
|
|
43
46
|
};
|
|
44
47
|
/**
|
|
45
48
|
* An action in the page header: a link (`href`, `external` for a new tab,
|
|
@@ -47,7 +50,7 @@ export type PageHeaderActionProps = Target & {
|
|
|
47
50
|
* button (`onClick`) or a menu (`menu`). Labeled actions read in the link
|
|
48
51
|
* color, so the page's commands stand apart from the trail.
|
|
49
52
|
*/
|
|
50
|
-
export declare function PageHeaderAction({ icon: Icon, label, ariaLabel, iconOnly, disabled, disabledReason, tooltip, destructive, pressed, ...target }: PageHeaderActionProps): import("react").JSX.Element;
|
|
53
|
+
export declare function PageHeaderAction({ icon: Icon, label, ariaLabel, iconOnly, disabled, disabledReason, tooltip, destructive, pressed, loading, ...target }: PageHeaderActionProps): import("react").JSX.Element;
|
|
51
54
|
export type PageHeaderAddButtonProps = Target & {
|
|
52
55
|
/** The full action, such as "New cluster": the tooltip and accessible name. */
|
|
53
56
|
label: string;
|
|
@@ -55,9 +58,11 @@ export type PageHeaderAddButtonProps = Target & {
|
|
|
55
58
|
word?: 'add' | 'create' | undefined;
|
|
56
59
|
disabled?: boolean | undefined;
|
|
57
60
|
disabledReason?: string | undefined;
|
|
61
|
+
/** Busy making it: a spinner takes the plus's place, and it can't be pressed again until done. */
|
|
62
|
+
loading?: boolean | undefined;
|
|
58
63
|
};
|
|
59
64
|
/** The page's "+ Add" or "+ Create": with `menu`, a chooser of what to make. */
|
|
60
|
-
export declare function PageHeaderAddButton({ label, word, disabled, disabledReason, ...target }: PageHeaderAddButtonProps): import("react").JSX.Element;
|
|
65
|
+
export declare function PageHeaderAddButton({ label, word, disabled, disabledReason, loading, ...target }: PageHeaderAddButtonProps): import("react").JSX.Element;
|
|
61
66
|
/** The "…" menu of actions on the page's subject. Renders nothing without items. */
|
|
62
67
|
export declare function PageHeaderMenu({ items, label, }: {
|
|
63
68
|
items: MenuEntry[];
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
2
|
import { buttonClasses } from "./buttonClasses.js";
|
|
3
3
|
import { AddIcon, MoreIcon } from "../icons.js";
|
|
4
|
+
import { Loader } from "./Loader.js";
|
|
4
5
|
import { Tooltip } from "./Tooltip.js";
|
|
5
6
|
import { useStrings } from "./Provider.js";
|
|
6
7
|
import { AppLink } from "./AppLink.js";
|
|
7
8
|
import { ActionMenu } from "./ActionMenu.js";
|
|
9
|
+
import { HeaderActionsFitContext } from "./headerActionsFit.js";
|
|
10
|
+
import { use, useId, useLayoutEffect, useSyncExternalStore } from "react";
|
|
8
11
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
12
|
//#region src/components/PageHeaderAction.tsx
|
|
10
13
|
/**
|
|
@@ -13,9 +16,9 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
13
16
|
* focusable (`aria-disabled`, not `disabled`), so its reason is reachable by
|
|
14
17
|
* keyboard and pointer, where a disabled button would swallow both.
|
|
15
18
|
*/
|
|
16
|
-
function HeaderControl({ name, tooltip, disabled, disabledReason, pressed, className, children, href, external, reloadDocument, onClick, menu }) {
|
|
19
|
+
function HeaderControl({ name, tooltip, disabled, disabledReason, loading = false, pressed, className, children, href, external, reloadDocument, onClick, menu }) {
|
|
17
20
|
const { common } = useStrings();
|
|
18
|
-
if (menu && !disabled) return /* @__PURE__ */ jsx(ActionMenu, {
|
|
21
|
+
if (menu && !disabled && !loading) return /* @__PURE__ */ jsx(ActionMenu, {
|
|
19
22
|
items: menu,
|
|
20
23
|
label: name,
|
|
21
24
|
triggerClassName: className,
|
|
@@ -28,7 +31,8 @@ function HeaderControl({ name, tooltip, disabled, disabledReason, pressed, class
|
|
|
28
31
|
href,
|
|
29
32
|
reloadDocument,
|
|
30
33
|
target: external ? "_blank" : void 0,
|
|
31
|
-
disabled,
|
|
34
|
+
disabled: disabled || loading,
|
|
35
|
+
"aria-busy": loading || void 0,
|
|
32
36
|
"aria-label": reason ? `${name}. ${reason}` : external ? `${name} ${common.opensInNewTab}` : name,
|
|
33
37
|
className,
|
|
34
38
|
children
|
|
@@ -38,9 +42,10 @@ function HeaderControl({ name, tooltip, disabled, disabledReason, pressed, class
|
|
|
38
42
|
content: disabled ? disabledReason ?? tooltip : tooltip,
|
|
39
43
|
children: /* @__PURE__ */ jsx("button", {
|
|
40
44
|
type: "button",
|
|
41
|
-
onClick: disabled ? void 0 : onClick,
|
|
45
|
+
onClick: disabled || loading ? void 0 : onClick,
|
|
42
46
|
"aria-label": reason ? `${name}. ${reason}` : name,
|
|
43
|
-
"aria-disabled": disabled || void 0,
|
|
47
|
+
"aria-disabled": disabled || loading || void 0,
|
|
48
|
+
"aria-busy": loading || void 0,
|
|
44
49
|
"aria-pressed": pressed,
|
|
45
50
|
className,
|
|
46
51
|
children
|
|
@@ -53,43 +58,126 @@ function HeaderControl({ name, tooltip, disabled, disabledReason, pressed, class
|
|
|
53
58
|
* button (`onClick`) or a menu (`menu`). Labeled actions read in the link
|
|
54
59
|
* color, so the page's commands stand apart from the trail.
|
|
55
60
|
*/
|
|
56
|
-
function PageHeaderAction({ icon: Icon, label, ariaLabel, iconOnly = false, disabled = false, disabledReason, tooltip, destructive = false, pressed, ...target }) {
|
|
61
|
+
function PageHeaderAction({ icon: Icon, label, ariaLabel, iconOnly = false, disabled = false, disabledReason, tooltip, destructive = false, pressed, loading = false, ...target }) {
|
|
57
62
|
const tone = destructive ? "*:text-(--theme-error-text)" : iconOnly ? void 0 : "*:text-(--theme-link)";
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
const icon = loading ? /* @__PURE__ */ jsx(Loader, {
|
|
64
|
+
inline: true,
|
|
65
|
+
decorative: true,
|
|
66
|
+
size: "1em"
|
|
67
|
+
}) : /* @__PURE__ */ jsx(Icon, {});
|
|
68
|
+
return /* @__PURE__ */ jsx(Fitted, {
|
|
69
|
+
entry: menuRow({
|
|
70
|
+
label: ariaLabel ?? label,
|
|
71
|
+
icon,
|
|
72
|
+
disabled: disabled || loading,
|
|
73
|
+
disabledReason,
|
|
74
|
+
destructive,
|
|
75
|
+
pressed,
|
|
76
|
+
target
|
|
77
|
+
}),
|
|
78
|
+
children: /* @__PURE__ */ jsxs(HeaderControl, {
|
|
79
|
+
...target,
|
|
80
|
+
name: ariaLabel ?? label,
|
|
81
|
+
tooltip: tooltip ?? label,
|
|
82
|
+
disabled,
|
|
83
|
+
disabledReason,
|
|
84
|
+
loading,
|
|
85
|
+
pressed,
|
|
86
|
+
className: cx(buttonClasses({
|
|
87
|
+
variant: "ghost",
|
|
88
|
+
size: "xs",
|
|
89
|
+
iconOnly
|
|
90
|
+
}), tone),
|
|
91
|
+
children: [icon, !iconOnly && /* @__PURE__ */ jsx("span", {
|
|
92
|
+
className: "@max-md:sr-only",
|
|
93
|
+
children: label
|
|
94
|
+
})]
|
|
95
|
+
})
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/** An action as a row of the header's "…" menu, for when the bar has no room for it. */
|
|
99
|
+
function menuRow({ label, icon, disabled, disabledReason, destructive, pressed, target }) {
|
|
100
|
+
const shared = {
|
|
101
|
+
label,
|
|
102
|
+
icon,
|
|
62
103
|
disabled,
|
|
63
104
|
disabledReason,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
105
|
+
destructive
|
|
106
|
+
};
|
|
107
|
+
if (target.menu) return disabled ? {
|
|
108
|
+
...shared,
|
|
109
|
+
onClick: () => {}
|
|
110
|
+
} : {
|
|
111
|
+
label,
|
|
112
|
+
icon,
|
|
113
|
+
items: target.menu
|
|
114
|
+
};
|
|
115
|
+
if (target.href) return {
|
|
116
|
+
...shared,
|
|
117
|
+
href: target.href,
|
|
118
|
+
reloadDocument: target.reloadDocument,
|
|
119
|
+
target: target.external ? "_blank" : void 0
|
|
120
|
+
};
|
|
121
|
+
return {
|
|
122
|
+
...shared,
|
|
123
|
+
onClick: target.onClick ?? (() => {}),
|
|
124
|
+
checked: pressed
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Lets an action in the header's `actions` move into the bar's "…" menu when
|
|
129
|
+
* the bar runs out of room: it registers its menu row, and hides while it has
|
|
130
|
+
* moved. Anywhere else, such as among the title actions, it is the action alone.
|
|
131
|
+
*/
|
|
132
|
+
function Fitted({ entry, children }) {
|
|
133
|
+
const fit = use(HeaderActionsFitContext);
|
|
134
|
+
const id = useId();
|
|
135
|
+
useLayoutEffect(() => {
|
|
136
|
+
fit?.register(id, entry);
|
|
137
|
+
});
|
|
138
|
+
useLayoutEffect(() => fit ? () => fit.unregister(id) : void 0, [fit, id]);
|
|
139
|
+
const moved = useSyncExternalStore(fit?.subscribe ?? subscribeNever, () => fit?.isOverflowed(id) ?? false, () => false);
|
|
140
|
+
if (!fit) return children;
|
|
141
|
+
return /* @__PURE__ */ jsx("span", {
|
|
142
|
+
"data-header-action": id,
|
|
143
|
+
hidden: moved,
|
|
144
|
+
className: moved ? void 0 : "contents",
|
|
145
|
+
children
|
|
74
146
|
});
|
|
75
147
|
}
|
|
148
|
+
var subscribeNever = () => () => {};
|
|
76
149
|
/** The page's "+ Add" or "+ Create": with `menu`, a chooser of what to make. */
|
|
77
|
-
function PageHeaderAddButton({ label, word = "add", disabled = false, disabledReason, ...target }) {
|
|
150
|
+
function PageHeaderAddButton({ label, word = "add", disabled = false, disabledReason, loading = false, ...target }) {
|
|
78
151
|
const { common } = useStrings();
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
152
|
+
const icon = loading ? /* @__PURE__ */ jsx(Loader, {
|
|
153
|
+
inline: true,
|
|
154
|
+
decorative: true,
|
|
155
|
+
size: "1em"
|
|
156
|
+
}) : /* @__PURE__ */ jsx(AddIcon, {});
|
|
157
|
+
return /* @__PURE__ */ jsx(Fitted, {
|
|
158
|
+
entry: menuRow({
|
|
159
|
+
label,
|
|
160
|
+
icon,
|
|
161
|
+
disabled: disabled || loading,
|
|
162
|
+
disabledReason,
|
|
163
|
+
target
|
|
88
164
|
}),
|
|
89
|
-
children:
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
165
|
+
children: /* @__PURE__ */ jsxs(HeaderControl, {
|
|
166
|
+
...target,
|
|
167
|
+
name: label,
|
|
168
|
+
tooltip: label,
|
|
169
|
+
disabled,
|
|
170
|
+
disabledReason,
|
|
171
|
+
loading,
|
|
172
|
+
className: buttonClasses({
|
|
173
|
+
variant: "outline",
|
|
174
|
+
size: "xs"
|
|
175
|
+
}),
|
|
176
|
+
children: [icon, /* @__PURE__ */ jsx("span", {
|
|
177
|
+
className: "@max-md:sr-only",
|
|
178
|
+
children: word === "create" ? common.create : common.add
|
|
179
|
+
})]
|
|
180
|
+
})
|
|
93
181
|
});
|
|
94
182
|
}
|
|
95
183
|
/** The "…" menu of actions on the page's subject. Renders nothing without items. */
|
|
@@ -20,9 +20,21 @@ export interface PaginationProps {
|
|
|
20
20
|
onPageSizeChange?: ((size: number) => void) | undefined;
|
|
21
21
|
/** Replaces "1–50 of 200", such as with the time range a page covers. */
|
|
22
22
|
summary?: ReactNode;
|
|
23
|
+
/** Numbers the pages between previous and next, for a list a reader jumps
|
|
24
|
+
* around in, such as a catalog: the first and last, and a window around
|
|
25
|
+
* the current one, with gaps between. `max` is how many steps show at
|
|
26
|
+
* most, gaps included (7 by default, 5 at least). Needs a `total`; hidden
|
|
27
|
+
* on a phone-width screen, where previous and next remain. */
|
|
28
|
+
pageNumbers?: boolean | {
|
|
29
|
+
max?: number | undefined;
|
|
30
|
+
} | undefined;
|
|
23
31
|
className?: string | undefined;
|
|
24
32
|
}
|
|
33
|
+
/** The pages to number, counting from 0, with `null` for a gap: all of them
|
|
34
|
+
* when they fit in `max` steps, and otherwise the first and last around a
|
|
35
|
+
* window on the current one, `max` steps in all. */
|
|
36
|
+
export declare function pageSteps(page: number, count: number, max?: number): (number | null)[];
|
|
25
37
|
/** Steps through a list a page at a time: where the page sits in the list,
|
|
26
38
|
* previous and next, and optionally how many rows a page holds. Renders
|
|
27
39
|
* nothing when everything fits on one page. */
|
|
28
|
-
export declare function Pagination({ page, pageSize, total, hasNext, onPageChange, pageHref, pageSizes, onPageSizeChange, summary, className, }: PaginationProps): import("react").JSX.Element | null;
|
|
40
|
+
export declare function Pagination({ page, pageSize, total, hasNext, onPageChange, pageHref, pageSizes, onPageSizeChange, summary, pageNumbers, className, }: PaginationProps): import("react").JSX.Element | null;
|