@ecoma-io/loom 0.1.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 (259) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +180 -0
  3. package/dist/a11y.d.ts +2 -0
  4. package/dist/a11y.d.ts.map +1 -0
  5. package/dist/a11y.js +2 -0
  6. package/dist/blocks/AppHeader/AppHeader.js +7 -0
  7. package/dist/blocks/AppHeader/AppHeader.js.map +1 -0
  8. package/dist/blocks/AppHeader/AppHeader.vue.d.ts +83 -0
  9. package/dist/blocks/AppHeader/AppHeader.vue.d.ts.map +1 -0
  10. package/dist/blocks/AppHeader/AppHeader.vue_vue_type_script_setup_true_lang.js +96 -0
  11. package/dist/blocks/AppHeader/AppHeader.vue_vue_type_script_setup_true_lang.js.map +1 -0
  12. package/dist/blocks/DashboardGrid/DashboardGrid.js +7 -0
  13. package/dist/blocks/DashboardGrid/DashboardGrid.js.map +1 -0
  14. package/dist/blocks/DashboardGrid/DashboardGrid.vue.d.ts +42 -0
  15. package/dist/blocks/DashboardGrid/DashboardGrid.vue.d.ts.map +1 -0
  16. package/dist/blocks/DashboardGrid/DashboardGrid.vue_vue_type_script_setup_true_lang.js +45 -0
  17. package/dist/blocks/DashboardGrid/DashboardGrid.vue_vue_type_script_setup_true_lang.js.map +1 -0
  18. package/dist/blocks/EmptyState/EmptyState.js +7 -0
  19. package/dist/blocks/EmptyState/EmptyState.js.map +1 -0
  20. package/dist/blocks/EmptyState/EmptyState.vue.d.ts +50 -0
  21. package/dist/blocks/EmptyState/EmptyState.vue.d.ts.map +1 -0
  22. package/dist/blocks/EmptyState/EmptyState.vue_vue_type_script_setup_true_lang.js +71 -0
  23. package/dist/blocks/EmptyState/EmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -0
  24. package/dist/blocks/PageHeader/PageHeader.js +7 -0
  25. package/dist/blocks/PageHeader/PageHeader.js.map +1 -0
  26. package/dist/blocks/PageHeader/PageHeader.vue.d.ts +54 -0
  27. package/dist/blocks/PageHeader/PageHeader.vue.d.ts.map +1 -0
  28. package/dist/blocks/PageHeader/PageHeader.vue_vue_type_script_setup_true_lang.js +68 -0
  29. package/dist/blocks/PageHeader/PageHeader.vue_vue_type_script_setup_true_lang.js.map +1 -0
  30. package/dist/blocks/RowActions/RowActions.js +7 -0
  31. package/dist/blocks/RowActions/RowActions.js.map +1 -0
  32. package/dist/blocks/RowActions/RowActions.vue.d.ts +14 -0
  33. package/dist/blocks/RowActions/RowActions.vue.d.ts.map +1 -0
  34. package/dist/blocks/RowActions/RowActions.vue_vue_type_script_setup_true_lang.js +47 -0
  35. package/dist/blocks/RowActions/RowActions.vue_vue_type_script_setup_true_lang.js.map +1 -0
  36. package/dist/blocks/SidebarNav/SidebarNav.js +7 -0
  37. package/dist/blocks/SidebarNav/SidebarNav.js.map +1 -0
  38. package/dist/blocks/SidebarNav/SidebarNav.vue.d.ts +40 -0
  39. package/dist/blocks/SidebarNav/SidebarNav.vue.d.ts.map +1 -0
  40. package/dist/blocks/SidebarNav/SidebarNav.vue_vue_type_script_setup_true_lang.js +125 -0
  41. package/dist/blocks/SidebarNav/SidebarNav.vue_vue_type_script_setup_true_lang.js.map +1 -0
  42. package/dist/blocks/TitleBar/TitleBar.js +7 -0
  43. package/dist/blocks/TitleBar/TitleBar.js.map +1 -0
  44. package/dist/blocks/TitleBar/TitleBar.vue.d.ts +49 -0
  45. package/dist/blocks/TitleBar/TitleBar.vue.d.ts.map +1 -0
  46. package/dist/blocks/TitleBar/TitleBar.vue_vue_type_script_setup_true_lang.js +66 -0
  47. package/dist/blocks/TitleBar/TitleBar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  48. package/dist/blocks/ToastStack/ToastStack.js +7 -0
  49. package/dist/blocks/ToastStack/ToastStack.js.map +1 -0
  50. package/dist/blocks/ToastStack/ToastStack.vue.d.ts +24 -0
  51. package/dist/blocks/ToastStack/ToastStack.vue.d.ts.map +1 -0
  52. package/dist/blocks/ToastStack/ToastStack.vue_vue_type_script_setup_true_lang.js +38 -0
  53. package/dist/blocks/ToastStack/ToastStack.vue_vue_type_script_setup_true_lang.js.map +1 -0
  54. package/dist/icons/BrandMark.d.ts +18 -0
  55. package/dist/icons/BrandMark.d.ts.map +1 -0
  56. package/dist/icons/BrandMark.js +47 -0
  57. package/dist/icons/BrandMark.js.map +1 -0
  58. package/dist/index.d.ts +75 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +46 -0
  61. package/dist/lib/a11y-scope.d.ts +19 -0
  62. package/dist/lib/a11y-scope.d.ts.map +1 -0
  63. package/dist/lib/a11y-scope.js +28 -0
  64. package/dist/lib/a11y-scope.js.map +1 -0
  65. package/dist/lib/attrs.d.ts +18 -0
  66. package/dist/lib/attrs.d.ts.map +1 -0
  67. package/dist/lib/attrs.js +28 -0
  68. package/dist/lib/attrs.js.map +1 -0
  69. package/dist/lib/cn.d.ts +9 -0
  70. package/dist/lib/cn.d.ts.map +1 -0
  71. package/dist/lib/cn.js +16 -0
  72. package/dist/lib/cn.js.map +1 -0
  73. package/dist/lib/icon-defaults.d.ts +22 -0
  74. package/dist/lib/icon-defaults.d.ts.map +1 -0
  75. package/dist/lib/icon-defaults.js +32 -0
  76. package/dist/lib/icon-defaults.js.map +1 -0
  77. package/dist/lib/motion.d.ts +14 -0
  78. package/dist/lib/motion.d.ts.map +1 -0
  79. package/dist/lib/motion.js +20 -0
  80. package/dist/lib/motion.js.map +1 -0
  81. package/dist/lib/props.d.ts +31 -0
  82. package/dist/lib/props.d.ts.map +1 -0
  83. package/dist/lib/props.js +37 -0
  84. package/dist/lib/props.js.map +1 -0
  85. package/dist/primitives/Avatar/Avatar.js +7 -0
  86. package/dist/primitives/Avatar/Avatar.js.map +1 -0
  87. package/dist/primitives/Avatar/Avatar.vue.d.ts +27 -0
  88. package/dist/primitives/Avatar/Avatar.vue.d.ts.map +1 -0
  89. package/dist/primitives/Avatar/Avatar.vue_vue_type_script_setup_true_lang.js +33 -0
  90. package/dist/primitives/Avatar/Avatar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  91. package/dist/primitives/Badge/Badge.js +7 -0
  92. package/dist/primitives/Badge/Badge.js.map +1 -0
  93. package/dist/primitives/Badge/Badge.vue.d.ts +27 -0
  94. package/dist/primitives/Badge/Badge.vue.d.ts.map +1 -0
  95. package/dist/primitives/Badge/Badge.vue_vue_type_script_setup_true_lang.js +30 -0
  96. package/dist/primitives/Badge/Badge.vue_vue_type_script_setup_true_lang.js.map +1 -0
  97. package/dist/primitives/Button/Button.js +7 -0
  98. package/dist/primitives/Button/Button.js.map +1 -0
  99. package/dist/primitives/Button/Button.vue.d.ts +70 -0
  100. package/dist/primitives/Button/Button.vue.d.ts.map +1 -0
  101. package/dist/primitives/Button/Button.vue_vue_type_script_setup_true_lang.js +122 -0
  102. package/dist/primitives/Button/Button.vue_vue_type_script_setup_true_lang.js.map +1 -0
  103. package/dist/primitives/Checkbox/Checkbox.js +7 -0
  104. package/dist/primitives/Checkbox/Checkbox.js.map +1 -0
  105. package/dist/primitives/Checkbox/Checkbox.vue.d.ts +34 -0
  106. package/dist/primitives/Checkbox/Checkbox.vue.d.ts.map +1 -0
  107. package/dist/primitives/Checkbox/Checkbox.vue_vue_type_script_setup_true_lang.js +94 -0
  108. package/dist/primitives/Checkbox/Checkbox.vue_vue_type_script_setup_true_lang.js.map +1 -0
  109. package/dist/primitives/Dialog/Dialog.js +7 -0
  110. package/dist/primitives/Dialog/Dialog.js.map +1 -0
  111. package/dist/primitives/Dialog/Dialog.vue.d.ts +58 -0
  112. package/dist/primitives/Dialog/Dialog.vue.d.ts.map +1 -0
  113. package/dist/primitives/Dialog/Dialog.vue_vue_type_script_setup_true_lang.js +88 -0
  114. package/dist/primitives/Dialog/Dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  115. package/dist/primitives/DropdownMenu/DropdownMenu.js +7 -0
  116. package/dist/primitives/DropdownMenu/DropdownMenu.js.map +1 -0
  117. package/dist/primitives/DropdownMenu/DropdownMenu.vue.d.ts +55 -0
  118. package/dist/primitives/DropdownMenu/DropdownMenu.vue.d.ts.map +1 -0
  119. package/dist/primitives/DropdownMenu/DropdownMenu.vue_vue_type_script_setup_true_lang.js +82 -0
  120. package/dist/primitives/DropdownMenu/DropdownMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  121. package/dist/primitives/Field/Field.js +7 -0
  122. package/dist/primitives/Field/Field.js.map +1 -0
  123. package/dist/primitives/Field/Field.vue.d.ts +53 -0
  124. package/dist/primitives/Field/Field.vue.d.ts.map +1 -0
  125. package/dist/primitives/Field/Field.vue_vue_type_script_setup_true_lang.js +84 -0
  126. package/dist/primitives/Field/Field.vue_vue_type_script_setup_true_lang.js.map +1 -0
  127. package/dist/primitives/InlineError/InlineError.js +7 -0
  128. package/dist/primitives/InlineError/InlineError.js.map +1 -0
  129. package/dist/primitives/InlineError/InlineError.vue.d.ts +32 -0
  130. package/dist/primitives/InlineError/InlineError.vue.d.ts.map +1 -0
  131. package/dist/primitives/InlineError/InlineError.vue_vue_type_script_setup_true_lang.js +44 -0
  132. package/dist/primitives/InlineError/InlineError.vue_vue_type_script_setup_true_lang.js.map +1 -0
  133. package/dist/primitives/Menubar/Menubar.js +7 -0
  134. package/dist/primitives/Menubar/Menubar.js.map +1 -0
  135. package/dist/primitives/Menubar/Menubar.vue.d.ts +41 -0
  136. package/dist/primitives/Menubar/Menubar.vue.d.ts.map +1 -0
  137. package/dist/primitives/Menubar/Menubar.vue_vue_type_script_setup_true_lang.js +184 -0
  138. package/dist/primitives/Menubar/Menubar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  139. package/dist/primitives/NumberField/NumberField.js +7 -0
  140. package/dist/primitives/NumberField/NumberField.js.map +1 -0
  141. package/dist/primitives/NumberField/NumberField.vue.d.ts +47 -0
  142. package/dist/primitives/NumberField/NumberField.vue.d.ts.map +1 -0
  143. package/dist/primitives/NumberField/NumberField.vue_vue_type_script_setup_true_lang.js +204 -0
  144. package/dist/primitives/NumberField/NumberField.vue_vue_type_script_setup_true_lang.js.map +1 -0
  145. package/dist/primitives/Popover/Popover.js +7 -0
  146. package/dist/primitives/Popover/Popover.js.map +1 -0
  147. package/dist/primitives/Popover/Popover.vue.d.ts +61 -0
  148. package/dist/primitives/Popover/Popover.vue.d.ts.map +1 -0
  149. package/dist/primitives/Popover/Popover.vue_vue_type_script_setup_true_lang.js +59 -0
  150. package/dist/primitives/Popover/Popover.vue_vue_type_script_setup_true_lang.js.map +1 -0
  151. package/dist/primitives/Progress/Progress.js +7 -0
  152. package/dist/primitives/Progress/Progress.js.map +1 -0
  153. package/dist/primitives/Progress/Progress.vue.d.ts +30 -0
  154. package/dist/primitives/Progress/Progress.vue.d.ts.map +1 -0
  155. package/dist/primitives/Progress/Progress.vue_vue_type_script_setup_true_lang.js +67 -0
  156. package/dist/primitives/Progress/Progress.vue_vue_type_script_setup_true_lang.js.map +1 -0
  157. package/dist/primitives/RadioGroup/RadioGroup.js +7 -0
  158. package/dist/primitives/RadioGroup/RadioGroup.js.map +1 -0
  159. package/dist/primitives/RadioGroup/RadioGroup.vue.d.ts +39 -0
  160. package/dist/primitives/RadioGroup/RadioGroup.vue.d.ts.map +1 -0
  161. package/dist/primitives/RadioGroup/RadioGroup.vue_vue_type_script_setup_true_lang.js +63 -0
  162. package/dist/primitives/RadioGroup/RadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
  163. package/dist/primitives/SegmentedControl/SegmentedControl.js +7 -0
  164. package/dist/primitives/SegmentedControl/SegmentedControl.js.map +1 -0
  165. package/dist/primitives/SegmentedControl/SegmentedControl.vue.d.ts +40 -0
  166. package/dist/primitives/SegmentedControl/SegmentedControl.vue.d.ts.map +1 -0
  167. package/dist/primitives/SegmentedControl/SegmentedControl.vue_vue_type_script_setup_true_lang.js +89 -0
  168. package/dist/primitives/SegmentedControl/SegmentedControl.vue_vue_type_script_setup_true_lang.js.map +1 -0
  169. package/dist/primitives/Select/Select.js +7 -0
  170. package/dist/primitives/Select/Select.js.map +1 -0
  171. package/dist/primitives/Select/Select.vue.d.ts +56 -0
  172. package/dist/primitives/Select/Select.vue.d.ts.map +1 -0
  173. package/dist/primitives/Select/Select.vue_vue_type_script_setup_true_lang.js +122 -0
  174. package/dist/primitives/Select/Select.vue_vue_type_script_setup_true_lang.js.map +1 -0
  175. package/dist/primitives/Separator/Separator.js +7 -0
  176. package/dist/primitives/Separator/Separator.js.map +1 -0
  177. package/dist/primitives/Separator/Separator.vue.d.ts +19 -0
  178. package/dist/primitives/Separator/Separator.vue.d.ts.map +1 -0
  179. package/dist/primitives/Separator/Separator.vue_vue_type_script_setup_true_lang.js +31 -0
  180. package/dist/primitives/Separator/Separator.vue_vue_type_script_setup_true_lang.js.map +1 -0
  181. package/dist/primitives/Skeleton/Skeleton.js +7 -0
  182. package/dist/primitives/Skeleton/Skeleton.js.map +1 -0
  183. package/dist/primitives/Skeleton/Skeleton.vue.d.ts +16 -0
  184. package/dist/primitives/Skeleton/Skeleton.vue.d.ts.map +1 -0
  185. package/dist/primitives/Skeleton/Skeleton.vue_vue_type_script_setup_true_lang.js +37 -0
  186. package/dist/primitives/Skeleton/Skeleton.vue_vue_type_script_setup_true_lang.js.map +1 -0
  187. package/dist/primitives/Slider/Slider.js +7 -0
  188. package/dist/primitives/Slider/Slider.js.map +1 -0
  189. package/dist/primitives/Slider/Slider.vue.d.ts +58 -0
  190. package/dist/primitives/Slider/Slider.vue.d.ts.map +1 -0
  191. package/dist/primitives/Slider/Slider.vue_vue_type_script_setup_true_lang.js +137 -0
  192. package/dist/primitives/Slider/Slider.vue_vue_type_script_setup_true_lang.js.map +1 -0
  193. package/dist/primitives/Spinner/Spinner.js +7 -0
  194. package/dist/primitives/Spinner/Spinner.js.map +1 -0
  195. package/dist/primitives/Spinner/Spinner.vue.d.ts +21 -0
  196. package/dist/primitives/Spinner/Spinner.vue.d.ts.map +1 -0
  197. package/dist/primitives/Spinner/Spinner.vue_vue_type_script_setup_true_lang.js +63 -0
  198. package/dist/primitives/Spinner/Spinner.vue_vue_type_script_setup_true_lang.js.map +1 -0
  199. package/dist/primitives/Surface/Surface.js +7 -0
  200. package/dist/primitives/Surface/Surface.js.map +1 -0
  201. package/dist/primitives/Surface/Surface.vue.d.ts +42 -0
  202. package/dist/primitives/Surface/Surface.vue.d.ts.map +1 -0
  203. package/dist/primitives/Surface/Surface.vue_vue_type_script_setup_true_lang.js +48 -0
  204. package/dist/primitives/Surface/Surface.vue_vue_type_script_setup_true_lang.js.map +1 -0
  205. package/dist/primitives/Switch/Switch.js +7 -0
  206. package/dist/primitives/Switch/Switch.js.map +1 -0
  207. package/dist/primitives/Switch/Switch.vue.d.ts +24 -0
  208. package/dist/primitives/Switch/Switch.vue.d.ts.map +1 -0
  209. package/dist/primitives/Switch/Switch.vue_vue_type_script_setup_true_lang.js +44 -0
  210. package/dist/primitives/Switch/Switch.vue_vue_type_script_setup_true_lang.js.map +1 -0
  211. package/dist/primitives/Tabs/Tabs.js +7 -0
  212. package/dist/primitives/Tabs/Tabs.js.map +1 -0
  213. package/dist/primitives/Tabs/Tabs.vue.d.ts +33 -0
  214. package/dist/primitives/Tabs/Tabs.vue.d.ts.map +1 -0
  215. package/dist/primitives/Tabs/Tabs.vue_vue_type_script_setup_true_lang.js +54 -0
  216. package/dist/primitives/Tabs/Tabs.vue_vue_type_script_setup_true_lang.js.map +1 -0
  217. package/dist/primitives/TextField/TextField.js +7 -0
  218. package/dist/primitives/TextField/TextField.js.map +1 -0
  219. package/dist/primitives/TextField/TextField.vue.d.ts +58 -0
  220. package/dist/primitives/TextField/TextField.vue.d.ts.map +1 -0
  221. package/dist/primitives/TextField/TextField.vue_vue_type_script_setup_true_lang.js +71 -0
  222. package/dist/primitives/TextField/TextField.vue_vue_type_script_setup_true_lang.js.map +1 -0
  223. package/dist/primitives/Textarea/Textarea.js +7 -0
  224. package/dist/primitives/Textarea/Textarea.js.map +1 -0
  225. package/dist/primitives/Textarea/Textarea.vue.d.ts +48 -0
  226. package/dist/primitives/Textarea/Textarea.vue.d.ts.map +1 -0
  227. package/dist/primitives/Textarea/Textarea.vue_vue_type_script_setup_true_lang.js +54 -0
  228. package/dist/primitives/Textarea/Textarea.vue_vue_type_script_setup_true_lang.js.map +1 -0
  229. package/dist/primitives/Toast/Toast.js +7 -0
  230. package/dist/primitives/Toast/Toast.js.map +1 -0
  231. package/dist/primitives/Toast/Toast.vue.d.ts +46 -0
  232. package/dist/primitives/Toast/Toast.vue.d.ts.map +1 -0
  233. package/dist/primitives/Toast/Toast.vue_vue_type_script_setup_true_lang.js +52 -0
  234. package/dist/primitives/Toast/Toast.vue_vue_type_script_setup_true_lang.js.map +1 -0
  235. package/dist/primitives/Toast/ToastItem.js +7 -0
  236. package/dist/primitives/Toast/ToastItem.js.map +1 -0
  237. package/dist/primitives/Toast/ToastItem.vue.d.ts +38 -0
  238. package/dist/primitives/Toast/ToastItem.vue.d.ts.map +1 -0
  239. package/dist/primitives/Toast/ToastItem.vue_vue_type_script_setup_true_lang.js +114 -0
  240. package/dist/primitives/Toast/ToastItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
  241. package/dist/primitives/Tooltip/Tooltip.js +7 -0
  242. package/dist/primitives/Tooltip/Tooltip.js.map +1 -0
  243. package/dist/primitives/Tooltip/Tooltip.vue.d.ts +52 -0
  244. package/dist/primitives/Tooltip/Tooltip.vue.d.ts.map +1 -0
  245. package/dist/primitives/Tooltip/Tooltip.vue_vue_type_script_setup_true_lang.js +56 -0
  246. package/dist/primitives/Tooltip/Tooltip.vue_vue_type_script_setup_true_lang.js.map +1 -0
  247. package/dist/primitives/WindowControls/WindowControls.js +7 -0
  248. package/dist/primitives/WindowControls/WindowControls.js.map +1 -0
  249. package/dist/primitives/WindowControls/WindowControls.vue.d.ts +41 -0
  250. package/dist/primitives/WindowControls/WindowControls.vue.d.ts.map +1 -0
  251. package/dist/primitives/WindowControls/WindowControls.vue_vue_type_script_setup_true_lang.js +111 -0
  252. package/dist/primitives/WindowControls/WindowControls.vue_vue_type_script_setup_true_lang.js.map +1 -0
  253. package/dist/styles/fonts/Geist-Variable.woff2 +0 -0
  254. package/dist/styles/fonts/GeistMono-Variable.woff2 +0 -0
  255. package/dist/styles/fonts/OFL.txt +92 -0
  256. package/dist/styles/fonts.css +30 -0
  257. package/dist/styles/global.css +181 -0
  258. package/dist/styles/theme.css +212 -0
  259. package/package.json +123 -0
