@squadbase/vantage 0.6.2-dev2.5e7a250 → 0.6.2-dev2.b5837f0

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 (336) hide show
  1. package/dist/add-4GHF2TX2.js +6 -0
  2. package/dist/add-4GHF2TX2.js.map +1 -0
  3. package/dist/{build-TVKFIVFQ.js → build-A23M4GCH.js} +9 -9
  4. package/dist/{build-TVKFIVFQ.js.map → build-A23M4GCH.js.map} +1 -1
  5. package/dist/{check-3KHZXZMQ.js → check-FBHT6W6J.js} +7 -7
  6. package/dist/{check-3KHZXZMQ.js.map → check-FBHT6W6J.js.map} +1 -1
  7. package/dist/chunk-2IAPIOPS.js +152 -0
  8. package/dist/chunk-2IAPIOPS.js.map +1 -0
  9. package/dist/{chunk-5ZOP4SQR.js → chunk-2N72FKLB.js} +12 -7
  10. package/dist/chunk-2N72FKLB.js.map +1 -0
  11. package/dist/chunk-57GHR5LN.js +163 -0
  12. package/dist/chunk-57GHR5LN.js.map +1 -0
  13. package/dist/{chunk-P7W4LR3Z.js → chunk-5C2SEDPH.js} +22 -5
  14. package/dist/chunk-5C2SEDPH.js.map +1 -0
  15. package/dist/chunk-6OTTGAPO.js +44 -0
  16. package/dist/chunk-6OTTGAPO.js.map +1 -0
  17. package/dist/{chunk-RPZAALCX.js → chunk-7S52M2SL.js} +256 -165
  18. package/dist/chunk-7S52M2SL.js.map +1 -0
  19. package/dist/{chunk-U2M6HGKQ.js → chunk-AABMKHEU.js} +4 -4
  20. package/dist/{chunk-U2M6HGKQ.js.map → chunk-AABMKHEU.js.map} +1 -1
  21. package/dist/{chunk-PVTHHV7X.js → chunk-ANZLVSEP.js} +28 -7
  22. package/dist/chunk-ANZLVSEP.js.map +1 -0
  23. package/dist/chunk-CKWPK4RO.js +50 -0
  24. package/dist/chunk-CKWPK4RO.js.map +1 -0
  25. package/dist/{chunk-QI3XQKHS.js → chunk-GNXCX4WE.js} +10 -3
  26. package/dist/chunk-GNXCX4WE.js.map +1 -0
  27. package/dist/chunk-JXFCSF3K.js +673 -0
  28. package/dist/chunk-JXFCSF3K.js.map +1 -0
  29. package/dist/{chunk-PXRX5PEC.js → chunk-PDOBHMUQ.js} +3 -3
  30. package/dist/chunk-PDOBHMUQ.js.map +1 -0
  31. package/dist/chunk-QOXXOFGL.js +7051 -0
  32. package/dist/chunk-QOXXOFGL.js.map +1 -0
  33. package/dist/{chunk-ZVANIULZ.js → chunk-RNTDBX6S.js} +4 -4
  34. package/dist/{chunk-ZVANIULZ.js.map → chunk-RNTDBX6S.js.map} +1 -1
  35. package/dist/{chunk-CEXAQQ5W.js → chunk-S5MDTHH7.js} +180 -18
  36. package/dist/chunk-S5MDTHH7.js.map +1 -0
  37. package/dist/chunk-SDJTTMLK.js +1877 -0
  38. package/dist/chunk-SDJTTMLK.js.map +1 -0
  39. package/dist/{chunk-LMUACBMA.js → chunk-SHZM3EXB.js} +68 -12
  40. package/dist/chunk-SHZM3EXB.js.map +1 -0
  41. package/dist/{chunk-A2UUGASH.js → chunk-U736PVHY.js} +2 -2
  42. package/dist/chunk-U736PVHY.js.map +1 -0
  43. package/dist/{chunk-JKLLFVEU.js → chunk-UWSQUHX6.js} +4 -99
  44. package/dist/chunk-UWSQUHX6.js.map +1 -0
  45. package/dist/cli.js +12 -11
  46. package/dist/cli.js.map +1 -1
  47. package/dist/client/index.d.ts +34 -3
  48. package/dist/client/index.js +211 -12
  49. package/dist/client/index.js.map +1 -1
  50. package/dist/components/index.d.ts +1740 -29
  51. package/dist/components/index.js +7 -4
  52. package/dist/delta-text-CvwBGJ95.d.ts +15 -0
  53. package/dist/{dev-GDKATCC7.js → dev-H4I2JL63.js} +10 -10
  54. package/dist/dev-H4I2JL63.js.map +1 -0
  55. package/dist/doc/index.d.ts +215 -2
  56. package/dist/doc/index.js +309 -5
  57. package/dist/doc/index.js.map +1 -1
  58. package/dist/{docs-EJJ3BECT.js → docs-JVP4RPKT.js} +3 -3
  59. package/dist/{docs-EJJ3BECT.js.map → docs-JVP4RPKT.js.map} +1 -1
  60. package/dist/{doctor-WQXPXP6K.js → doctor-B2O3GJDU.js} +7 -7
  61. package/dist/{doctor-WQXPXP6K.js.map → doctor-B2O3GJDU.js.map} +1 -1
  62. package/dist/format-U0cQl069.d.ts +243 -0
  63. package/dist/markdown/index.js +1 -1
  64. package/dist/markdown/index.js.map +1 -1
  65. package/dist/{preview-OGMCNQUO.js → preview-T6CLSQVX.js} +3 -3
  66. package/dist/{preview-OGMCNQUO.js.map → preview-T6CLSQVX.js.map} +1 -1
  67. package/dist/query/index.d.ts +0 -11
  68. package/dist/query/index.js +2 -2
  69. package/dist/{routes-MWBWWOJ2.js → routes-PVKNT777.js} +6 -6
  70. package/dist/{routes-MWBWWOJ2.js.map → routes-PVKNT777.js.map} +1 -1
  71. package/dist/{search-6Y422SV6.js → search-5LC4XPB5.js} +3 -3
  72. package/dist/{search-6Y422SV6.js.map → search-5LC4XPB5.js.map} +1 -1
  73. package/dist/slide/index.d.ts +272 -1
  74. package/dist/slide/index.js +974 -4
  75. package/dist/slide/index.js.map +1 -1
  76. package/dist/table/index.js +14 -10
  77. package/dist/table/index.js.map +1 -1
  78. package/dist/ui/index.d.ts +148 -12
  79. package/dist/ui/index.js +1340 -88
  80. package/dist/ui/index.js.map +1 -1
  81. package/dist/{upgrade-HCANX4GQ.js → upgrade-6DT7ADRP.js} +7 -7
  82. package/dist/{upgrade-HCANX4GQ.js.map → upgrade-6DT7ADRP.js.map} +1 -1
  83. package/dist/vite/index.d.ts +10 -0
  84. package/dist/vite/index.js +4 -4
  85. package/docs/en/changelog.md +2 -0
  86. package/docs/en/components.md +42 -17
  87. package/docs/en/doc/delta-text.md +40 -0
  88. package/docs/en/doc/doc-action-items.md +49 -0
  89. package/docs/en/doc/doc-callout.md +38 -0
  90. package/docs/en/doc/doc-data-table.md +60 -0
  91. package/docs/en/doc/doc-executive-summary.md +64 -0
  92. package/docs/en/doc/doc-figure.md +56 -0
  93. package/docs/en/doc/doc-key-findings.md +61 -0
  94. package/docs/en/doc/doc-kpi-scorecard.md +80 -0
  95. package/docs/en/doc/doc-notes-and-sources.md +43 -0
  96. package/docs/en/doc/doc-report-header.md +46 -0
  97. package/docs/en/pages-and-metadata.md +15 -0
  98. package/docs/en/parts/area-chart.md +99 -0
  99. package/docs/en/parts/bar-chart.md +91 -0
  100. package/docs/en/parts/bar-list.md +50 -0
  101. package/docs/en/parts/category-bar.md +37 -0
  102. package/docs/en/parts/chart-frame.md +39 -0
  103. package/docs/en/parts/data-table.md +22 -0
  104. package/docs/en/parts/delta.md +51 -0
  105. package/docs/en/parts/donut-chart.md +72 -0
  106. package/docs/en/parts/format.md +43 -0
  107. package/docs/en/parts/funnel-steps.md +2 -1
  108. package/docs/en/parts/heatmap.md +53 -0
  109. package/docs/en/parts/kpi-card.md +58 -0
  110. package/docs/en/parts/legend.md +35 -0
  111. package/docs/en/parts/line-chart.md +94 -0
  112. package/docs/en/parts/metric-value.md +3 -2
  113. package/docs/en/parts/progress-circle.md +33 -0
  114. package/docs/en/parts/sample-data.md +39 -0
  115. package/docs/en/parts/scatter-chart.md +56 -0
  116. package/docs/en/parts/sparkline.md +1 -1
  117. package/docs/en/parts/tracker.md +36 -0
  118. package/docs/en/parts/trend-indicator.md +17 -1
  119. package/docs/en/parts/updated-at.md +30 -0
  120. package/docs/en/parts/waterfall-chart.md +56 -0
  121. package/docs/en/slide/slide-chart-full.md +48 -0
  122. package/docs/en/slide/slide-chart-insight.md +52 -0
  123. package/docs/en/slide/slide-columns.md +46 -0
  124. package/docs/en/slide/slide-comparison.md +68 -0
  125. package/docs/en/slide/slide-cover.md +39 -0
  126. package/docs/en/slide/slide-exec-summary.md +47 -0
  127. package/docs/en/slide/slide-heading.md +38 -0
  128. package/docs/en/slide/slide-kpi-grid.md +55 -0
  129. package/docs/en/slide/slide-kpi-hero.md +58 -0
  130. package/docs/en/slide/slide-next-actions.md +49 -0
  131. package/docs/en/slide/slide-scorecard-table.md +54 -0
  132. package/docs/en/slide/slide-section.md +44 -0
  133. package/docs/en/slide/slide-source-line.md +34 -0
  134. package/docs/en/ui/alert-dialog.md +42 -0
  135. package/docs/en/ui/avatar.md +31 -0
  136. package/docs/en/ui/combobox.md +74 -0
  137. package/docs/en/ui/drawer.md +41 -0
  138. package/docs/en/ui/empty.md +1 -1
  139. package/docs/en/ui/error-state.md +4 -3
  140. package/docs/en/ui/field.md +42 -0
  141. package/docs/en/ui/hover-card.md +21 -0
  142. package/docs/en/ui/kbd.md +17 -0
  143. package/docs/en/ui/loading.md +1 -1
  144. package/docs/en/ui/pagination.md +36 -0
  145. package/docs/en/ui/radio-group.md +21 -0
  146. package/docs/en/ui/toast.md +44 -0
  147. package/docs/en/ui/toggle-group.md +4 -3
  148. package/docs/en/ui-and-theming.md +1 -1
  149. package/docs/index.json +1184 -114
  150. package/docs/ja/changelog.md +33 -0
  151. package/docs/ja/components.md +68 -101
  152. package/docs/ja/doc/delta-text.md +40 -0
  153. package/docs/ja/doc/doc-action-items.md +49 -0
  154. package/docs/ja/doc/doc-callout.md +38 -0
  155. package/docs/ja/doc/doc-data-table.md +60 -0
  156. package/docs/ja/doc/doc-executive-summary.md +64 -0
  157. package/docs/ja/doc/doc-figure.md +56 -0
  158. package/docs/ja/doc/doc-key-findings.md +61 -0
  159. package/docs/ja/doc/doc-kpi-scorecard.md +80 -0
  160. package/docs/ja/doc/doc-notes-and-sources.md +43 -0
  161. package/docs/ja/doc/doc-report-header.md +46 -0
  162. package/docs/ja/page-types/csv.md +83 -0
  163. package/docs/ja/page-types/doc.md +83 -0
  164. package/docs/ja/page-types/excel.md +82 -0
  165. package/docs/ja/page-types/slide.md +133 -0
  166. package/docs/ja/page-types.md +47 -0
  167. package/docs/ja/pages-and-metadata.md +15 -0
  168. package/docs/ja/parts/area-chart.md +85 -0
  169. package/docs/ja/parts/bar-chart.md +95 -0
  170. package/docs/ja/parts/bar-list.md +58 -0
  171. package/docs/ja/parts/category-bar.md +36 -0
  172. package/docs/ja/parts/chart-frame.md +36 -0
  173. package/docs/ja/parts/data-table.md +22 -0
  174. package/docs/ja/parts/delta.md +51 -0
  175. package/docs/ja/parts/donut-chart.md +66 -0
  176. package/docs/ja/parts/echart.md +3 -0
  177. package/docs/ja/parts/format.md +44 -0
  178. package/docs/ja/parts/funnel-steps.md +27 -8
  179. package/docs/ja/parts/heatmap.md +45 -0
  180. package/docs/ja/parts/kpi-card.md +56 -0
  181. package/docs/ja/parts/legend.md +36 -0
  182. package/docs/ja/parts/line-chart.md +84 -0
  183. package/docs/ja/parts/metric-value.md +3 -2
  184. package/docs/ja/parts/progress-circle.md +34 -0
  185. package/docs/ja/parts/sample-data.md +61 -0
  186. package/docs/ja/parts/scatter-chart.md +69 -0
  187. package/docs/ja/parts/sparkline.md +2 -2
  188. package/docs/ja/parts/tracker.md +32 -0
  189. package/docs/ja/parts/trend-indicator.md +17 -1
  190. package/docs/ja/parts/updated-at.md +27 -0
  191. package/docs/ja/parts/waterfall-chart.md +61 -0
  192. package/docs/ja/routing.md +8 -86
  193. package/docs/ja/slide/slide-chart-full.md +48 -0
  194. package/docs/ja/slide/slide-chart-insight.md +52 -0
  195. package/docs/ja/slide/slide-columns.md +46 -0
  196. package/docs/ja/slide/slide-comparison.md +68 -0
  197. package/docs/ja/slide/slide-cover.md +39 -0
  198. package/docs/ja/slide/slide-exec-summary.md +47 -0
  199. package/docs/ja/slide/slide-heading.md +38 -0
  200. package/docs/ja/slide/slide-kpi-grid.md +55 -0
  201. package/docs/ja/slide/slide-kpi-hero.md +58 -0
  202. package/docs/ja/slide/slide-next-actions.md +49 -0
  203. package/docs/ja/slide/slide-scorecard-table.md +54 -0
  204. package/docs/ja/slide/slide-section.md +44 -0
  205. package/docs/ja/slide/slide-source-line.md +34 -0
  206. package/docs/ja/ui/alert-dialog.md +41 -0
  207. package/docs/ja/ui/avatar.md +31 -0
  208. package/docs/ja/ui/combobox.md +74 -0
  209. package/docs/ja/ui/drawer.md +41 -0
  210. package/docs/ja/ui/empty.md +1 -1
  211. package/docs/ja/ui/error-state.md +4 -3
  212. package/docs/ja/ui/field.md +42 -0
  213. package/docs/ja/ui/hover-card.md +21 -0
  214. package/docs/ja/ui/kbd.md +16 -0
  215. package/docs/ja/ui/loading.md +1 -1
  216. package/docs/ja/ui/pagination.md +36 -0
  217. package/docs/ja/ui/radio-group.md +21 -0
  218. package/docs/ja/ui/toast.md +46 -0
  219. package/docs/ja/ui/toggle-group.md +4 -3
  220. package/docs/ja/ui-and-theming.md +14 -7
  221. package/package.json +41 -31
  222. package/registry/ui/accordion.tsx +76 -0
  223. package/registry/ui/alert-dialog.tsx +189 -0
  224. package/registry/ui/alert.tsx +80 -0
  225. package/registry/ui/app-shell.tsx +287 -0
  226. package/registry/ui/area-chart.tsx +3701 -0
  227. package/registry/ui/attention-list.tsx +303 -0
  228. package/registry/ui/avatar.tsx +110 -0
  229. package/registry/ui/badge.tsx +56 -0
  230. package/registry/ui/bar-chart.tsx +3698 -0
  231. package/registry/ui/bar-list.tsx +3743 -0
  232. package/registry/ui/box-plot-chart.tsx +3906 -0
  233. package/registry/ui/breadcrumb.tsx +128 -0
  234. package/registry/ui/button.tsx +62 -0
  235. package/registry/ui/calendar.tsx +223 -0
  236. package/registry/ui/card.tsx +107 -0
  237. package/registry/ui/category-bar.tsx +1290 -0
  238. package/registry/ui/chart-frame.tsx +1393 -0
  239. package/registry/ui/checkbox.tsx +30 -0
  240. package/registry/ui/collapsible.tsx +23 -0
  241. package/registry/ui/combobox.tsx +310 -0
  242. package/registry/ui/command.tsx +198 -0
  243. package/registry/ui/dashboard-card.tsx +217 -0
  244. package/registry/ui/data-table.tsx +693 -146
  245. package/registry/ui/date-range-picker.tsx +390 -0
  246. package/registry/ui/delta.tsx +191 -0
  247. package/registry/ui/dialog.tsx +161 -0
  248. package/registry/ui/donut-chart.tsx +3751 -0
  249. package/registry/ui/drawer.tsx +229 -0
  250. package/registry/ui/dropdown-menu.tsx +274 -0
  251. package/registry/ui/echart.tsx +1040 -0
  252. package/registry/ui/field.tsx +240 -0
  253. package/registry/ui/filter-bar.tsx +392 -0
  254. package/registry/ui/funnel-steps.tsx +3569 -0
  255. package/registry/ui/heatmap.tsx +1786 -0
  256. package/registry/ui/histogram-chart.tsx +3986 -0
  257. package/registry/ui/hover-card.tsx +52 -0
  258. package/registry/ui/input-group.tsx +160 -0
  259. package/registry/ui/input.tsx +24 -0
  260. package/registry/ui/kbd.tsx +30 -0
  261. package/registry/ui/kpi-card.tsx +704 -0
  262. package/registry/ui/label.tsx +22 -0
  263. package/registry/ui/legend.tsx +3563 -0
  264. package/registry/ui/line-chart.tsx +3699 -0
  265. package/registry/ui/metric-value.tsx +62 -0
  266. package/registry/ui/multi-select.tsx +232 -0
  267. package/registry/ui/page-shell.tsx +282 -0
  268. package/registry/ui/pagination.tsx +140 -0
  269. package/registry/ui/paired-chart.tsx +3827 -0
  270. package/registry/ui/placeholder.tsx +36 -0
  271. package/registry/ui/popover.tsx +92 -0
  272. package/registry/ui/progress-circle.tsx +867 -0
  273. package/registry/ui/progress.tsx +85 -0
  274. package/registry/ui/radio-group.tsx +39 -0
  275. package/registry/ui/sample-data.tsx +86 -0
  276. package/registry/ui/scatter-chart.tsx +4212 -0
  277. package/registry/ui/scroll-area.tsx +56 -0
  278. package/registry/ui/searchable-select.tsx +214 -0
  279. package/registry/ui/section-header.tsx +43 -0
  280. package/registry/ui/segmented-control.tsx +76 -0
  281. package/registry/ui/select.tsx +255 -0
  282. package/registry/ui/separator.tsx +27 -0
  283. package/registry/ui/sheet.tsx +139 -0
  284. package/registry/ui/sidebar.tsx +725 -0
  285. package/registry/ui/skeleton.tsx +17 -0
  286. package/registry/ui/slider.tsx +56 -0
  287. package/registry/ui/sparkline.tsx +230 -0
  288. package/registry/ui/spinner.tsx +14 -0
  289. package/registry/ui/states.tsx +90 -0
  290. package/registry/ui/status-badge.tsx +121 -0
  291. package/registry/ui/switch.tsx +34 -0
  292. package/registry/ui/table.tsx +118 -0
  293. package/registry/ui/tabs.tsx +84 -0
  294. package/registry/ui/textarea.tsx +22 -0
  295. package/registry/ui/toast.tsx +250 -0
  296. package/registry/ui/toggle-group.tsx +91 -0
  297. package/registry/ui/toggle.tsx +47 -0
  298. package/registry/ui/tooltip.tsx +72 -0
  299. package/registry/ui/tracker.tsx +849 -0
  300. package/registry/ui/trend-indicator.tsx +74 -0
  301. package/registry/ui/updated-at.tsx +122 -0
  302. package/registry/ui/waterfall-chart.tsx +4248 -0
  303. package/skills/vantage-add-feature/SKILL.md +9 -7
  304. package/skills/vantage-design/SKILL.md +36 -24
  305. package/skills/vantage-design/references/extract.md +16 -14
  306. package/skills/vantage-design/references/format.md +6 -5
  307. package/skills/vantage-design/references/presets.md +60 -110
  308. package/skills/vantage-pitfalls/SKILL.md +10 -1
  309. package/skills/vantage-slide/SKILL.md +68 -36
  310. package/templates/AGENTS.md +26 -3
  311. package/templates/agents/api.md +29 -0
  312. package/templates/agents/csv.md +2 -1
  313. package/templates/agents/doc.md +52 -3
  314. package/templates/agents/page.md +54 -9
  315. package/templates/agents/slide.md +76 -3
  316. package/templates/agents/xlsx.md +2 -1
  317. package/theme.css +247 -132
  318. package/dist/add-DY4AXANK.js +0 -6
  319. package/dist/add-DY4AXANK.js.map +0 -1
  320. package/dist/chunk-5ZOP4SQR.js.map +0 -1
  321. package/dist/chunk-A2UUGASH.js.map +0 -1
  322. package/dist/chunk-CEXAQQ5W.js.map +0 -1
  323. package/dist/chunk-DTDVSFRY.js +0 -29
  324. package/dist/chunk-DTDVSFRY.js.map +0 -1
  325. package/dist/chunk-JKLLFVEU.js.map +0 -1
  326. package/dist/chunk-LMUACBMA.js.map +0 -1
  327. package/dist/chunk-MP3QSOXL.js +0 -2232
  328. package/dist/chunk-MP3QSOXL.js.map +0 -1
  329. package/dist/chunk-P7W4LR3Z.js.map +0 -1
  330. package/dist/chunk-PVTHHV7X.js.map +0 -1
  331. package/dist/chunk-PXRX5PEC.js.map +0 -1
  332. package/dist/chunk-QI3XQKHS.js.map +0 -1
  333. package/dist/chunk-RPZAALCX.js.map +0 -1
  334. package/dist/chunk-VA776YE5.js +0 -316
  335. package/dist/chunk-VA776YE5.js.map +0 -1
  336. package/dist/dev-GDKATCC7.js.map +0 -1
