@poodle64/ui 2026.8.7

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 (387) hide show
  1. package/README.md +624 -0
  2. package/dist/components/ui/alert/alert-description.svelte +23 -0
  3. package/dist/components/ui/alert/alert-description.svelte.d.ts +9 -0
  4. package/dist/components/ui/alert/alert-title.svelte +23 -0
  5. package/dist/components/ui/alert/alert-title.svelte.d.ts +9 -0
  6. package/dist/components/ui/alert/alert.svelte +46 -0
  7. package/dist/components/ui/alert/alert.svelte.d.ts +28 -0
  8. package/dist/components/ui/alert/index.d.ts +4 -0
  9. package/dist/components/ui/alert/index.js +4 -0
  10. package/dist/components/ui/alert-dialog/alert-dialog-action.svelte +27 -0
  11. package/dist/components/ui/alert-dialog/alert-dialog-action.svelte.d.ts +9 -0
  12. package/dist/components/ui/alert-dialog/alert-dialog-cancel.svelte +27 -0
  13. package/dist/components/ui/alert-dialog/alert-dialog-cancel.svelte.d.ts +9 -0
  14. package/dist/components/ui/alert-dialog/alert-dialog-content.svelte +39 -0
  15. package/dist/components/ui/alert-dialog/alert-dialog-content.svelte.d.ts +11 -0
  16. package/dist/components/ui/alert-dialog/alert-dialog-description.svelte +20 -0
  17. package/dist/components/ui/alert-dialog/alert-dialog-description.svelte.d.ts +4 -0
  18. package/dist/components/ui/alert-dialog/alert-dialog-footer.svelte +23 -0
  19. package/dist/components/ui/alert-dialog/alert-dialog-footer.svelte.d.ts +5 -0
  20. package/dist/components/ui/alert-dialog/alert-dialog-header.svelte +23 -0
  21. package/dist/components/ui/alert-dialog/alert-dialog-header.svelte.d.ts +5 -0
  22. package/dist/components/ui/alert-dialog/alert-dialog-media.svelte +23 -0
  23. package/dist/components/ui/alert-dialog/alert-dialog-media.svelte.d.ts +5 -0
  24. package/dist/components/ui/alert-dialog/alert-dialog-overlay.svelte +20 -0
  25. package/dist/components/ui/alert-dialog/alert-dialog-overlay.svelte.d.ts +4 -0
  26. package/dist/components/ui/alert-dialog/alert-dialog-portal.svelte +7 -0
  27. package/dist/components/ui/alert-dialog/alert-dialog-portal.svelte.d.ts +3 -0
  28. package/dist/components/ui/alert-dialog/alert-dialog-title.svelte +20 -0
  29. package/dist/components/ui/alert-dialog/alert-dialog-title.svelte.d.ts +4 -0
  30. package/dist/components/ui/alert-dialog/alert-dialog-trigger.svelte +7 -0
  31. package/dist/components/ui/alert-dialog/alert-dialog-trigger.svelte.d.ts +4 -0
  32. package/dist/components/ui/alert-dialog/alert-dialog.svelte +7 -0
  33. package/dist/components/ui/alert-dialog/alert-dialog.svelte.d.ts +3 -0
  34. package/dist/components/ui/alert-dialog/index.d.ts +13 -0
  35. package/dist/components/ui/alert-dialog/index.js +15 -0
  36. package/dist/components/ui/app-dialog/app-dialog.svelte +111 -0
  37. package/dist/components/ui/app-dialog/app-dialog.svelte.d.ts +41 -0
  38. package/dist/components/ui/app-dialog/index.d.ts +2 -0
  39. package/dist/components/ui/app-dialog/index.js +2 -0
  40. package/dist/components/ui/app-shell/app-nav.svelte +299 -0
  41. package/dist/components/ui/app-shell/app-nav.svelte.d.ts +22 -0
  42. package/dist/components/ui/app-shell/app-shell.svelte +675 -0
  43. package/dist/components/ui/app-shell/app-shell.svelte.d.ts +157 -0
  44. package/dist/components/ui/app-shell/index.d.ts +6 -0
  45. package/dist/components/ui/app-shell/index.js +6 -0
  46. package/dist/components/ui/app-shell/measure.d.ts +28 -0
  47. package/dist/components/ui/app-shell/measure.js +21 -0
  48. package/dist/components/ui/app-shell/texture.d.ts +32 -0
  49. package/dist/components/ui/app-shell/texture.js +27 -0
  50. package/dist/components/ui/app-shell/types.d.ts +134 -0
  51. package/dist/components/ui/app-shell/types.js +88 -0
  52. package/dist/components/ui/arc-gauge/arc-gauge.svelte +112 -0
  53. package/dist/components/ui/arc-gauge/arc-gauge.svelte.d.ts +15 -0
  54. package/dist/components/ui/arc-gauge/index.d.ts +3 -0
  55. package/dist/components/ui/arc-gauge/index.js +2 -0
  56. package/dist/components/ui/avatar/avatar-fallback.svelte +26 -0
  57. package/dist/components/ui/avatar/avatar-fallback.svelte.d.ts +4 -0
  58. package/dist/components/ui/avatar/avatar-image.svelte +17 -0
  59. package/dist/components/ui/avatar/avatar-image.svelte.d.ts +4 -0
  60. package/dist/components/ui/avatar/avatar.svelte +31 -0
  61. package/dist/components/ui/avatar/avatar.svelte.d.ts +4 -0
  62. package/dist/components/ui/avatar/index.d.ts +4 -0
  63. package/dist/components/ui/avatar/index.js +6 -0
  64. package/dist/components/ui/badge/badge.svelte +50 -0
  65. package/dist/components/ui/badge/badge.svelte.d.ts +38 -0
  66. package/dist/components/ui/badge/index.d.ts +2 -0
  67. package/dist/components/ui/badge/index.js +2 -0
  68. package/dist/components/ui/bar-row/bar-row.svelte +42 -0
  69. package/dist/components/ui/bar-row/bar-row.svelte.d.ts +12 -0
  70. package/dist/components/ui/bar-row/index.d.ts +2 -0
  71. package/dist/components/ui/bar-row/index.js +2 -0
  72. package/dist/components/ui/button/button.svelte +89 -0
  73. package/dist/components/ui/button/button.svelte.d.ts +70 -0
  74. package/dist/components/ui/button/index.d.ts +2 -0
  75. package/dist/components/ui/button/index.js +4 -0
  76. package/dist/components/ui/card/card-action.svelte +23 -0
  77. package/dist/components/ui/card/card-action.svelte.d.ts +5 -0
  78. package/dist/components/ui/card/card-content.svelte +20 -0
  79. package/dist/components/ui/card/card-content.svelte.d.ts +5 -0
  80. package/dist/components/ui/card/card-description.svelte +20 -0
  81. package/dist/components/ui/card/card-description.svelte.d.ts +5 -0
  82. package/dist/components/ui/card/card-footer.svelte +23 -0
  83. package/dist/components/ui/card/card-footer.svelte.d.ts +5 -0
  84. package/dist/components/ui/card/card-header.svelte +23 -0
  85. package/dist/components/ui/card/card-header.svelte.d.ts +5 -0
  86. package/dist/components/ui/card/card-title.svelte +52 -0
  87. package/dist/components/ui/card/card-title.svelte.d.ts +8 -0
  88. package/dist/components/ui/card/card.svelte +25 -0
  89. package/dist/components/ui/card/card.svelte.d.ts +8 -0
  90. package/dist/components/ui/card/index.d.ts +8 -0
  91. package/dist/components/ui/card/index.js +10 -0
  92. package/dist/components/ui/checkbox/checkbox.svelte +36 -0
  93. package/dist/components/ui/checkbox/checkbox.svelte.d.ts +8 -0
  94. package/dist/components/ui/checkbox/index.d.ts +2 -0
  95. package/dist/components/ui/checkbox/index.js +2 -0
  96. package/dist/components/ui/command/command-dialog.svelte +42 -0
  97. package/dist/components/ui/command/command-dialog.svelte.d.ts +14 -0
  98. package/dist/components/ui/command/command-empty.svelte +17 -0
  99. package/dist/components/ui/command/command-empty.svelte.d.ts +4 -0
  100. package/dist/components/ui/command/command-group.svelte +33 -0
  101. package/dist/components/ui/command/command-group.svelte.d.ts +7 -0
  102. package/dist/components/ui/command/command-input.svelte +36 -0
  103. package/dist/components/ui/command/command-input.svelte.d.ts +4 -0
  104. package/dist/components/ui/command/command-item.svelte +27 -0
  105. package/dist/components/ui/command/command-item.svelte.d.ts +4 -0
  106. package/dist/components/ui/command/command-link-item.svelte +20 -0
  107. package/dist/components/ui/command/command-link-item.svelte.d.ts +4 -0
  108. package/dist/components/ui/command/command-list.svelte +20 -0
  109. package/dist/components/ui/command/command-list.svelte.d.ts +4 -0
  110. package/dist/components/ui/command/command-loading.svelte +7 -0
  111. package/dist/components/ui/command/command-loading.svelte.d.ts +4 -0
  112. package/dist/components/ui/command/command-separator.svelte +17 -0
  113. package/dist/components/ui/command/command-separator.svelte.d.ts +4 -0
  114. package/dist/components/ui/command/command-shortcut.svelte +23 -0
  115. package/dist/components/ui/command/command-shortcut.svelte.d.ts +5 -0
  116. package/dist/components/ui/command/command.svelte +28 -0
  117. package/dist/components/ui/command/command.svelte.d.ts +8 -0
  118. package/dist/components/ui/command/index.d.ts +12 -0
  119. package/dist/components/ui/command/index.js +14 -0
  120. package/dist/components/ui/command-palette/command-palette.svelte +94 -0
  121. package/dist/components/ui/command-palette/command-palette.svelte.d.ts +40 -0
  122. package/dist/components/ui/command-palette/index.d.ts +3 -0
  123. package/dist/components/ui/command-palette/index.js +2 -0
  124. package/dist/components/ui/context-column/context-column.svelte +56 -0
  125. package/dist/components/ui/context-column/context-column.svelte.d.ts +14 -0
  126. package/dist/components/ui/context-column/index.d.ts +2 -0
  127. package/dist/components/ui/context-column/index.js +2 -0
  128. package/dist/components/ui/data-table/data-table.svelte.d.ts +40 -0
  129. package/dist/components/ui/data-table/data-table.svelte.js +110 -0
  130. package/dist/components/ui/data-table/flex-render.svelte +40 -0
  131. package/dist/components/ui/data-table/flex-render.svelte.d.ts +33 -0
  132. package/dist/components/ui/data-table/index.d.ts +3 -0
  133. package/dist/components/ui/data-table/index.js +3 -0
  134. package/dist/components/ui/data-table/render-helpers.d.ts +90 -0
  135. package/dist/components/ui/data-table/render-helpers.js +99 -0
  136. package/dist/components/ui/data-table-tanstack/data-table-tanstack.svelte +247 -0
  137. package/dist/components/ui/data-table-tanstack/data-table-tanstack.svelte.d.ts +79 -0
  138. package/dist/components/ui/data-table-tanstack/index.d.ts +3 -0
  139. package/dist/components/ui/data-table-tanstack/index.js +2 -0
  140. package/dist/components/ui/data-table-toolbar/data-table-toolbar.svelte +102 -0
  141. package/dist/components/ui/data-table-toolbar/data-table-toolbar.svelte.d.ts +32 -0
  142. package/dist/components/ui/data-table-toolbar/index.d.ts +3 -0
  143. package/dist/components/ui/data-table-toolbar/index.js +2 -0
  144. package/dist/components/ui/detail-panel/detail-panel.svelte +95 -0
  145. package/dist/components/ui/detail-panel/detail-panel.svelte.d.ts +26 -0
  146. package/dist/components/ui/detail-panel/index.d.ts +2 -0
  147. package/dist/components/ui/detail-panel/index.js +2 -0
  148. package/dist/components/ui/dialog/dialog-close.svelte +11 -0
  149. package/dist/components/ui/dialog/dialog-close.svelte.d.ts +4 -0
  150. package/dist/components/ui/dialog/dialog-content.svelte +48 -0
  151. package/dist/components/ui/dialog/dialog-content.svelte.d.ts +13 -0
  152. package/dist/components/ui/dialog/dialog-description.svelte +20 -0
  153. package/dist/components/ui/dialog/dialog-description.svelte.d.ts +4 -0
  154. package/dist/components/ui/dialog/dialog-footer.svelte +35 -0
  155. package/dist/components/ui/dialog/dialog-footer.svelte.d.ts +8 -0
  156. package/dist/components/ui/dialog/dialog-header.svelte +20 -0
  157. package/dist/components/ui/dialog/dialog-header.svelte.d.ts +5 -0
  158. package/dist/components/ui/dialog/dialog-overlay.svelte +20 -0
  159. package/dist/components/ui/dialog/dialog-overlay.svelte.d.ts +4 -0
  160. package/dist/components/ui/dialog/dialog-portal.svelte +7 -0
  161. package/dist/components/ui/dialog/dialog-portal.svelte.d.ts +3 -0
  162. package/dist/components/ui/dialog/dialog-title.svelte +17 -0
  163. package/dist/components/ui/dialog/dialog-title.svelte.d.ts +4 -0
  164. package/dist/components/ui/dialog/dialog-trigger.svelte +11 -0
  165. package/dist/components/ui/dialog/dialog-trigger.svelte.d.ts +4 -0
  166. package/dist/components/ui/dialog/dialog.svelte +7 -0
  167. package/dist/components/ui/dialog/dialog.svelte.d.ts +3 -0
  168. package/dist/components/ui/dialog/index.d.ts +11 -0
  169. package/dist/components/ui/dialog/index.js +13 -0
  170. package/dist/components/ui/dialog-section/dialog-section.svelte +20 -0
  171. package/dist/components/ui/dialog-section/dialog-section.svelte.d.ts +8 -0
  172. package/dist/components/ui/dialog-section/index.d.ts +2 -0
  173. package/dist/components/ui/dialog-section/index.js +2 -0
  174. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
  175. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +4 -0
  176. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +44 -0
  177. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
  178. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +31 -0
  179. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +10 -0
  180. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
  181. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +8 -0
  182. package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
  183. package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte.d.ts +4 -0
  184. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
  185. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +8 -0
  186. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +27 -0
  187. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +8 -0
  188. package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
  189. package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte.d.ts +3 -0
  190. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
  191. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +4 -0
  192. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +34 -0
  193. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +4 -0
  194. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
  195. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +4 -0
  196. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +23 -0
  197. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +5 -0
  198. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +20 -0
  199. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +4 -0
  200. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
  201. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +7 -0
  202. package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
  203. package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte.d.ts +3 -0
  204. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
  205. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +4 -0
  206. package/dist/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
  207. package/dist/components/ui/dropdown-menu/dropdown-menu.svelte.d.ts +3 -0
  208. package/dist/components/ui/dropdown-menu/index.d.ts +18 -0
  209. package/dist/components/ui/dropdown-menu/index.js +18 -0
  210. package/dist/components/ui/empty-state/empty-state.svelte +44 -0
  211. package/dist/components/ui/empty-state/empty-state.svelte.d.ts +14 -0
  212. package/dist/components/ui/empty-state/index.d.ts +2 -0
  213. package/dist/components/ui/empty-state/index.js +2 -0
  214. package/dist/components/ui/error-state/error-state.svelte +52 -0
  215. package/dist/components/ui/error-state/error-state.svelte.d.ts +10 -0
  216. package/dist/components/ui/error-state/index.d.ts +2 -0
  217. package/dist/components/ui/error-state/index.js +2 -0
  218. package/dist/components/ui/info-tip/index.d.ts +2 -0
  219. package/dist/components/ui/info-tip/index.js +2 -0
  220. package/dist/components/ui/info-tip/info-tip.svelte +37 -0
  221. package/dist/components/ui/info-tip/info-tip.svelte.d.ts +10 -0
  222. package/dist/components/ui/input/index.d.ts +2 -0
  223. package/dist/components/ui/input/index.js +4 -0
  224. package/dist/components/ui/input/input.svelte +48 -0
  225. package/dist/components/ui/input/input.svelte.d.ts +13 -0
  226. package/dist/components/ui/input-group/index.d.ts +7 -0
  227. package/dist/components/ui/input-group/index.js +9 -0
  228. package/dist/components/ui/input-group/input-group-addon.svelte +53 -0
  229. package/dist/components/ui/input-group/input-group-addon.svelte.d.ts +32 -0
  230. package/dist/components/ui/input-group/input-group-button.svelte +49 -0
  231. package/dist/components/ui/input-group/input-group-button.svelte.d.ts +32 -0
  232. package/dist/components/ui/input-group/input-group-input.svelte +23 -0
  233. package/dist/components/ui/input-group/input-group-input.svelte.d.ts +11 -0
  234. package/dist/components/ui/input-group/input-group-text.svelte +22 -0
  235. package/dist/components/ui/input-group/input-group-text.svelte.d.ts +5 -0
  236. package/dist/components/ui/input-group/input-group-textarea.svelte +23 -0
  237. package/dist/components/ui/input-group/input-group-textarea.svelte.d.ts +3 -0
  238. package/dist/components/ui/input-group/input-group.svelte +24 -0
  239. package/dist/components/ui/input-group/input-group.svelte.d.ts +5 -0
  240. package/dist/components/ui/label/index.d.ts +2 -0
  241. package/dist/components/ui/label/index.js +4 -0
  242. package/dist/components/ui/label/label.svelte +20 -0
  243. package/dist/components/ui/label/label.svelte.d.ts +4 -0
  244. package/dist/components/ui/loading-state/index.d.ts +2 -0
  245. package/dist/components/ui/loading-state/index.js +2 -0
  246. package/dist/components/ui/loading-state/loading-state.svelte +28 -0
  247. package/dist/components/ui/loading-state/loading-state.svelte.d.ts +8 -0
  248. package/dist/components/ui/page-header/index.d.ts +2 -0
  249. package/dist/components/ui/page-header/index.js +2 -0
  250. package/dist/components/ui/page-header/page-header.svelte +100 -0
  251. package/dist/components/ui/page-header/page-header.svelte.d.ts +17 -0
  252. package/dist/components/ui/panel/index.d.ts +2 -0
  253. package/dist/components/ui/panel/index.js +2 -0
  254. package/dist/components/ui/panel/panel.svelte +54 -0
  255. package/dist/components/ui/panel/panel.svelte.d.ts +16 -0
  256. package/dist/components/ui/password-input/index.d.ts +2 -0
  257. package/dist/components/ui/password-input/index.js +4 -0
  258. package/dist/components/ui/password-input/password-input.svelte +48 -0
  259. package/dist/components/ui/password-input/password-input.svelte.d.ts +8 -0
  260. package/dist/components/ui/popover/index.d.ts +4 -0
  261. package/dist/components/ui/popover/index.js +6 -0
  262. package/dist/components/ui/popover/popover-content.svelte +45 -0
  263. package/dist/components/ui/popover/popover-content.svelte.d.ts +7 -0
  264. package/dist/components/ui/popover/popover-trigger.svelte +7 -0
  265. package/dist/components/ui/popover/popover-trigger.svelte.d.ts +4 -0
  266. package/dist/components/ui/popover/popover.svelte +7 -0
  267. package/dist/components/ui/popover/popover.svelte.d.ts +3 -0
  268. package/dist/components/ui/progress/index.d.ts +2 -0
  269. package/dist/components/ui/progress/index.js +4 -0
  270. package/dist/components/ui/progress/progress.svelte +30 -0
  271. package/dist/components/ui/progress/progress.svelte.d.ts +4 -0
  272. package/dist/components/ui/scorecard/index.d.ts +2 -0
  273. package/dist/components/ui/scorecard/index.js +2 -0
  274. package/dist/components/ui/scorecard/scorecard.svelte +35 -0
  275. package/dist/components/ui/scorecard/scorecard.svelte.d.ts +8 -0
  276. package/dist/components/ui/select/index.d.ts +12 -0
  277. package/dist/components/ui/select/index.js +14 -0
  278. package/dist/components/ui/select/select-content.svelte +45 -0
  279. package/dist/components/ui/select/select-content.svelte.d.ts +11 -0
  280. package/dist/components/ui/select/select-group-heading.svelte +21 -0
  281. package/dist/components/ui/select/select-group-heading.svelte.d.ts +10 -0
  282. package/dist/components/ui/select/select-group.svelte +17 -0
  283. package/dist/components/ui/select/select-group.svelte.d.ts +4 -0
  284. package/dist/components/ui/select/select-item.svelte +38 -0
  285. package/dist/components/ui/select/select-item.svelte.d.ts +4 -0
  286. package/dist/components/ui/select/select-label.svelte +20 -0
  287. package/dist/components/ui/select/select-label.svelte.d.ts +6 -0
  288. package/dist/components/ui/select/select-portal.svelte +7 -0
  289. package/dist/components/ui/select/select-portal.svelte.d.ts +3 -0
  290. package/dist/components/ui/select/select-scroll-down-button.svelte +23 -0
  291. package/dist/components/ui/select/select-scroll-down-button.svelte.d.ts +4 -0
  292. package/dist/components/ui/select/select-scroll-up-button.svelte +23 -0
  293. package/dist/components/ui/select/select-scroll-up-button.svelte.d.ts +4 -0
  294. package/dist/components/ui/select/select-separator.svelte +18 -0
  295. package/dist/components/ui/select/select-separator.svelte.d.ts +4 -0
  296. package/dist/components/ui/select/select-trigger.svelte +29 -0
  297. package/dist/components/ui/select/select-trigger.svelte.d.ts +8 -0
  298. package/dist/components/ui/select/select.svelte +11 -0
  299. package/dist/components/ui/select/select.svelte.d.ts +3 -0
  300. package/dist/components/ui/separator/index.d.ts +2 -0
  301. package/dist/components/ui/separator/index.js +4 -0
  302. package/dist/components/ui/separator/separator.svelte +23 -0
  303. package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
  304. package/dist/components/ui/skeleton/index.d.ts +2 -0
  305. package/dist/components/ui/skeleton/index.js +4 -0
  306. package/dist/components/ui/skeleton/skeleton.svelte +17 -0
  307. package/dist/components/ui/skeleton/skeleton.svelte.d.ts +5 -0
  308. package/dist/components/ui/sonner/index.d.ts +1 -0
  309. package/dist/components/ui/sonner/index.js +1 -0
  310. package/dist/components/ui/sonner/sonner.svelte +34 -0
  311. package/dist/components/ui/sonner/sonner.svelte.d.ts +4 -0
  312. package/dist/components/ui/sparkline/index.d.ts +3 -0
  313. package/dist/components/ui/sparkline/index.js +2 -0
  314. package/dist/components/ui/sparkline/sparkline.svelte +90 -0
  315. package/dist/components/ui/sparkline/sparkline.svelte.d.ts +16 -0
  316. package/dist/components/ui/stat-card/index.d.ts +2 -0
  317. package/dist/components/ui/stat-card/index.js +2 -0
  318. package/dist/components/ui/stat-card/stat-card.svelte +77 -0
  319. package/dist/components/ui/stat-card/stat-card.svelte.d.ts +34 -0
  320. package/dist/components/ui/stat-list/index.d.ts +3 -0
  321. package/dist/components/ui/stat-list/index.js +2 -0
  322. package/dist/components/ui/stat-list/stat-list.svelte +80 -0
  323. package/dist/components/ui/stat-list/stat-list.svelte.d.ts +23 -0
  324. package/dist/components/ui/status/index.d.ts +1 -0
  325. package/dist/components/ui/status/index.js +1 -0
  326. package/dist/components/ui/status-badge/index.d.ts +3 -0
  327. package/dist/components/ui/status-badge/index.js +2 -0
  328. package/dist/components/ui/status-badge/status-badge.svelte +53 -0
  329. package/dist/components/ui/status-badge/status-badge.svelte.d.ts +39 -0
  330. package/dist/components/ui/switch/index.d.ts +2 -0
  331. package/dist/components/ui/switch/index.js +4 -0
  332. package/dist/components/ui/switch/switch.svelte +39 -0
  333. package/dist/components/ui/switch/switch.svelte.d.ts +4 -0
  334. package/dist/components/ui/table/index.d.ts +10 -0
  335. package/dist/components/ui/table/index.js +12 -0
  336. package/dist/components/ui/table/table-body.svelte +20 -0
  337. package/dist/components/ui/table/table-body.svelte.d.ts +5 -0
  338. package/dist/components/ui/table/table-caption.svelte +20 -0
  339. package/dist/components/ui/table/table-caption.svelte.d.ts +5 -0
  340. package/dist/components/ui/table/table-cell.svelte +20 -0
  341. package/dist/components/ui/table/table-cell.svelte.d.ts +5 -0
  342. package/dist/components/ui/table/table-classes.d.ts +15 -0
  343. package/dist/components/ui/table/table-classes.js +15 -0
  344. package/dist/components/ui/table/table-footer.svelte +20 -0
  345. package/dist/components/ui/table/table-footer.svelte.d.ts +5 -0
  346. package/dist/components/ui/table/table-head.svelte +23 -0
  347. package/dist/components/ui/table/table-head.svelte.d.ts +5 -0
  348. package/dist/components/ui/table/table-header.svelte +20 -0
  349. package/dist/components/ui/table/table-header.svelte.d.ts +5 -0
  350. package/dist/components/ui/table/table-row.svelte +23 -0
  351. package/dist/components/ui/table/table-row.svelte.d.ts +5 -0
  352. package/dist/components/ui/table/table.svelte +37 -0
  353. package/dist/components/ui/table/table.svelte.d.ts +20 -0
  354. package/dist/components/ui/tabs/index.d.ts +5 -0
  355. package/dist/components/ui/tabs/index.js +7 -0
  356. package/dist/components/ui/tabs/tabs-content.svelte +13 -0
  357. package/dist/components/ui/tabs/tabs-content.svelte.d.ts +4 -0
  358. package/dist/components/ui/tabs/tabs-list.svelte +16 -0
  359. package/dist/components/ui/tabs/tabs-list.svelte.d.ts +4 -0
  360. package/dist/components/ui/tabs/tabs-trigger.svelte +16 -0
  361. package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
  362. package/dist/components/ui/tabs/tabs.svelte +19 -0
  363. package/dist/components/ui/tabs/tabs.svelte.d.ts +4 -0
  364. package/dist/components/ui/textarea/index.d.ts +2 -0
  365. package/dist/components/ui/textarea/index.js +4 -0
  366. package/dist/components/ui/textarea/textarea.svelte +22 -0
  367. package/dist/components/ui/textarea/textarea.svelte.d.ts +5 -0
  368. package/dist/components/ui/tile-grid/index.d.ts +2 -0
  369. package/dist/components/ui/tile-grid/index.js +2 -0
  370. package/dist/components/ui/tile-grid/tile-grid.svelte +66 -0
  371. package/dist/components/ui/tile-grid/tile-grid.svelte.d.ts +43 -0
  372. package/dist/components/ui/tooltip/index.d.ts +6 -0
  373. package/dist/components/ui/tooltip/index.js +8 -0
  374. package/dist/components/ui/tooltip/tooltip-content.svelte +52 -0
  375. package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +11 -0
  376. package/dist/components/ui/tooltip/tooltip-portal.svelte +7 -0
  377. package/dist/components/ui/tooltip/tooltip-portal.svelte.d.ts +4 -0
  378. package/dist/components/ui/tooltip/tooltip-provider.svelte +7 -0
  379. package/dist/components/ui/tooltip/tooltip-provider.svelte.d.ts +4 -0
  380. package/dist/components/ui/tooltip/tooltip-trigger.svelte +7 -0
  381. package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +4 -0
  382. package/dist/components/ui/tooltip/tooltip.svelte +7 -0
  383. package/dist/components/ui/tooltip/tooltip.svelte.d.ts +4 -0
  384. package/dist/styles.css +961 -0
  385. package/dist/utils.d.ts +12 -0
  386. package/dist/utils.js +5 -0
  387. package/package.json +81 -0
