@hoardodile/ui 0.0.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/LICENSE +18 -0
- package/README.md +70 -0
- package/dist/components/alert.d.ts +13 -0
- package/dist/components/alert.js +97 -0
- package/dist/components/alert.js.map +1 -0
- package/dist/components/app-dialog.d.ts +62 -0
- package/dist/components/app-dialog.js +656 -0
- package/dist/components/app-dialog.js.map +1 -0
- package/dist/components/badge.d.ts +11 -0
- package/dist/components/badge.js +70 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/breadcrumb.d.ts +12 -0
- package/dist/components/breadcrumb.js +617 -0
- package/dist/components/breadcrumb.js.map +1 -0
- package/dist/components/button.d.ts +17 -0
- package/dist/components/button.js +78 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/caption-bar.d.ts +44 -0
- package/dist/components/caption-bar.js +827 -0
- package/dist/components/caption-bar.js.map +1 -0
- package/dist/components/chart-card.d.ts +15 -0
- package/dist/components/chart-card.js +27 -0
- package/dist/components/chart-card.js.map +1 -0
- package/dist/components/checkbox.d.ts +6 -0
- package/dist/components/checkbox.js +76 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/chip-button.d.ts +28 -0
- package/dist/components/chip-button.js +87 -0
- package/dist/components/chip-button.js.map +1 -0
- package/dist/components/close-confirm-dialog.d.ts +19 -0
- package/dist/components/close-confirm-dialog.js +743 -0
- package/dist/components/close-confirm-dialog.js.map +1 -0
- package/dist/components/color-picker.d.ts +32 -0
- package/dist/components/color-picker.js +667 -0
- package/dist/components/color-picker.js.map +1 -0
- package/dist/components/combobox.d.ts +32 -0
- package/dist/components/combobox.js +1211 -0
- package/dist/components/combobox.js.map +1 -0
- package/dist/components/confirm-by-typing-dialog.d.ts +48 -0
- package/dist/components/confirm-by-typing-dialog.js +759 -0
- package/dist/components/confirm-by-typing-dialog.js.map +1 -0
- package/dist/components/confirm-dialog.d.ts +34 -0
- package/dist/components/confirm-dialog.js +710 -0
- package/dist/components/confirm-dialog.js.map +1 -0
- package/dist/components/count-badge.d.ts +13 -0
- package/dist/components/count-badge.js +39 -0
- package/dist/components/count-badge.js.map +1 -0
- package/dist/components/dialog.d.ts +40 -0
- package/dist/components/dialog.js +571 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/dropdown-menu.d.ts +45 -0
- package/dist/components/dropdown-menu.js +1003 -0
- package/dist/components/dropdown-menu.js.map +1 -0
- package/dist/components/dropdown-select.d.ts +29 -0
- package/dist/components/dropdown-select.js +1036 -0
- package/dist/components/dropdown-select.js.map +1 -0
- package/dist/components/empty.d.ts +15 -0
- package/dist/components/empty.js +119 -0
- package/dist/components/empty.js.map +1 -0
- package/dist/components/filter-rail.d.ts +48 -0
- package/dist/components/filter-rail.js +231 -0
- package/dist/components/filter-rail.js.map +1 -0
- package/dist/components/fixed-action-bar.d.ts +24 -0
- package/dist/components/fixed-action-bar.js +48 -0
- package/dist/components/fixed-action-bar.js.map +1 -0
- package/dist/components/font-picker.d.ts +45 -0
- package/dist/components/font-picker.js +759 -0
- package/dist/components/font-picker.js.map +1 -0
- package/dist/components/form.d.ts +17 -0
- package/dist/components/form.js +150 -0
- package/dist/components/form.js.map +1 -0
- package/dist/components/group-label.d.ts +12 -0
- package/dist/components/group-label.js +10 -0
- package/dist/components/group-label.js.map +1 -0
- package/dist/components/icon-tile.d.ts +16 -0
- package/dist/components/icon-tile.js +67 -0
- package/dist/components/icon-tile.js.map +1 -0
- package/dist/components/icon-toggle.d.ts +24 -0
- package/dist/components/icon-toggle.js +81 -0
- package/dist/components/icon-toggle.js.map +1 -0
- package/dist/components/icon.d.ts +2 -0
- package/dist/components/icon.js +49 -0
- package/dist/components/icon.js.map +1 -0
- package/dist/components/image-crop-panel.d.ts +80 -0
- package/dist/components/image-crop-panel.js +1104 -0
- package/dist/components/image-crop-panel.js.map +1 -0
- package/dist/components/image-cropper.d.ts +63 -0
- package/dist/components/image-cropper.js +166 -0
- package/dist/components/image-cropper.js.map +1 -0
- package/dist/components/input-group.d.ts +22 -0
- package/dist/components/input-group.js +270 -0
- package/dist/components/input-group.js.map +1 -0
- package/dist/components/input.d.ts +16 -0
- package/dist/components/input.js +60 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/label.d.ts +5 -0
- package/dist/components/label.js +40 -0
- package/dist/components/label.js.map +1 -0
- package/dist/components/list-empty-row.d.ts +16 -0
- package/dist/components/list-empty-row.js +40 -0
- package/dist/components/list-empty-row.js.map +1 -0
- package/dist/components/management-empty.d.ts +14 -0
- package/dist/components/management-empty.js +40 -0
- package/dist/components/management-empty.js.map +1 -0
- package/dist/components/management-skeleton.d.ts +11 -0
- package/dist/components/management-skeleton.js +72 -0
- package/dist/components/management-skeleton.js.map +1 -0
- package/dist/components/meta-chip.d.ts +17 -0
- package/dist/components/meta-chip.js +49 -0
- package/dist/components/meta-chip.js.map +1 -0
- package/dist/components/mobile-drawer.d.ts +29 -0
- package/dist/components/mobile-drawer.js +331 -0
- package/dist/components/mobile-drawer.js.map +1 -0
- package/dist/components/page-header.d.ts +20 -0
- package/dist/components/page-header.js +44 -0
- package/dist/components/page-header.js.map +1 -0
- package/dist/components/page-scaffold.d.ts +34 -0
- package/dist/components/page-scaffold.js +157 -0
- package/dist/components/page-scaffold.js.map +1 -0
- package/dist/components/pagination-bar.d.ts +22 -0
- package/dist/components/pagination-bar.js +703 -0
- package/dist/components/pagination-bar.js.map +1 -0
- package/dist/components/pagination.d.ts +22 -0
- package/dist/components/pagination.js +680 -0
- package/dist/components/pagination.js.map +1 -0
- package/dist/components/panel-toolbar.d.ts +37 -0
- package/dist/components/panel-toolbar.js +781 -0
- package/dist/components/panel-toolbar.js.map +1 -0
- package/dist/components/pill-tabs.d.ts +33 -0
- package/dist/components/pill-tabs.js +66 -0
- package/dist/components/pill-tabs.js.map +1 -0
- package/dist/components/plugin-download-consent.d.ts +52 -0
- package/dist/components/plugin-download-consent.js +780 -0
- package/dist/components/plugin-download-consent.js.map +1 -0
- package/dist/components/popover.d.ts +26 -0
- package/dist/components/popover.js +343 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/progress.d.ts +10 -0
- package/dist/components/progress.js +103 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/query-state-view.d.ts +36 -0
- package/dist/components/query-state-view.js +17 -0
- package/dist/components/query-state-view.js.map +1 -0
- package/dist/components/radio-group.d.ts +8 -0
- package/dist/components/radio-group.js +60 -0
- package/dist/components/radio-group.js.map +1 -0
- package/dist/components/scroll-area.d.ts +7 -0
- package/dist/components/scroll-area.js +80 -0
- package/dist/components/scroll-area.js.map +1 -0
- package/dist/components/search-field.d.ts +49 -0
- package/dist/components/search-field.js +586 -0
- package/dist/components/search-field.js.map +1 -0
- package/dist/components/secondary-stat.d.ts +13 -0
- package/dist/components/secondary-stat.js +56 -0
- package/dist/components/secondary-stat.js.map +1 -0
- package/dist/components/section-header.d.ts +23 -0
- package/dist/components/section-header.js +76 -0
- package/dist/components/section-header.js.map +1 -0
- package/dist/components/section-label.d.ts +20 -0
- package/dist/components/section-label.js +46 -0
- package/dist/components/section-label.js.map +1 -0
- package/dist/components/section-tabs.d.ts +47 -0
- package/dist/components/section-tabs.js +145 -0
- package/dist/components/section-tabs.js.map +1 -0
- package/dist/components/separator.d.ts +14 -0
- package/dist/components/separator.js +49 -0
- package/dist/components/separator.js.map +1 -0
- package/dist/components/sheet.d.ts +22 -0
- package/dist/components/sheet.js +469 -0
- package/dist/components/sheet.js.map +1 -0
- package/dist/components/sidebar.d.ts +69 -0
- package/dist/components/sidebar.js +1645 -0
- package/dist/components/sidebar.js.map +1 -0
- package/dist/components/skeleton.d.ts +8 -0
- package/dist/components/skeleton.js +41 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/slider.d.ts +6 -0
- package/dist/components/slider.js +75 -0
- package/dist/components/slider.js.map +1 -0
- package/dist/components/sortable-chip-list.d.ts +26 -0
- package/dist/components/sortable-chip-list.js +59 -0
- package/dist/components/sortable-chip-list.js.map +1 -0
- package/dist/components/spinner.d.ts +5 -0
- package/dist/components/spinner.js +65 -0
- package/dist/components/spinner.js.map +1 -0
- package/dist/components/surface.d.ts +13 -0
- package/dist/components/surface.js +51 -0
- package/dist/components/surface.js.map +1 -0
- package/dist/components/switch.d.ts +8 -0
- package/dist/components/switch.js +53 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/table.d.ts +12 -0
- package/dist/components/table.js +129 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/textarea.d.ts +15 -0
- package/dist/components/textarea.js +58 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/toast.d.ts +19 -0
- package/dist/components/toast.js +805 -0
- package/dist/components/toast.js.map +1 -0
- package/dist/components/toggle.d.ts +12 -0
- package/dist/components/toggle.js +63 -0
- package/dist/components/toggle.js.map +1 -0
- package/dist/components/tooltip.d.ts +9 -0
- package/dist/components/tooltip.js +82 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/hooks/use-dialog-footer-actions.d.ts +18 -0
- package/dist/hooks/use-dialog-footer-actions.js +11 -0
- package/dist/hooks/use-dialog-footer-actions.js.map +1 -0
- package/dist/hooks/use-form-field.d.ts +33 -0
- package/dist/hooks/use-form-field.js +36 -0
- package/dist/hooks/use-form-field.js.map +1 -0
- package/dist/hooks/use-mobile.d.ts +34 -0
- package/dist/hooks/use-mobile.js +29 -0
- package/dist/hooks/use-mobile.js.map +1 -0
- package/dist/hooks/use-pinch-pan.d.ts +56 -0
- package/dist/hooks/use-pinch-pan.js +223 -0
- package/dist/hooks/use-pinch-pan.js.map +1 -0
- package/dist/hooks/useMobileBackToClose.d.ts +61 -0
- package/dist/hooks/useMobileBackToClose.js +234 -0
- package/dist/hooks/useMobileBackToClose.js.map +1 -0
- package/dist/icon-BOgL5bpL.d.ts +85 -0
- package/dist/icons/actions.d.ts +4 -0
- package/dist/icons/actions.js +520 -0
- package/dist/icons/actions.js.map +1 -0
- package/dist/icons/icon-style.d.ts +2 -0
- package/dist/icons/icon-style.js +51 -0
- package/dist/icons/icon-style.js.map +1 -0
- package/dist/icons/marks.d.ts +15 -0
- package/dist/icons/marks.js +48 -0
- package/dist/icons/marks.js.map +1 -0
- package/dist/icons/registry.d.ts +177 -0
- package/dist/icons/registry.js +1180 -0
- package/dist/icons/registry.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +653 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/merge-config.d.ts +15 -0
- package/dist/lib/merge-config.js +20 -0
- package/dist/lib/merge-config.js.map +1 -0
- package/dist/lib/pagination.d.ts +19 -0
- package/dist/lib/pagination.js +26 -0
- package/dist/lib/pagination.js.map +1 -0
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.js +26 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/styles/theme.css +480 -0
- package/dist/styles/theme.css.map +1 -0
- package/dist/styles/theme.d.ts +2 -0
- package/dist/viewport.d.ts +64 -0
- package/dist/viewport.js +13 -0
- package/dist/viewport.js.map +1 -0
- package/package.json +122 -0
- package/src/components/alert.tsx +76 -0
- package/src/components/app-dialog.tsx +187 -0
- package/src/components/badge.tsx +52 -0
- package/src/components/breadcrumb.tsx +129 -0
- package/src/components/button.tsx +70 -0
- package/src/components/caption-bar.test.tsx +151 -0
- package/src/components/caption-bar.tsx +392 -0
- package/src/components/chart-card.tsx +31 -0
- package/src/components/checkbox.tsx +28 -0
- package/src/components/chip-button.tsx +69 -0
- package/src/components/close-confirm-dialog.tsx +99 -0
- package/src/components/color-picker.tsx +186 -0
- package/src/components/combobox.tsx +335 -0
- package/src/components/confirm-by-typing-dialog.tsx +130 -0
- package/src/components/confirm-dialog.test.tsx +39 -0
- package/src/components/confirm-dialog.tsx +98 -0
- package/src/components/count-badge.tsx +23 -0
- package/src/components/dialog.tsx +315 -0
- package/src/components/dropdown-menu.tsx +311 -0
- package/src/components/dropdown-select.tsx +211 -0
- package/src/components/empty.tsx +104 -0
- package/src/components/filter-rail.tsx +139 -0
- package/src/components/fixed-action-bar.tsx +46 -0
- package/src/components/font-picker.tsx +257 -0
- package/src/components/form.tsx +127 -0
- package/src/components/group-label.tsx +13 -0
- package/src/components/icon-tile.tsx +35 -0
- package/src/components/icon-toggle.tsx +57 -0
- package/src/components/icon.tsx +66 -0
- package/src/components/image-crop-panel.test.tsx +167 -0
- package/src/components/image-crop-panel.tsx +465 -0
- package/src/components/image-cropper.test.tsx +144 -0
- package/src/components/image-cropper.tsx +265 -0
- package/src/components/input-group.tsx +156 -0
- package/src/components/input.tsx +45 -0
- package/src/components/label.tsx +20 -0
- package/src/components/list-empty-row.tsx +27 -0
- package/src/components/management-empty.tsx +25 -0
- package/src/components/management-skeleton.tsx +23 -0
- package/src/components/meta-chip.tsx +40 -0
- package/src/components/mobile-drawer.test.tsx +52 -0
- package/src/components/mobile-drawer.tsx +98 -0
- package/src/components/page-header.tsx +47 -0
- package/src/components/page-scaffold.test.tsx +24 -0
- package/src/components/page-scaffold.tsx +131 -0
- package/src/components/pagination-bar.test.tsx +87 -0
- package/src/components/pagination-bar.tsx +139 -0
- package/src/components/pagination.tsx +139 -0
- package/src/components/panel-toolbar.tsx +99 -0
- package/src/components/pill-tabs.test.tsx +84 -0
- package/src/components/pill-tabs.tsx +77 -0
- package/src/components/plugin-download-consent.test.tsx +90 -0
- package/src/components/plugin-download-consent.tsx +183 -0
- package/src/components/popover.tsx +133 -0
- package/src/components/progress.tsx +88 -0
- package/src/components/query-state-view.tsx +47 -0
- package/src/components/radio-group.tsx +36 -0
- package/src/components/scroll-area.tsx +52 -0
- package/src/components/search-field.test.tsx +86 -0
- package/src/components/search-field.tsx +119 -0
- package/src/components/secondary-stat.tsx +24 -0
- package/src/components/section-header.tsx +54 -0
- package/src/components/section-label.tsx +40 -0
- package/src/components/section-tabs.test.tsx +154 -0
- package/src/components/section-tabs.tsx +190 -0
- package/src/components/separator.tsx +38 -0
- package/src/components/sheet.tsx +170 -0
- package/src/components/sidebar.tsx +725 -0
- package/src/components/skeleton.tsx +18 -0
- package/src/components/slider.tsx +52 -0
- package/src/components/sortable-chip-list.tsx +56 -0
- package/src/components/spinner.tsx +35 -0
- package/src/components/surface.tsx +37 -0
- package/src/components/switch.tsx +30 -0
- package/src/components/table.tsx +116 -0
- package/src/components/textarea.tsx +41 -0
- package/src/components/toast.tsx +239 -0
- package/src/components/toggle.tsx +45 -0
- package/src/components/tooltip.tsx +64 -0
- package/src/hooks/use-dialog-footer-actions.ts +23 -0
- package/src/hooks/use-form-field.ts +62 -0
- package/src/hooks/use-mobile.ts +54 -0
- package/src/hooks/use-pinch-pan.test.tsx +42 -0
- package/src/hooks/use-pinch-pan.ts +340 -0
- package/src/hooks/useMobileBackToClose.test.tsx +140 -0
- package/src/hooks/useMobileBackToClose.ts +508 -0
- package/src/icons/actions.ts +10 -0
- package/src/icons/icon-style.test.tsx +69 -0
- package/src/icons/icon-style.ts +104 -0
- package/src/icons/marks.tsx +72 -0
- package/src/icons/registry.test.ts +65 -0
- package/src/icons/registry.ts +1163 -0
- package/src/index.ts +22 -0
- package/src/lib/merge-config.test.ts +109 -0
- package/src/lib/merge-config.ts +22 -0
- package/src/lib/pagination.test.ts +55 -0
- package/src/lib/pagination.ts +42 -0
- package/src/lib/utils.ts +6 -0
- package/src/styles/scan-contract.test.ts +74 -0
- package/src/styles/theme.css +798 -0
- package/src/test/i18n.tsx +22 -0
- package/src/test/setup.ts +104 -0
- package/src/viewport.ts +69 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import { extendTailwindMerge } from 'tailwind-merge';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/lib/utils.ts
|
|
6
|
+
var mergeTheme = {
|
|
7
|
+
text: ["tiny", "ui", "doc", "doc-title", "doc-heading", "quote"],
|
|
8
|
+
spacing: ["chip", "control", "nav", "sidebar", "panel"],
|
|
9
|
+
tracking: ["label"],
|
|
10
|
+
shadow: ["card", "dialog"],
|
|
11
|
+
container: ["reading", "medium", "content"],
|
|
12
|
+
font: ["doc", "heading"],
|
|
13
|
+
ease: ["standard"],
|
|
14
|
+
animate: ["skel", "pop"]
|
|
15
|
+
};
|
|
16
|
+
var twMerge = extendTailwindMerge({
|
|
17
|
+
extend: { theme: mergeTheme }
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// src/lib/utils.ts
|
|
21
|
+
function cn(...inputs) {
|
|
22
|
+
return twMerge(clsx(inputs));
|
|
23
|
+
}
|
|
24
|
+
function PageHeader(props) {
|
|
25
|
+
const { title, count, description, actions, className } = props;
|
|
26
|
+
return /* @__PURE__ */ jsxs("header", { className: cn("mb-6", className), children: [
|
|
27
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-end justify-between gap-x-6 gap-y-3", children: [
|
|
28
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-baseline gap-3", children: [
|
|
29
|
+
title !== void 0 ? /* @__PURE__ */ jsx("h1", { className: "text-doc-heading font-bold text-foreground", children: title }) : null,
|
|
30
|
+
count !== void 0 ? /* @__PURE__ */ jsx("span", { className: "text-ui text-muted-foreground", children: count }) : null
|
|
31
|
+
] }),
|
|
32
|
+
actions !== void 0 ? (
|
|
33
|
+
// `ml-auto` keeps a wrapped actions line right-aligned on
|
|
34
|
+
// narrow viewports, matching the same-line justify-between.
|
|
35
|
+
/* @__PURE__ */ jsx("div", { className: "ml-auto flex shrink-0 flex-wrap items-center gap-4 pb-1", children: actions })
|
|
36
|
+
) : null
|
|
37
|
+
] }),
|
|
38
|
+
description !== void 0 ? /* @__PURE__ */ jsx("p", { className: "mt-2 text-ui text-muted-foreground", children: description }) : null
|
|
39
|
+
] });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { PageHeader };
|
|
43
|
+
//# sourceMappingURL=page-header.js.map
|
|
44
|
+
//# sourceMappingURL=page-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/merge-config.ts","../../src/lib/utils.ts","../../src/components/page-header.tsx"],"names":[],"mappings":";;;;;AAQO,IAAM,UAAA,GAAa;AAAA,EACzB,MAAM,CAAC,MAAA,EAAQ,MAAM,KAAA,EAAO,WAAA,EAAa,eAAe,OAAO,CAAA;AAAA,EAC/D,SAAS,CAAC,MAAA,EAAQ,SAAA,EAAW,KAAA,EAAO,WAAW,OAAO,CAAA;AAAA,EACtD,QAAA,EAAU,CAAC,OAAO,CAAA;AAAA,EAClB,MAAA,EAAQ,CAAC,MAAA,EAAQ,QAAQ,CAAA;AAAA,EACzB,SAAA,EAAW,CAAC,SAAA,EAAW,QAAA,EAAU,SAAS,CAAA;AAAA,EAC1C,IAAA,EAAM,CAAC,KAAA,EAAO,SAAS,CAAA;AAAA,EACvB,IAAA,EAAM,CAAC,UAAU,CAAA;AAAA,EACjB,OAAA,EAAS,CAAC,MAAA,EAAQ,KAAK;AACxB,CAAA;AAEO,IAAM,UAAU,mBAAA,CAAoB;AAAA,EAC1C,MAAA,EAAQ,EAAE,KAAA,EAAO,UAAA;AAClB,CAAC,CAAA;;;AClBM,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACaO,SAAS,WAAW,KAAA,EAAwB;AAClD,EAAA,MAAM,EAAE,KAAA,EAAO,KAAA,EAAO,WAAA,EAAa,OAAA,EAAS,WAAU,GAAI,KAAA;AAC1D,EAAA,4BACE,QAAA,EAAA,EAAO,SAAA,EAAW,EAAA,CAAG,MAAA,EAAQ,SAAS,CAAA,EACtC,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,0DAAA,EACd,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,mCAAA,EACb,QAAA,EAAA;AAAA,QAAA,KAAA,KAAU,yBACV,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,4CAAA,EACZ,iBACF,CAAA,GACG,IAAA;AAAA,QACH,UAAU,MAAA,mBACV,GAAA,CAAC,UAAK,SAAA,EAAU,+BAAA,EAAiC,iBAAM,CAAA,GACpD;AAAA,OAAA,EACL,CAAA;AAAA,MACC,OAAA,KAAY,MAAA;AAAA;AAAA;AAAA,wBAGZ,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yDAAA,EACb,QAAA,EAAA,OAAA,EACF;AAAA,UACG;AAAA,KAAA,EACL,CAAA;AAAA,IACC,gBAAgB,MAAA,mBAChB,GAAA,CAAC,OAAE,SAAA,EAAU,oCAAA,EAAsC,uBAAY,CAAA,GAC5D;AAAA,GAAA,EACL,CAAA;AAEF","file":"page-header.js","sourcesContent":["import { extendTailwindMerge } from \"tailwind-merge\"\n\n// The app's `@theme inline` tokens (theme.css) generate utility names\n// tailwind-merge doesn't know, so it misclassifies them — e.g. `text-ui` is\n// parsed as a text color and dropped next to any `text-*` color. The default\n// class groups are theme-backed, so extending the theme (keys mirror the v4\n// token namespaces one-to-one) registers every custom utility with correct\n// conflict semantics. merge-config.test.ts pins this list against theme.css.\nexport const mergeTheme = {\n\ttext: [\"tiny\", \"ui\", \"doc\", \"doc-title\", \"doc-heading\", \"quote\"],\n\tspacing: [\"chip\", \"control\", \"nav\", \"sidebar\", \"panel\"],\n\ttracking: [\"label\"],\n\tshadow: [\"card\", \"dialog\"],\n\tcontainer: [\"reading\", \"medium\", \"content\"],\n\tfont: [\"doc\", \"heading\"],\n\tease: [\"standard\"],\n\tanimate: [\"skel\", \"pop\"],\n} as const\n\nexport const twMerge = extendTailwindMerge({\n\textend: { theme: mergeTheme },\n})\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"./merge-config\"\n\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs))\n}\n","import { cn } from \"@hoardodile/ui/lib/utils\"\nimport type { ReactNode } from \"react\"\n\ntype PageHeaderProps = {\n\treadonly title?: ReactNode\n\t/** Muted total on the title baseline (e.g. the item count). */\n\treadonly count?: string\n\treadonly description?: ReactNode\n\treadonly actions?: ReactNode\n\treadonly className?: string\n}\n\n/**\n * Page header — 28px bold title with the total count muted on its baseline,\n * optional muted description below, page actions on the right. The literary\n * serif (font-doc) is scoped to the documents section; chrome and index\n * pages speak in the app sans.\n */\nexport function PageHeader(props: PageHeaderProps) {\n\tconst { title, count, description, actions, className } = props\n\treturn (\n\t\t<header className={cn(\"mb-6\", className)}>\n\t\t\t<div className=\"flex flex-wrap items-end justify-between gap-x-6 gap-y-3\">\n\t\t\t\t<div className=\"flex min-w-0 items-baseline gap-3\">\n\t\t\t\t\t{title !== undefined ? (\n\t\t\t\t\t\t<h1 className=\"text-doc-heading font-bold text-foreground\">\n\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t</h1>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{count !== undefined ? (\n\t\t\t\t\t\t<span className=\"text-ui text-muted-foreground\">{count}</span>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t\t{actions !== undefined ? (\n\t\t\t\t\t// `ml-auto` keeps a wrapped actions line right-aligned on\n\t\t\t\t\t// narrow viewports, matching the same-line justify-between.\n\t\t\t\t\t<div className=\"ml-auto flex shrink-0 flex-wrap items-center gap-4 pb-1\">\n\t\t\t\t\t\t{actions}\n\t\t\t\t\t</div>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t{description !== undefined ? (\n\t\t\t\t<p className=\"mt-2 text-ui text-muted-foreground\">{description}</p>\n\t\t\t) : null}\n\t\t</header>\n\t)\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/** Content widths (DESIGN.md — Layout): the three fixed measures
|
|
5
|
+
index/detail pages are held to, centered beyond them. The measure is
|
|
6
|
+
the content width — padding never counts toward it (DESIGN.md),
|
|
7
|
+
so it lives on the outer wrapper, not on the measure element. Desktop
|
|
8
|
+
padding is `px-10 pt-10 pb-16`; mobile
|
|
9
|
+
and tablet keep their own tighter gutters. */
|
|
10
|
+
type PageScaffoldWidth = "reading" | "medium" | "content";
|
|
11
|
+
type PageScaffoldProps = {
|
|
12
|
+
readonly children: ReactNode;
|
|
13
|
+
/** Center the page at one of the three content measures; omitted when
|
|
14
|
+
the page's own component owns the measure. */
|
|
15
|
+
readonly width?: PageScaffoldWidth;
|
|
16
|
+
/** Drop the desktop bottom padding — pages ending in a sticky ActionBar. */
|
|
17
|
+
readonly bottomPad?: boolean;
|
|
18
|
+
readonly className?: string;
|
|
19
|
+
};
|
|
20
|
+
declare function PageScaffold(props: PageScaffoldProps): React.JSX.Element;
|
|
21
|
+
type SurfaceProps = {
|
|
22
|
+
readonly children: ReactNode;
|
|
23
|
+
readonly className?: string;
|
|
24
|
+
};
|
|
25
|
+
declare function FlatSurface(props: SurfaceProps): React.JSX.Element;
|
|
26
|
+
type PillProps = {
|
|
27
|
+
readonly children: ReactNode;
|
|
28
|
+
readonly tone?: "primary" | "secondary" | "accent" | "muted";
|
|
29
|
+
readonly className?: string;
|
|
30
|
+
};
|
|
31
|
+
declare function InfoPill(props: PillProps): React.JSX.Element;
|
|
32
|
+
declare function RoutePendingFallback(): React.JSX.Element;
|
|
33
|
+
|
|
34
|
+
export { FlatSurface, InfoPill, PageScaffold, type PageScaffoldWidth, RoutePendingFallback };
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import { extendTailwindMerge } from 'tailwind-merge';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/lib/utils.ts
|
|
6
|
+
var mergeTheme = {
|
|
7
|
+
text: ["tiny", "ui", "doc", "doc-title", "doc-heading", "quote"],
|
|
8
|
+
spacing: ["chip", "control", "nav", "sidebar", "panel"],
|
|
9
|
+
tracking: ["label"],
|
|
10
|
+
shadow: ["card", "dialog"],
|
|
11
|
+
container: ["reading", "medium", "content"],
|
|
12
|
+
font: ["doc", "heading"],
|
|
13
|
+
ease: ["standard"],
|
|
14
|
+
animate: ["skel", "pop"]
|
|
15
|
+
};
|
|
16
|
+
var twMerge = extendTailwindMerge({
|
|
17
|
+
extend: { theme: mergeTheme }
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// src/lib/utils.ts
|
|
21
|
+
function cn(...inputs) {
|
|
22
|
+
return twMerge(clsx(inputs));
|
|
23
|
+
}
|
|
24
|
+
function Skeleton({
|
|
25
|
+
className,
|
|
26
|
+
element: Element = "div",
|
|
27
|
+
...props
|
|
28
|
+
}) {
|
|
29
|
+
return /* @__PURE__ */ jsx(
|
|
30
|
+
Element,
|
|
31
|
+
{
|
|
32
|
+
"data-slot": "skeleton",
|
|
33
|
+
className: cn("animate-pulse rounded-md bg-muted", className),
|
|
34
|
+
...props
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
function Surface({
|
|
39
|
+
as,
|
|
40
|
+
size = "default",
|
|
41
|
+
tone = "flat",
|
|
42
|
+
className,
|
|
43
|
+
...props
|
|
44
|
+
}) {
|
|
45
|
+
const Component = as || "div";
|
|
46
|
+
return /* @__PURE__ */ jsx(
|
|
47
|
+
Component,
|
|
48
|
+
{
|
|
49
|
+
"data-slot": "surface",
|
|
50
|
+
"data-size": size,
|
|
51
|
+
"data-tone": tone,
|
|
52
|
+
className: cn(
|
|
53
|
+
"rounded-md border bg-card text-card-foreground",
|
|
54
|
+
size === "default" && "p-4",
|
|
55
|
+
size === "compact" && "p-2",
|
|
56
|
+
className
|
|
57
|
+
),
|
|
58
|
+
...props
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
function PageHeader(props) {
|
|
63
|
+
const { title, count, description, actions, className } = props;
|
|
64
|
+
return /* @__PURE__ */ jsxs("header", { className: cn("mb-6", className), children: [
|
|
65
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-end justify-between gap-x-6 gap-y-3", children: [
|
|
66
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-baseline gap-3", children: [
|
|
67
|
+
title !== void 0 ? /* @__PURE__ */ jsx("h1", { className: "text-doc-heading font-bold text-foreground", children: title }) : null,
|
|
68
|
+
count !== void 0 ? /* @__PURE__ */ jsx("span", { className: "text-ui text-muted-foreground", children: count }) : null
|
|
69
|
+
] }),
|
|
70
|
+
actions !== void 0 ? (
|
|
71
|
+
// `ml-auto` keeps a wrapped actions line right-aligned on
|
|
72
|
+
// narrow viewports, matching the same-line justify-between.
|
|
73
|
+
/* @__PURE__ */ jsx("div", { className: "ml-auto flex shrink-0 flex-wrap items-center gap-4 pb-1", children: actions })
|
|
74
|
+
) : null
|
|
75
|
+
] }),
|
|
76
|
+
description !== void 0 ? /* @__PURE__ */ jsx("p", { className: "mt-2 text-ui text-muted-foreground", children: description }) : null
|
|
77
|
+
] });
|
|
78
|
+
}
|
|
79
|
+
var widthClasses = {
|
|
80
|
+
reading: "max-w-reading",
|
|
81
|
+
medium: "max-w-medium",
|
|
82
|
+
content: "max-w-content"
|
|
83
|
+
};
|
|
84
|
+
function frameClassName(props) {
|
|
85
|
+
return cn(
|
|
86
|
+
"pb-4 pt-2 px-3 md:px-4 md:pt-4.5 lg:px-10",
|
|
87
|
+
props.bottomPad !== false && "lg:pb-16",
|
|
88
|
+
props.className
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
function PageScaffold(props) {
|
|
92
|
+
if (props.width === void 0) {
|
|
93
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex w-full flex-col", frameClassName(props)), children: props.children });
|
|
94
|
+
}
|
|
95
|
+
return /* @__PURE__ */ jsx("div", { className: frameClassName(props), children: /* @__PURE__ */ jsx(
|
|
96
|
+
"div",
|
|
97
|
+
{
|
|
98
|
+
className: cn(
|
|
99
|
+
"mx-auto flex w-full flex-col",
|
|
100
|
+
widthClasses[props.width]
|
|
101
|
+
),
|
|
102
|
+
children: props.children
|
|
103
|
+
}
|
|
104
|
+
) });
|
|
105
|
+
}
|
|
106
|
+
function FlatSurface(props) {
|
|
107
|
+
return /* @__PURE__ */ jsx(Surface, { as: "section", size: "compact", className: props.className, children: props.children });
|
|
108
|
+
}
|
|
109
|
+
function InfoPill(props) {
|
|
110
|
+
return /* @__PURE__ */ jsx(
|
|
111
|
+
"span",
|
|
112
|
+
{
|
|
113
|
+
className: cn(
|
|
114
|
+
"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium",
|
|
115
|
+
pillToneClassName(props.tone),
|
|
116
|
+
props.className
|
|
117
|
+
),
|
|
118
|
+
children: props.children
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
function RoutePendingFallback() {
|
|
123
|
+
return /* @__PURE__ */ jsxs(PageScaffold, { children: [
|
|
124
|
+
/* @__PURE__ */ jsx(
|
|
125
|
+
PageHeader,
|
|
126
|
+
{
|
|
127
|
+
title: (
|
|
128
|
+
// Span elements: the header wraps title in h1 and description
|
|
129
|
+
// in p, and a block div inside either is invalid HTML.
|
|
130
|
+
/* @__PURE__ */ jsx(Skeleton, { element: "span", className: "block h-8 w-64 max-w-full" })
|
|
131
|
+
),
|
|
132
|
+
description: /* @__PURE__ */ jsx(Skeleton, { element: "span", className: "block h-4 w-full max-w-lg" })
|
|
133
|
+
}
|
|
134
|
+
),
|
|
135
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-4 md:grid-cols-2 xl:grid-cols-3", children: [
|
|
136
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-32 rounded-lg" }),
|
|
137
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-32 rounded-lg" }),
|
|
138
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-32 rounded-lg md:col-span-2 xl:col-span-1" })
|
|
139
|
+
] })
|
|
140
|
+
] });
|
|
141
|
+
}
|
|
142
|
+
function pillToneClassName(tone) {
|
|
143
|
+
if (tone === "primary") {
|
|
144
|
+
return "bg-primary/10 text-primary";
|
|
145
|
+
}
|
|
146
|
+
if (tone === "secondary") {
|
|
147
|
+
return "bg-secondary text-secondary-foreground";
|
|
148
|
+
}
|
|
149
|
+
if (tone === "accent") {
|
|
150
|
+
return "bg-accent text-accent-foreground";
|
|
151
|
+
}
|
|
152
|
+
return "bg-muted text-muted-foreground";
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export { FlatSurface, InfoPill, PageScaffold, RoutePendingFallback };
|
|
156
|
+
//# sourceMappingURL=page-scaffold.js.map
|
|
157
|
+
//# sourceMappingURL=page-scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/merge-config.ts","../../src/lib/utils.ts","../../src/components/skeleton.tsx","../../src/components/surface.tsx","../../src/components/page-header.tsx","../../src/components/page-scaffold.tsx"],"names":["jsx","jsxs"],"mappings":"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","file":"page-scaffold.js","sourcesContent":["import { extendTailwindMerge } from \"tailwind-merge\"\n\n// The app's `@theme inline` tokens (theme.css) generate utility names\n// tailwind-merge doesn't know, so it misclassifies them — e.g. `text-ui` is\n// parsed as a text color and dropped next to any `text-*` color. The default\n// class groups are theme-backed, so extending the theme (keys mirror the v4\n// token namespaces one-to-one) registers every custom utility with correct\n// conflict semantics. merge-config.test.ts pins this list against theme.css.\nexport const mergeTheme = {\n\ttext: [\"tiny\", \"ui\", \"doc\", \"doc-title\", \"doc-heading\", \"quote\"],\n\tspacing: [\"chip\", \"control\", \"nav\", \"sidebar\", \"panel\"],\n\ttracking: [\"label\"],\n\tshadow: [\"card\", \"dialog\"],\n\tcontainer: [\"reading\", \"medium\", \"content\"],\n\tfont: [\"doc\", \"heading\"],\n\tease: [\"standard\"],\n\tanimate: [\"skel\", \"pop\"],\n} as const\n\nexport const twMerge = extendTailwindMerge({\n\textend: { theme: mergeTheme },\n})\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"./merge-config\"\n\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs))\n}\n","import { cn } from \"@hoardodile/ui/lib/utils\"\nimport type { ElementType } from \"react\"\n\nfunction Skeleton({\n className,\n element: Element = \"div\",\n ...props\n}: React.ComponentProps<\"div\"> & { readonly element?: ElementType }) {\n return (\n <Element\n data-slot=\"skeleton\"\n className={cn(\"animate-pulse rounded-md bg-muted\", className)}\n {...props}\n />\n )\n}\n\nexport { Skeleton }\n","import { cn } from \"@hoardodile/ui/lib/utils\"\nimport type * as React from \"react\"\n\ntype SurfaceProps<C extends React.ElementType = \"div\"> = {\n\tas?: C\n\tsize?: \"default\" | \"compact\"\n\t/**\n\t * Visual tone. `flat` (default) is the hairline card\n\t */\n\ttone?: \"flat\"\n} & Omit<React.ComponentPropsWithoutRef<C>, \"as\" | \"size\" | \"tone\">\n\nfunction Surface<C extends React.ElementType = \"div\">({\n\tas,\n\tsize = \"default\",\n\ttone = \"flat\",\n\tclassName,\n\t...props\n}: SurfaceProps<C>) {\n\tconst Component = as || \"div\"\n\treturn (\n\t\t<Component\n\t\t\tdata-slot=\"surface\"\n\t\t\tdata-size={size}\n\t\t\tdata-tone={tone}\n\t\t\tclassName={cn(\n\t\t\t\t\"rounded-md border bg-card text-card-foreground\",\n\t\t\t\tsize === \"default\" && \"p-4\",\n\t\t\t\tsize === \"compact\" && \"p-2\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nexport { Surface }\n","import { cn } from \"@hoardodile/ui/lib/utils\"\nimport type { ReactNode } from \"react\"\n\ntype PageHeaderProps = {\n\treadonly title?: ReactNode\n\t/** Muted total on the title baseline (e.g. the item count). */\n\treadonly count?: string\n\treadonly description?: ReactNode\n\treadonly actions?: ReactNode\n\treadonly className?: string\n}\n\n/**\n * Page header — 28px bold title with the total count muted on its baseline,\n * optional muted description below, page actions on the right. The literary\n * serif (font-doc) is scoped to the documents section; chrome and index\n * pages speak in the app sans.\n */\nexport function PageHeader(props: PageHeaderProps) {\n\tconst { title, count, description, actions, className } = props\n\treturn (\n\t\t<header className={cn(\"mb-6\", className)}>\n\t\t\t<div className=\"flex flex-wrap items-end justify-between gap-x-6 gap-y-3\">\n\t\t\t\t<div className=\"flex min-w-0 items-baseline gap-3\">\n\t\t\t\t\t{title !== undefined ? (\n\t\t\t\t\t\t<h1 className=\"text-doc-heading font-bold text-foreground\">\n\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t</h1>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{count !== undefined ? (\n\t\t\t\t\t\t<span className=\"text-ui text-muted-foreground\">{count}</span>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t\t{actions !== undefined ? (\n\t\t\t\t\t// `ml-auto` keeps a wrapped actions line right-aligned on\n\t\t\t\t\t// narrow viewports, matching the same-line justify-between.\n\t\t\t\t\t<div className=\"ml-auto flex shrink-0 flex-wrap items-center gap-4 pb-1\">\n\t\t\t\t\t\t{actions}\n\t\t\t\t\t</div>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t\t{description !== undefined ? (\n\t\t\t\t<p className=\"mt-2 text-ui text-muted-foreground\">{description}</p>\n\t\t\t) : null}\n\t\t</header>\n\t)\n}\n","import { Skeleton } from \"@hoardodile/ui/components/skeleton\"\nimport { Surface } from \"@hoardodile/ui/components/surface\"\nimport { cn } from \"@hoardodile/ui/lib/utils\"\nimport type { ReactNode } from \"react\"\nimport { PageHeader } from \"./page-header\"\n\n/** Content widths (DESIGN.md — Layout): the three fixed measures\n index/detail pages are held to, centered beyond them. The measure is\n the content width — padding never counts toward it (DESIGN.md),\n so it lives on the outer wrapper, not on the measure element. Desktop\n padding is `px-10 pt-10 pb-16`; mobile\n and tablet keep their own tighter gutters. */\nexport type PageScaffoldWidth = \"reading\" | \"medium\" | \"content\"\n\nconst widthClasses: Record<PageScaffoldWidth, string> = {\n\treading: \"max-w-reading\",\n\tmedium: \"max-w-medium\",\n\tcontent: \"max-w-content\",\n}\n\ntype PageScaffoldProps = {\n\treadonly children: ReactNode\n\t/** Center the page at one of the three content measures; omitted when\n\t the page's own component owns the measure. */\n\treadonly width?: PageScaffoldWidth\n\t/** Drop the desktop bottom padding — pages ending in a sticky ActionBar. */\n\treadonly bottomPad?: boolean\n\treadonly className?: string\n}\n\nfunction frameClassName(props: PageScaffoldProps) {\n\treturn cn(\n\t\t\"pb-4 pt-2 px-3 md:px-4 md:pt-4.5 lg:px-10\",\n\t\tprops.bottomPad !== false && \"lg:pb-16\",\n\t\tprops.className,\n\t)\n}\n\nexport function PageScaffold(props: PageScaffoldProps) {\n\tif (props.width === undefined) {\n\t\treturn (\n\t\t\t<div className={cn(\"flex w-full flex-col\", frameClassName(props))}>\n\t\t\t\t{props.children}\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div className={frameClassName(props)}>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"mx-auto flex w-full flex-col\",\n\t\t\t\t\twidthClasses[props.width],\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{props.children}\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\ntype SurfaceProps = {\n\treadonly children: ReactNode\n\treadonly className?: string\n}\n\nexport function FlatSurface(props: SurfaceProps) {\n\treturn (\n\t\t<Surface as=\"section\" size=\"compact\" className={props.className}>\n\t\t\t{props.children}\n\t\t</Surface>\n\t)\n}\n\ntype PillProps = {\n\treadonly children: ReactNode\n\treadonly tone?: \"primary\" | \"secondary\" | \"accent\" | \"muted\"\n\treadonly className?: string\n}\n\nexport function InfoPill(props: PillProps) {\n\treturn (\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"inline-flex items-center rounded-md px-2 py-1 text-xs font-medium\",\n\t\t\t\tpillToneClassName(props.tone),\n\t\t\t\tprops.className,\n\t\t\t)}\n\t\t>\n\t\t\t{props.children}\n\t\t</span>\n\t)\n}\n\nexport function RoutePendingFallback() {\n\treturn (\n\t\t<PageScaffold>\n\t\t\t<PageHeader\n\t\t\t\ttitle={\n\t\t\t\t\t// Span elements: the header wraps title in h1 and description\n\t\t\t\t\t// in p, and a block div inside either is invalid HTML.\n\t\t\t\t\t<Skeleton element=\"span\" className=\"block h-8 w-64 max-w-full\" />\n\t\t\t\t}\n\t\t\t\tdescription={\n\t\t\t\t\t<Skeleton element=\"span\" className=\"block h-4 w-full max-w-lg\" />\n\t\t\t\t}\n\t\t\t/>\n\t\t\t<div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\">\n\t\t\t\t<Skeleton className=\"h-32 rounded-lg\" />\n\t\t\t\t<Skeleton className=\"h-32 rounded-lg\" />\n\t\t\t\t<Skeleton className=\"h-32 rounded-lg md:col-span-2 xl:col-span-1\" />\n\t\t\t</div>\n\t\t</PageScaffold>\n\t)\n}\n\nfunction pillToneClassName(tone: PillProps[\"tone\"]) {\n\tif (tone === \"primary\") {\n\t\treturn \"bg-primary/10 text-primary\"\n\t}\n\n\tif (tone === \"secondary\") {\n\t\treturn \"bg-secondary text-secondary-foreground\"\n\t}\n\n\tif (tone === \"accent\") {\n\t\treturn \"bg-accent text-accent-foreground\"\n\t}\n\n\treturn \"bg-muted text-muted-foreground\"\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
type PaginationBarProps = {
|
|
4
|
+
readonly page: number;
|
|
5
|
+
readonly pageCount: number;
|
|
6
|
+
readonly onChangePage: (page: number) => void;
|
|
7
|
+
/** Result-count label rendered in the left slot (e.g. "56 messages"). */
|
|
8
|
+
readonly totalLabel: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The paginator: the result count on the left, balanced by the page-jump
|
|
12
|
+
* field on the right, and the centered row of h-control page chips —
|
|
13
|
+
* chevrons, first and last page always visible with an asymmetric window
|
|
14
|
+
* around the active page (one leading, two trailing) and ellipses for the
|
|
15
|
+
* gap (see {@link paginationWindow}). Below the md breakpoint the window
|
|
16
|
+
* collapses to a compact `page/total` chip, so narrow screens still see
|
|
17
|
+
* how many pages exist. Shared by every paged list (resources,
|
|
18
|
+
* characters, comments, stats, footprints).
|
|
19
|
+
*/
|
|
20
|
+
declare function PaginationBar(props: PaginationBarProps): React.JSX.Element;
|
|
21
|
+
|
|
22
|
+
export { PaginationBar, type PaginationBarProps };
|