@@ -0,0 +1,42 @@
1
+ /**
2
+ * DashboardGrid — the reflowing tile grid a dashboard's panels sit in: a CSS
3
+ * grid that fits as many `minTileWidth`-wide tracks as the container allows,
4
+ * so a KPI row and a couple of wider panels share one layout without the
5
+ * host authoring a single breakpoint.
6
+ *
7
+ * `auto-fit` + `minmax` (never fixed `grid-cols-N` breakpoints) is the
8
+ * deliberate choice: a fixed column count needs one breakpoint per host
9
+ * viewport, while auto-fit recomputes the column count from the container's
10
+ * own width — it reflows identically inside a sidebar-narrowed workspace and
11
+ * full-bleed on an ultra-wide monitor, with zero Tailwind breakpoints
12
+ * authored here or at the call site. The `minmax` lower bound is wrapped in
13
+ * `min(100%, …)` so a tile never forces horizontal overflow on a container
14
+ * narrower than `minTileWidth` itself.
15
+ *
16
+ * Presentational only: panels arrive through the default slot, and a panel
17
+ * spans multiple tracks with its own `col-span-*` utility at the call
18
+ * site — the grid does not know or count how many panels it holds.
19
+ */
20
+ type __VLS_Props = {
21
+ /** Narrowest a tile may get before the grid drops to fewer columns. Any valid CSS length (e.g. "14rem"). */
22
+ minTileWidth?: string;
23
+ /** Row/column gap step — mirrors Surface's `pad` scale at `sm` and up (sm 12px · md 16px · lg 24px); each step drops one notch below `sm`. */
24
+ gap?: "sm" | "md" | "lg";
25
+ };
26
+ declare var __VLS_1: {};
27
+ type __VLS_Slots = {} & {
28
+ default?: (props: typeof __VLS_1) => any;
29
+ };
30
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
31
+ minTileWidth: string;
32
+ gap: "sm" | "md" | "lg";
33
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
34
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
35
+ declare const _default: typeof __VLS_export;
36
+ export default _default;
37
+ type __VLS_WithSlots<T, S> = T & {
38
+ new (): {
39
+ $slots: S;
40
+ };
41
+ };
42
+ //# sourceMappingURL=DashboardGrid.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardGrid.vue.d.ts","sourceRoot":"","sources":["../../../src/blocks/DashboardGrid/DashboardGrid.vue"],"names":[],"mappings":"AAsDA;;;;;;;;;;;;;;;;;;GAkBG;AACH,KAAK,WAAW,GAAG;IACf,4GAA4G;IAC5G,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8IAA8I;IAC9I,GAAG,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC1B,CAAC;AA4CJ,QAAA,IAAI,OAAO,IAAW,CAAE;AACxB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAK/C,QAAA,MAAM,UAAU;kBAtDG,MAAM;SAEf,IAAI,GAAG,IAAI,GAAG,IAAI;6EAuD1B,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AAWzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { createElementBlock, defineComponent, normalizeClass, normalizeStyle, openBlock, renderSlot } from "vue";
2
+ //#region src/blocks/DashboardGrid/DashboardGrid.vue?vue&type=script&setup=true&lang.ts
3
+ var DashboardGrid_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
4
+ __name: "DashboardGrid",
5
+ props: {
6
+ minTileWidth: { default: "16rem" },
7
+ gap: { default: "md" }
8
+ },
9
+ setup(__props) {
10
+ /**
11
+ * DashboardGrid — the reflowing tile grid a dashboard's panels sit in: a CSS
12
+ * grid that fits as many `minTileWidth`-wide tracks as the container allows,
13
+ * so a KPI row and a couple of wider panels share one layout without the
14
+ * host authoring a single breakpoint.
15
+ *
16
+ * `auto-fit` + `minmax` (never fixed `grid-cols-N` breakpoints) is the
17
+ * deliberate choice: a fixed column count needs one breakpoint per host
18
+ * viewport, while auto-fit recomputes the column count from the container's
19
+ * own width — it reflows identically inside a sidebar-narrowed workspace and
20
+ * full-bleed on an ultra-wide monitor, with zero Tailwind breakpoints
21
+ * authored here or at the call site. The `minmax` lower bound is wrapped in
22
+ * `min(100%, …)` so a tile never forces horizontal overflow on a container
23
+ * narrower than `minTileWidth` itself.
24
+ *
25
+ * Presentational only: panels arrive through the default slot, and a panel
26
+ * spans multiple tracks with its own `col-span-*` utility at the call
27
+ * site — the grid does not know or count how many panels it holds.
28
+ */
29
+ const gapClass = {
30
+ sm: "gap-2 sm:gap-3",
31
+ md: "gap-3 sm:gap-4",
32
+ lg: "gap-4 sm:gap-6"
33
+ };
34
+ return (_ctx, _cache) => {
35
+ return openBlock(), createElementBlock("div", {
36
+ class: normalizeClass(["grid", gapClass[__props.gap]]),
37
+ style: normalizeStyle({ gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, ${__props.minTileWidth}), 1fr))` })
38
+ }, [renderSlot(_ctx.$slots, "default")], 6);
39
+ };
40
+ }
41
+ });
42
+ //#endregion
43
+ export { DashboardGrid_vue_vue_type_script_setup_true_lang_default as default };
44
+
45
+ //# sourceMappingURL=DashboardGrid.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardGrid.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/blocks/DashboardGrid/DashboardGrid.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * DashboardGrid — the reflowing tile grid a dashboard's panels sit in: a CSS\n * grid that fits as many `minTileWidth`-wide tracks as the container allows,\n * so a KPI row and a couple of wider panels share one layout without the\n * host authoring a single breakpoint.\n *\n * `auto-fit` + `minmax` (never fixed `grid-cols-N` breakpoints) is the\n * deliberate choice: a fixed column count needs one breakpoint per host\n * viewport, while auto-fit recomputes the column count from the container's\n * own width — it reflows identically inside a sidebar-narrowed workspace and\n * full-bleed on an ultra-wide monitor, with zero Tailwind breakpoints\n * authored here or at the call site. The `minmax` lower bound is wrapped in\n * `min(100%, …)` so a tile never forces horizontal overflow on a container\n * narrower than `minTileWidth` itself.\n *\n * Presentational only: panels arrive through the default slot, and a panel\n * spans multiple tracks with its own `col-span-*` utility at the call\n * site — the grid does not know or count how many panels it holds.\n */\nwithDefaults(\n defineProps<{\n /** Narrowest a tile may get before the grid drops to fewer columns. Any valid CSS length (e.g. \"14rem\"). */\n minTileWidth?: string;\n /** Row/column gap step — mirrors Surface's `pad` scale at `sm` and up (sm 12px · md 16px · lg 24px); each step drops one notch below `sm`. */\n gap?: \"sm\" | \"md\" | \"lg\";\n }>(),\n { minTileWidth: \"16rem\", gap: \"md\" },\n);\n\n// One notch tighter below the `sm` breakpoint. A gutter is spent viewport, and\n// on a phone the grid is already single-column — 24px of air between stacked\n// tiles buys no separation the tile borders do not already give, it just\n// pushes the second tile off screen. From `sm` up each step is its\n// documented value.\nconst gapClass = {\n sm: \"gap-2 sm:gap-3\",\n md: \"gap-3 sm:gap-4\",\n lg: \"gap-4 sm:gap-6\",\n} as const;\n</script>\n\n<template>\n <div\n class=\"grid\"\n :class=\"gapClass[gap]\"\n :style=\"{ gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, ${minTileWidth}), 1fr))` }\"\n >\n <slot />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCA,MAAM,WAAW;GACf,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;;GAIE,OAAA,UAAA,GAAA,mBAMM,OAAA;IALJ,OAAK,eAAA,CAAC,QACE,SAAS,QAAA,IAAG,CAAA;IACnB,OAAK,eAAA,EAAA,qBAAA,qCAA8D,QAAA,aAAY,UAAA,CAAA;GAEhF,GAAA,CAAA,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,CAAA"}
@@ -0,0 +1,7 @@
1
+ import EmptyState_vue_vue_type_script_setup_true_lang_default from "./EmptyState.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/blocks/EmptyState/EmptyState.vue
3
+ var EmptyState_default = EmptyState_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { EmptyState_default as default };
6
+
7
+ //# sourceMappingURL=EmptyState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmptyState.js","names":[],"sources":["../../../src/blocks/EmptyState/EmptyState.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * EmptyState — the shape of \"nothing here yet\": icon → title → optional\n * description → at most ONE call-to-action, centered in the empty region. An\n * empty region should explain itself and invite the next step — empty is a\n * welcome, never an error (a failed load renders `InlineError`; an empty\n * *result* renders this).\n *\n * The entrance is a staggered fade-rise film (icon, title, description,\n * action — 60ms apart): this is content appearing, not action feedback, so\n * it budgets like a panel rather than against the interaction-feedback\n * ceiling, all token-tier CSS. Purely presentational: the icon comes via the\n * `icon` slot (decorative, hidden from assistive tech), the CTA via the\n * `action` slot — the host owns behavior and wording, and no fallback copy\n * ships with the component.\n *\n * The icon sits in a hairline medallion — a `bg-subtle` disc with a `border`\n * ring — rather than floating bare. Two reasons: the glyph itself is sized\n * 20px, the emphasis step for an empty-state icon, and a 20px stroke drawing\n * alone in a large blank region has nothing to hold it, so it reads as a\n * stray mark; the medallion gives it a shape to anchor without adding a\n * shadow (a disc is a surface plus a hairline, never a float). `bg-subtle`\n * is chosen over `bg-card` so the disc stays visible on `bg-card` and\n * `bg-background` alike — this block is dropped into both.\n *\n * Type comes from the named scale (`text-title` / `text-small`), not\n * hand-picked `text-sm`/`text-xs` — the empty state is a titled moment, not\n * a caption.\n */\ndefineProps<{\n /** What is missing, stated plainly — always shown. */\n title: string;\n /** What to do about it. Omit rather than pad the region with filler copy. */\n description?: string;\n}>();\n</script>\n\n<template>\n <div class=\"flex flex-col items-center justify-center gap-1.5 px-6 py-10 text-center sm:py-14\">\n <div\n v-if=\"$slots.icon\"\n aria-hidden=\"true\"\n class=\"animate-fade-rise mb-3 grid h-12 w-12 place-items-center rounded-full border border-border bg-subtle text-muted-foreground [&_svg]:h-5 [&_svg]:w-5\"\n >\n <slot name=\"icon\" />\n </div>\n <p class=\"animate-fade-rise text-title text-foreground\" :style=\"{ animationDelay: '60ms' }\">\n {{ title }}\n </p>\n <p\n v-if=\"description\"\n class=\"animate-fade-rise max-w-sm text-balance text-small text-muted-foreground\"\n :style=\"{ animationDelay: '120ms' }\"\n >\n {{ description }}\n </p>\n <div v-if=\"$slots.action\" class=\"animate-fade-rise mt-4\" :style=\"{ animationDelay: '180ms' }\">\n <slot name=\"action\" />\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * EmptyState — the shape of "nothing here yet": icon → title → optional
3
+ * description → at most ONE call-to-action, centered in the empty region. An
4
+ * empty region should explain itself and invite the next step — empty is a
5
+ * welcome, never an error (a failed load renders `InlineError`; an empty
6
+ * *result* renders this).
7
+ *
8
+ * The entrance is a staggered fade-rise film (icon, title, description,
9
+ * action — 60ms apart): this is content appearing, not action feedback, so
10
+ * it budgets like a panel rather than against the interaction-feedback
11
+ * ceiling, all token-tier CSS. Purely presentational: the icon comes via the
12
+ * `icon` slot (decorative, hidden from assistive tech), the CTA via the
13
+ * `action` slot — the host owns behavior and wording, and no fallback copy
14
+ * ships with the component.
15
+ *
16
+ * The icon sits in a hairline medallion — a `bg-subtle` disc with a `border`
17
+ * ring — rather than floating bare. Two reasons: the glyph itself is sized
18
+ * 20px, the emphasis step for an empty-state icon, and a 20px stroke drawing
19
+ * alone in a large blank region has nothing to hold it, so it reads as a
20
+ * stray mark; the medallion gives it a shape to anchor without adding a
21
+ * shadow (a disc is a surface plus a hairline, never a float). `bg-subtle`
22
+ * is chosen over `bg-card` so the disc stays visible on `bg-card` and
23
+ * `bg-background` alike — this block is dropped into both.
24
+ *
25
+ * Type comes from the named scale (`text-title` / `text-small`), not
26
+ * hand-picked `text-sm`/`text-xs` — the empty state is a titled moment, not
27
+ * a caption.
28
+ */
29
+ type __VLS_Props = {
30
+ /** What is missing, stated plainly — always shown. */
31
+ title: string;
32
+ /** What to do about it. Omit rather than pad the region with filler copy. */
33
+ description?: string;
34
+ };
35
+ declare var __VLS_1: {}, __VLS_3: {};
36
+ type __VLS_Slots = {} & {
37
+ icon?: (props: typeof __VLS_1) => any;
38
+ } & {
39
+ action?: (props: typeof __VLS_3) => any;
40
+ };
41
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
42
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
43
+ declare const _default: typeof __VLS_export;
44
+ export default _default;
45
+ type __VLS_WithSlots<T, S> = T & {
46
+ new (): {
47
+ $slots: S;
48
+ };
49
+ };
50
+ //# sourceMappingURL=EmptyState.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmptyState.vue.d.ts","sourceRoot":"","sources":["../../../src/blocks/EmptyState/EmptyState.vue"],"names":[],"mappings":"AAgEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,KAAK,WAAW,GAAG;IACjB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAgFF,QAAA,IAAI,OAAO,IAAU,EAAE,OAAO,IAAW,CAAE;AAC3C,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GACzC;IAAE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAK9C,QAAA,MAAM,UAAU,kSAEd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { createCommentVNode, createElementBlock, createElementVNode, defineComponent, openBlock, renderSlot, toDisplayString } from "vue";
2
+ //#region src/blocks/EmptyState/EmptyState.vue?vue&type=script&setup=true&lang.ts
3
+ var _hoisted_1 = { class: "flex flex-col items-center justify-center gap-1.5 px-6 py-10 text-center sm:py-14" };
4
+ var _hoisted_2 = {
5
+ key: 0,
6
+ "aria-hidden": "true",
7
+ class: "animate-fade-rise mb-3 grid h-12 w-12 place-items-center rounded-full border border-border bg-subtle text-muted-foreground [&_svg]:h-5 [&_svg]:w-5"
8
+ };
9
+ var _hoisted_3 = {
10
+ class: "animate-fade-rise text-title text-foreground",
11
+ style: { animationDelay: "60ms" }
12
+ };
13
+ var _hoisted_4 = {
14
+ key: 1,
15
+ class: "animate-fade-rise max-w-sm text-balance text-small text-muted-foreground",
16
+ style: { animationDelay: "120ms" }
17
+ };
18
+ var _hoisted_5 = {
19
+ key: 2,
20
+ class: "animate-fade-rise mt-4",
21
+ style: { animationDelay: "180ms" }
22
+ };
23
+ var EmptyState_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
24
+ __name: "EmptyState",
25
+ props: {
26
+ title: {},
27
+ description: {}
28
+ },
29
+ setup(__props) {
30
+ /**
31
+ * EmptyState — the shape of "nothing here yet": icon → title → optional
32
+ * description → at most ONE call-to-action, centered in the empty region. An
33
+ * empty region should explain itself and invite the next step — empty is a
34
+ * welcome, never an error (a failed load renders `InlineError`; an empty
35
+ * *result* renders this).
36
+ *
37
+ * The entrance is a staggered fade-rise film (icon, title, description,
38
+ * action — 60ms apart): this is content appearing, not action feedback, so
39
+ * it budgets like a panel rather than against the interaction-feedback
40
+ * ceiling, all token-tier CSS. Purely presentational: the icon comes via the
41
+ * `icon` slot (decorative, hidden from assistive tech), the CTA via the
42
+ * `action` slot — the host owns behavior and wording, and no fallback copy
43
+ * ships with the component.
44
+ *
45
+ * The icon sits in a hairline medallion — a `bg-subtle` disc with a `border`
46
+ * ring — rather than floating bare. Two reasons: the glyph itself is sized
47
+ * 20px, the emphasis step for an empty-state icon, and a 20px stroke drawing
48
+ * alone in a large blank region has nothing to hold it, so it reads as a
49
+ * stray mark; the medallion gives it a shape to anchor without adding a
50
+ * shadow (a disc is a surface plus a hairline, never a float). `bg-subtle`
51
+ * is chosen over `bg-card` so the disc stays visible on `bg-card` and
52
+ * `bg-background` alike — this block is dropped into both.
53
+ *
54
+ * Type comes from the named scale (`text-title` / `text-small`), not
55
+ * hand-picked `text-sm`/`text-xs` — the empty state is a titled moment, not
56
+ * a caption.
57
+ */
58
+ return (_ctx, _cache) => {
59
+ return openBlock(), createElementBlock("div", _hoisted_1, [
60
+ _ctx.$slots.icon ? (openBlock(), createElementBlock("div", _hoisted_2, [renderSlot(_ctx.$slots, "icon")])) : createCommentVNode("", true),
61
+ createElementVNode("p", _hoisted_3, toDisplayString(__props.title), 1),
62
+ __props.description ? (openBlock(), createElementBlock("p", _hoisted_4, toDisplayString(__props.description), 1)) : createCommentVNode("", true),
63
+ _ctx.$slots.action ? (openBlock(), createElementBlock("div", _hoisted_5, [renderSlot(_ctx.$slots, "action")])) : createCommentVNode("", true)
64
+ ]);
65
+ };
66
+ }
67
+ });
68
+ //#endregion
69
+ export { EmptyState_vue_vue_type_script_setup_true_lang_default as default };
70
+
71
+ //# sourceMappingURL=EmptyState.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmptyState.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/blocks/EmptyState/EmptyState.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * EmptyState — the shape of \"nothing here yet\": icon → title → optional\n * description → at most ONE call-to-action, centered in the empty region. An\n * empty region should explain itself and invite the next step — empty is a\n * welcome, never an error (a failed load renders `InlineError`; an empty\n * *result* renders this).\n *\n * The entrance is a staggered fade-rise film (icon, title, description,\n * action — 60ms apart): this is content appearing, not action feedback, so\n * it budgets like a panel rather than against the interaction-feedback\n * ceiling, all token-tier CSS. Purely presentational: the icon comes via the\n * `icon` slot (decorative, hidden from assistive tech), the CTA via the\n * `action` slot — the host owns behavior and wording, and no fallback copy\n * ships with the component.\n *\n * The icon sits in a hairline medallion — a `bg-subtle` disc with a `border`\n * ring — rather than floating bare. Two reasons: the glyph itself is sized\n * 20px, the emphasis step for an empty-state icon, and a 20px stroke drawing\n * alone in a large blank region has nothing to hold it, so it reads as a\n * stray mark; the medallion gives it a shape to anchor without adding a\n * shadow (a disc is a surface plus a hairline, never a float). `bg-subtle`\n * is chosen over `bg-card` so the disc stays visible on `bg-card` and\n * `bg-background` alike — this block is dropped into both.\n *\n * Type comes from the named scale (`text-title` / `text-small`), not\n * hand-picked `text-sm`/`text-xs` — the empty state is a titled moment, not\n * a caption.\n */\ndefineProps<{\n /** What is missing, stated plainly — always shown. */\n title: string;\n /** What to do about it. Omit rather than pad the region with filler copy. */\n description?: string;\n}>();\n</script>\n\n<template>\n <div class=\"flex flex-col items-center justify-center gap-1.5 px-6 py-10 text-center sm:py-14\">\n <div\n v-if=\"$slots.icon\"\n aria-hidden=\"true\"\n class=\"animate-fade-rise mb-3 grid h-12 w-12 place-items-center rounded-full border border-border bg-subtle text-muted-foreground [&_svg]:h-5 [&_svg]:w-5\"\n >\n <slot name=\"icon\" />\n </div>\n <p class=\"animate-fade-rise text-title text-foreground\" :style=\"{ animationDelay: '60ms' }\">\n {{ title }}\n </p>\n <p\n v-if=\"description\"\n class=\"animate-fade-rise max-w-sm text-balance text-small text-muted-foreground\"\n :style=\"{ animationDelay: '120ms' }\"\n >\n {{ description }}\n </p>\n <div v-if=\"$slots.action\" class=\"animate-fade-rise mt-4\" :style=\"{ animationDelay: '180ms' }\">\n <slot name=\"action\" />\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCE,OAAA,UAAA,GAAA,mBAqBM,OArBN,YAqBM;IAnBIA,KAAAA,OAAO,QADf,UAAA,GAAA,mBAMM,OANN,YAMM,CADJ,WAAoB,KAAA,QAAA,MAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;IAEtB,mBAEI,KAFJ,YAEI,gBADC,QAAA,KAAK,GAAA,CAAA;IAGF,QAAA,eADR,UAAA,GAAA,mBAMI,KANJ,YAMI,gBADC,QAAA,WAAW,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;IAELA,KAAAA,OAAO,UAAlB,UAAA,GAAA,mBAEM,OAFN,YAEM,CADJ,WAAsB,KAAA,QAAA,QAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA"}
@@ -0,0 +1,7 @@
1
+ import PageHeader_vue_vue_type_script_setup_true_lang_default from "./PageHeader.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/blocks/PageHeader/PageHeader.vue
3
+ var PageHeader_default = PageHeader_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { PageHeader_default as default };
6
+
7
+ //# sourceMappingURL=PageHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageHeader.js","names":[],"sources":["../../../src/blocks/PageHeader/PageHeader.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * PageHeader — the band that turns a scrolling document into a workspace\n * surface: it pins to the top of the scroll container, carries the\n * surface's name, its live count and one line of orientation, and owns the\n * surface's primary actions.\n *\n * Two things it deliberately does:\n *\n * - **Pinned, and separated by a hairline — never a shadow.** It sits on\n * `bg-background`, the same plane as the work area rather than a sunken\n * navigation plane, because this is the surface's own header, not chrome\n * that recedes. Rows scroll *under* it, so the plane is translucent and\n * blurred; the opaque `bg-background` is declared first and remains the\n * fallback wherever `backdrop-filter` is unsupported.\n * - **The count is a number, so it is `tabular`** — a count that changes as\n * items resolve must not shift the title beside it. It is deliberately\n * NOT a Badge: a badge is a status chip, and \"how many rows are below\" is\n * a fact, not a status. Wrap it in a Badge at the call site on the rare\n * surface where the count itself is the alarm.\n *\n * Presentational only: the host owns wording, the actions, and the scroll\n * container this sticks inside (`position: sticky` resolves against the\n * nearest scrolling ancestor — a header that will not stick is almost\n * always an ancestor with `overflow: hidden`, not this component).\n *\n * Two width behaviors. Gutters step up (`sm`, then `3xl`) rather than\n * holding one value, so the band is not padded like a phone on a 1920px\n * canvas. And the description is capped at `max-w-prose` instead of\n * tracking the viewport — a one-line orientation stretched across an\n * ultra-wide monitor is unreadable; the width that opens up belongs to the\n * actions and the work below, not to a longer measure. The title itself is\n * uncapped: it truncates, so it can only ever occupy one line.\n */\ndefineProps<{\n title: string;\n /** One line of orientation under the title. Say what the surface is FOR, not what it is called again. */\n description?: string;\n /** Live row count shown beside the title. Omit rather than pass 0 — \"0\" beside a title reads as a broken fetch; the empty state carries that message. */\n count?: number;\n}>();\n</script>\n\n<template>\n <header\n class=\"sticky top-0 z-20 flex flex-wrap items-start gap-x-6 gap-y-3 border-b border-border bg-background px-4 py-3 backdrop-blur-md supports-[backdrop-filter]:bg-background/80 sm:px-6 sm:py-4 3xl:px-8\"\n >\n <!-- `basis-56` is the wrap threshold, not a width: flex line-breaking reads\n the basis, so the actions drop to their own row once the title cannot\n hold ~14rem — instead of staying crammed alongside a title truncated to\n a few glyphs. `min-w-0` still lets the block shrink under that on the\n narrowest screens, and keeps the h1's truncate working. -->\n <div class=\"min-w-0 flex-1 basis-56\">\n <div class=\"flex items-baseline gap-2\">\n <h1 class=\"text-heading min-w-0 truncate text-foreground\">{{ title }}</h1>\n <span v-if=\"count !== undefined\" class=\"tabular shrink-0 text-small text-muted-foreground\">\n {{ count }}\n </span>\n </div>\n <p v-if=\"description\" class=\"mt-0.5 max-w-prose text-small text-muted-foreground\">\n {{ description }}\n </p>\n </div>\n <!-- `ml-auto`, not the header's `justify-between`: once the actions wrap to\n their own line the two are no longer distributed, and justify-between\n would drop them flush LEFT under the title. -->\n <div v-if=\"$slots.actions\" class=\"ml-auto flex shrink-0 items-center gap-2\">\n <!-- @slot The surface's primary actions, trailing the title. Convention: at most one `variant=\"primary\"` Button, the rest `outline`/`subtle`. -->\n <slot name=\"actions\" />\n </div>\n </header>\n</template>\n"],"mappings":""}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * PageHeader — the band that turns a scrolling document into a workspace
3
+ * surface: it pins to the top of the scroll container, carries the
4
+ * surface's name, its live count and one line of orientation, and owns the
5
+ * surface's primary actions.
6
+ *
7
+ * Two things it deliberately does:
8
+ *
9
+ * - **Pinned, and separated by a hairline — never a shadow.** It sits on
10
+ * `bg-background`, the same plane as the work area rather than a sunken
11
+ * navigation plane, because this is the surface's own header, not chrome
12
+ * that recedes. Rows scroll *under* it, so the plane is translucent and
13
+ * blurred; the opaque `bg-background` is declared first and remains the
14
+ * fallback wherever `backdrop-filter` is unsupported.
15
+ * - **The count is a number, so it is `tabular`** — a count that changes as
16
+ * items resolve must not shift the title beside it. It is deliberately
17
+ * NOT a Badge: a badge is a status chip, and "how many rows are below" is
18
+ * a fact, not a status. Wrap it in a Badge at the call site on the rare
19
+ * surface where the count itself is the alarm.
20
+ *
21
+ * Presentational only: the host owns wording, the actions, and the scroll
22
+ * container this sticks inside (`position: sticky` resolves against the
23
+ * nearest scrolling ancestor — a header that will not stick is almost
24
+ * always an ancestor with `overflow: hidden`, not this component).
25
+ *
26
+ * Two width behaviors. Gutters step up (`sm`, then `3xl`) rather than
27
+ * holding one value, so the band is not padded like a phone on a 1920px
28
+ * canvas. And the description is capped at `max-w-prose` instead of
29
+ * tracking the viewport — a one-line orientation stretched across an
30
+ * ultra-wide monitor is unreadable; the width that opens up belongs to the
31
+ * actions and the work below, not to a longer measure. The title itself is
32
+ * uncapped: it truncates, so it can only ever occupy one line.
33
+ */
34
+ type __VLS_Props = {
35
+ title: string;
36
+ /** One line of orientation under the title. Say what the surface is FOR, not what it is called again. */
37
+ description?: string;
38
+ /** Live row count shown beside the title. Omit rather than pass 0 — "0" beside a title reads as a broken fetch; the empty state carries that message. */
39
+ count?: number;
40
+ };
41
+ declare var __VLS_1: {};
42
+ type __VLS_Slots = {} & {
43
+ actions?: (props: typeof __VLS_1) => any;
44
+ };
45
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
46
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
47
+ declare const _default: typeof __VLS_export;
48
+ export default _default;
49
+ type __VLS_WithSlots<T, S> = T & {
50
+ new (): {
51
+ $slots: S;
52
+ };
53
+ };
54
+ //# sourceMappingURL=PageHeader.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageHeader.vue.d.ts","sourceRoot":"","sources":["../../../src/blocks/PageHeader/PageHeader.vue"],"names":[],"mappings":"AA2EA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,yGAAyG;IACzG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yJAAyJ;IACzJ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA0FF,QAAA,IAAI,OAAO,IAAW,CAAE;AACxB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAK/C,QAAA,MAAM,UAAU,kSAEd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { createCommentVNode, createElementBlock, createElementVNode, defineComponent, openBlock, renderSlot, toDisplayString } from "vue";
2
+ //#region src/blocks/PageHeader/PageHeader.vue?vue&type=script&setup=true&lang.ts
3
+ var _hoisted_1 = { class: "sticky top-0 z-20 flex flex-wrap items-start gap-x-6 gap-y-3 border-b border-border bg-background px-4 py-3 backdrop-blur-md supports-[backdrop-filter]:bg-background/80 sm:px-6 sm:py-4 3xl:px-8" };
4
+ var _hoisted_2 = { class: "min-w-0 flex-1 basis-56" };
5
+ var _hoisted_3 = { class: "flex items-baseline gap-2" };
6
+ var _hoisted_4 = { class: "text-heading min-w-0 truncate text-foreground" };
7
+ var _hoisted_5 = {
8
+ key: 0,
9
+ class: "tabular shrink-0 text-small text-muted-foreground"
10
+ };
11
+ var _hoisted_6 = {
12
+ key: 0,
13
+ class: "mt-0.5 max-w-prose text-small text-muted-foreground"
14
+ };
15
+ var _hoisted_7 = {
16
+ key: 0,
17
+ class: "ml-auto flex shrink-0 items-center gap-2"
18
+ };
19
+ var PageHeader_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
20
+ __name: "PageHeader",
21
+ props: {
22
+ title: {},
23
+ description: {},
24
+ count: {}
25
+ },
26
+ setup(__props) {
27
+ /**
28
+ * PageHeader — the band that turns a scrolling document into a workspace
29
+ * surface: it pins to the top of the scroll container, carries the
30
+ * surface's name, its live count and one line of orientation, and owns the
31
+ * surface's primary actions.
32
+ *
33
+ * Two things it deliberately does:
34
+ *
35
+ * - **Pinned, and separated by a hairline — never a shadow.** It sits on
36
+ * `bg-background`, the same plane as the work area rather than a sunken
37
+ * navigation plane, because this is the surface's own header, not chrome
38
+ * that recedes. Rows scroll *under* it, so the plane is translucent and
39
+ * blurred; the opaque `bg-background` is declared first and remains the
40
+ * fallback wherever `backdrop-filter` is unsupported.
41
+ * - **The count is a number, so it is `tabular`** — a count that changes as
42
+ * items resolve must not shift the title beside it. It is deliberately
43
+ * NOT a Badge: a badge is a status chip, and "how many rows are below" is
44
+ * a fact, not a status. Wrap it in a Badge at the call site on the rare
45
+ * surface where the count itself is the alarm.
46
+ *
47
+ * Presentational only: the host owns wording, the actions, and the scroll
48
+ * container this sticks inside (`position: sticky` resolves against the
49
+ * nearest scrolling ancestor — a header that will not stick is almost
50
+ * always an ancestor with `overflow: hidden`, not this component).
51
+ *
52
+ * Two width behaviors. Gutters step up (`sm`, then `3xl`) rather than
53
+ * holding one value, so the band is not padded like a phone on a 1920px
54
+ * canvas. And the description is capped at `max-w-prose` instead of
55
+ * tracking the viewport — a one-line orientation stretched across an
56
+ * ultra-wide monitor is unreadable; the width that opens up belongs to the
57
+ * actions and the work below, not to a longer measure. The title itself is
58
+ * uncapped: it truncates, so it can only ever occupy one line.
59
+ */
60
+ return (_ctx, _cache) => {
61
+ return openBlock(), createElementBlock("header", _hoisted_1, [createElementVNode("div", _hoisted_2, [createElementVNode("div", _hoisted_3, [createElementVNode("h1", _hoisted_4, toDisplayString(__props.title), 1), __props.count !== void 0 ? (openBlock(), createElementBlock("span", _hoisted_5, toDisplayString(__props.count), 1)) : createCommentVNode("", true)]), __props.description ? (openBlock(), createElementBlock("p", _hoisted_6, toDisplayString(__props.description), 1)) : createCommentVNode("", true)]), _ctx.$slots.actions ? (openBlock(), createElementBlock("div", _hoisted_7, [renderSlot(_ctx.$slots, "actions")])) : createCommentVNode("", true)]);
62
+ };
63
+ }
64
+ });
65
+ //#endregion
66
+ export { PageHeader_vue_vue_type_script_setup_true_lang_default as default };
67
+
68
+ //# sourceMappingURL=PageHeader.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageHeader.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/blocks/PageHeader/PageHeader.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * PageHeader — the band that turns a scrolling document into a workspace\n * surface: it pins to the top of the scroll container, carries the\n * surface's name, its live count and one line of orientation, and owns the\n * surface's primary actions.\n *\n * Two things it deliberately does:\n *\n * - **Pinned, and separated by a hairline — never a shadow.** It sits on\n * `bg-background`, the same plane as the work area rather than a sunken\n * navigation plane, because this is the surface's own header, not chrome\n * that recedes. Rows scroll *under* it, so the plane is translucent and\n * blurred; the opaque `bg-background` is declared first and remains the\n * fallback wherever `backdrop-filter` is unsupported.\n * - **The count is a number, so it is `tabular`** — a count that changes as\n * items resolve must not shift the title beside it. It is deliberately\n * NOT a Badge: a badge is a status chip, and \"how many rows are below\" is\n * a fact, not a status. Wrap it in a Badge at the call site on the rare\n * surface where the count itself is the alarm.\n *\n * Presentational only: the host owns wording, the actions, and the scroll\n * container this sticks inside (`position: sticky` resolves against the\n * nearest scrolling ancestor — a header that will not stick is almost\n * always an ancestor with `overflow: hidden`, not this component).\n *\n * Two width behaviors. Gutters step up (`sm`, then `3xl`) rather than\n * holding one value, so the band is not padded like a phone on a 1920px\n * canvas. And the description is capped at `max-w-prose` instead of\n * tracking the viewport — a one-line orientation stretched across an\n * ultra-wide monitor is unreadable; the width that opens up belongs to the\n * actions and the work below, not to a longer measure. The title itself is\n * uncapped: it truncates, so it can only ever occupy one line.\n */\ndefineProps<{\n title: string;\n /** One line of orientation under the title. Say what the surface is FOR, not what it is called again. */\n description?: string;\n /** Live row count shown beside the title. Omit rather than pass 0 — \"0\" beside a title reads as a broken fetch; the empty state carries that message. */\n count?: number;\n}>();\n</script>\n\n<template>\n <header\n class=\"sticky top-0 z-20 flex flex-wrap items-start gap-x-6 gap-y-3 border-b border-border bg-background px-4 py-3 backdrop-blur-md supports-[backdrop-filter]:bg-background/80 sm:px-6 sm:py-4 3xl:px-8\"\n >\n <!-- `basis-56` is the wrap threshold, not a width: flex line-breaking reads\n the basis, so the actions drop to their own row once the title cannot\n hold ~14rem — instead of staying crammed alongside a title truncated to\n a few glyphs. `min-w-0` still lets the block shrink under that on the\n narrowest screens, and keeps the h1's truncate working. -->\n <div class=\"min-w-0 flex-1 basis-56\">\n <div class=\"flex items-baseline gap-2\">\n <h1 class=\"text-heading min-w-0 truncate text-foreground\">{{ title }}</h1>\n <span v-if=\"count !== undefined\" class=\"tabular shrink-0 text-small text-muted-foreground\">\n {{ count }}\n </span>\n </div>\n <p v-if=\"description\" class=\"mt-0.5 max-w-prose text-small text-muted-foreground\">\n {{ description }}\n </p>\n </div>\n <!-- `ml-auto`, not the header's `justify-between`: once the actions wrap to\n their own line the two are no longer distributed, and justify-between\n would drop them flush LEFT under the title. -->\n <div v-if=\"$slots.actions\" class=\"ml-auto flex shrink-0 items-center gap-2\">\n <!-- @slot The surface's primary actions, trailing the title. Convention: at most one `variant=\"primary\"` Button, the rest `outline`/`subtle`. -->\n <slot name=\"actions\" />\n </div>\n </header>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CE,OAAA,UAAA,GAAA,mBA0BS,UA1BT,YA0BS,CAlBP,mBAUM,OAVN,YAUM,CATJ,mBAKM,OALN,YAKM,CAJJ,mBAA0E,MAA1E,YAA0E,gBAAb,QAAA,KAAK,GAAA,CAAA,GACtD,QAAA,UAAU,KAAA,KAAtB,UAAA,GAAA,mBAEO,QAFP,YAEO,gBADF,QAAA,KAAK,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,GAGH,QAAA,eAAT,UAAA,GAAA,mBAEI,KAFJ,YAEI,gBADC,QAAA,WAAW,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,GAMPA,KAAAA,OAAO,WAAlB,UAAA,GAAA,mBAGM,OAHN,YAGM,CADJ,WAAuB,KAAA,QAAA,SAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA"}
@@ -0,0 +1,7 @@
1
+ import RowActions_vue_vue_type_script_setup_true_lang_default from "./RowActions.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/blocks/RowActions/RowActions.vue
3
+ var RowActions_default = RowActions_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { RowActions_default as default };
6
+
7
+ //# sourceMappingURL=RowActions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RowActions.js","names":[],"sources":["../../../src/blocks/RowActions/RowActions.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * RowActions — the actions belonging to one row of a dense list, quiet at\n * rest and revealed on hover or keyboard focus.\n *\n * Why this is a component and not three utility classes copied per view: the\n * reveal carries an accessibility contract that is easy to get wrong in a way\n * nothing fails on.\n *\n * - **Revealed by `opacity`, never by `display`/`v-if`.** A row action hidden\n * with `hidden` or unmounted until hover leaves the tab order, so a\n * keyboard-only or screen-reader user simply cannot reach it — and no test\n * notices, because the pointer path still works.\n * - **`group-focus-within`, not only `group-hover`.** Tabbing into the row\n * must bring the actions up; otherwise focus lands on something invisible\n * and the focus ring appears to come from nowhere.\n * - **The actions stay mounted and named.** Each child keeps its own\n * `aria-label` — the reveal changes what is *seen*, never what exists.\n * - **`pointer-coarse` opts out of the reveal entirely.** A hover reveal has\n * no trigger on a touch screen: there is no hover state to enter, and the\n * `focus-within` fallback only fires after a tap has already landed on\n * something invisible. So on a coarse pointer the actions are simply always\n * visible — the reveal is a refinement for precise pointers, not a gate on\n * reaching the actions at all.\n *\n * The reveal rides a 4px inward slide alongside the fade so it reads as the\n * actions arriving rather than a panel blinking on (motion carries cause and\n * effect); both are token-tier and `duration-fast`, and the global\n * reduced-motion rule flattens them together.\n *\n * Requires the row element to carry Tailwind's `group` class; the reveal is\n * scoped to that group so sibling rows stay quiet.\n */\n</script>\n\n<template>\n <div\n class=\"flex translate-x-1 items-center gap-1 opacity-0 transition duration-fast ease-out group-hover:translate-x-0 group-hover:opacity-100 group-focus-within:translate-x-0 group-focus-within:opacity-100 pointer-coarse:translate-x-0 pointer-coarse:opacity-100\"\n >\n <slot />\n </div>\n</template>\n"],"mappings":""}
@@ -0,0 +1,14 @@
1
+ declare var __VLS_1: {};
2
+ type __VLS_Slots = {} & {
3
+ default?: (props: typeof __VLS_1) => any;
4
+ };
5
+ declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
6
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
7
+ declare const _default: typeof __VLS_export;
8
+ export default _default;
9
+ type __VLS_WithSlots<T, S> = T & {
10
+ new (): {
11
+ $slots: S;
12
+ };
13
+ };
14
+ //# sourceMappingURL=RowActions.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RowActions.vue.d.ts","sourceRoot":"","sources":["../../../src/blocks/RowActions/RowActions.vue"],"names":[],"mappings":"AA0GA,QAAA,IAAI,OAAO,IAAW,CAAE;AACxB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAG/C,QAAA,MAAM,UAAU,+QACd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { createElementBlock, defineComponent, openBlock, renderSlot } from "vue";
2
+ //#region src/blocks/RowActions/RowActions.vue?vue&type=script&setup=true&lang.ts
3
+ var _hoisted_1 = { class: "flex translate-x-1 items-center gap-1 opacity-0 transition duration-fast ease-out group-hover:translate-x-0 group-hover:opacity-100 group-focus-within:translate-x-0 group-focus-within:opacity-100 pointer-coarse:translate-x-0 pointer-coarse:opacity-100" };
4
+ var RowActions_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
5
+ __name: "RowActions",
6
+ setup(__props) {
7
+ /**
8
+ * RowActions — the actions belonging to one row of a dense list, quiet at
9
+ * rest and revealed on hover or keyboard focus.
10
+ *
11
+ * Why this is a component and not three utility classes copied per view: the
12
+ * reveal carries an accessibility contract that is easy to get wrong in a way
13
+ * nothing fails on.
14
+ *
15
+ * - **Revealed by `opacity`, never by `display`/`v-if`.** A row action hidden
16
+ * with `hidden` or unmounted until hover leaves the tab order, so a
17
+ * keyboard-only or screen-reader user simply cannot reach it — and no test
18
+ * notices, because the pointer path still works.
19
+ * - **`group-focus-within`, not only `group-hover`.** Tabbing into the row
20
+ * must bring the actions up; otherwise focus lands on something invisible
21
+ * and the focus ring appears to come from nowhere.
22
+ * - **The actions stay mounted and named.** Each child keeps its own
23
+ * `aria-label` — the reveal changes what is *seen*, never what exists.
24
+ * - **`pointer-coarse` opts out of the reveal entirely.** A hover reveal has
25
+ * no trigger on a touch screen: there is no hover state to enter, and the
26
+ * `focus-within` fallback only fires after a tap has already landed on
27
+ * something invisible. So on a coarse pointer the actions are simply always
28
+ * visible — the reveal is a refinement for precise pointers, not a gate on
29
+ * reaching the actions at all.
30
+ *
31
+ * The reveal rides a 4px inward slide alongside the fade so it reads as the
32
+ * actions arriving rather than a panel blinking on (motion carries cause and
33
+ * effect); both are token-tier and `duration-fast`, and the global
34
+ * reduced-motion rule flattens them together.
35
+ *
36
+ * Requires the row element to carry Tailwind's `group` class; the reveal is
37
+ * scoped to that group so sibling rows stay quiet.
38
+ */
39
+ return (_ctx, _cache) => {
40
+ return openBlock(), createElementBlock("div", _hoisted_1, [renderSlot(_ctx.$slots, "default")]);
41
+ };
42
+ }
43
+ });
44
+ //#endregion
45
+ export { RowActions_vue_vue_type_script_setup_true_lang_default as default };
46
+
47
+ //# sourceMappingURL=RowActions.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RowActions.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/blocks/RowActions/RowActions.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * RowActions — the actions belonging to one row of a dense list, quiet at\n * rest and revealed on hover or keyboard focus.\n *\n * Why this is a component and not three utility classes copied per view: the\n * reveal carries an accessibility contract that is easy to get wrong in a way\n * nothing fails on.\n *\n * - **Revealed by `opacity`, never by `display`/`v-if`.** A row action hidden\n * with `hidden` or unmounted until hover leaves the tab order, so a\n * keyboard-only or screen-reader user simply cannot reach it — and no test\n * notices, because the pointer path still works.\n * - **`group-focus-within`, not only `group-hover`.** Tabbing into the row\n * must bring the actions up; otherwise focus lands on something invisible\n * and the focus ring appears to come from nowhere.\n * - **The actions stay mounted and named.** Each child keeps its own\n * `aria-label` — the reveal changes what is *seen*, never what exists.\n * - **`pointer-coarse` opts out of the reveal entirely.** A hover reveal has\n * no trigger on a touch screen: there is no hover state to enter, and the\n * `focus-within` fallback only fires after a tap has already landed on\n * something invisible. So on a coarse pointer the actions are simply always\n * visible — the reveal is a refinement for precise pointers, not a gate on\n * reaching the actions at all.\n *\n * The reveal rides a 4px inward slide alongside the fade so it reads as the\n * actions arriving rather than a panel blinking on (motion carries cause and\n * effect); both are token-tier and `duration-fast`, and the global\n * reduced-motion rule flattens them together.\n *\n * Requires the row element to carry Tailwind's `group` class; the reveal is\n * scoped to that group so sibling rows stay quiet.\n */\n</script>\n\n<template>\n <div\n class=\"flex translate-x-1 items-center gap-1 opacity-0 transition duration-fast ease-out group-hover:translate-x-0 group-hover:opacity-100 group-focus-within:translate-x-0 group-focus-within:opacity-100 pointer-coarse:translate-x-0 pointer-coarse:opacity-100\"\n >\n <slot />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCE,OAAA,UAAA,GAAA,mBAIM,OAJN,YAIM,CADJ,WAAQ,KAAA,QAAA,SAAA,CAAA,CAAA"}
@@ -0,0 +1,7 @@
1
+ import SidebarNav_vue_vue_type_script_setup_true_lang_default from "./SidebarNav.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/blocks/SidebarNav/SidebarNav.vue
3
+ var SidebarNav_default = SidebarNav_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { SidebarNav_default as default };
6
+
7
+ //# sourceMappingURL=SidebarNav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SidebarNav.js","names":[],"sources":["../../../src/blocks/SidebarNav/SidebarNav.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Component } from \"vue\";\n\n/** One destination in the sidebar. */\nexport interface SidebarNavItem {\n /** A Lucide icon component (e.g. `Home` from `@lucide/vue`) — decorative; the label carries the meaning. */\n icon?: Component;\n label: string;\n /** Marks this as the current page — the sole `--primary` accent drawn in the list. */\n active?: boolean;\n /** Renders the item as a real `<a>` instead of a `<button>`. The host owns the router/navigation. */\n href?: string;\n /** Short count/status shown after the label. Hidden in collapsed mode — folded into its tooltip instead. */\n badge?: string | number;\n}\n\n/** A labeled group of items; `label` may be omitted for an unlabeled leading group. */\nexport interface SidebarNavSection {\n label?: string;\n items: SidebarNavItem[];\n}\n</script>\n\n<script setup lang=\"ts\">\nimport Tooltip from \"../../primitives/Tooltip/Tooltip.vue\";\nimport Badge from \"../../primitives/Badge/Badge.vue\";\nimport Separator from \"../../primitives/Separator/Separator.vue\";\nimport { cn } from \"../../lib/cn\";\n\n/**\n * SidebarNav — the primary NAVIGATION chrome: a `<nav>` landmark of sections\n * and destinations, pinned to the sunken plane (the recessed layer of the\n * shell — sunken < background < card, so work surfaces read as lifted and\n * navigation recedes).\n *\n * The active item carries a flat `--primary` fill and an inset accent bar —\n * a human decides which surface they are on, so this is the human/warp force\n * alone. It never mixes in `--agent`: this is navigation chrome, not a place\n * reporting automated work.\n *\n * Presentational only: the host owns routing (`href` renders a real anchor)\n * and which item is `active` — this component does not track a current\n * route itself.\n *\n * Collapsed mode drops to icon-only rows: each item still needs an\n * accessible name once its label text is hidden, so it moves to `aria-label`\n * (Tooltip's own contract is `aria-describedby`, never the *only* source of\n * a name) and its Tooltip doubles as the visible hint. Native `<a>`/`<button>`\n * elements are used throughout, so Enter/Space activation and tab order come\n * from the platform, not custom key handling.\n *\n * Collapsed rows are square (`h-9 w-9`) rather than full-width, so the nav\n * centers its own children in that mode. The host is what narrows the rail,\n * and it may narrow it late or not at all — without the centering, a collapsed\n * nav still sitting in an expanded-width container leaves a column of icons\n * hugging the left edge of a wide empty panel. Centering makes the mode read\n * correctly at every container width, and the host's width animation then only\n * has to tighten what already looks right.\n */\nwithDefaults(\n defineProps<{\n sections: SidebarNavSection[];\n /** Icon-only rail: section headings and item labels hide; each item's name moves into a Tooltip. */\n collapsed?: boolean;\n /** Accessible name for the `<nav>` landmark — the host owns wording (see `AppHeader`'s same prop). */\n ariaLabel?: string;\n }>(),\n { collapsed: false },\n);\n\nconst emit = defineEmits<{ select: [item: SidebarNavItem] }>();\n\nfunction tooltipContent(item: SidebarNavItem): string {\n return item.badge !== undefined && item.badge !== null\n ? `${item.label} · ${item.badge}`\n : item.label;\n}\n\nfunction itemClass(item: SidebarNavItem, collapsed: boolean): string {\n return cn(\n \"relative flex items-center gap-2 rounded-md text-left text-sm outline-none\",\n \"transition-colors duration-fast ease-out\",\n \"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo\",\n collapsed ? \"h-9 w-9 justify-center\" : \"h-9 w-full px-2.5\",\n item.active\n ? \"bg-primary/10 font-medium text-primary\"\n : // Hover lifts the row to the raised plane rather than tinting it with\n // `--subtle`. `--subtle` is the neutral hover fill for surfaces sitting\n // on `--background` (96% L), where it lands 2% darker and reads. This\n // nav sits on `--sunken` (93% L) and `--subtle` is 94% — one percent\n // apart, so the hover state was there in the markup and invisible on\n // screen. Lifting to `bg-card` is the elevation rhythm's own answer\n // (sunken < background < card): the row the pointer is on comes\n // forward.\n \"text-muted-foreground hover:bg-card hover:text-foreground\",\n );\n}\n</script>\n\n<template>\n <nav\n :aria-label=\"ariaLabel\"\n class=\"flex h-full w-full flex-col gap-1 overflow-y-auto overscroll-contain bg-sunken p-2\"\n :class=\"collapsed && 'items-center'\"\n >\n <template v-for=\"(section, sectionIndex) in sections\" :key=\"sectionIndex\">\n <Separator v-if=\"sectionIndex > 0\" class=\"my-1\" />\n <p\n v-if=\"section.label && !collapsed\"\n class=\"select-none px-2 pb-1 pt-2 text-micro font-medium uppercase tracking-wide text-muted-foreground\"\n >\n {{ section.label }}\n </p>\n <ul class=\"flex flex-col gap-0.5\">\n <li v-for=\"(item, itemIndex) in section.items\" :key=\"itemIndex\">\n <Tooltip v-if=\"collapsed\" :content=\"tooltipContent(item)\" side=\"right\">\n <template #trigger>\n <component\n :is=\"item.href ? 'a' : 'button'\"\n :type=\"item.href ? undefined : 'button'\"\n :href=\"item.href\"\n :aria-current=\"item.active ? 'page' : undefined\"\n :aria-label=\"item.label\"\n :class=\"itemClass(item, true)\"\n @click=\"emit('select', item)\"\n >\n <span\n v-if=\"item.active\"\n aria-hidden=\"true\"\n class=\"absolute inset-y-1.5 left-0 w-0.5 rounded-full bg-primary\"\n />\n <component :is=\"item.icon\" v-if=\"item.icon\" aria-hidden=\"true\" class=\"shrink-0\" />\n </component>\n </template>\n </Tooltip>\n\n <component\n :is=\"item.href ? 'a' : 'button'\"\n v-else\n :type=\"item.href ? undefined : 'button'\"\n :href=\"item.href\"\n :aria-current=\"item.active ? 'page' : undefined\"\n :class=\"itemClass(item, false)\"\n @click=\"emit('select', item)\"\n >\n <span\n v-if=\"item.active\"\n aria-hidden=\"true\"\n class=\"absolute inset-y-1.5 left-0 w-0.5 rounded-full bg-primary\"\n />\n <component :is=\"item.icon\" v-if=\"item.icon\" aria-hidden=\"true\" class=\"shrink-0\" />\n <span class=\"min-w-0 flex-1 truncate\">{{ item.label }}</span>\n <Badge v-if=\"item.badge !== undefined\" variant=\"neutral\" class=\"shrink-0\">\n {{ item.badge }}\n </Badge>\n </component>\n </li>\n </ul>\n </template>\n </nav>\n</template>\n"],"mappings":""}
@@ -0,0 +1,40 @@
1
+ import type { Component } from "vue";
2
+ /** One destination in the sidebar. */
3
+ export interface SidebarNavItem {
4
+ /** A Lucide icon component (e.g. `Home` from `@lucide/vue`) — decorative; the label carries the meaning. */
5
+ icon?: Component;
6
+ label: string;
7
+ /** Marks this as the current page — the sole `--primary` accent drawn in the list. */
8
+ active?: boolean;
9
+ /** Renders the item as a real `<a>` instead of a `<button>`. The host owns the router/navigation. */
10
+ href?: string;
11
+ /** Short count/status shown after the label. Hidden in collapsed mode — folded into its tooltip instead. */
12
+ badge?: string | number;
13
+ }
14
+ /** A labeled group of items; `label` may be omitted for an unlabeled leading group. */
15
+ export interface SidebarNavSection {
16
+ label?: string;
17
+ items: SidebarNavItem[];
18
+ }
19
+ declare const _default: typeof __VLS_export;
20
+ export default _default;
21
+ declare const __VLS_export: import("vue").DefineComponent<{
22
+ sections: SidebarNavSection[];
23
+ /** Icon-only rail: section headings and item labels hide; each item's name moves into a Tooltip. */
24
+ collapsed?: boolean;
25
+ /** Accessible name for the `<nav>` landmark — the host owns wording (see `AppHeader`'s same prop). */
26
+ ariaLabel?: string;
27
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
28
+ select: (item: SidebarNavItem) => any;
29
+ }, string, import("vue").PublicProps, Readonly<{
30
+ sections: SidebarNavSection[];
31
+ /** Icon-only rail: section headings and item labels hide; each item's name moves into a Tooltip. */
32
+ collapsed?: boolean;
33
+ /** Accessible name for the `<nav>` landmark — the host owns wording (see `AppHeader`'s same prop). */
34
+ ariaLabel?: string;
35
+ }> & Readonly<{
36
+ onSelect?: (item: SidebarNavItem) => any;
37
+ }>, {
38
+ collapsed: boolean;
39
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
40
+ //# sourceMappingURL=SidebarNav.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SidebarNav.vue.d.ts","sourceRoot":"","sources":["../../../src/blocks/SidebarNav/SidebarNav.vue"],"names":[],"mappings":"AA0KA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAErC,sCAAsC;AACtC,MAAM,WAAW,cAAc;IAC7B,4GAA4G;IAC5G,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qGAAqG;IACrG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4GAA4G;IAC5G,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED,uFAAuF;AACvF,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;wBACoB,OAAO,YAAY;AAAxC,wBAAyC;AACzC,QAAA,MAAM,YAAY;cAgCJ,iBAAiB,EAAE;IAC7B,oGAAoG;gBACxF,OAAO;IACnB,sGAAsG;gBAC1F,MAAM;;;;cAJR,iBAAiB,EAAE;IAC7B,oGAAoG;gBACxF,OAAO;IACnB,sGAAsG;gBAC1F,MAAM;;;;eAFN,OAAO;6EAmSnB,CAAC"}