@@ -0,0 +1,157 @@
1
+ /**
2
+ * The application shell: navigation, top bar and page frame, once.
3
+ *
4
+ * Primitives and page chrome are not what makes an app feel like an app — the
5
+ * shell is. Five household frontends were surveyed before this API was
6
+ * settled, and between them they had built five shells: a rail-plus-drawer,
7
+ * an eleven-file collapsible sidebar tree under its own top bar, and three
8
+ * header-only bars that each solved the mobile question differently. They
9
+ * agreed on almost nothing structurally while looking like they were trying
10
+ * to be the same thing.
11
+ *
12
+ * There is now exactly one composition, no variant prop to choose it: a
13
+ * permanent side rail on md+ (an overlay drawer below it) carrying primary
14
+ * navigation and a brand row that also carries the collapse toggle, PLUS a
15
+ * real top navbar (search, leading/trailing slots, theme toggle, identity) —
16
+ * always both together. Operator ruling, 31/07/2026: every household app
17
+ * renders one shell shape; apps do not choose variants.
18
+ *
19
+ * The collapse toggle sits at the rail's own top edge, on the brand row,
20
+ * where every comparable shell puts a control that acts on the rail — icon
21
+ * only, right of the wordmark, stacking under the mark when the rail is
22
+ * collapsed. The foot is left to the app.
23
+ *
24
+ * Search can sit in either of two places, because it reads as a different
25
+ * thing depending on what is beside it. `searchPlacement` defaults to
26
+ * `leading` — its historical spot just after the `context` slot, so a shell
27
+ * that never names the prop is unchanged — and `trailing` moves it into the
28
+ * right-hand group with the theme toggle and identity, so that when `context`
29
+ * carries route content the global affordance reads as global rather than as
30
+ * part of the switcher next to it.
31
+ *
32
+ * Content WIDTH is the one dimension that came back, as `measure`, and it
33
+ * came back on a measurement rather than on taste. "Always full-width" did
34
+ * not remove the decision, it pushed it down into every page: a consumer was
35
+ * surveyed at 2560px and had six distinct caps across nine routes, every one
36
+ * of them a hand-written `mx-auto max-w-*` at the top of a `+page.svelte`,
37
+ * between them using 15% to 79% of the width actually available. That is
38
+ * fifteen independent guesses, not a shell shape.
39
+ *
40
+ * `measure` is a small named scale, chosen once in the layout, and it is not
41
+ * the old `content` prop returning. It defaults to `full`, so a shell that
42
+ * never mentions it renders byte-identically; its tiers are CSS custom
43
+ * properties an app retunes without a release; and it exists to REPLACE
44
+ * per-page width decisions rather than to offer an app a look.
45
+ *
46
+ * Content TEXTURE came back the same way, on the same kind of evidence. Two
47
+ * apps had separately built one picture — a faint dot-grid floor with a soft
48
+ * accent vignette — under two names in two app.css files, and one of them
49
+ * applied it as a helper class per route, so it reached four routes out of
50
+ * about fifteen. Which pages wore the house atmosphere was decided by which
51
+ * pages someone had happened to touch. `texture` is one named picture the
52
+ * SHELL paints once, off by default, its inks tuned by custom properties.
53
+ *
54
+ * Everything else the surveyed apps differed on turned out to be a slot, not
55
+ * a variant: the brand, the identity surface, a context switcher, a banner, a
56
+ * secondary column. Those are snippets, so this package imports no app store,
57
+ * no app route and no app brand — the coupling that made the best shell in
58
+ * the estate unliftable in the first place.
59
+ *
60
+ * The minimum useful call is two props:
61
+ *
62
+ * <AppShell nav={navGroups} brandTitle="Console" currentPath={page.url.pathname}>
63
+ * {@render children()}
64
+ * </AppShell>
65
+ */
66
+ import type { Snippet } from 'svelte';
67
+ import type { ShellMeasure } from './measure.js';
68
+ import type { ShellTexture } from './texture.js';
69
+ import { type NavSource } from './types.js';
70
+ type $$ComponentProps = {
71
+ /** Navigation: bare items, groups, or a mix. Filter for permissions first. */
72
+ nav?: NavSource;
73
+ /** The primary nav landmark's accessible name — forwarded to the rail/drawer
74
+ AppNav. Distinguish it from a second shell on the same page, or from a
75
+ route-scoped secondary AppNav. */
76
+ navLabel?: string;
77
+ /**
78
+ * The current path, for active state and for closing the mobile nav on
79
+ * navigation. Apps pass `page.url.pathname`.
80
+ *
81
+ * It is a prop rather than a `$app/state` import on purpose: this package
82
+ * is built with svelte-package and has no SvelteKit runtime of its own, so
83
+ * importing `$app/state` would make SvelteKit a hard peer AND make the
84
+ * shell untestable outside a running app. One line at the call site buys
85
+ * a component that is framework-agnostic and genuinely drivable.
86
+ */
87
+ currentPath?: string;
88
+ /** Offer an icon-only collapse toggle at the rail head, on the brand row. */
89
+ collapsible?: boolean;
90
+ /** Rail collapse state. Bind it to persist the choice across sessions. */
91
+ collapsed?: boolean;
92
+ /** Full control of the brand lockup. Overrides brandTitle/brandMark. */
93
+ brand?: Snippet;
94
+ /** Wordmark text, rendered in the display face. */
95
+ brandTitle?: string;
96
+ /** The mark beside the wordmark — an app's own logo component. */
97
+ brandMark?: Snippet;
98
+ /** Where the brand links. */
99
+ homeHref?: string;
100
+ /** Full-width region directly under the top bar: reconnect notices, trials. */
101
+ banner?: Snippet;
102
+ /** Leading top-bar slot, before the search affordance: a context switcher. */
103
+ context?: Snippet;
104
+ /** Trailing top-bar slot, before the theme toggle: app-level action buttons. */
105
+ actions?: Snippet;
106
+ /** The signed-in user surface. Rendered once, at the end of the top bar. */
107
+ identity?: Snippet;
108
+ /** A secondary, route-scoped column between the nav and the page body. */
109
+ sidebar?: Snippet;
110
+ /** Provide to render the search affordance. Usually opens a CommandPalette. */
111
+ onSearch?: () => void;
112
+ searchLabel?: string;
113
+ /** The shortcut hint rendered in the search affordance; '' hides the kbd. */
114
+ searchShortcut?: string;
115
+ /**
116
+ * Where the search affordance sits in the top bar. `leading` (default)
117
+ * keeps its historical position just after the `context` slot; `trailing`
118
+ * moves it into the right-hand group with the theme toggle and identity —
119
+ * for when `context` carries route content and search should read as a
120
+ * global control rather than as part of it.
121
+ */
122
+ searchPlacement?: 'leading' | 'trailing';
123
+ themeToggle?: boolean;
124
+ /** Override the theme action. Defaults to mode-watcher's toggleMode. */
125
+ onToggleTheme?: () => void;
126
+ padded?: boolean;
127
+ /**
128
+ * How wide the page body may get, from a named scale: `prose` (72ch, for
129
+ * long-form running text), `page` (80rem — forms, detail views,
130
+ * settings), `wide` (120rem — indexes, grids, tables, dashboards), or
131
+ * `full` (no cap).
132
+ *
133
+ * Defaults to `full`, so a shell that does not mention it is unchanged.
134
+ * Set it in the layout, once: the point is that pages stop each deciding
135
+ * their own width. The cap is the content box's border box, so `padded`
136
+ * spends its padding inside the measure.
137
+ */
138
+ measure?: ShellMeasure;
139
+ /**
140
+ * The house atmosphere on the content region: `grid` (a dot-grid floor
141
+ * plus a corner vignette) or `none`.
142
+ *
143
+ * Defaults to `none`, so a shell that does not mention it is unchanged.
144
+ * Set it in the layout, once — that the SHELL paints it is the whole
145
+ * point, because a helper class apps apply per route is how one consumer
146
+ * ended up wearing the house texture on four routes out of fifteen. The
147
+ * inks and the pitch are `--ds-shell-texture-*` custom properties an app
148
+ * retunes in one declaration.
149
+ */
150
+ texture?: ShellTexture;
151
+ /** Extra classes on the scrolling content container. */
152
+ mainClass?: string;
153
+ children: Snippet;
154
+ };
155
+ declare const AppShell: import("svelte").Component<$$ComponentProps, {}, "collapsed">;
156
+ type AppShell = ReturnType<typeof AppShell>;
157
+ export default AppShell;
@@ -0,0 +1,6 @@
1
+ export { default as AppShell } from './app-shell.svelte';
2
+ export { default as AppNav } from './app-nav.svelte';
3
+ export { default } from './app-shell.svelte';
4
+ export { SHELL_MEASURES, type ShellMeasure } from './measure.js';
5
+ export { SHELL_TEXTURES, type ShellTexture } from './texture.js';
6
+ export { hasActiveNavChild, isNavGroup, isNavItemActive, navChildren, toGroups, toItems, type IconComponent, type NavChildItem, type NavEntry, type NavGroup, type NavItem, type NavSource } from './types.js';
@@ -0,0 +1,6 @@
1
+ export { default as AppShell } from './app-shell.svelte';
2
+ export { default as AppNav } from './app-nav.svelte';
3
+ export { default } from './app-shell.svelte';
4
+ export { SHELL_MEASURES } from './measure.js';
5
+ export { SHELL_TEXTURES } from './texture.js';
6
+ export { hasActiveNavChild, isNavGroup, isNavItemActive, navChildren, toGroups, toItems } from './types.js';
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The content measure: how wide the page body is allowed to get.
3
+ *
4
+ * A named scale rather than a width, because a width at the call site is the
5
+ * problem this exists to solve. Surveyed at 2560px, one consumer had six
6
+ * distinct caps across nine routes — `max-w-4xl` here, `max-w-[1600px]` there,
7
+ * a `max-w-md` form somewhere else — each written by whoever built that page,
8
+ * none of them wrong on its own, and no two agreeing. Between them they used
9
+ * 15% to 79% of the width available. A scale with four names cannot drift like
10
+ * that: it is one decision, taken once, in the layout.
11
+ *
12
+ * The tiers resolve through `--ds-shell-measure-*` custom properties (see
13
+ * `styles.css`), so an app retunes any of them in one declaration.
14
+ */
15
+ /**
16
+ * - `prose` — a genuine reading measure (`72ch`) for long-form running text.
17
+ * - `page` — everyday pages: forms, detail views, settings (`80rem`).
18
+ * - `wide` — indexes, card grids, tables, dashboards (`120rem`).
19
+ * - `full` — no cap. The default, so omitting `measure` changes nothing.
20
+ *
21
+ * The 80rem tier is `page` rather than `default` on purpose. The prop's default
22
+ * is `full`, and a value literally named `default` that you do NOT get by
23
+ * default is a trap a reader falls into once each. It is also not `standard`,
24
+ * which this package already retired for being a name that says nothing.
25
+ */
26
+ export type ShellMeasure = 'prose' | 'page' | 'wide' | 'full';
27
+ /** Every measure, narrowest first — the order the scale is documented in. */
28
+ export declare const SHELL_MEASURES: readonly ["prose", "page", "wide", "full"];
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The content measure: how wide the page body is allowed to get.
3
+ *
4
+ * A named scale rather than a width, because a width at the call site is the
5
+ * problem this exists to solve. Surveyed at 2560px, one consumer had six
6
+ * distinct caps across nine routes — `max-w-4xl` here, `max-w-[1600px]` there,
7
+ * a `max-w-md` form somewhere else — each written by whoever built that page,
8
+ * none of them wrong on its own, and no two agreeing. Between them they used
9
+ * 15% to 79% of the width available. A scale with four names cannot drift like
10
+ * that: it is one decision, taken once, in the layout.
11
+ *
12
+ * The tiers resolve through `--ds-shell-measure-*` custom properties (see
13
+ * `styles.css`), so an app retunes any of them in one declaration.
14
+ */
15
+ /** Every measure, narrowest first — the order the scale is documented in. */
16
+ export const SHELL_MEASURES = [
17
+ 'prose',
18
+ 'page',
19
+ 'wide',
20
+ 'full'
21
+ ];
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The content texture: the house "atmosphere" the shell paints on its own
3
+ * scrolling content region.
4
+ *
5
+ * Two apps had independently built the same thing — a faint dot-grid floor with
6
+ * a soft accent vignette in one corner — under two names, in two app.css files,
7
+ * with two sets of local variables. Neither was wrong; between them they are
8
+ * exactly the drift this package exists to end. Worse, one of them applied it as
9
+ * a helper class per route: four routes out of about fifteen carried it, so
10
+ * whether a page wore the house atmosphere came down to which page someone had
11
+ * happened to touch. A texture an app has to REMEMBER to apply is not a texture,
12
+ * it is a coin toss with a stylesheet.
13
+ *
14
+ * So it moves onto the shell, where there is exactly one place to say it and no
15
+ * per-route decision left to get wrong. `none` is the default, so a shell that
16
+ * never mentions it renders byte-identically.
17
+ *
18
+ * It is one texture, not a menu. Both apps wanted the same picture, and the
19
+ * axes they actually differed on — how dark the dots are, how the vignette is
20
+ * tinted, how far apart the dots sit — are values, not designs. They are
21
+ * `--ds-shell-texture-*` custom properties an app retunes in one declaration
22
+ * (see `styles.css`), which is also how a "plain wash" is reached without a
23
+ * second name in this union: set the grid ink to `transparent` and the vignette
24
+ * remains.
25
+ */
26
+ /**
27
+ * - `grid` — the house atmosphere: a dot-grid floor plus a corner vignette.
28
+ * - `none` — no texture. The default, so omitting `texture` changes nothing.
29
+ */
30
+ export type ShellTexture = 'none' | 'grid';
31
+ /** Every texture, the untextured default first — the order it is documented in. */
32
+ export declare const SHELL_TEXTURES: readonly ["none", "grid"];
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The content texture: the house "atmosphere" the shell paints on its own
3
+ * scrolling content region.
4
+ *
5
+ * Two apps had independently built the same thing — a faint dot-grid floor with
6
+ * a soft accent vignette in one corner — under two names, in two app.css files,
7
+ * with two sets of local variables. Neither was wrong; between them they are
8
+ * exactly the drift this package exists to end. Worse, one of them applied it as
9
+ * a helper class per route: four routes out of about fifteen carried it, so
10
+ * whether a page wore the house atmosphere came down to which page someone had
11
+ * happened to touch. A texture an app has to REMEMBER to apply is not a texture,
12
+ * it is a coin toss with a stylesheet.
13
+ *
14
+ * So it moves onto the shell, where there is exactly one place to say it and no
15
+ * per-route decision left to get wrong. `none` is the default, so a shell that
16
+ * never mentions it renders byte-identically.
17
+ *
18
+ * It is one texture, not a menu. Both apps wanted the same picture, and the
19
+ * axes they actually differed on — how dark the dots are, how the vignette is
20
+ * tinted, how far apart the dots sit — are values, not designs. They are
21
+ * `--ds-shell-texture-*` custom properties an app retunes in one declaration
22
+ * (see `styles.css`), which is also how a "plain wash" is reached without a
23
+ * second name in this union: set the grid ink to `transparent` and the vignette
24
+ * remains.
25
+ */
26
+ /** Every texture, the untextured default first — the order it is documented in. */
27
+ export const SHELL_TEXTURES = ['none', 'grid'];
@@ -0,0 +1,134 @@
1
+ /**
2
+ * The navigation vocabulary every app types its own config against.
3
+ *
4
+ * Five apps in the estate were surveyed before this shape was settled, and each
5
+ * had reinvented the same three fields under different names (`label`/`title`,
6
+ * `href`/`path`) plus one or two extras nobody else had. The intersection —
7
+ * label, href, icon — is what every one of them actually needed; `badge`,
8
+ * `exact` and `external` are the union of the genuine extras, each optional so
9
+ * the common case stays two fields.
10
+ *
11
+ * Deliberately ABSENT: any notion of who may see an item. Two apps gate nav on
12
+ * `is_admin` / per-module permission, and both do it with their own auth store.
13
+ * A shared package that knew about permissions would have to know about auth,
14
+ * which is exactly the coupling that made the reference shell unliftable. Apps
15
+ * filter before they pass:
16
+ *
17
+ * const nav = $derived(allNav.filter((i) => !i.adminOnly || user.isAdmin));
18
+ */
19
+ import type { Component } from 'svelte';
20
+ /** A Lucide (or equivalent) icon component: takes a class, renders an SVG. */
21
+ export type IconComponent = Component<{
22
+ class?: string;
23
+ }>;
24
+ /** One navigable destination. */
25
+ export interface NavItem {
26
+ /** The visible text. Also the accessible name when the rail is collapsed. */
27
+ label: string;
28
+ /** Destination path. */
29
+ href: string;
30
+ /** Optional leading icon. Omit it for a label-only row; alignment is kept. */
31
+ icon?: IconComponent;
32
+ /** Optional trailing count or short tag (an unread count, a "beta" tag). */
33
+ badge?: string | number;
34
+ /**
35
+ * Match the current path exactly rather than by prefix. Prefix is the
36
+ * default because a section root should stay lit while you are inside it;
37
+ * `href: '/'` is always treated as exact, since every path is prefixed by it.
38
+ */
39
+ exact?: boolean;
40
+ /** Open in a new tab. Renders the standard rel and an off-site affordance. */
41
+ external?: boolean;
42
+ /**
43
+ * Additional path prefixes this item also owns, beyond its own `href`.
44
+ *
45
+ * Flat navigation has every section's children living under the section's
46
+ * own path, which `href`'s prefix match already covers. It breaks for a
47
+ * section whose children live under a different top-level route — a
48
+ * "browse" list whose detail pages sit at their own short URL rather than
49
+ * nested under the list. Each prefix here is matched exactly like `href`
50
+ * is (prefix, with the same path-segment boundary), independently of
51
+ * `exact` and independently of `href` being forced to exact at `/`: a root
52
+ * item can still claim an additional prefix by full path match.
53
+ */
54
+ matchPrefixes?: string[];
55
+ /**
56
+ * A section's own sub-navigation, disclosed in place beneath it.
57
+ *
58
+ * Without this, an app whose sections have their own inner navigation has
59
+ * nowhere to put it inside the rail. The observed workaround was modules in
60
+ * `nav` and the current module's pages in the `sidebar` snippet — two
61
+ * left-hand columns on a desktop, and, the reason this shape won over moving
62
+ * modules to a top bar, two surfaces on a phone that both want the same
63
+ * hamburger. One nested tree collapses to one drawer.
64
+ *
65
+ * Named `children`, not `items`, for a mechanical reason as well as a
66
+ * readable one: `isNavGroup` narrows on `'items' in entry`, so an item
67
+ * carrying `items` would be misread as a GROUP by every consumer of this
68
+ * vocabulary, this package's own renderer included.
69
+ *
70
+ * ONE level, and the type is what enforces it: a child is `NavItem` minus
71
+ * this field, so a second nesting is a compile error where the nav is
72
+ * authored rather than a rail nobody can read. The cap is deliberate. The
73
+ * rail is 15.5rem and every level costs an indent; by depth three the label
74
+ * has less room than the chevron beside it. Every household case is one
75
+ * level, and a genuinely deeper tree belongs in the page body, which has the
76
+ * width for it.
77
+ */
78
+ children?: readonly NavChildItem[];
79
+ }
80
+ /**
81
+ * A row inside a parent's disclosure: everything an item is, minus the ability
82
+ * to nest again.
83
+ */
84
+ export type NavChildItem = Omit<NavItem, 'children'>;
85
+ /** A titled run of items. The heading is optional — a leading group usually has none. */
86
+ export interface NavGroup {
87
+ heading?: string;
88
+ items: NavItem[];
89
+ }
90
+ /**
91
+ * What the `nav` prop accepts: bare items, groups, or a mix.
92
+ *
93
+ * Three of the five surveyed apps have flat navigation and two have groups, so
94
+ * requiring one shape would have made three apps write `[{ items: [...] }]`
95
+ * wrapper noise or two apps flatten away their headings. A mixed array costs one
96
+ * type guard here and nothing at the call site.
97
+ */
98
+ export type NavEntry = NavItem | NavGroup;
99
+ export type NavSource = readonly NavEntry[];
100
+ /** Narrow a mixed entry to a group. */
101
+ export declare function isNavGroup(entry: NavEntry): entry is NavGroup;
102
+ /** Normalise any accepted shape to groups, dropping groups that would render empty. */
103
+ export declare function toGroups(nav: NavSource | undefined): NavGroup[];
104
+ /** An item's disclosed rows, normalised — an empty list where there are none. */
105
+ export declare function navChildren(item: NavItem): readonly NavChildItem[];
106
+ /**
107
+ * Every item in source order, ignoring grouping — a parent immediately followed
108
+ * by its own children. Used by the command palette.
109
+ *
110
+ * Children are included because they are destinations like any other, and the
111
+ * palette is the fastest route to a page three levels into a section. An item
112
+ * with no children flattens exactly as it always did.
113
+ */
114
+ export declare function toItems(nav: NavSource | undefined): NavItem[];
115
+ /**
116
+ * Whether `item` is the current page.
117
+ *
118
+ * Prefix matching is what makes a section root stay lit on its children; the
119
+ * `+ '/'` is what stops `/audit` lighting up on `/audit-log`. A root href is
120
+ * forced to exact or it would match every path in the app — but that forcing
121
+ * applies only to `href` itself; `matchPrefixes` is always prefix-matched, so
122
+ * a root item can still claim a second, unrelated section by full path.
123
+ */
124
+ export declare function isNavItemActive(item: NavItem, currentPath: string | undefined): boolean;
125
+ /**
126
+ * Whether one of `item`'s disclosed children is the current page.
127
+ *
128
+ * Two things read this. It is what auto-opens the group you have navigated
129
+ * into — a rail that will not show you where you are is the defect this whole
130
+ * feature exists to avoid. And it marks a parent whose section you are inside
131
+ * but whose own `href` does not match, which flat prefix matching cannot see
132
+ * when the children live at their own top-level routes.
133
+ */
134
+ export declare function hasActiveNavChild(item: NavItem, currentPath: string | undefined): boolean;
@@ -0,0 +1,88 @@
1
+ /** Narrow a mixed entry to a group. */
2
+ export function isNavGroup(entry) {
3
+ return 'items' in entry && Array.isArray(entry.items);
4
+ }
5
+ /** Normalise any accepted shape to groups, dropping groups that would render empty. */
6
+ export function toGroups(nav) {
7
+ if (!nav)
8
+ return [];
9
+ const groups = [];
10
+ // Consecutive bare items collapse into one unheaded run, so a flat array
11
+ // renders as a single group rather than one group per item (which would
12
+ // space every link apart). A group entry closes the run.
13
+ let run = null;
14
+ for (const entry of nav) {
15
+ if (isNavGroup(entry)) {
16
+ run = null;
17
+ if (entry.items.length > 0)
18
+ groups.push(entry);
19
+ }
20
+ else {
21
+ if (!run) {
22
+ run = { items: [] };
23
+ groups.push(run);
24
+ }
25
+ run.items.push(entry);
26
+ }
27
+ }
28
+ return groups;
29
+ }
30
+ /** No allocation per call for the overwhelmingly common childless item. */
31
+ const NO_CHILDREN = [];
32
+ /** An item's disclosed rows, normalised — an empty list where there are none. */
33
+ export function navChildren(item) {
34
+ return item.children ?? NO_CHILDREN;
35
+ }
36
+ /**
37
+ * Every item in source order, ignoring grouping — a parent immediately followed
38
+ * by its own children. Used by the command palette.
39
+ *
40
+ * Children are included because they are destinations like any other, and the
41
+ * palette is the fastest route to a page three levels into a section. An item
42
+ * with no children flattens exactly as it always did.
43
+ */
44
+ export function toItems(nav) {
45
+ if (!nav)
46
+ return [];
47
+ return nav.flatMap((entry) => {
48
+ const items = isNavGroup(entry) ? entry.items : [entry];
49
+ return items.flatMap((item) => [item, ...navChildren(item)]);
50
+ });
51
+ }
52
+ /** Prefix-match `path` against `prefix`, without running past a path segment. */
53
+ function matchesPrefix(path, prefix) {
54
+ return path === prefix || path.startsWith(prefix + '/');
55
+ }
56
+ /**
57
+ * Whether `item` is the current page.
58
+ *
59
+ * Prefix matching is what makes a section root stay lit on its children; the
60
+ * `+ '/'` is what stops `/audit` lighting up on `/audit-log`. A root href is
61
+ * forced to exact or it would match every path in the app — but that forcing
62
+ * applies only to `href` itself; `matchPrefixes` is always prefix-matched, so
63
+ * a root item can still claim a second, unrelated section by full path.
64
+ */
65
+ export function isNavItemActive(item, currentPath) {
66
+ if (!currentPath)
67
+ return false;
68
+ const ownMatch = item.exact || item.href === '/'
69
+ ? currentPath === item.href
70
+ : matchesPrefix(currentPath, item.href);
71
+ if (ownMatch)
72
+ return true;
73
+ return (item.matchPrefixes ?? []).some((prefix) => matchesPrefix(currentPath, prefix));
74
+ }
75
+ /**
76
+ * Whether one of `item`'s disclosed children is the current page.
77
+ *
78
+ * Two things read this. It is what auto-opens the group you have navigated
79
+ * into — a rail that will not show you where you are is the defect this whole
80
+ * feature exists to avoid. And it marks a parent whose section you are inside
81
+ * but whose own `href` does not match, which flat prefix matching cannot see
82
+ * when the children live at their own top-level routes.
83
+ */
84
+ export function hasActiveNavChild(item, currentPath) {
85
+ if (!currentPath)
86
+ return false;
87
+ return navChildren(item).some((child) => isNavItemActive(child, currentPath));
88
+ }
@@ -0,0 +1,112 @@
1
+ <script lang="ts" module>
2
+ import type { Status } from '../status/index.js';
3
+
4
+ // The gauge's tone is a health read, not the full five-state vocabulary —
5
+ // info/neutral have no caller today, so the type stays a named subset
6
+ // rather than widening to all of Status speculatively.
7
+ export type GaugeTone = Extract<Status, 'success' | 'warning' | 'error'>;
8
+ </script>
9
+
10
+ <script lang="ts">
11
+ import type { SVGAttributes } from 'svelte/elements';
12
+ import { cn } from '../../../utils.js';
13
+
14
+ // Radial capacity/percentage gauge: a compact SVG ring for a single 0–100
15
+ // metric where a StatCard's full metric tile would be too heavy — a
16
+ // token-burn dial, a rate-limit-window ring. `size` is both the viewBox
17
+ // unit and the gauge's physical footprint, so a consumer picks its
18
+ // on-screen size directly (36 for a small inline dial, 42 for a
19
+ // standalone one) rather than trusting ambient sizing.
20
+ let {
21
+ pct = 0,
22
+ tone = 'success',
23
+ size = 42,
24
+ showLabel = false,
25
+ label = '',
26
+ ref = $bindable(null),
27
+ class: className,
28
+ ...restProps
29
+ }: Omit<SVGAttributes<SVGSVGElement>, 'class'> & {
30
+ pct?: number;
31
+ tone?: GaugeTone;
32
+ size?: number;
33
+ showLabel?: boolean;
34
+ label?: string;
35
+ ref?: SVGSVGElement | null;
36
+ class?: string;
37
+ } = $props();
38
+
39
+ const clampedPct = $derived(Math.max(0, Math.min(100, pct)));
40
+
41
+ const toneVar: Record<GaugeTone, string> = {
42
+ success: 'var(--ds-color-status-success)',
43
+ warning: 'var(--ds-color-status-warning)',
44
+ error: 'var(--ds-color-status-error)'
45
+ };
46
+
47
+ const cx = $derived(size / 2);
48
+ const cy = $derived(size / 2);
49
+ const r = $derived(size / 2 - 4);
50
+ const circumference = $derived(2 * Math.PI * r);
51
+ const offset = $derived(circumference * (1 - clampedPct / 100));
52
+ const color = $derived(toneVar[tone] ?? toneVar.success);
53
+ const big = $derived(size >= 40);
54
+ const strokeWidth = 4;
55
+ </script>
56
+
57
+ <svg
58
+ bind:this={ref}
59
+ viewBox="0 0 {size} {size}"
60
+ width={size}
61
+ height={size}
62
+ aria-label="{clampedPct}% used"
63
+ class={cn(className)}
64
+ {...restProps}
65
+ >
66
+ <circle cx={cx} cy={cy} r={r} fill="none" stroke="var(--ds-color-surface-3)" stroke-width={strokeWidth} />
67
+ <circle
68
+ cx={cx}
69
+ cy={cy}
70
+ r={r}
71
+ fill="none"
72
+ stroke={color}
73
+ stroke-width={strokeWidth}
74
+ stroke-linecap="round"
75
+ stroke-dasharray={circumference}
76
+ stroke-dashoffset={offset}
77
+ transform="rotate(-90 {cx} {cy})"
78
+ />
79
+ {#if big && showLabel}
80
+ <!--
81
+ The percentage and unit-label glyphs below are graphic annotations
82
+ scaled by the viewBox, not CSS/DOM running text — the household's
83
+ ~0.75rem type floor governs body copy, not a numeral drawn inside a
84
+ purpose-built, self-contained radial gauge. Growing them to clear
85
+ that floor would blow out the ring's established compact geometry
86
+ (a 36–42 SVG-unit footprint), so they stay at their literal 10 and
87
+ 5.4 user-unit sizes deliberately (design-system#15).
88
+ -->
89
+ <text
90
+ x={cx}
91
+ y={cy - 0.5}
92
+ text-anchor="middle"
93
+ dominant-baseline="central"
94
+ font-family="var(--ds-font-code)"
95
+ font-size="10"
96
+ font-weight="600"
97
+ fill="var(--ds-color-foreground)"
98
+ >{clampedPct}%</text>
99
+ {#if label}
100
+ <text
101
+ x={cx}
102
+ y={cy + 7.5}
103
+ text-anchor="middle"
104
+ dominant-baseline="central"
105
+ font-family="var(--ds-font-body)"
106
+ font-size="5.4"
107
+ fill="var(--ds-color-muted-foreground)"
108
+ letter-spacing="0.5"
109
+ >{label.toUpperCase()}</text>
110
+ {/if}
111
+ {/if}
112
+ </svg>
@@ -0,0 +1,15 @@
1
+ import type { Status } from '../status/index.js';
2
+ export type GaugeTone = Extract<Status, 'success' | 'warning' | 'error'>;
3
+ import type { SVGAttributes } from 'svelte/elements';
4
+ type $$ComponentProps = Omit<SVGAttributes<SVGSVGElement>, 'class'> & {
5
+ pct?: number;
6
+ tone?: GaugeTone;
7
+ size?: number;
8
+ showLabel?: boolean;
9
+ label?: string;
10
+ ref?: SVGSVGElement | null;
11
+ class?: string;
12
+ };
13
+ declare const ArcGauge: import("svelte").Component<$$ComponentProps, {}, "ref">;
14
+ type ArcGauge = ReturnType<typeof ArcGauge>;
15
+ export default ArcGauge;
@@ -0,0 +1,3 @@
1
+ export { default as ArcGauge } from './arc-gauge.svelte';
2
+ export { default } from './arc-gauge.svelte';
3
+ export type { GaugeTone } from './arc-gauge.svelte';
@@ -0,0 +1,2 @@
1
+ export { default as ArcGauge } from './arc-gauge.svelte';
2
+ export { default } from './arc-gauge.svelte';