@@ -0,0 +1,287 @@
1
+ // Copied by `vantage add ui app-shell`. This file is yours to edit.
2
+ // Generated from @squadbase/squadkit registry/components/app-shell.tsx by `pnpm run registry` (in Vantage, edit packages/squadkit, not registry/).
3
+ "use client"
4
+
5
+ /**
6
+ * AppShell — the outermost application frame. `variant="sidebar"` (default)
7
+ * renders a collapsible sidebar with nested nav groups; `variant="header"`
8
+ * collapses the same nav into a single select in a top bar.
9
+ *
10
+ * Navigation is router-agnostic: pass `linkComponent` to render links with your
11
+ * router's Link, or leave it and `onNavigate` handles the header variant.
12
+ */
13
+ import { forwardRef, type ElementType, type ReactNode } from "react"
14
+ import { ChevronRight } from "lucide-react"
15
+
16
+ import { cn } from "@squadbase/vantage/ui"
17
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@squadbase/vantage/ui"
18
+ import { Separator } from "@squadbase/vantage/ui"
19
+ import {
20
+ Select,
21
+ SelectContent,
22
+ SelectGroup,
23
+ SelectItem,
24
+ SelectLabel,
25
+ SelectTrigger,
26
+ SelectValue,
27
+ } from "@squadbase/vantage/ui"
28
+ import {
29
+ Sidebar,
30
+ SidebarContent,
31
+ SidebarFooter,
32
+ SidebarGroup,
33
+ SidebarGroupLabel,
34
+ SidebarInset,
35
+ SidebarMenu,
36
+ SidebarMenuBadge,
37
+ SidebarMenuButton,
38
+ SidebarMenuItem,
39
+ SidebarMenuSub,
40
+ SidebarMenuSubButton,
41
+ SidebarMenuSubItem,
42
+ SidebarProvider,
43
+ SidebarRail,
44
+ SidebarTrigger,
45
+ } from "@squadbase/vantage/ui"
46
+ import type { NavGroup, NavItem } from "@squadbase/vantage/components"
47
+
48
+ export interface AppShellSidebarProps {
49
+ variant?: "sidebar"
50
+ groups: NavGroup[]
51
+ actions?: ReactNode
52
+ header?: ReactNode
53
+ children: ReactNode
54
+ defaultOpen?: boolean
55
+ className?: string
56
+ linkComponent?: ElementType
57
+ onNavigate?: (href: string) => void
58
+ }
59
+
60
+ export interface AppShellHeaderProps {
61
+ variant: "header"
62
+ groups: NavGroup[]
63
+ actions?: ReactNode
64
+ header?: ReactNode
65
+ children: ReactNode
66
+ className?: string
67
+ linkComponent?: ElementType
68
+ onNavigate?: (href: string) => void
69
+ }
70
+
71
+ export type AppShellProps = AppShellSidebarProps | AppShellHeaderProps
72
+
73
+ /** Nested groups collapse to their leaves — the select is a flat list. */
74
+ function flattenItems(item: NavItem): NavItem[] {
75
+ if (item.children && item.children.length > 0) {
76
+ return item.children.flatMap(flattenItems)
77
+ }
78
+ return [item]
79
+ }
80
+
81
+ function NavSelect({
82
+ groups,
83
+ onNavigate,
84
+ }: {
85
+ groups: NavGroup[]
86
+ onNavigate: (href: string) => void
87
+ }) {
88
+ const allItems = groups.flatMap((g) => g.items.flatMap(flattenItems))
89
+ const currentValue = allItems.find((item) => item.isActive)?.href ?? ""
90
+ // Base UI's SelectValue renders the raw value (the href) unless `items` maps
91
+ // it to a label, so pass the page names explicitly.
92
+ const selectItems = allItems.map((item) => ({ value: item.href, label: item.label }))
93
+
94
+ return (
95
+ <Select
96
+ items={selectItems}
97
+ value={currentValue}
98
+ onValueChange={(href) => {
99
+ // Base UI reports `null` when the selection is cleared; there is no
100
+ // page to navigate to in that case.
101
+ if (href !== null) onNavigate(href)
102
+ }}
103
+ >
104
+ <SelectTrigger size="sm" className="w-48">
105
+ <SelectValue placeholder="ページを選択" />
106
+ </SelectTrigger>
107
+ {/*
108
+ Page titles are author-written and often longer than the 12rem trigger,
109
+ so the list is allowed to grow past the anchor width (bounded by the
110
+ viewport) instead of clamping every title to the trigger's width.
111
+ */}
112
+ <SelectContent
113
+ align="start"
114
+ className="w-auto min-w-(--anchor-width) max-w-[min(24rem,var(--available-width))]"
115
+ >
116
+ {groups.map((group, index) => (
117
+ <SelectGroup key={group.label ?? index}>
118
+ {group.label && <SelectLabel>{group.label}</SelectLabel>}
119
+ {group.items.flatMap(flattenItems).map((item) => (
120
+ <SelectItem key={item.href} value={item.href} disabled={item.disabled}>
121
+ {item.label}
122
+ </SelectItem>
123
+ ))}
124
+ </SelectGroup>
125
+ ))}
126
+ </SelectContent>
127
+ </Select>
128
+ )
129
+ }
130
+
131
+ function NavItemWithChildren({
132
+ item,
133
+ linkComponent: LinkComponent = "a",
134
+ }: {
135
+ item: NavItem
136
+ linkComponent?: ElementType
137
+ }) {
138
+ return (
139
+ <Collapsible
140
+ defaultOpen={item.isActive}
141
+ className="group/collapsible"
142
+ render={<SidebarMenuItem />}
143
+ >
144
+ <CollapsibleTrigger
145
+ render={
146
+ <SidebarMenuButton
147
+ tooltip={item.label}
148
+ aria-disabled={item.disabled}
149
+ className={cn(item.disabled && "pointer-events-none")}
150
+ />
151
+ }
152
+ >
153
+ {item.icon && <item.icon />}
154
+ <span>{item.label}</span>
155
+ <ChevronRight className="ml-auto transition-transform duration-200 group-data-open/collapsible:rotate-90" />
156
+ </CollapsibleTrigger>
157
+ {item.badge && <SidebarMenuBadge>{item.badge}</SidebarMenuBadge>}
158
+ <CollapsibleContent>
159
+ <SidebarMenuSub>
160
+ {item.children!.map((child) => (
161
+ <SidebarMenuSubItem key={child.href}>
162
+ <SidebarMenuSubButton
163
+ isActive={child.isActive}
164
+ render={
165
+ <LinkComponent
166
+ href={child.href}
167
+ aria-disabled={child.disabled}
168
+ tabIndex={child.disabled ? -1 : undefined}
169
+ className={cn(child.disabled && "pointer-events-none opacity-50")}
170
+ />
171
+ }
172
+ >
173
+ {child.icon && <child.icon />}
174
+ <span>{child.label}</span>
175
+ </SidebarMenuSubButton>
176
+ </SidebarMenuSubItem>
177
+ ))}
178
+ </SidebarMenuSub>
179
+ </CollapsibleContent>
180
+ </Collapsible>
181
+ )
182
+ }
183
+
184
+ function NavItemLink({
185
+ item,
186
+ linkComponent: LinkComponent = "a",
187
+ }: {
188
+ item: NavItem
189
+ linkComponent?: ElementType
190
+ }) {
191
+ return (
192
+ <SidebarMenuItem>
193
+ <SidebarMenuButton
194
+ tooltip={item.label}
195
+ isActive={item.isActive}
196
+ render={
197
+ <LinkComponent
198
+ href={item.href}
199
+ aria-disabled={item.disabled}
200
+ tabIndex={item.disabled ? -1 : undefined}
201
+ className={cn(item.disabled && "pointer-events-none")}
202
+ />
203
+ }
204
+ >
205
+ {item.icon && <item.icon />}
206
+ <span>{item.label}</span>
207
+ </SidebarMenuButton>
208
+ {item.badge && <SidebarMenuBadge>{item.badge}</SidebarMenuBadge>}
209
+ </SidebarMenuItem>
210
+ )
211
+ }
212
+
213
+ const defaultNavigate = (href: string) => {
214
+ window.location.assign(href)
215
+ }
216
+
217
+ export const AppShell = forwardRef<HTMLDivElement, AppShellProps>((props, ref) => {
218
+ const {
219
+ variant = "sidebar",
220
+ groups,
221
+ actions,
222
+ header,
223
+ children,
224
+ className,
225
+ linkComponent,
226
+ onNavigate = defaultNavigate,
227
+ } = props
228
+
229
+ if (variant === "header") {
230
+ return (
231
+ <div ref={ref} data-slot="app-shell" className={cn("flex h-full flex-col", className)}>
232
+ {header !== undefined ? (
233
+ header
234
+ ) : (
235
+ <header className="flex h-14 shrink-0 items-center gap-3 border-b px-4">
236
+ {groups.length > 0 && <NavSelect groups={groups} onNavigate={onNavigate} />}
237
+ {actions && <div className="ml-auto flex items-center gap-2">{actions}</div>}
238
+ </header>
239
+ )}
240
+ <main className="flex-1 overflow-auto">{children}</main>
241
+ </div>
242
+ )
243
+ }
244
+
245
+ const { defaultOpen = true } = props as AppShellSidebarProps
246
+
247
+ return (
248
+ <SidebarProvider defaultOpen={defaultOpen}>
249
+ <Sidebar data-slot="app-sidebar" collapsible="offcanvas">
250
+ <SidebarContent>
251
+ {groups.map((group, index) => (
252
+ <SidebarGroup key={group.label ?? index}>
253
+ {group.label && <SidebarGroupLabel>{group.label}</SidebarGroupLabel>}
254
+ <SidebarMenu>
255
+ {group.items.map((item) =>
256
+ item.children && item.children.length > 0 ? (
257
+ <NavItemWithChildren
258
+ key={item.href}
259
+ item={item}
260
+ linkComponent={linkComponent}
261
+ />
262
+ ) : (
263
+ <NavItemLink key={item.href} item={item} linkComponent={linkComponent} />
264
+ ),
265
+ )}
266
+ </SidebarMenu>
267
+ </SidebarGroup>
268
+ ))}
269
+ </SidebarContent>
270
+ {actions && <SidebarFooter>{actions}</SidebarFooter>}
271
+ <SidebarRail />
272
+ </Sidebar>
273
+ <SidebarInset ref={ref} data-slot="app-shell" className={className}>
274
+ {header !== undefined ? (
275
+ header
276
+ ) : (
277
+ <header className="flex h-14 shrink-0 items-center gap-2 border-b px-4">
278
+ <SidebarTrigger />
279
+ <Separator orientation="vertical" className="h-4" />
280
+ </header>
281
+ )}
282
+ <main className="flex-1 overflow-auto">{children}</main>
283
+ </SidebarInset>
284
+ </SidebarProvider>
285
+ )
286
+ })
287
+ AppShell.displayName = "AppShell"