@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,19 @@
1
+ /**
2
+ * The WCAG scope Loom holds itself to: the assistive-technology and keyboard
3
+ * rules, not axe's SEO and document-structure best-practice set. A component
4
+ * library cannot know what document it will be rendered into, so a rule about
5
+ * the document is the consumer's to answer, not ours.
6
+ *
7
+ * Single source for every axe run against this package, and there is more
8
+ * than one, in different processes: the documentation site's live
9
+ * accessibility panel and the end-to-end gate that scans the built site. Both
10
+ * import this. The list must never be restated, or the panel a contributor
11
+ * reads and the gate that blocks the merge drift into disagreeing about what
12
+ * counts as a violation.
13
+ *
14
+ * Exported from the narrow `@ecoma-io/loom/a11y` entry so a tool that only
15
+ * needs this array — a Playwright run, a CI script — can read it without
16
+ * pulling in a single Vue component.
17
+ */
18
+ export declare const WCAG_TAGS: readonly ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"];
19
+ //# sourceMappingURL=a11y-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11y-scope.d.ts","sourceRoot":"","sources":["../../src/lib/a11y-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,SAAS,uDAAwD,CAAC"}
@@ -0,0 +1,28 @@
1
+ //#region src/lib/a11y-scope.ts
2
+ /**
3
+ * The WCAG scope Loom holds itself to: the assistive-technology and keyboard
4
+ * rules, not axe's SEO and document-structure best-practice set. A component
5
+ * library cannot know what document it will be rendered into, so a rule about
6
+ * the document is the consumer's to answer, not ours.
7
+ *
8
+ * Single source for every axe run against this package, and there is more
9
+ * than one, in different processes: the documentation site's live
10
+ * accessibility panel and the end-to-end gate that scans the built site. Both
11
+ * import this. The list must never be restated, or the panel a contributor
12
+ * reads and the gate that blocks the merge drift into disagreeing about what
13
+ * counts as a violation.
14
+ *
15
+ * Exported from the narrow `@ecoma-io/loom/a11y` entry so a tool that only
16
+ * needs this array — a Playwright run, a CI script — can read it without
17
+ * pulling in a single Vue component.
18
+ */
19
+ var WCAG_TAGS = [
20
+ "wcag2a",
21
+ "wcag2aa",
22
+ "wcag21a",
23
+ "wcag21aa"
24
+ ];
25
+ //#endregion
26
+ export { WCAG_TAGS };
27
+
28
+ //# sourceMappingURL=a11y-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a11y-scope.js","names":[],"sources":["../../src/lib/a11y-scope.ts"],"sourcesContent":["/**\n * The WCAG scope Loom holds itself to: the assistive-technology and keyboard\n * rules, not axe's SEO and document-structure best-practice set. A component\n * library cannot know what document it will be rendered into, so a rule about\n * the document is the consumer's to answer, not ours.\n *\n * Single source for every axe run against this package, and there is more\n * than one, in different processes: the documentation site's live\n * accessibility panel and the end-to-end gate that scans the built site. Both\n * import this. The list must never be restated, or the panel a contributor\n * reads and the gate that blocks the merge drift into disagreeing about what\n * counts as a violation.\n *\n * Exported from the narrow `@ecoma-io/loom/a11y` entry so a tool that only\n * needs this array — a Playwright run, a CI script — can read it without\n * pulling in a single Vue component.\n */\nexport const WCAG_TAGS = [\"wcag2a\", \"wcag2aa\", \"wcag21a\", \"wcag21aa\"] as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,IAAa,YAAY;CAAC;CAAU;CAAW;CAAW;AAAU"}
@@ -0,0 +1,18 @@
1
+ import { type ComputedRef } from "vue";
2
+ /**
3
+ * Split `useAttrs()` into the raw fallthrough attributes — read `.class` off
4
+ * `attrs` for a `cn()` merge — and the same attributes minus `class` (`rest`,
5
+ * for `v-bind` onto whichever node is not the `class` target).
6
+ *
7
+ * Every caller pairs this with `defineOptions({ inheritAttrs: false })`.
8
+ * NumberField's input, Slider's thumb and Select's trigger each route `class`
9
+ * onto one specific rendered node rather than taking Vue's default
10
+ * single-root fallthrough, because `class` needs a Tailwind-aware merge while
11
+ * the rest of the fallthrough — aria-*, data-testid — only needs to land
12
+ * somewhere real.
13
+ */
14
+ export declare function useSplitAttrs(): {
15
+ attrs: Record<string, unknown>;
16
+ rest: ComputedRef<Record<string, unknown>>;
17
+ };
18
+ //# sourceMappingURL=attrs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attrs.d.ts","sourceRoot":"","sources":["../../src/lib/attrs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,KAAK,CAAC;AAE3D;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,IAAI;IAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC5C,CAOA"}
@@ -0,0 +1,28 @@
1
+ import { computed, useAttrs } from "vue";
2
+ //#region src/lib/attrs.ts
3
+ /**
4
+ * Split `useAttrs()` into the raw fallthrough attributes — read `.class` off
5
+ * `attrs` for a `cn()` merge — and the same attributes minus `class` (`rest`,
6
+ * for `v-bind` onto whichever node is not the `class` target).
7
+ *
8
+ * Every caller pairs this with `defineOptions({ inheritAttrs: false })`.
9
+ * NumberField's input, Slider's thumb and Select's trigger each route `class`
10
+ * onto one specific rendered node rather than taking Vue's default
11
+ * single-root fallthrough, because `class` needs a Tailwind-aware merge while
12
+ * the rest of the fallthrough — aria-*, data-testid — only needs to land
13
+ * somewhere real.
14
+ */
15
+ function useSplitAttrs() {
16
+ const attrs = useAttrs();
17
+ return {
18
+ attrs,
19
+ rest: computed(() => {
20
+ const { class: _class, ...others } = attrs;
21
+ return others;
22
+ })
23
+ };
24
+ }
25
+ //#endregion
26
+ export { useSplitAttrs };
27
+
28
+ //# sourceMappingURL=attrs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attrs.js","names":[],"sources":["../../src/lib/attrs.ts"],"sourcesContent":["import { computed, useAttrs, type ComputedRef } from \"vue\";\n\n/**\n * Split `useAttrs()` into the raw fallthrough attributes — read `.class` off\n * `attrs` for a `cn()` merge — and the same attributes minus `class` (`rest`,\n * for `v-bind` onto whichever node is not the `class` target).\n *\n * Every caller pairs this with `defineOptions({ inheritAttrs: false })`.\n * NumberField's input, Slider's thumb and Select's trigger each route `class`\n * onto one specific rendered node rather than taking Vue's default\n * single-root fallthrough, because `class` needs a Tailwind-aware merge while\n * the rest of the fallthrough — aria-*, data-testid — only needs to land\n * somewhere real.\n */\nexport function useSplitAttrs(): {\n attrs: Record<string, unknown>;\n rest: ComputedRef<Record<string, unknown>>;\n} {\n const attrs = useAttrs();\n const rest = computed(() => {\n const { class: _class, ...others } = attrs;\n return others;\n });\n return { attrs, rest };\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,SAAgB,gBAGd;CACA,MAAM,QAAQ,SAAS;CAKvB,OAAO;EAAE;EAAO,MAJH,eAAe;GAC1B,MAAM,EAAE,OAAO,QAAQ,GAAG,WAAW;GACrC,OAAO;EACT,CACgB;CAAK;AACvB"}
@@ -0,0 +1,9 @@
1
+ import { type ClassValue } from "clsx";
2
+ /**
3
+ * Merge conditional class names, resolving Tailwind conflicts so the last
4
+ * utility in a group wins. Every component routes its `class` through this,
5
+ * which is what lets a consumer override any utility from the outside without
6
+ * reaching for `!important`.
7
+ */
8
+ export declare function cn(...inputs: ClassValue[]): string;
9
+ //# sourceMappingURL=cn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../../src/lib/cn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAG7C;;;;;GAKG;AACH,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAElD"}
package/dist/lib/cn.js ADDED
@@ -0,0 +1,16 @@
1
+ import { clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+ //#region src/lib/cn.ts
4
+ /**
5
+ * Merge conditional class names, resolving Tailwind conflicts so the last
6
+ * utility in a group wins. Every component routes its `class` through this,
7
+ * which is what lets a consumer override any utility from the outside without
8
+ * reaching for `!important`.
9
+ */
10
+ function cn(...inputs) {
11
+ return twMerge(clsx(inputs));
12
+ }
13
+ //#endregion
14
+ export { cn };
15
+
16
+ //# sourceMappingURL=cn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cn.js","names":[],"sources":["../../src/lib/cn.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge conditional class names, resolving Tailwind conflicts so the last\n * utility in a group wins. Every component routes its `class` through this,\n * which is what lets a consumer override any utility from the outside without\n * reaching for `!important`.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,GAAG,GAAG,QAA8B;CAClD,OAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Apply the Loom icon defaults once at a host's root: size 16, stroke 1.5 —
3
+ * hairline-first, matching the 1px border language. Every `@lucide/vue` icon
4
+ * rendered after this call inherits them, so an individual icon declares
5
+ * `size` or `strokeWidth` only where it deliberately diverges.
6
+ *
7
+ * The one standing divergence: a glyph rendered at 12px or below declares
8
+ * `stroke-width` 2.5 exactly. Stroke lives on the 24 grid and scales with
9
+ * size, so 1.5 at 12px renders 0.75 device pixels against 1.0 at 16px; 2.5
10
+ * restores the optical weight.
11
+ *
12
+ * The numbers live here, not in each host.
13
+ *
14
+ * Call it from the `setup()` of the host's root component — `App.vue`, or the
15
+ * component a documentation theme wraps its layout in. It resolves to Vue's
16
+ * `provide()`, so it needs an active component instance: called from a plain
17
+ * entry module it silently provides nothing, and every icon keeps Lucide's own
18
+ * 24/2 defaults. There is no app-level alternative, because the injection key
19
+ * Lucide provides under is not part of its public surface.
20
+ */
21
+ export declare function applyLoomIconDefaults(): void;
22
+ //# sourceMappingURL=icon-defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-defaults.d.ts","sourceRoot":"","sources":["../../src/lib/icon-defaults.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}
@@ -0,0 +1,32 @@
1
+ import { setLucideProps } from "@lucide/vue";
2
+ //#region src/lib/icon-defaults.ts
3
+ /**
4
+ * Apply the Loom icon defaults once at a host's root: size 16, stroke 1.5 —
5
+ * hairline-first, matching the 1px border language. Every `@lucide/vue` icon
6
+ * rendered after this call inherits them, so an individual icon declares
7
+ * `size` or `strokeWidth` only where it deliberately diverges.
8
+ *
9
+ * The one standing divergence: a glyph rendered at 12px or below declares
10
+ * `stroke-width` 2.5 exactly. Stroke lives on the 24 grid and scales with
11
+ * size, so 1.5 at 12px renders 0.75 device pixels against 1.0 at 16px; 2.5
12
+ * restores the optical weight.
13
+ *
14
+ * The numbers live here, not in each host.
15
+ *
16
+ * Call it from the `setup()` of the host's root component — `App.vue`, or the
17
+ * component a documentation theme wraps its layout in. It resolves to Vue's
18
+ * `provide()`, so it needs an active component instance: called from a plain
19
+ * entry module it silently provides nothing, and every icon keeps Lucide's own
20
+ * 24/2 defaults. There is no app-level alternative, because the injection key
21
+ * Lucide provides under is not part of its public surface.
22
+ */
23
+ function applyLoomIconDefaults() {
24
+ setLucideProps({
25
+ size: 16,
26
+ strokeWidth: 1.5
27
+ });
28
+ }
29
+ //#endregion
30
+ export { applyLoomIconDefaults };
31
+
32
+ //# sourceMappingURL=icon-defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-defaults.js","names":[],"sources":["../../src/lib/icon-defaults.ts"],"sourcesContent":["import { setLucideProps } from \"@lucide/vue\";\n\n/**\n * Apply the Loom icon defaults once at a host's root: size 16, stroke 1.5 —\n * hairline-first, matching the 1px border language. Every `@lucide/vue` icon\n * rendered after this call inherits them, so an individual icon declares\n * `size` or `strokeWidth` only where it deliberately diverges.\n *\n * The one standing divergence: a glyph rendered at 12px or below declares\n * `stroke-width` 2.5 exactly. Stroke lives on the 24 grid and scales with\n * size, so 1.5 at 12px renders 0.75 device pixels against 1.0 at 16px; 2.5\n * restores the optical weight.\n *\n * The numbers live here, not in each host.\n *\n * Call it from the `setup()` of the host's root component — `App.vue`, or the\n * component a documentation theme wraps its layout in. It resolves to Vue's\n * `provide()`, so it needs an active component instance: called from a plain\n * entry module it silently provides nothing, and every icon keeps Lucide's own\n * 24/2 defaults. There is no app-level alternative, because the injection key\n * Lucide provides under is not part of its public surface.\n */\nexport function applyLoomIconDefaults(): void {\n setLucideProps({ size: 16, strokeWidth: 1.5 });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,wBAA8B;CAC5C,eAAe;EAAE,MAAM;EAAI,aAAa;CAAI,CAAC;AAC/C"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The list-reveal stagger vocabulary — one source for every overlay that
3
+ * reveals rows (DropdownMenu, Menubar, Select) and for the Motion
4
+ * documentation page. Each revealed row is delayed one step after the
5
+ * previous, capped so a long list does not tail off indefinitely.
6
+ *
7
+ * It lives here rather than in each template because it was written into
8
+ * three of them independently once, which is how the three drifted.
9
+ */
10
+ export declare const LIST_STAGGER_STEP_MS = 24;
11
+ export declare const LIST_STAGGER_CAP = 5;
12
+ /** The inline `animation-delay` for the i-th revealed row. */
13
+ export declare function listStaggerDelay(i: number): string;
14
+ //# sourceMappingURL=motion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.d.ts","sourceRoot":"","sources":["../../src/lib/motion.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAElD"}
@@ -0,0 +1,20 @@
1
+ //#region src/lib/motion.ts
2
+ /**
3
+ * The list-reveal stagger vocabulary — one source for every overlay that
4
+ * reveals rows (DropdownMenu, Menubar, Select) and for the Motion
5
+ * documentation page. Each revealed row is delayed one step after the
6
+ * previous, capped so a long list does not tail off indefinitely.
7
+ *
8
+ * It lives here rather than in each template because it was written into
9
+ * three of them independently once, which is how the three drifted.
10
+ */
11
+ var LIST_STAGGER_STEP_MS = 24;
12
+ var LIST_STAGGER_CAP = 5;
13
+ /** The inline `animation-delay` for the i-th revealed row. */
14
+ function listStaggerDelay(i) {
15
+ return `${String(Math.min(i, 5) * 24)}ms`;
16
+ }
17
+ //#endregion
18
+ export { LIST_STAGGER_CAP, LIST_STAGGER_STEP_MS, listStaggerDelay };
19
+
20
+ //# sourceMappingURL=motion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.js","names":[],"sources":["../../src/lib/motion.ts"],"sourcesContent":["/**\n * The list-reveal stagger vocabulary — one source for every overlay that\n * reveals rows (DropdownMenu, Menubar, Select) and for the Motion\n * documentation page. Each revealed row is delayed one step after the\n * previous, capped so a long list does not tail off indefinitely.\n *\n * It lives here rather than in each template because it was written into\n * three of them independently once, which is how the three drifted.\n */\nexport const LIST_STAGGER_STEP_MS = 24;\nexport const LIST_STAGGER_CAP = 5;\n\n/** The inline `animation-delay` for the i-th revealed row. */\nexport function listStaggerDelay(i: number): string {\n return `${String(Math.min(i, LIST_STAGGER_CAP) * LIST_STAGGER_STEP_MS)}ms`;\n}\n"],"mappings":";;;;;;;;;;AASA,IAAa,uBAAuB;AACpC,IAAa,mBAAmB;;AAGhC,SAAgB,iBAAiB,GAAmB;CAClD,OAAO,GAAG,OAAO,KAAK,IAAI,GAAA,CAAmB,IAAA,EAAwB,EAAE;AACzE"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Drops the keys whose value is `undefined`, so a `v-bind` passes only the
3
+ * props that were actually set.
4
+ *
5
+ * Two rules collide to make this necessary, and neither is avoidable.
6
+ *
7
+ * Vue treats a prop that is absent and a prop explicitly set to `undefined` as
8
+ * the same thing — both resolve to the child's default. TypeScript, under
9
+ * `exactOptionalPropertyTypes`, does not: passing `undefined` to a `foo?: T` is
10
+ * an error, because the flag exists precisely to tell "missing" apart from
11
+ * "present and undefined". A Vue template always emits every key it binds, so
12
+ * forwarding an optional prop straight through (`:open="open"`) hands a child's
13
+ * `open?: boolean` an explicit `undefined` and fails to compile, while behaving
14
+ * correctly at run time.
15
+ *
16
+ * That distinction is not academic for the components underneath. Reka reads
17
+ * `undefined` as "no value supplied — manage this yourself", and any concrete
18
+ * value, `false` included, as "the host owns this". So a control whose
19
+ * `modelValue` is coerced to `false` on its way through stops being
20
+ * uncontrolled and becomes permanently, silently off: it still emits its update
21
+ * event, and its rendered state never moves. That failure has no error and no
22
+ * warning; it looks like a component that ignores clicks.
23
+ *
24
+ * A cast (`open as boolean`) silences the compiler and is the reason to prefer
25
+ * this: it states that a value is there when the whole point is that one may
26
+ * not be. Omitting the key says what is true.
27
+ */
28
+ export declare function optional<T extends Record<string, unknown>>(values: T): {
29
+ [K in keyof T]?: Exclude<T[K], undefined>;
30
+ };
31
+ //# sourceMappingURL=props.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../src/lib/props.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxD,MAAM,EAAE,CAAC,GACR;KAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;CAAE,CAM/C"}
@@ -0,0 +1,37 @@
1
+ //#region src/lib/props.ts
2
+ /**
3
+ * Drops the keys whose value is `undefined`, so a `v-bind` passes only the
4
+ * props that were actually set.
5
+ *
6
+ * Two rules collide to make this necessary, and neither is avoidable.
7
+ *
8
+ * Vue treats a prop that is absent and a prop explicitly set to `undefined` as
9
+ * the same thing — both resolve to the child's default. TypeScript, under
10
+ * `exactOptionalPropertyTypes`, does not: passing `undefined` to a `foo?: T` is
11
+ * an error, because the flag exists precisely to tell "missing" apart from
12
+ * "present and undefined". A Vue template always emits every key it binds, so
13
+ * forwarding an optional prop straight through (`:open="open"`) hands a child's
14
+ * `open?: boolean` an explicit `undefined` and fails to compile, while behaving
15
+ * correctly at run time.
16
+ *
17
+ * That distinction is not academic for the components underneath. Reka reads
18
+ * `undefined` as "no value supplied — manage this yourself", and any concrete
19
+ * value, `false` included, as "the host owns this". So a control whose
20
+ * `modelValue` is coerced to `false` on its way through stops being
21
+ * uncontrolled and becomes permanently, silently off: it still emits its update
22
+ * event, and its rendered state never moves. That failure has no error and no
23
+ * warning; it looks like a component that ignores clicks.
24
+ *
25
+ * A cast (`open as boolean`) silences the compiler and is the reason to prefer
26
+ * this: it states that a value is there when the whole point is that one may
27
+ * not be. Omitting the key says what is true.
28
+ */
29
+ function optional(values) {
30
+ const set = {};
31
+ for (const key of Object.keys(values)) if (values[key] !== void 0) set[key] = values[key];
32
+ return set;
33
+ }
34
+ //#endregion
35
+ export { optional };
36
+
37
+ //# sourceMappingURL=props.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"props.js","names":[],"sources":["../../src/lib/props.ts"],"sourcesContent":["/**\n * Drops the keys whose value is `undefined`, so a `v-bind` passes only the\n * props that were actually set.\n *\n * Two rules collide to make this necessary, and neither is avoidable.\n *\n * Vue treats a prop that is absent and a prop explicitly set to `undefined` as\n * the same thing — both resolve to the child's default. TypeScript, under\n * `exactOptionalPropertyTypes`, does not: passing `undefined` to a `foo?: T` is\n * an error, because the flag exists precisely to tell \"missing\" apart from\n * \"present and undefined\". A Vue template always emits every key it binds, so\n * forwarding an optional prop straight through (`:open=\"open\"`) hands a child's\n * `open?: boolean` an explicit `undefined` and fails to compile, while behaving\n * correctly at run time.\n *\n * That distinction is not academic for the components underneath. Reka reads\n * `undefined` as \"no value supplied — manage this yourself\", and any concrete\n * value, `false` included, as \"the host owns this\". So a control whose\n * `modelValue` is coerced to `false` on its way through stops being\n * uncontrolled and becomes permanently, silently off: it still emits its update\n * event, and its rendered state never moves. That failure has no error and no\n * warning; it looks like a component that ignores clicks.\n *\n * A cast (`open as boolean`) silences the compiler and is the reason to prefer\n * this: it states that a value is there when the whole point is that one may\n * not be. Omitting the key says what is true.\n */\nexport function optional<T extends Record<string, unknown>>(\n values: T,\n): { [K in keyof T]?: Exclude<T[K], undefined> } {\n const set: Record<string, unknown> = {};\n for (const key of Object.keys(values)) {\n if (values[key] !== undefined) set[key] = values[key];\n }\n return set as { [K in keyof T]?: Exclude<T[K], undefined> };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,SACd,QAC+C;CAC/C,MAAM,MAA+B,CAAC;CACtC,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM,GAClC,IAAI,OAAO,SAAS,KAAA,GAAW,IAAI,OAAO,OAAO;CAEnD,OAAO;AACT"}
@@ -0,0 +1,7 @@
1
+ import Avatar_vue_vue_type_script_setup_true_lang_default from "./Avatar.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/primitives/Avatar/Avatar.vue
3
+ var Avatar_default = Avatar_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { Avatar_default as default };
6
+
7
+ //# sourceMappingURL=Avatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.js","names":[],"sources":["../../../src/primitives/Avatar/Avatar.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Control height, and text size for the initials fallback. */\nexport type AvatarSize = \"sm\" | \"md\" | \"lg\";\n</script>\n\n<script setup lang=\"ts\">\nimport { AvatarRoot, AvatarImage, AvatarFallback } from \"reka-ui\";\nimport { cn } from \"../../lib/cn\";\n\n/**\n * Avatar — a user or agent's picture, with a graceful initials fallback for\n * no `src`, a broken URL, or a still-loading image. Built on Reka UI's\n * Avatar: the image only paints once it has actually finished loading, so\n * the fallback stays visible the whole time until then — first paint is\n * either the real photo or the initials, never a broken-image icon.\n */\nwithDefaults(\n defineProps<{\n /** Image URL. Omit it to render the fallback outright. */\n src?: string;\n /** Accessible name for the photo — required on `AvatarImage` so a screen reader announces who it is, not just that an image loaded. */\n alt?: string;\n /** Initials to show while there is no image, or once one has failed — computed by the caller, never derived from `alt` here. */\n fallback?: string;\n /** Control height. */\n size?: AvatarSize;\n }>(),\n {\n alt: \"\",\n size: \"md\",\n },\n);\n</script>\n\n<template>\n <AvatarRoot\n :class=\"\n cn(\n 'relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-muted text-muted-foreground select-none',\n size === 'sm' && 'h-8 w-8 text-xs',\n size === 'md' && 'h-10 w-10 text-sm',\n size === 'lg' && 'h-12 w-12 text-base',\n )\n \"\n >\n <!-- Reka paints AvatarImage only once the photo has loaded, so scale-in\n plays exactly on that swap-in — a gentle settle over the fallback. -->\n <AvatarImage\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt\"\n class=\"h-full w-full animate-scale-in object-cover\"\n />\n <AvatarFallback class=\"font-medium\">{{ fallback }}</AvatarFallback>\n </AvatarRoot>\n</template>\n"],"mappings":""}
@@ -0,0 +1,27 @@
1
+ /** Control height, and text size for the initials fallback. */
2
+ export type AvatarSize = "sm" | "md" | "lg";
3
+ declare const _default: typeof __VLS_export;
4
+ export default _default;
5
+ declare const __VLS_export: import("vue").DefineComponent<{
6
+ /** Image URL. Omit it to render the fallback outright. */
7
+ src?: string;
8
+ /** Accessible name for the photo — required on `AvatarImage` so a screen reader announces who it is, not just that an image loaded. */
9
+ alt?: string;
10
+ /** Initials to show while there is no image, or once one has failed — computed by the caller, never derived from `alt` here. */
11
+ fallback?: string;
12
+ /** Control height. */
13
+ size?: AvatarSize;
14
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
15
+ /** Image URL. Omit it to render the fallback outright. */
16
+ src?: string;
17
+ /** Accessible name for the photo — required on `AvatarImage` so a screen reader announces who it is, not just that an image loaded. */
18
+ alt?: string;
19
+ /** Initials to show while there is no image, or once one has failed — computed by the caller, never derived from `alt` here. */
20
+ fallback?: string;
21
+ /** Control height. */
22
+ size?: AvatarSize;
23
+ }> & Readonly<{}>, {
24
+ alt: string;
25
+ size: AvatarSize;
26
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
+ //# sourceMappingURL=Avatar.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.vue.d.ts","sourceRoot":"","sources":["../../../src/primitives/Avatar/Avatar.vue"],"names":[],"mappings":"AA+DA,+DAA+D;AAC/D,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;wBACvB,OAAO,YAAY;AAAxC,wBAAyC;AACzC,QAAA,MAAM,YAAY;IASd,0DAA0D;UACpD,MAAM;IACZ,uIAAuI;UACjI,MAAM;IACZ,gIAAgI;eACrH,MAAM;IACjB,sBAAsB;WACf,UAAU;;IAPjB,0DAA0D;UACpD,MAAM;IACZ,uIAAuI;UACjI,MAAM;IACZ,gIAAgI;eACrH,MAAM;IACjB,sBAAsB;WACf,UAAU;;SAJX,MAAM;UAIL,UAAU;6EA2GjB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { createBlock, createCommentVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, toDisplayString, unref, withCtx } from "vue";
3
+ import { AvatarFallback, AvatarImage, AvatarRoot } from "reka-ui";
4
+ //#region src/primitives/Avatar/Avatar.vue?vue&type=script&setup=true&lang.ts
5
+ var Avatar_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
6
+ __name: "Avatar",
7
+ props: {
8
+ src: {},
9
+ alt: { default: "" },
10
+ fallback: {},
11
+ size: { default: "md" }
12
+ },
13
+ setup(__props) {
14
+ return (_ctx, _cache) => {
15
+ return openBlock(), createBlock(unref(AvatarRoot), { class: normalizeClass(unref(cn)("relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-muted text-muted-foreground select-none", __props.size === "sm" && "h-8 w-8 text-xs", __props.size === "md" && "h-10 w-10 text-sm", __props.size === "lg" && "h-12 w-12 text-base")) }, {
16
+ default: withCtx(() => [__props.src ? (openBlock(), createBlock(unref(AvatarImage), {
17
+ key: 0,
18
+ src: __props.src,
19
+ alt: __props.alt,
20
+ class: "h-full w-full animate-scale-in object-cover"
21
+ }, null, 8, ["src", "alt"])) : createCommentVNode("", true), createVNode(unref(AvatarFallback), { class: "font-medium" }, {
22
+ default: withCtx(() => [createTextVNode(toDisplayString(__props.fallback), 1)]),
23
+ _: 1
24
+ })]),
25
+ _: 1
26
+ }, 8, ["class"]);
27
+ };
28
+ }
29
+ });
30
+ //#endregion
31
+ export { Avatar_vue_vue_type_script_setup_true_lang_default as default };
32
+
33
+ //# sourceMappingURL=Avatar.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/primitives/Avatar/Avatar.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Control height, and text size for the initials fallback. */\nexport type AvatarSize = \"sm\" | \"md\" | \"lg\";\n</script>\n\n<script setup lang=\"ts\">\nimport { AvatarRoot, AvatarImage, AvatarFallback } from \"reka-ui\";\nimport { cn } from \"../../lib/cn\";\n\n/**\n * Avatar — a user or agent's picture, with a graceful initials fallback for\n * no `src`, a broken URL, or a still-loading image. Built on Reka UI's\n * Avatar: the image only paints once it has actually finished loading, so\n * the fallback stays visible the whole time until then — first paint is\n * either the real photo or the initials, never a broken-image icon.\n */\nwithDefaults(\n defineProps<{\n /** Image URL. Omit it to render the fallback outright. */\n src?: string;\n /** Accessible name for the photo — required on `AvatarImage` so a screen reader announces who it is, not just that an image loaded. */\n alt?: string;\n /** Initials to show while there is no image, or once one has failed — computed by the caller, never derived from `alt` here. */\n fallback?: string;\n /** Control height. */\n size?: AvatarSize;\n }>(),\n {\n alt: \"\",\n size: \"md\",\n },\n);\n</script>\n\n<template>\n <AvatarRoot\n :class=\"\n cn(\n 'relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-muted text-muted-foreground select-none',\n size === 'sm' && 'h-8 w-8 text-xs',\n size === 'md' && 'h-10 w-10 text-sm',\n size === 'lg' && 'h-12 w-12 text-base',\n )\n \"\n >\n <!-- Reka paints AvatarImage only once the photo has loaded, so scale-in\n plays exactly on that swap-in — a gentle settle over the fallback. -->\n <AvatarImage\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt\"\n class=\"h-full w-full animate-scale-in object-cover\"\n />\n <AvatarFallback class=\"font-medium\">{{ fallback }}</AvatarFallback>\n </AvatarRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;GAmCE,OAAA,UAAA,GAAA,YAmBa,MAAA,UAAA,GAAA,EAlBV,OAAK,eAAS,MAAA,EAAA,CAAE,CAAA,qIAAuJ,QAAA,SAAI,QAAA,mBAAwC,QAAA,SAAI,QAAA,qBAA0C,QAAA,SAAI,QAAA,qBAAA,CAAA,EAAA,GAAA;IAWtQ,SAAA,cAKE,CAJM,QAAA,OADR,UAAA,GAAA,YAKE,MAAA,WAAA,GAAA;;KAHC,KAAK,QAAA;KACL,KAAK,QAAA;KACN,OAAM;IAER,GAAA,MAAA,GAAA,CAAA,OAAA,KAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,GAAA,YAAmE,MAAA,cAAA,GAAA,EAAnD,OAAM,cAAa,GAAA;KAAC,SAAA,cAAc,CAAX,gBAAA,gBAAA,QAAA,QAAQ,GAAA,CAAA,CAAA,CAAA"}
@@ -0,0 +1,7 @@
1
+ import Badge_vue_vue_type_script_setup_true_lang_default, { badgeVariants } from "./Badge.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/primitives/Badge/Badge.vue
3
+ var Badge_default = Badge_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { badgeVariants, Badge_default as default };
6
+
7
+ //# sourceMappingURL=Badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.js","names":[],"sources":["../../../src/primitives/Badge/Badge.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/**\n * Badge — small status / meta chip. The `ai` variant wears the agent weft\n * used to signal AI presence across the product.\n */\nexport type BadgeVariant =\n \"neutral\" | \"outline\" | \"primary\" | \"success\" | \"warning\" | \"info\" | \"destructive\" | \"ai\";\n\nexport const badgeVariants = cva(\n \"inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium transition-colors duration-fast\",\n {\n variants: {\n variant: {\n neutral: \"border-transparent bg-subtle text-subtle-foreground\",\n outline: \"border-border bg-transparent text-muted-foreground\",\n primary: \"border-transparent bg-primary/12 text-primary\",\n success: \"border-transparent bg-success/12 text-success\",\n warning: \"border-transparent bg-warning/12 text-warning\",\n info: \"border-transparent bg-info/12 text-info\",\n destructive: \"border-transparent bg-destructive/12 text-destructive\",\n ai: \"border-agent/40 bg-agent-muted text-agent\",\n } satisfies Record<BadgeVariant, string>,\n },\n defaultVariants: { variant: \"neutral\" },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { cn } from \"../../lib/cn\";\n\nwithDefaults(\n defineProps<{\n /** Which status or meta this chip carries. `ai` is reserved for signalling agent-produced or agent-running work. */\n variant?: BadgeVariant;\n }>(),\n { variant: \"neutral\" },\n);\n</script>\n\n<template>\n <span :class=\"cn(badgeVariants({ variant }))\"><slot /></span>\n</template>\n"],"mappings":""}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Badge — small status / meta chip. The `ai` variant wears the agent weft
3
+ * used to signal AI presence across the product.
4
+ */
5
+ export type BadgeVariant = "neutral" | "outline" | "primary" | "success" | "warning" | "info" | "destructive" | "ai";
6
+ export declare const badgeVariants: (props?: ({
7
+ variant?: "neutral" | "outline" | "primary" | "success" | "warning" | "info" | "destructive" | "ai" | null | undefined;
8
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
9
+ declare const _default: typeof __VLS_export;
10
+ export default _default;
11
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
12
+ /** Which status or meta this chip carries. `ai` is reserved for signalling agent-produced or agent-running work. */
13
+ variant?: BadgeVariant;
14
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
15
+ /** Which status or meta this chip carries. `ai` is reserved for signalling agent-produced or agent-running work. */
16
+ variant?: BadgeVariant;
17
+ }> & Readonly<{}>, {
18
+ variant: BadgeVariant;
19
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
20
+ default?: (props: {}) => any;
21
+ }>;
22
+ type __VLS_WithSlots<T, S> = T & {
23
+ new (): {
24
+ $slots: S;
25
+ };
26
+ };
27
+ //# sourceMappingURL=Badge.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.vue.d.ts","sourceRoot":"","sources":["../../../src/primitives/Badge/Badge.vue"],"names":[],"mappings":"AAqDA;;;GAGG;AACH,MAAM,MAAM,YAAY,GACtB,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,aAAa,GAAG,IAAI,CAAC;AAE5F,eAAO,MAAM,aAAa;;8EAiBzB,CAAC;wBACmB,OAAO,YAAY;AAAxC,wBAAyC;AACzC,QAAA,MAAM,YAAY;IAEd,oHAAoH;cAC1G,YAAY;;IADtB,oHAAoH;cAC1G,YAAY;;aAAZ,YAAY;;cAkCZ,CAAC,KAAK,IAAgB,KAAK,GAAG;EAUxC,CAAC;AAWL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { createElementBlock, defineComponent, normalizeClass, openBlock, renderSlot, unref } from "vue";
3
+ import { cva } from "class-variance-authority";
4
+ //#region src/primitives/Badge/Badge.vue?vue&type=script&setup=true&lang.ts
5
+ var badgeVariants = cva("inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium transition-colors duration-fast", {
6
+ variants: { variant: {
7
+ neutral: "border-transparent bg-subtle text-subtle-foreground",
8
+ outline: "border-border bg-transparent text-muted-foreground",
9
+ primary: "border-transparent bg-primary/12 text-primary",
10
+ success: "border-transparent bg-success/12 text-success",
11
+ warning: "border-transparent bg-warning/12 text-warning",
12
+ info: "border-transparent bg-info/12 text-info",
13
+ destructive: "border-transparent bg-destructive/12 text-destructive",
14
+ ai: "border-agent/40 bg-agent-muted text-agent"
15
+ } },
16
+ defaultVariants: { variant: "neutral" }
17
+ });
18
+ var Badge_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
19
+ __name: "Badge",
20
+ props: { variant: { default: "neutral" } },
21
+ setup(__props) {
22
+ return (_ctx, _cache) => {
23
+ return openBlock(), createElementBlock("span", { class: normalizeClass(unref(cn)(unref(badgeVariants)({ variant: __props.variant }))) }, [renderSlot(_ctx.$slots, "default")], 2);
24
+ };
25
+ }
26
+ });
27
+ //#endregion
28
+ export { badgeVariants, Badge_vue_vue_type_script_setup_true_lang_default as default };
29
+
30
+ //# sourceMappingURL=Badge.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/primitives/Badge/Badge.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/**\n * Badge — small status / meta chip. The `ai` variant wears the agent weft\n * used to signal AI presence across the product.\n */\nexport type BadgeVariant =\n \"neutral\" | \"outline\" | \"primary\" | \"success\" | \"warning\" | \"info\" | \"destructive\" | \"ai\";\n\nexport const badgeVariants = cva(\n \"inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium transition-colors duration-fast\",\n {\n variants: {\n variant: {\n neutral: \"border-transparent bg-subtle text-subtle-foreground\",\n outline: \"border-border bg-transparent text-muted-foreground\",\n primary: \"border-transparent bg-primary/12 text-primary\",\n success: \"border-transparent bg-success/12 text-success\",\n warning: \"border-transparent bg-warning/12 text-warning\",\n info: \"border-transparent bg-info/12 text-info\",\n destructive: \"border-transparent bg-destructive/12 text-destructive\",\n ai: \"border-agent/40 bg-agent-muted text-agent\",\n } satisfies Record<BadgeVariant, string>,\n },\n defaultVariants: { variant: \"neutral\" },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { cn } from \"../../lib/cn\";\n\nwithDefaults(\n defineProps<{\n /** Which status or meta this chip carries. `ai` is reserved for signalling agent-produced or agent-running work. */\n variant?: BadgeVariant;\n }>(),\n { variant: \"neutral\" },\n);\n</script>\n\n<template>\n <span :class=\"cn(badgeVariants({ variant }))\"><slot /></span>\n</template>\n"],"mappings":";;;;AAUA,IAAa,gBAAgB,IAC3B,sHACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,SAAS;EACT,SAAS;EACT,SAAS;EACT,SAAS;EACT,MAAM;EACN,aAAa;EACb,IAAI;CACN,EACF;CACA,iBAAiB,EAAE,SAAS,UAAU;AACxC,CACF;;;;;;GAgBE,OAAA,UAAA,GAAA,mBAA6D,QAAA,EAAtD,OAAK,eAAE,MAAA,EAAA,CAAE,CAAC,MAAA,aAAA,CAAa,CAAA,EAAA,SAAG,QAAA,QAAO,CAAA,CAAA,CAAA,EAAA,GAAA,CAAM,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,CAAA"}
@@ -0,0 +1,7 @@
1
+ import Button_vue_vue_type_script_setup_true_lang_default, { buttonVariants } from "./Button.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/primitives/Button/Button.vue
3
+ var Button_default = Button_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { buttonVariants, Button_default as default };
6
+
7
+ //# sourceMappingURL=Button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.js","names":[],"sources":["../../../src/primitives/Button/Button.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/**\n * The six weights, and the choice between them is about emphasis rather than\n * colour: `primary` is the one action a screen is asking for, `destructive` is\n * the one it is warning about, and the four between them step down.\n */\nexport type ButtonVariant =\n \"primary\" | \"secondary\" | \"subtle\" | \"outline\" | \"ghost\" | \"destructive\";\n\nexport type ButtonSize = \"sm\" | \"md\" | \"lg\" | \"icon\" | \"icon-sm\";\n\n/**\n * Button — the workhorse, and the primitive that encodes Loom's press\n * language:\n *\n * • hover lifts by fill, not by shadow\n * • active presses down (scale 0.97) — physical, causal feedback\n * • focus blooms the warp ring\n * • loading plays a kinetic swap under a shimmer sweep: the label rolls up\n * and out, a progress arc springs in, the loading text rises last — and\n * both layers share one grid cell, so the width never jumps mid-film\n *\n * The 50% dim belongs to a *disabled* button only. It is applied off the\n * `disabled` prop rather than off the DOM disabled state, because a loading\n * button is also DOM-disabled yet has to read as \"working\", not\n * \"unavailable\".\n */\nexport const buttonVariants = cva(\n [\n \"relative inline-flex items-center justify-center gap-2 whitespace-nowrap select-none\",\n \"rounded-md text-sm font-medium\",\n \"[transition:transform_var(--duration-fast)_var(--ease-spring),background-color_var(--duration-fast)_var(--ease-out),color_var(--duration-fast)_var(--ease-out),box-shadow_var(--duration-fast)_var(--ease-out)]\",\n \"active:scale-[0.97] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo\",\n \"disabled:pointer-events-none\",\n ],\n {\n // `satisfies` is what keeps the two halves honest. The union above is the\n // name a consumer imports and the documentation prints; the map below is\n // the classes. Adding a member to one and not the other stops compiling,\n // so neither can be the stale copy of the other.\n variants: {\n variant: {\n primary: \"bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm\",\n secondary: \"bg-secondary text-secondary-foreground hover:bg-secondary/70\",\n subtle: \"bg-transparent text-foreground hover:bg-subtle\",\n outline: \"border border-input bg-transparent text-foreground hover:bg-subtle\",\n ghost: \"bg-transparent text-muted-foreground hover:bg-subtle hover:text-foreground\",\n destructive: \"bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm\",\n } satisfies Record<ButtonVariant, string>,\n size: {\n sm: \"h-8 px-3 text-xs\",\n md: \"h-9 px-4\",\n lg: \"h-11 px-6 text-base\",\n icon: \"h-9 w-9 p-0\",\n // A square icon button for dense rows, matching `sm`'s height so a row\n // action lines up with that row's text controls. Still 32px — well\n // over the 24px minimum target size (WCAG 2.2 SC 2.5.8) — so density\n // here costs no reachability. It exists because consumers were\n // reaching for `size=\"icon\"` and then hand-overriding `class=\"h-8 w-8\"`,\n // which silently re-litigates the target-size question at every call\n // site.\n \"icon-sm\": \"h-8 w-8 p-0\",\n } satisfies Record<ButtonSize, string>,\n },\n defaultVariants: { variant: \"primary\", size: \"md\" },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { cn } from \"../../lib/cn\";\n\nwithDefaults(\n defineProps<{\n /** How much emphasis the action carries. */\n variant?: ButtonVariant;\n /** Control height. `icon` and `icon-sm` are square, for a glyph alone. */\n size?: ButtonSize;\n /** Locks the button and plays the kinetic swap (label → arc + loadingText). */\n loading?: boolean;\n /** Text shown beside the progress arc while loading, e.g. \"Saving…\". */\n loadingText?: string;\n /** Unavailable rather than busy — dims to 50% and blocks pointer events. */\n disabled?: boolean;\n /** The native button type. Defaults to `button`, never an accidental submit. */\n type?: \"button\" | \"submit\" | \"reset\";\n }>(),\n { variant: \"primary\", size: \"md\", loading: false, disabled: false, type: \"button\" },\n);\n</script>\n\n<template>\n <button\n :type=\"type\"\n :disabled=\"disabled || loading\"\n :data-loading=\"loading || undefined\"\n :aria-busy=\"loading || undefined\"\n :class=\"cn(buttonVariants({ variant, size }), 'group', disabled && 'opacity-50')\"\n >\n <!-- The shimmer sweep, while loading. -->\n <span\n v-if=\"loading\"\n aria-hidden=\"true\"\n class=\"pointer-events-none absolute inset-0 rounded-md bg-[linear-gradient(110deg,transparent_35%,--alpha(var(--color-primary)/25%)_50%,transparent_65%)] bg-[length:220%_100%] animate-shimmer\"\n />\n <!-- The kinetic swap. Both layers live in the same grid cell, so the\n button keeps the width of the wider one and nothing jumps mid-swap.\n Only the layer for the current state is exposed to assistive\n technology; the other is aria-hidden, because opacity alone does not\n hide anything from a screen reader. -->\n <span class=\"inline-grid place-items-center\">\n <!-- Beat 1 — the label rolls up and out. -->\n <span\n :aria-hidden=\"loading || undefined\"\n class=\"[grid-area:1/1] inline-flex items-center gap-2 transition-[opacity,transform] duration-fast ease-out group-data-[loading]:-translate-y-1 group-data-[loading]:opacity-0\"\n >\n <slot />\n </span>\n <span\n :aria-hidden=\"!loading || undefined\"\n class=\"pointer-events-none [grid-area:1/1] inline-flex items-center gap-2\"\n >\n <!-- Beat 2 — the progress arc springs in from below. The spinning svg\n sits inside a wrapper because `animate-spin` owns `transform`: the\n entry scale and translate have to live on a separate element, or\n the spin keyframe would overwrite them. It is the same arc the\n standalone Spinner draws, inlined and aria-hidden — Spinner's\n role=\"status\" contract is wrong inside an aria-busy button, where\n it would announce the state twice. -->\n <span\n class=\"transition-[opacity,transform] duration-fast ease-spring opacity-0 scale-50 translate-y-1 group-data-[loading]:translate-y-0 group-data-[loading]:scale-100 group-data-[loading]:opacity-100\"\n >\n <svg class=\"h-4 w-4 animate-spin\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <circle class=\"stroke-current opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke-width=\"4\" />\n <path\n class=\"fill-current opacity-75\"\n d=\"M4 12a8 8 0 0 1 8-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n </span>\n <!-- Beat 3 — the loading text rises last. The stagger delay applies on\n entry only (exit keeps delay 0, so the film cuts out clean), and\n it is cancelled under reduced motion so the instant swap is not\n lagged by a delay nobody asked for. -->\n <span\n v-if=\"loadingText\"\n class=\"transition-[opacity,transform] duration-100 ease-out opacity-0 translate-y-1 group-data-[loading]:translate-y-0 group-data-[loading]:opacity-100 group-data-[loading]:delay-75 motion-reduce:group-data-[loading]:delay-0\"\n >\n {{ loadingText }}\n </span>\n </span>\n </span>\n </button>\n</template>\n"],"mappings":""}