@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.
Files changed (356) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +70 -0
  3. package/dist/components/alert.d.ts +13 -0
  4. package/dist/components/alert.js +97 -0
  5. package/dist/components/alert.js.map +1 -0
  6. package/dist/components/app-dialog.d.ts +62 -0
  7. package/dist/components/app-dialog.js +656 -0
  8. package/dist/components/app-dialog.js.map +1 -0
  9. package/dist/components/badge.d.ts +11 -0
  10. package/dist/components/badge.js +70 -0
  11. package/dist/components/badge.js.map +1 -0
  12. package/dist/components/breadcrumb.d.ts +12 -0
  13. package/dist/components/breadcrumb.js +617 -0
  14. package/dist/components/breadcrumb.js.map +1 -0
  15. package/dist/components/button.d.ts +17 -0
  16. package/dist/components/button.js +78 -0
  17. package/dist/components/button.js.map +1 -0
  18. package/dist/components/caption-bar.d.ts +44 -0
  19. package/dist/components/caption-bar.js +827 -0
  20. package/dist/components/caption-bar.js.map +1 -0
  21. package/dist/components/chart-card.d.ts +15 -0
  22. package/dist/components/chart-card.js +27 -0
  23. package/dist/components/chart-card.js.map +1 -0
  24. package/dist/components/checkbox.d.ts +6 -0
  25. package/dist/components/checkbox.js +76 -0
  26. package/dist/components/checkbox.js.map +1 -0
  27. package/dist/components/chip-button.d.ts +28 -0
  28. package/dist/components/chip-button.js +87 -0
  29. package/dist/components/chip-button.js.map +1 -0
  30. package/dist/components/close-confirm-dialog.d.ts +19 -0
  31. package/dist/components/close-confirm-dialog.js +743 -0
  32. package/dist/components/close-confirm-dialog.js.map +1 -0
  33. package/dist/components/color-picker.d.ts +32 -0
  34. package/dist/components/color-picker.js +667 -0
  35. package/dist/components/color-picker.js.map +1 -0
  36. package/dist/components/combobox.d.ts +32 -0
  37. package/dist/components/combobox.js +1211 -0
  38. package/dist/components/combobox.js.map +1 -0
  39. package/dist/components/confirm-by-typing-dialog.d.ts +48 -0
  40. package/dist/components/confirm-by-typing-dialog.js +759 -0
  41. package/dist/components/confirm-by-typing-dialog.js.map +1 -0
  42. package/dist/components/confirm-dialog.d.ts +34 -0
  43. package/dist/components/confirm-dialog.js +710 -0
  44. package/dist/components/confirm-dialog.js.map +1 -0
  45. package/dist/components/count-badge.d.ts +13 -0
  46. package/dist/components/count-badge.js +39 -0
  47. package/dist/components/count-badge.js.map +1 -0
  48. package/dist/components/dialog.d.ts +40 -0
  49. package/dist/components/dialog.js +571 -0
  50. package/dist/components/dialog.js.map +1 -0
  51. package/dist/components/dropdown-menu.d.ts +45 -0
  52. package/dist/components/dropdown-menu.js +1003 -0
  53. package/dist/components/dropdown-menu.js.map +1 -0
  54. package/dist/components/dropdown-select.d.ts +29 -0
  55. package/dist/components/dropdown-select.js +1036 -0
  56. package/dist/components/dropdown-select.js.map +1 -0
  57. package/dist/components/empty.d.ts +15 -0
  58. package/dist/components/empty.js +119 -0
  59. package/dist/components/empty.js.map +1 -0
  60. package/dist/components/filter-rail.d.ts +48 -0
  61. package/dist/components/filter-rail.js +231 -0
  62. package/dist/components/filter-rail.js.map +1 -0
  63. package/dist/components/fixed-action-bar.d.ts +24 -0
  64. package/dist/components/fixed-action-bar.js +48 -0
  65. package/dist/components/fixed-action-bar.js.map +1 -0
  66. package/dist/components/font-picker.d.ts +45 -0
  67. package/dist/components/font-picker.js +759 -0
  68. package/dist/components/font-picker.js.map +1 -0
  69. package/dist/components/form.d.ts +17 -0
  70. package/dist/components/form.js +150 -0
  71. package/dist/components/form.js.map +1 -0
  72. package/dist/components/group-label.d.ts +12 -0
  73. package/dist/components/group-label.js +10 -0
  74. package/dist/components/group-label.js.map +1 -0
  75. package/dist/components/icon-tile.d.ts +16 -0
  76. package/dist/components/icon-tile.js +67 -0
  77. package/dist/components/icon-tile.js.map +1 -0
  78. package/dist/components/icon-toggle.d.ts +24 -0
  79. package/dist/components/icon-toggle.js +81 -0
  80. package/dist/components/icon-toggle.js.map +1 -0
  81. package/dist/components/icon.d.ts +2 -0
  82. package/dist/components/icon.js +49 -0
  83. package/dist/components/icon.js.map +1 -0
  84. package/dist/components/image-crop-panel.d.ts +80 -0
  85. package/dist/components/image-crop-panel.js +1104 -0
  86. package/dist/components/image-crop-panel.js.map +1 -0
  87. package/dist/components/image-cropper.d.ts +63 -0
  88. package/dist/components/image-cropper.js +166 -0
  89. package/dist/components/image-cropper.js.map +1 -0
  90. package/dist/components/input-group.d.ts +22 -0
  91. package/dist/components/input-group.js +270 -0
  92. package/dist/components/input-group.js.map +1 -0
  93. package/dist/components/input.d.ts +16 -0
  94. package/dist/components/input.js +60 -0
  95. package/dist/components/input.js.map +1 -0
  96. package/dist/components/label.d.ts +5 -0
  97. package/dist/components/label.js +40 -0
  98. package/dist/components/label.js.map +1 -0
  99. package/dist/components/list-empty-row.d.ts +16 -0
  100. package/dist/components/list-empty-row.js +40 -0
  101. package/dist/components/list-empty-row.js.map +1 -0
  102. package/dist/components/management-empty.d.ts +14 -0
  103. package/dist/components/management-empty.js +40 -0
  104. package/dist/components/management-empty.js.map +1 -0
  105. package/dist/components/management-skeleton.d.ts +11 -0
  106. package/dist/components/management-skeleton.js +72 -0
  107. package/dist/components/management-skeleton.js.map +1 -0
  108. package/dist/components/meta-chip.d.ts +17 -0
  109. package/dist/components/meta-chip.js +49 -0
  110. package/dist/components/meta-chip.js.map +1 -0
  111. package/dist/components/mobile-drawer.d.ts +29 -0
  112. package/dist/components/mobile-drawer.js +331 -0
  113. package/dist/components/mobile-drawer.js.map +1 -0
  114. package/dist/components/page-header.d.ts +20 -0
  115. package/dist/components/page-header.js +44 -0
  116. package/dist/components/page-header.js.map +1 -0
  117. package/dist/components/page-scaffold.d.ts +34 -0
  118. package/dist/components/page-scaffold.js +157 -0
  119. package/dist/components/page-scaffold.js.map +1 -0
  120. package/dist/components/pagination-bar.d.ts +22 -0
  121. package/dist/components/pagination-bar.js +703 -0
  122. package/dist/components/pagination-bar.js.map +1 -0
  123. package/dist/components/pagination.d.ts +22 -0
  124. package/dist/components/pagination.js +680 -0
  125. package/dist/components/pagination.js.map +1 -0
  126. package/dist/components/panel-toolbar.d.ts +37 -0
  127. package/dist/components/panel-toolbar.js +781 -0
  128. package/dist/components/panel-toolbar.js.map +1 -0
  129. package/dist/components/pill-tabs.d.ts +33 -0
  130. package/dist/components/pill-tabs.js +66 -0
  131. package/dist/components/pill-tabs.js.map +1 -0
  132. package/dist/components/plugin-download-consent.d.ts +52 -0
  133. package/dist/components/plugin-download-consent.js +780 -0
  134. package/dist/components/plugin-download-consent.js.map +1 -0
  135. package/dist/components/popover.d.ts +26 -0
  136. package/dist/components/popover.js +343 -0
  137. package/dist/components/popover.js.map +1 -0
  138. package/dist/components/progress.d.ts +10 -0
  139. package/dist/components/progress.js +103 -0
  140. package/dist/components/progress.js.map +1 -0
  141. package/dist/components/query-state-view.d.ts +36 -0
  142. package/dist/components/query-state-view.js +17 -0
  143. package/dist/components/query-state-view.js.map +1 -0
  144. package/dist/components/radio-group.d.ts +8 -0
  145. package/dist/components/radio-group.js +60 -0
  146. package/dist/components/radio-group.js.map +1 -0
  147. package/dist/components/scroll-area.d.ts +7 -0
  148. package/dist/components/scroll-area.js +80 -0
  149. package/dist/components/scroll-area.js.map +1 -0
  150. package/dist/components/search-field.d.ts +49 -0
  151. package/dist/components/search-field.js +586 -0
  152. package/dist/components/search-field.js.map +1 -0
  153. package/dist/components/secondary-stat.d.ts +13 -0
  154. package/dist/components/secondary-stat.js +56 -0
  155. package/dist/components/secondary-stat.js.map +1 -0
  156. package/dist/components/section-header.d.ts +23 -0
  157. package/dist/components/section-header.js +76 -0
  158. package/dist/components/section-header.js.map +1 -0
  159. package/dist/components/section-label.d.ts +20 -0
  160. package/dist/components/section-label.js +46 -0
  161. package/dist/components/section-label.js.map +1 -0
  162. package/dist/components/section-tabs.d.ts +47 -0
  163. package/dist/components/section-tabs.js +145 -0
  164. package/dist/components/section-tabs.js.map +1 -0
  165. package/dist/components/separator.d.ts +14 -0
  166. package/dist/components/separator.js +49 -0
  167. package/dist/components/separator.js.map +1 -0
  168. package/dist/components/sheet.d.ts +22 -0
  169. package/dist/components/sheet.js +469 -0
  170. package/dist/components/sheet.js.map +1 -0
  171. package/dist/components/sidebar.d.ts +69 -0
  172. package/dist/components/sidebar.js +1645 -0
  173. package/dist/components/sidebar.js.map +1 -0
  174. package/dist/components/skeleton.d.ts +8 -0
  175. package/dist/components/skeleton.js +41 -0
  176. package/dist/components/skeleton.js.map +1 -0
  177. package/dist/components/slider.d.ts +6 -0
  178. package/dist/components/slider.js +75 -0
  179. package/dist/components/slider.js.map +1 -0
  180. package/dist/components/sortable-chip-list.d.ts +26 -0
  181. package/dist/components/sortable-chip-list.js +59 -0
  182. package/dist/components/sortable-chip-list.js.map +1 -0
  183. package/dist/components/spinner.d.ts +5 -0
  184. package/dist/components/spinner.js +65 -0
  185. package/dist/components/spinner.js.map +1 -0
  186. package/dist/components/surface.d.ts +13 -0
  187. package/dist/components/surface.js +51 -0
  188. package/dist/components/surface.js.map +1 -0
  189. package/dist/components/switch.d.ts +8 -0
  190. package/dist/components/switch.js +53 -0
  191. package/dist/components/switch.js.map +1 -0
  192. package/dist/components/table.d.ts +12 -0
  193. package/dist/components/table.js +129 -0
  194. package/dist/components/table.js.map +1 -0
  195. package/dist/components/textarea.d.ts +15 -0
  196. package/dist/components/textarea.js +58 -0
  197. package/dist/components/textarea.js.map +1 -0
  198. package/dist/components/toast.d.ts +19 -0
  199. package/dist/components/toast.js +805 -0
  200. package/dist/components/toast.js.map +1 -0
  201. package/dist/components/toggle.d.ts +12 -0
  202. package/dist/components/toggle.js +63 -0
  203. package/dist/components/toggle.js.map +1 -0
  204. package/dist/components/tooltip.d.ts +9 -0
  205. package/dist/components/tooltip.js +82 -0
  206. package/dist/components/tooltip.js.map +1 -0
  207. package/dist/hooks/use-dialog-footer-actions.d.ts +18 -0
  208. package/dist/hooks/use-dialog-footer-actions.js +11 -0
  209. package/dist/hooks/use-dialog-footer-actions.js.map +1 -0
  210. package/dist/hooks/use-form-field.d.ts +33 -0
  211. package/dist/hooks/use-form-field.js +36 -0
  212. package/dist/hooks/use-form-field.js.map +1 -0
  213. package/dist/hooks/use-mobile.d.ts +34 -0
  214. package/dist/hooks/use-mobile.js +29 -0
  215. package/dist/hooks/use-mobile.js.map +1 -0
  216. package/dist/hooks/use-pinch-pan.d.ts +56 -0
  217. package/dist/hooks/use-pinch-pan.js +223 -0
  218. package/dist/hooks/use-pinch-pan.js.map +1 -0
  219. package/dist/hooks/useMobileBackToClose.d.ts +61 -0
  220. package/dist/hooks/useMobileBackToClose.js +234 -0
  221. package/dist/hooks/useMobileBackToClose.js.map +1 -0
  222. package/dist/icon-BOgL5bpL.d.ts +85 -0
  223. package/dist/icons/actions.d.ts +4 -0
  224. package/dist/icons/actions.js +520 -0
  225. package/dist/icons/actions.js.map +1 -0
  226. package/dist/icons/icon-style.d.ts +2 -0
  227. package/dist/icons/icon-style.js +51 -0
  228. package/dist/icons/icon-style.js.map +1 -0
  229. package/dist/icons/marks.d.ts +15 -0
  230. package/dist/icons/marks.js +48 -0
  231. package/dist/icons/marks.js.map +1 -0
  232. package/dist/icons/registry.d.ts +177 -0
  233. package/dist/icons/registry.js +1180 -0
  234. package/dist/icons/registry.js.map +1 -0
  235. package/dist/index.d.ts +6 -0
  236. package/dist/index.js +653 -0
  237. package/dist/index.js.map +1 -0
  238. package/dist/lib/merge-config.d.ts +15 -0
  239. package/dist/lib/merge-config.js +20 -0
  240. package/dist/lib/merge-config.js.map +1 -0
  241. package/dist/lib/pagination.d.ts +19 -0
  242. package/dist/lib/pagination.js +26 -0
  243. package/dist/lib/pagination.js.map +1 -0
  244. package/dist/lib/utils.d.ts +5 -0
  245. package/dist/lib/utils.js +26 -0
  246. package/dist/lib/utils.js.map +1 -0
  247. package/dist/styles/theme.css +480 -0
  248. package/dist/styles/theme.css.map +1 -0
  249. package/dist/styles/theme.d.ts +2 -0
  250. package/dist/viewport.d.ts +64 -0
  251. package/dist/viewport.js +13 -0
  252. package/dist/viewport.js.map +1 -0
  253. package/package.json +122 -0
  254. package/src/components/alert.tsx +76 -0
  255. package/src/components/app-dialog.tsx +187 -0
  256. package/src/components/badge.tsx +52 -0
  257. package/src/components/breadcrumb.tsx +129 -0
  258. package/src/components/button.tsx +70 -0
  259. package/src/components/caption-bar.test.tsx +151 -0
  260. package/src/components/caption-bar.tsx +392 -0
  261. package/src/components/chart-card.tsx +31 -0
  262. package/src/components/checkbox.tsx +28 -0
  263. package/src/components/chip-button.tsx +69 -0
  264. package/src/components/close-confirm-dialog.tsx +99 -0
  265. package/src/components/color-picker.tsx +186 -0
  266. package/src/components/combobox.tsx +335 -0
  267. package/src/components/confirm-by-typing-dialog.tsx +130 -0
  268. package/src/components/confirm-dialog.test.tsx +39 -0
  269. package/src/components/confirm-dialog.tsx +98 -0
  270. package/src/components/count-badge.tsx +23 -0
  271. package/src/components/dialog.tsx +315 -0
  272. package/src/components/dropdown-menu.tsx +311 -0
  273. package/src/components/dropdown-select.tsx +211 -0
  274. package/src/components/empty.tsx +104 -0
  275. package/src/components/filter-rail.tsx +139 -0
  276. package/src/components/fixed-action-bar.tsx +46 -0
  277. package/src/components/font-picker.tsx +257 -0
  278. package/src/components/form.tsx +127 -0
  279. package/src/components/group-label.tsx +13 -0
  280. package/src/components/icon-tile.tsx +35 -0
  281. package/src/components/icon-toggle.tsx +57 -0
  282. package/src/components/icon.tsx +66 -0
  283. package/src/components/image-crop-panel.test.tsx +167 -0
  284. package/src/components/image-crop-panel.tsx +465 -0
  285. package/src/components/image-cropper.test.tsx +144 -0
  286. package/src/components/image-cropper.tsx +265 -0
  287. package/src/components/input-group.tsx +156 -0
  288. package/src/components/input.tsx +45 -0
  289. package/src/components/label.tsx +20 -0
  290. package/src/components/list-empty-row.tsx +27 -0
  291. package/src/components/management-empty.tsx +25 -0
  292. package/src/components/management-skeleton.tsx +23 -0
  293. package/src/components/meta-chip.tsx +40 -0
  294. package/src/components/mobile-drawer.test.tsx +52 -0
  295. package/src/components/mobile-drawer.tsx +98 -0
  296. package/src/components/page-header.tsx +47 -0
  297. package/src/components/page-scaffold.test.tsx +24 -0
  298. package/src/components/page-scaffold.tsx +131 -0
  299. package/src/components/pagination-bar.test.tsx +87 -0
  300. package/src/components/pagination-bar.tsx +139 -0
  301. package/src/components/pagination.tsx +139 -0
  302. package/src/components/panel-toolbar.tsx +99 -0
  303. package/src/components/pill-tabs.test.tsx +84 -0
  304. package/src/components/pill-tabs.tsx +77 -0
  305. package/src/components/plugin-download-consent.test.tsx +90 -0
  306. package/src/components/plugin-download-consent.tsx +183 -0
  307. package/src/components/popover.tsx +133 -0
  308. package/src/components/progress.tsx +88 -0
  309. package/src/components/query-state-view.tsx +47 -0
  310. package/src/components/radio-group.tsx +36 -0
  311. package/src/components/scroll-area.tsx +52 -0
  312. package/src/components/search-field.test.tsx +86 -0
  313. package/src/components/search-field.tsx +119 -0
  314. package/src/components/secondary-stat.tsx +24 -0
  315. package/src/components/section-header.tsx +54 -0
  316. package/src/components/section-label.tsx +40 -0
  317. package/src/components/section-tabs.test.tsx +154 -0
  318. package/src/components/section-tabs.tsx +190 -0
  319. package/src/components/separator.tsx +38 -0
  320. package/src/components/sheet.tsx +170 -0
  321. package/src/components/sidebar.tsx +725 -0
  322. package/src/components/skeleton.tsx +18 -0
  323. package/src/components/slider.tsx +52 -0
  324. package/src/components/sortable-chip-list.tsx +56 -0
  325. package/src/components/spinner.tsx +35 -0
  326. package/src/components/surface.tsx +37 -0
  327. package/src/components/switch.tsx +30 -0
  328. package/src/components/table.tsx +116 -0
  329. package/src/components/textarea.tsx +41 -0
  330. package/src/components/toast.tsx +239 -0
  331. package/src/components/toggle.tsx +45 -0
  332. package/src/components/tooltip.tsx +64 -0
  333. package/src/hooks/use-dialog-footer-actions.ts +23 -0
  334. package/src/hooks/use-form-field.ts +62 -0
  335. package/src/hooks/use-mobile.ts +54 -0
  336. package/src/hooks/use-pinch-pan.test.tsx +42 -0
  337. package/src/hooks/use-pinch-pan.ts +340 -0
  338. package/src/hooks/useMobileBackToClose.test.tsx +140 -0
  339. package/src/hooks/useMobileBackToClose.ts +508 -0
  340. package/src/icons/actions.ts +10 -0
  341. package/src/icons/icon-style.test.tsx +69 -0
  342. package/src/icons/icon-style.ts +104 -0
  343. package/src/icons/marks.tsx +72 -0
  344. package/src/icons/registry.test.ts +65 -0
  345. package/src/icons/registry.ts +1163 -0
  346. package/src/index.ts +22 -0
  347. package/src/lib/merge-config.test.ts +109 -0
  348. package/src/lib/merge-config.ts +22 -0
  349. package/src/lib/pagination.test.ts +55 -0
  350. package/src/lib/pagination.ts +42 -0
  351. package/src/lib/utils.ts +6 -0
  352. package/src/styles/scan-contract.test.ts +74 -0
  353. package/src/styles/theme.css +798 -0
  354. package/src/test/i18n.tsx +22 -0
  355. package/src/test/setup.ts +104 -0
  356. 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 };