@ecoma-io/loom 0.4.0 → 0.6.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 (1073) hide show
  1. package/README.md +202 -113
  2. package/dist/a11y.js +4 -3
  3. package/dist/composition/center/src/Center.js.map +1 -0
  4. package/dist/composition/center/src/Center.vue_vue_type_script_setup_true_lang.js.map +1 -0
  5. package/dist/composition/dashboard-grid/src/DashboardGrid.js +7 -0
  6. package/dist/composition/dashboard-grid/src/DashboardGrid.js.map +1 -0
  7. package/dist/composition/dashboard-grid/src/DashboardGrid.vue_vue_type_script_setup_true_lang.js +45 -0
  8. package/dist/composition/dashboard-grid/src/DashboardGrid.vue_vue_type_script_setup_true_lang.js.map +1 -0
  9. package/dist/composition/frame/src/Frame.js.map +1 -0
  10. package/dist/composition/frame/src/Frame.vue_vue_type_script_setup_true_lang.js.map +1 -0
  11. package/dist/composition/grid/src/Grid.js.map +1 -0
  12. package/dist/composition/grid/src/Grid.vue_vue_type_script_setup_true_lang.js.map +1 -0
  13. package/dist/composition/inline/src/Inline.js.map +1 -0
  14. package/dist/composition/inline/src/Inline.vue_vue_type_script_setup_true_lang.js.map +1 -0
  15. package/dist/composition/scroll-reel/src/ScrollReel.js.map +1 -0
  16. package/dist/composition/scroll-reel/src/ScrollReel.vue_vue_type_script_setup_true_lang.js +101 -0
  17. package/dist/composition/scroll-reel/src/ScrollReel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  18. package/dist/composition/sidebar/src/Sidebar.js.map +1 -0
  19. package/dist/composition/sidebar/src/Sidebar.vue_vue_type_script_setup_true_lang.js +46 -0
  20. package/dist/composition/sidebar/src/Sidebar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  21. package/dist/composition/split/src/Split.js.map +1 -0
  22. package/dist/composition/split/src/Split.vue_vue_type_script_setup_true_lang.js +51 -0
  23. package/dist/composition/split/src/Split.vue_vue_type_script_setup_true_lang.js.map +1 -0
  24. package/dist/composition/stack/src/Stack.js.map +1 -0
  25. package/dist/composition/stack/src/Stack.vue_vue_type_script_setup_true_lang.js.map +1 -0
  26. package/dist/core/src/a11y-contract.js +558 -0
  27. package/dist/core/src/a11y-contract.js.map +1 -0
  28. package/dist/core/src/a11y-scope.js +151 -0
  29. package/dist/core/src/a11y-scope.js.map +1 -0
  30. package/dist/core/src/attrs.js.map +1 -0
  31. package/dist/core/src/cn.js +61 -0
  32. package/dist/core/src/cn.js.map +1 -0
  33. package/dist/core/src/icon-defaults.js.map +1 -0
  34. package/dist/core/src/index.js +9 -0
  35. package/dist/core/src/motion.js +31 -0
  36. package/dist/core/src/motion.js.map +1 -0
  37. package/dist/core/src/props.js.map +1 -0
  38. package/dist/core/src/theme.js.map +1 -0
  39. package/dist/index.js +287 -250
  40. package/dist/labels/src/ancestor-disabled.js.map +1 -0
  41. package/dist/labels/src/count-labels.js.map +1 -0
  42. package/dist/labels/src/date-labels.js +206 -0
  43. package/dist/labels/src/date-labels.js.map +1 -0
  44. package/dist/labels/src/field-context.js.map +1 -0
  45. package/dist/labels/src/index.js +6 -0
  46. package/dist/labels/src/labels.js.map +1 -0
  47. package/dist/layouts/app-shell/src/AppShell.js.map +1 -0
  48. package/dist/layouts/app-shell/src/AppShell.vue_vue_type_script_setup_true_lang.js.map +1 -0
  49. package/dist/layouts/centered/src/Centered.js.map +1 -0
  50. package/dist/layouts/centered/src/Centered.vue_vue_type_script_setup_true_lang.js.map +1 -0
  51. package/dist/layouts/dashboard/src/Dashboard.js.map +1 -0
  52. package/dist/layouts/dashboard/src/Dashboard.vue_vue_type_script_setup_true_lang.js +65 -0
  53. package/dist/layouts/dashboard/src/Dashboard.vue_vue_type_script_setup_true_lang.js.map +1 -0
  54. package/dist/layouts/desktop-app-shell/src/DesktopAppShell.js +7 -0
  55. package/dist/layouts/desktop-app-shell/src/DesktopAppShell.js.map +1 -0
  56. package/dist/layouts/desktop-app-shell/src/DesktopAppShell.vue_vue_type_script_setup_true_lang.js +76 -0
  57. package/dist/layouts/desktop-app-shell/src/DesktopAppShell.vue_vue_type_script_setup_true_lang.js.map +1 -0
  58. package/dist/layouts/form-layout/src/FormLayout.js.map +1 -0
  59. package/dist/layouts/form-layout/src/FormLayout.vue_vue_type_script_setup_true_lang.js.map +1 -0
  60. package/dist/layouts/master-detail/src/MasterDetail.js.map +1 -0
  61. package/dist/layouts/master-detail/src/MasterDetail.vue_vue_type_script_setup_true_lang.js.map +1 -0
  62. package/dist/layouts/reading/src/Reading.js.map +1 -0
  63. package/dist/layouts/reading/src/Reading.vue_vue_type_script_setup_true_lang.js.map +1 -0
  64. package/dist/layouts/settings/src/Settings.js.map +1 -0
  65. package/dist/layouts/settings/src/Settings.vue_vue_type_script_setup_true_lang.js.map +1 -0
  66. package/dist/layouts/split-layout/src/SplitLayout.js.map +1 -0
  67. package/dist/layouts/split-layout/src/SplitLayout.vue_vue_type_script_setup_true_lang.js +62 -0
  68. package/dist/layouts/split-layout/src/SplitLayout.vue_vue_type_script_setup_true_lang.js.map +1 -0
  69. package/dist/packages/composition/dashboard-grid/src/DashboardGrid.vue.d.ts +26 -0
  70. package/dist/packages/composition/dashboard-grid/src/DashboardGrid.vue.d.ts.map +1 -0
  71. package/dist/packages/composition/dashboard-grid/src/index.d.ts.map +1 -0
  72. package/dist/packages/composition/sidebar/src/Sidebar.vue.d.ts +4 -0
  73. package/dist/packages/composition/sidebar/src/Sidebar.vue.d.ts.map +1 -1
  74. package/dist/packages/composition/split/src/Split.vue.d.ts +11 -12
  75. package/dist/packages/composition/split/src/Split.vue.d.ts.map +1 -1
  76. package/dist/packages/core/src/a11y-contract.d.ts +417 -0
  77. package/dist/packages/core/src/a11y-contract.d.ts.map +1 -0
  78. package/dist/packages/core/src/a11y-scope.d.ts +73 -5
  79. package/dist/packages/core/src/a11y-scope.d.ts.map +1 -1
  80. package/dist/packages/core/src/index.d.ts +8 -2
  81. package/dist/packages/core/src/index.d.ts.map +1 -1
  82. package/dist/packages/core/src/motion.d.ts +15 -6
  83. package/dist/packages/core/src/motion.d.ts.map +1 -1
  84. package/dist/packages/core/src/responsive-contract.d.ts +155 -0
  85. package/dist/packages/core/src/responsive-contract.d.ts.map +1 -0
  86. package/dist/packages/labels/src/component-shapes.d.ts +165 -1
  87. package/dist/packages/labels/src/component-shapes.d.ts.map +1 -1
  88. package/dist/packages/labels/src/date-labels.d.ts +82 -5
  89. package/dist/packages/labels/src/date-labels.d.ts.map +1 -1
  90. package/dist/packages/labels/src/field-context.d.ts +2 -2
  91. package/dist/packages/labels/src/index.d.ts +3 -3
  92. package/dist/packages/labels/src/index.d.ts.map +1 -1
  93. package/dist/packages/labels/src/label-registry.d.ts +9 -1
  94. package/dist/packages/labels/src/label-registry.d.ts.map +1 -1
  95. package/dist/packages/layouts/dashboard/src/Dashboard.vue.d.ts +4 -4
  96. package/dist/packages/layouts/dashboard/src/Dashboard.vue.d.ts.map +1 -1
  97. package/dist/packages/layouts/desktop-app-shell/src/DesktopAppShell.vue.d.ts +103 -0
  98. package/dist/packages/layouts/desktop-app-shell/src/index.d.ts.map +1 -0
  99. package/dist/packages/layouts/settings/src/Settings.vue.d.ts +3 -3
  100. package/dist/packages/layouts/settings/src/Settings.vue.d.ts.map +1 -1
  101. package/dist/packages/layouts/split-layout/src/SplitLayout.vue.d.ts +4 -6
  102. package/dist/packages/layouts/split-layout/src/SplitLayout.vue.d.ts.map +1 -1
  103. package/dist/packages/layouts/split-layout/src/index.d.ts +1 -1
  104. package/dist/packages/layouts/split-layout/src/index.d.ts.map +1 -1
  105. package/dist/packages/loom/src/a11y.d.ts +2 -1
  106. package/dist/packages/loom/src/index.d.ts +47 -21
  107. package/dist/packages/patterns/app-header/src/AppHeader.vue.d.ts +82 -0
  108. package/dist/packages/patterns/app-header/src/AppHeader.vue.d.ts.map +1 -0
  109. package/dist/packages/patterns/app-header/src/index.d.ts.map +1 -0
  110. package/dist/packages/patterns/empty-state/src/EmptyState.vue.d.ts +54 -0
  111. package/dist/packages/patterns/empty-state/src/EmptyState.vue.d.ts.map +1 -0
  112. package/dist/packages/patterns/empty-state/src/index.d.ts.map +1 -0
  113. package/dist/packages/patterns/error-state/src/ErrorState.vue.d.ts +44 -0
  114. package/dist/packages/patterns/error-state/src/ErrorState.vue.d.ts.map +1 -0
  115. package/dist/packages/patterns/error-state/src/index.d.ts.map +1 -0
  116. package/dist/packages/patterns/error-summary/src/ErrorSummary.vue.d.ts +31 -0
  117. package/dist/packages/patterns/error-summary/src/index.d.ts +4 -0
  118. package/dist/packages/patterns/form-actions/src/FormActions.vue.d.ts +56 -0
  119. package/dist/packages/patterns/form-actions/src/FormActions.vue.d.ts.map +1 -0
  120. package/dist/packages/patterns/form-actions/src/index.d.ts.map +1 -0
  121. package/dist/packages/patterns/form-section/src/FormSection.vue.d.ts +85 -0
  122. package/dist/packages/patterns/form-section/src/FormSection.vue.d.ts.map +1 -0
  123. package/dist/packages/patterns/form-section/src/index.d.ts.map +1 -0
  124. package/dist/packages/patterns/loading-state/src/LoadingState.vue.d.ts.map +1 -0
  125. package/dist/packages/patterns/loading-state/src/index.d.ts.map +1 -0
  126. package/dist/packages/patterns/metric-card/src/MetricCard.vue.d.ts +77 -0
  127. package/dist/packages/patterns/metric-card/src/MetricCard.vue.d.ts.map +1 -0
  128. package/dist/packages/patterns/metric-card/src/index.d.ts.map +1 -0
  129. package/dist/packages/patterns/page-header/src/PageHeader.vue.d.ts.map +1 -0
  130. package/dist/packages/patterns/page-header/src/index.d.ts.map +1 -0
  131. package/dist/packages/patterns/row-actions/src/RowActions.vue.d.ts.map +1 -0
  132. package/dist/packages/patterns/row-actions/src/index.d.ts.map +1 -0
  133. package/dist/packages/patterns/sidebar-nav/src/SidebarNav.vue.d.ts.map +1 -0
  134. package/dist/packages/patterns/sidebar-nav/src/index.d.ts.map +1 -0
  135. package/dist/packages/patterns/title-bar/src/TitleBar.vue.d.ts +83 -0
  136. package/dist/packages/patterns/title-bar/src/index.d.ts.map +1 -0
  137. package/dist/packages/patterns/toast-stack/src/index.d.ts.map +1 -0
  138. package/dist/packages/primitives/alert/src/Alert.vue.d.ts +18 -0
  139. package/dist/packages/primitives/avatar/src/Avatar.vue.d.ts +2 -2
  140. package/dist/packages/primitives/avatar/src/Avatar.vue.d.ts.map +1 -1
  141. package/dist/packages/primitives/calendar/src/Calendar.vue.d.ts +95 -0
  142. package/dist/packages/primitives/calendar/src/index.d.ts +3 -0
  143. package/dist/packages/primitives/combobox/src/Combobox.vue.d.ts +1 -1
  144. package/dist/packages/primitives/command/src/Command.vue.d.ts +77 -0
  145. package/dist/packages/primitives/command/src/index.d.ts +4 -0
  146. package/dist/packages/primitives/copy-button/src/CopyButton.vue.d.ts +64 -0
  147. package/dist/packages/primitives/copy-button/src/index.d.ts +4 -0
  148. package/dist/packages/primitives/data-grid/src/DataGrid.vue.d.ts +128 -0
  149. package/dist/packages/primitives/data-grid/src/index.d.ts +4 -0
  150. package/dist/packages/primitives/dialog/src/Dialog.vue.d.ts +15 -7
  151. package/dist/packages/primitives/drawer/src/Drawer.vue.d.ts +10 -2
  152. package/dist/packages/primitives/hover-card/src/index.d.ts.map +1 -1
  153. package/dist/packages/primitives/list/src/ListItem.vue.d.ts +1 -1
  154. package/dist/packages/primitives/list/src/ListItem.vue.d.ts.map +1 -1
  155. package/dist/packages/primitives/live-region/src/LiveRegion.vue.d.ts +36 -0
  156. package/dist/packages/primitives/live-region/src/LiveRegion.vue.d.ts.map +1 -0
  157. package/dist/packages/primitives/live-region/src/context.d.ts +40 -0
  158. package/dist/packages/primitives/live-region/src/context.d.ts.map +1 -0
  159. package/dist/packages/primitives/live-region/src/index.d.ts +4 -0
  160. package/dist/packages/primitives/live-region/src/index.d.ts.map +1 -0
  161. package/dist/packages/primitives/live-region/src/useAnnounce.d.ts +17 -0
  162. package/dist/packages/primitives/live-region/src/useAnnounce.d.ts.map +1 -0
  163. package/dist/packages/primitives/menubar/src/Menubar.vue.d.ts.map +1 -1
  164. package/dist/packages/primitives/meter/src/Meter.vue.d.ts +87 -0
  165. package/dist/packages/primitives/meter/src/index.d.ts +4 -0
  166. package/dist/packages/primitives/navigation-menu/src/NavigationMenu.vue.d.ts +69 -0
  167. package/dist/packages/primitives/navigation-menu/src/NavigationMenu.vue.d.ts.map +1 -0
  168. package/dist/packages/primitives/navigation-menu/src/index.d.ts +3 -0
  169. package/dist/packages/primitives/navigation-menu/src/index.d.ts.map +1 -0
  170. package/dist/packages/primitives/segmented-control/src/SegmentedControl.vue.d.ts.map +1 -1
  171. package/dist/packages/primitives/skip-link/src/SkipLink.vue.d.ts +62 -0
  172. package/dist/packages/primitives/skip-link/src/index.d.ts +3 -0
  173. package/dist/packages/primitives/surface/src/Surface.vue.d.ts +2 -2
  174. package/dist/packages/primitives/surface/src/Surface.vue.d.ts.map +1 -1
  175. package/dist/packages/primitives/switch/src/Switch.vue.d.ts.map +1 -1
  176. package/dist/packages/primitives/table/src/TableRow.vue.d.ts +2 -2
  177. package/dist/packages/primitives/table/src/TableRow.vue.d.ts.map +1 -1
  178. package/dist/packages/primitives/table/src/index.d.ts +1 -1
  179. package/dist/packages/primitives/toggle-group/src/ToggleGroup.vue.d.ts +53 -0
  180. package/dist/packages/primitives/toggle-group/src/ToggleGroup.vue.d.ts.map +1 -0
  181. package/dist/packages/primitives/toggle-group/src/index.d.ts +3 -0
  182. package/dist/packages/primitives/toggle-group/src/index.d.ts.map +1 -0
  183. package/dist/packages/primitives/toolbar/src/Toolbar.vue.d.ts +31 -0
  184. package/dist/packages/primitives/toolbar/src/Toolbar.vue.d.ts.map +1 -0
  185. package/dist/packages/primitives/toolbar/src/ToolbarSeparator.vue.d.ts +24 -0
  186. package/dist/packages/primitives/toolbar/src/ToolbarSeparator.vue.d.ts.map +1 -0
  187. package/dist/packages/primitives/toolbar/src/index.d.ts +4 -0
  188. package/dist/packages/primitives/toolbar/src/index.d.ts.map +1 -0
  189. package/dist/packages/primitives/tree-view/src/TreeView.vue.d.ts +99 -0
  190. package/dist/packages/primitives/tree-view/src/TreeViewNode.vue.d.ts +15 -0
  191. package/dist/packages/primitives/tree-view/src/TreeViewNode.vue.d.ts.map +1 -0
  192. package/dist/packages/primitives/tree-view/src/context.d.ts +39 -0
  193. package/dist/packages/primitives/tree-view/src/context.d.ts.map +1 -0
  194. package/dist/packages/primitives/tree-view/src/index.d.ts +4 -0
  195. package/dist/packages/primitives/visually-hidden/src/VisuallyHidden.vue.d.ts +21 -0
  196. package/dist/packages/primitives/visually-hidden/src/VisuallyHidden.vue.d.ts.map +1 -0
  197. package/dist/packages/primitives/visually-hidden/src/index.d.ts +3 -0
  198. package/dist/packages/primitives/visually-hidden/src/index.d.ts.map +1 -0
  199. package/dist/patterns/app-header/src/AppHeader.js +7 -0
  200. package/dist/patterns/app-header/src/AppHeader.js.map +1 -0
  201. package/dist/patterns/app-header/src/AppHeader.vue_vue_type_script_setup_true_lang.js +96 -0
  202. package/dist/patterns/app-header/src/AppHeader.vue_vue_type_script_setup_true_lang.js.map +1 -0
  203. package/dist/patterns/empty-state/src/EmptyState.js +7 -0
  204. package/dist/patterns/empty-state/src/EmptyState.js.map +1 -0
  205. package/dist/patterns/empty-state/src/EmptyState.vue_vue_type_script_setup_true_lang.js +73 -0
  206. package/dist/patterns/empty-state/src/EmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -0
  207. package/dist/patterns/error-state/src/ErrorState.js +7 -0
  208. package/dist/patterns/error-state/src/ErrorState.js.map +1 -0
  209. package/dist/patterns/error-state/src/ErrorState.vue_vue_type_script_setup_true_lang.js +60 -0
  210. package/dist/patterns/error-state/src/ErrorState.vue_vue_type_script_setup_true_lang.js.map +1 -0
  211. package/dist/patterns/error-summary/src/ErrorSummary.js +7 -0
  212. package/dist/patterns/error-summary/src/ErrorSummary.js.map +1 -0
  213. package/dist/patterns/error-summary/src/ErrorSummary.vue_vue_type_script_setup_true_lang.js +90 -0
  214. package/dist/patterns/error-summary/src/ErrorSummary.vue_vue_type_script_setup_true_lang.js.map +1 -0
  215. package/dist/patterns/error-summary/src/index.js +3 -0
  216. package/dist/patterns/form-actions/src/FormActions.js +7 -0
  217. package/dist/patterns/form-actions/src/FormActions.js.map +1 -0
  218. package/dist/patterns/form-actions/src/FormActions.vue_vue_type_script_setup_true_lang.js +22 -0
  219. package/dist/patterns/form-actions/src/FormActions.vue_vue_type_script_setup_true_lang.js.map +1 -0
  220. package/dist/patterns/form-section/src/FormSection.js +7 -0
  221. package/dist/patterns/form-section/src/FormSection.js.map +1 -0
  222. package/dist/patterns/form-section/src/FormSection.vue_vue_type_script_setup_true_lang.js +64 -0
  223. package/dist/patterns/form-section/src/FormSection.vue_vue_type_script_setup_true_lang.js.map +1 -0
  224. package/dist/patterns/loading-state/src/LoadingState.js +7 -0
  225. package/dist/patterns/loading-state/src/LoadingState.js.map +1 -0
  226. package/dist/patterns/loading-state/src/LoadingState.vue_vue_type_script_setup_true_lang.js +59 -0
  227. package/dist/patterns/loading-state/src/LoadingState.vue_vue_type_script_setup_true_lang.js.map +1 -0
  228. package/dist/patterns/metric-card/src/MetricCard.js +7 -0
  229. package/dist/patterns/metric-card/src/MetricCard.js.map +1 -0
  230. package/dist/patterns/metric-card/src/MetricCard.vue_vue_type_script_setup_true_lang.js +87 -0
  231. package/dist/patterns/metric-card/src/MetricCard.vue_vue_type_script_setup_true_lang.js.map +1 -0
  232. package/dist/patterns/page-header/src/PageHeader.js +7 -0
  233. package/dist/patterns/page-header/src/PageHeader.js.map +1 -0
  234. package/dist/patterns/page-header/src/PageHeader.vue_vue_type_script_setup_true_lang.js +68 -0
  235. package/dist/patterns/page-header/src/PageHeader.vue_vue_type_script_setup_true_lang.js.map +1 -0
  236. package/dist/patterns/row-actions/src/RowActions.js +7 -0
  237. package/dist/patterns/row-actions/src/RowActions.js.map +1 -0
  238. package/dist/patterns/row-actions/src/RowActions.vue_vue_type_script_setup_true_lang.js +47 -0
  239. package/dist/patterns/row-actions/src/RowActions.vue_vue_type_script_setup_true_lang.js.map +1 -0
  240. package/dist/patterns/sidebar-nav/src/SidebarNav.js +7 -0
  241. package/dist/patterns/sidebar-nav/src/SidebarNav.js.map +1 -0
  242. package/dist/patterns/sidebar-nav/src/SidebarNav.vue_vue_type_script_setup_true_lang.js +129 -0
  243. package/dist/patterns/sidebar-nav/src/SidebarNav.vue_vue_type_script_setup_true_lang.js.map +1 -0
  244. package/dist/patterns/title-bar/src/TitleBar.js +7 -0
  245. package/dist/patterns/title-bar/src/TitleBar.js.map +1 -0
  246. package/dist/patterns/title-bar/src/TitleBar.vue_vue_type_script_setup_true_lang.js +69 -0
  247. package/dist/patterns/title-bar/src/TitleBar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  248. package/dist/patterns/toast-stack/src/ToastStack.js +7 -0
  249. package/dist/patterns/toast-stack/src/ToastStack.js.map +1 -0
  250. package/dist/patterns/toast-stack/src/ToastStack.vue_vue_type_script_setup_true_lang.js +52 -0
  251. package/dist/patterns/toast-stack/src/ToastStack.vue_vue_type_script_setup_true_lang.js.map +1 -0
  252. package/dist/primitives/accordion/src/Accordion.js.map +1 -0
  253. package/dist/primitives/accordion/src/Accordion.vue_vue_type_script_setup_true_lang.js.map +1 -0
  254. package/dist/primitives/alert/src/Alert.js.map +1 -0
  255. package/dist/primitives/alert/src/Alert.vue_vue_type_script_setup_true_lang.js +130 -0
  256. package/dist/primitives/alert/src/Alert.vue_vue_type_script_setup_true_lang.js.map +1 -0
  257. package/dist/primitives/alert-dialog/src/AlertDialog.js.map +1 -0
  258. package/dist/primitives/alert-dialog/src/AlertDialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  259. package/dist/primitives/avatar/src/Avatar.js.map +1 -0
  260. package/dist/primitives/avatar/src/Avatar.vue_vue_type_script_setup_true_lang.js +115 -0
  261. package/dist/primitives/avatar/src/Avatar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  262. package/dist/primitives/avatar-group/src/AvatarGroup.js.map +1 -0
  263. package/dist/primitives/avatar-group/src/AvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
  264. package/dist/primitives/badge/src/Badge.js.map +1 -0
  265. package/dist/primitives/badge/src/Badge.vue_vue_type_script_setup_true_lang.js.map +1 -0
  266. package/dist/primitives/breadcrumb/src/Breadcrumb.js.map +1 -0
  267. package/dist/primitives/breadcrumb/src/Breadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -0
  268. package/dist/primitives/button/src/Button.js.map +1 -0
  269. package/dist/primitives/button/src/Button.vue_vue_type_script_setup_true_lang.js.map +1 -0
  270. package/dist/primitives/calendar/src/Calendar.js +7 -0
  271. package/dist/primitives/calendar/src/Calendar.js.map +1 -0
  272. package/dist/primitives/calendar/src/Calendar.vue_vue_type_script_setup_true_lang.js +202 -0
  273. package/dist/primitives/calendar/src/Calendar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  274. package/dist/primitives/calendar/src/index.js +3 -0
  275. package/dist/primitives/card/src/Card.js.map +1 -0
  276. package/dist/primitives/card/src/Card.vue_vue_type_script_setup_true_lang.js.map +1 -0
  277. package/dist/primitives/carousel/src/Carousel.js.map +1 -0
  278. package/dist/primitives/carousel/src/Carousel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  279. package/dist/primitives/checkbox/src/Checkbox.js.map +1 -0
  280. package/dist/primitives/checkbox/src/Checkbox.vue_vue_type_script_setup_true_lang.js.map +1 -0
  281. package/dist/primitives/chip/src/Chip.js.map +1 -0
  282. package/dist/primitives/chip/src/Chip.vue_vue_type_script_setup_true_lang.js.map +1 -0
  283. package/dist/primitives/collapse/src/Collapse.js.map +1 -0
  284. package/dist/primitives/collapse/src/Collapse.vue_vue_type_script_setup_true_lang.js.map +1 -0
  285. package/dist/primitives/color-picker/src/ColorPicker.js.map +1 -0
  286. package/dist/primitives/color-picker/src/ColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
  287. package/dist/primitives/combobox/src/Combobox.js.map +1 -0
  288. package/dist/primitives/combobox/src/Combobox.vue_vue_type_script_setup_true_lang.js.map +1 -0
  289. package/dist/primitives/command/src/Command.js +7 -0
  290. package/dist/primitives/command/src/Command.js.map +1 -0
  291. package/dist/primitives/command/src/Command.vue_vue_type_script_setup_true_lang.js +333 -0
  292. package/dist/primitives/command/src/Command.vue_vue_type_script_setup_true_lang.js.map +1 -0
  293. package/dist/primitives/command/src/index.js +3 -0
  294. package/dist/primitives/context-menu/src/ContextMenu.js.map +1 -0
  295. package/dist/primitives/context-menu/src/ContextMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  296. package/dist/primitives/copy-button/src/CopyButton.js +7 -0
  297. package/dist/primitives/copy-button/src/CopyButton.js.map +1 -0
  298. package/dist/primitives/copy-button/src/CopyButton.vue_vue_type_script_setup_true_lang.js +113 -0
  299. package/dist/primitives/copy-button/src/CopyButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
  300. package/dist/primitives/copy-button/src/index.js +3 -0
  301. package/dist/primitives/data-grid/src/DataGrid.js +7 -0
  302. package/dist/primitives/data-grid/src/DataGrid.js.map +1 -0
  303. package/dist/primitives/data-grid/src/DataGrid.vue_vue_type_script_setup_true_lang.js +347 -0
  304. package/dist/primitives/data-grid/src/DataGrid.vue_vue_type_script_setup_true_lang.js.map +1 -0
  305. package/dist/primitives/data-grid/src/index.js +3 -0
  306. package/dist/primitives/date-picker/src/DatePicker.js.map +1 -0
  307. package/dist/primitives/date-picker/src/DatePicker.vue_vue_type_script_setup_true_lang.js +292 -0
  308. package/dist/primitives/date-picker/src/DatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
  309. package/dist/primitives/date-range-picker/src/DateRangePicker.js.map +1 -0
  310. package/dist/primitives/date-range-picker/src/DateRangePicker.vue_vue_type_script_setup_true_lang.js +417 -0
  311. package/dist/primitives/date-range-picker/src/DateRangePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
  312. package/dist/primitives/date-time-picker/src/DateTimePicker.js.map +1 -0
  313. package/dist/primitives/date-time-picker/src/DateTimePicker.vue_vue_type_script_setup_true_lang.js +359 -0
  314. package/dist/primitives/date-time-picker/src/DateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
  315. package/dist/primitives/date-time-range-picker/src/DateTimeRangePicker.js.map +1 -0
  316. package/dist/primitives/date-time-range-picker/src/DateTimeRangePicker.vue_vue_type_script_setup_true_lang.js +563 -0
  317. package/dist/primitives/date-time-range-picker/src/DateTimeRangePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
  318. package/dist/primitives/dialog/src/Dialog.js.map +1 -0
  319. package/dist/primitives/dialog/src/Dialog.vue_vue_type_script_setup_true_lang.js +103 -0
  320. package/dist/primitives/dialog/src/Dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  321. package/dist/primitives/drawer/src/Drawer.js.map +1 -0
  322. package/dist/primitives/drawer/src/Drawer.vue_vue_type_script_setup_true_lang.js +235 -0
  323. package/dist/primitives/drawer/src/Drawer.vue_vue_type_script_setup_true_lang.js.map +1 -0
  324. package/dist/primitives/dropdown-menu/src/DropdownMenu.js.map +1 -0
  325. package/dist/primitives/dropdown-menu/src/DropdownMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  326. package/dist/primitives/editable/src/Editable.js.map +1 -0
  327. package/dist/primitives/editable/src/Editable.vue_vue_type_script_setup_true_lang.js.map +1 -0
  328. package/dist/primitives/field/src/Field.js.map +1 -0
  329. package/dist/primitives/field/src/Field.vue_vue_type_script_setup_true_lang.js.map +1 -0
  330. package/dist/primitives/fieldset/src/Fieldset.js.map +1 -0
  331. package/dist/primitives/fieldset/src/Fieldset.vue_vue_type_script_setup_true_lang.js.map +1 -0
  332. package/dist/primitives/file-upload/src/FileUpload.js.map +1 -0
  333. package/dist/primitives/file-upload/src/FileUpload.vue_vue_type_script_setup_true_lang.js.map +1 -0
  334. package/dist/primitives/hover-card/src/HoverCard.js.map +1 -0
  335. package/dist/primitives/hover-card/src/HoverCard.vue_vue_type_script_setup_true_lang.js.map +1 -0
  336. package/dist/primitives/icon-button/src/IconButton.js.map +1 -0
  337. package/dist/primitives/icon-button/src/IconButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
  338. package/dist/primitives/indicator/src/Indicator.js.map +1 -0
  339. package/dist/primitives/indicator/src/Indicator.vue_vue_type_script_setup_true_lang.js.map +1 -0
  340. package/dist/primitives/inline-error/src/InlineError.js.map +1 -0
  341. package/dist/primitives/inline-error/src/InlineError.vue_vue_type_script_setup_true_lang.js.map +1 -0
  342. package/dist/primitives/kbd/src/Kbd.js.map +1 -0
  343. package/dist/primitives/kbd/src/Kbd.vue_vue_type_script_setup_true_lang.js.map +1 -0
  344. package/dist/primitives/link/src/Link.js.map +1 -0
  345. package/dist/primitives/link/src/Link.vue_vue_type_script_setup_true_lang.js.map +1 -0
  346. package/dist/primitives/list/src/List.js.map +1 -0
  347. package/dist/primitives/list/src/List.vue_vue_type_script_setup_true_lang.js.map +1 -0
  348. package/dist/primitives/list/src/ListItem.js.map +1 -0
  349. package/dist/primitives/list/src/ListItem.vue_vue_type_script_setup_true_lang.js +101 -0
  350. package/dist/primitives/list/src/ListItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
  351. package/dist/primitives/live-region/src/LiveRegion.js +7 -0
  352. package/dist/primitives/live-region/src/LiveRegion.js.map +1 -0
  353. package/dist/primitives/live-region/src/LiveRegion.vue_vue_type_script_setup_true_lang.js +59 -0
  354. package/dist/primitives/live-region/src/LiveRegion.vue_vue_type_script_setup_true_lang.js.map +1 -0
  355. package/dist/primitives/live-region/src/context.js +85 -0
  356. package/dist/primitives/live-region/src/context.js.map +1 -0
  357. package/dist/primitives/live-region/src/index.js +3 -0
  358. package/dist/primitives/live-region/src/useAnnounce.js +25 -0
  359. package/dist/primitives/live-region/src/useAnnounce.js.map +1 -0
  360. package/dist/primitives/menubar/src/Menubar.js.map +1 -0
  361. package/dist/primitives/menubar/src/Menubar.vue_vue_type_script_setup_true_lang.js +332 -0
  362. package/dist/primitives/menubar/src/Menubar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  363. package/dist/primitives/meter/src/Meter.js +7 -0
  364. package/dist/primitives/meter/src/Meter.js.map +1 -0
  365. package/dist/primitives/meter/src/Meter.vue_vue_type_script_setup_true_lang.js +236 -0
  366. package/dist/primitives/meter/src/Meter.vue_vue_type_script_setup_true_lang.js.map +1 -0
  367. package/dist/primitives/meter/src/index.js +3 -0
  368. package/dist/primitives/navigation-menu/src/NavigationMenu.js +7 -0
  369. package/dist/primitives/navigation-menu/src/NavigationMenu.js.map +1 -0
  370. package/dist/primitives/navigation-menu/src/NavigationMenu.vue_vue_type_script_setup_true_lang.js +118 -0
  371. package/dist/primitives/navigation-menu/src/NavigationMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  372. package/dist/primitives/navigation-menu/src/index.js +2 -0
  373. package/dist/primitives/number-field/src/NumberField.js.map +1 -0
  374. package/dist/primitives/number-field/src/NumberField.vue_vue_type_script_setup_true_lang.js.map +1 -0
  375. package/dist/primitives/otp-input/src/OtpInput.js.map +1 -0
  376. package/dist/primitives/otp-input/src/OtpInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
  377. package/dist/primitives/pagination/src/Pagination.js.map +1 -0
  378. package/dist/primitives/pagination/src/Pagination.vue_vue_type_script_setup_true_lang.js.map +1 -0
  379. package/dist/primitives/popover/src/Popover.js.map +1 -0
  380. package/dist/primitives/popover/src/Popover.vue_vue_type_script_setup_true_lang.js.map +1 -0
  381. package/dist/primitives/progress/src/Progress.js.map +1 -0
  382. package/dist/primitives/progress/src/Progress.vue_vue_type_script_setup_true_lang.js.map +1 -0
  383. package/dist/primitives/radial-progress/src/RadialProgress.js.map +1 -0
  384. package/dist/primitives/radial-progress/src/RadialProgress.vue_vue_type_script_setup_true_lang.js.map +1 -0
  385. package/dist/primitives/radio-group/src/RadioGroup.js.map +1 -0
  386. package/dist/primitives/radio-group/src/RadioGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
  387. package/dist/primitives/rating/src/Rating.js.map +1 -0
  388. package/dist/primitives/rating/src/Rating.vue_vue_type_script_setup_true_lang.js.map +1 -0
  389. package/dist/primitives/scroll-area/src/ScrollArea.js.map +1 -0
  390. package/dist/primitives/scroll-area/src/ScrollArea.vue_vue_type_script_setup_true_lang.js.map +1 -0
  391. package/dist/primitives/segmented-control/src/SegmentedControl.js.map +1 -0
  392. package/dist/primitives/segmented-control/src/SegmentedControl.vue_vue_type_script_setup_true_lang.js +133 -0
  393. package/dist/primitives/segmented-control/src/SegmentedControl.vue_vue_type_script_setup_true_lang.js.map +1 -0
  394. package/dist/primitives/select/src/Select.js.map +1 -0
  395. package/dist/primitives/select/src/Select.vue_vue_type_script_setup_true_lang.js.map +1 -0
  396. package/dist/primitives/separator/src/Separator.js.map +1 -0
  397. package/dist/primitives/separator/src/Separator.vue_vue_type_script_setup_true_lang.js.map +1 -0
  398. package/dist/primitives/skeleton/src/Skeleton.js.map +1 -0
  399. package/dist/primitives/skeleton/src/Skeleton.vue_vue_type_script_setup_true_lang.js.map +1 -0
  400. package/dist/primitives/skip-link/src/SkipLink.js +7 -0
  401. package/dist/primitives/skip-link/src/SkipLink.js.map +1 -0
  402. package/dist/primitives/skip-link/src/SkipLink.vue_vue_type_script_setup_true_lang.js +64 -0
  403. package/dist/primitives/skip-link/src/SkipLink.vue_vue_type_script_setup_true_lang.js.map +1 -0
  404. package/dist/primitives/skip-link/src/index.js +3 -0
  405. package/dist/primitives/slider/src/Slider.js.map +1 -0
  406. package/dist/primitives/slider/src/Slider.vue_vue_type_script_setup_true_lang.js.map +1 -0
  407. package/dist/primitives/speed-dial/src/SpeedDial.js.map +1 -0
  408. package/dist/primitives/speed-dial/src/SpeedDial.vue_vue_type_script_setup_true_lang.js.map +1 -0
  409. package/dist/primitives/spinner/src/Spinner.js.map +1 -0
  410. package/dist/primitives/spinner/src/Spinner.vue_vue_type_script_setup_true_lang.js.map +1 -0
  411. package/dist/primitives/stepper/src/Stepper.js.map +1 -0
  412. package/dist/primitives/stepper/src/Stepper.vue_vue_type_script_setup_true_lang.js +208 -0
  413. package/dist/primitives/stepper/src/Stepper.vue_vue_type_script_setup_true_lang.js.map +1 -0
  414. package/dist/primitives/surface/src/Surface.js.map +1 -0
  415. package/dist/primitives/surface/src/Surface.vue_vue_type_script_setup_true_lang.js.map +1 -0
  416. package/dist/primitives/switch/src/Switch.js.map +1 -0
  417. package/dist/primitives/switch/src/Switch.vue_vue_type_script_setup_true_lang.js +75 -0
  418. package/dist/primitives/switch/src/Switch.vue_vue_type_script_setup_true_lang.js.map +1 -0
  419. package/dist/primitives/table/src/Table.js.map +1 -0
  420. package/dist/primitives/table/src/Table.vue_vue_type_script_setup_true_lang.js.map +1 -0
  421. package/dist/primitives/table/src/TableCell.js.map +1 -0
  422. package/dist/primitives/table/src/TableCell.vue_vue_type_script_setup_true_lang.js.map +1 -0
  423. package/dist/primitives/table/src/TableHead.js.map +1 -0
  424. package/dist/primitives/table/src/TableHead.vue_vue_type_script_setup_true_lang.js.map +1 -0
  425. package/dist/primitives/table/src/TableRow.js.map +1 -0
  426. package/dist/primitives/table/src/TableRow.vue_vue_type_script_setup_true_lang.js.map +1 -0
  427. package/dist/primitives/table/src/index.js +8 -0
  428. package/dist/primitives/tabs/src/Tabs.js.map +1 -0
  429. package/dist/primitives/tabs/src/Tabs.vue_vue_type_script_setup_true_lang.js.map +1 -0
  430. package/dist/primitives/tags-input/src/TagsInput.js.map +1 -0
  431. package/dist/primitives/tags-input/src/TagsInput.vue_vue_type_script_setup_true_lang.js.map +1 -0
  432. package/dist/primitives/text-field/src/TextField.js.map +1 -0
  433. package/dist/primitives/text-field/src/TextField.vue_vue_type_script_setup_true_lang.js.map +1 -0
  434. package/dist/primitives/textarea/src/Textarea.js.map +1 -0
  435. package/dist/primitives/textarea/src/Textarea.vue_vue_type_script_setup_true_lang.js.map +1 -0
  436. package/dist/primitives/time-picker/src/TimePicker.js.map +1 -0
  437. package/dist/primitives/time-picker/src/TimePicker.vue_vue_type_script_setup_true_lang.js +189 -0
  438. package/dist/primitives/time-picker/src/TimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -0
  439. package/dist/primitives/timeline/src/Timeline.js.map +1 -0
  440. package/dist/primitives/timeline/src/Timeline.vue_vue_type_script_setup_true_lang.js.map +1 -0
  441. package/dist/primitives/timeline/src/TimelineItem.js.map +1 -0
  442. package/dist/primitives/timeline/src/TimelineItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
  443. package/dist/primitives/timeline/src/index.js +5 -0
  444. package/dist/primitives/toast/src/Toast.js.map +1 -0
  445. package/dist/primitives/toast/src/Toast.vue_vue_type_script_setup_true_lang.js.map +1 -0
  446. package/dist/primitives/toast/src/ToastItem.js.map +1 -0
  447. package/dist/primitives/toast/src/ToastItem.vue_vue_type_script_setup_true_lang.js +120 -0
  448. package/dist/primitives/toast/src/ToastItem.vue_vue_type_script_setup_true_lang.js.map +1 -0
  449. package/dist/primitives/toggle-group/src/ToggleGroup.js +7 -0
  450. package/dist/primitives/toggle-group/src/ToggleGroup.js.map +1 -0
  451. package/dist/primitives/toggle-group/src/ToggleGroup.vue_vue_type_script_setup_true_lang.js +111 -0
  452. package/dist/primitives/toggle-group/src/ToggleGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
  453. package/dist/primitives/toggle-group/src/index.js +2 -0
  454. package/dist/primitives/toolbar/src/Toolbar.js +7 -0
  455. package/dist/primitives/toolbar/src/Toolbar.js.map +1 -0
  456. package/dist/primitives/toolbar/src/Toolbar.vue_vue_type_script_setup_true_lang.js +149 -0
  457. package/dist/primitives/toolbar/src/Toolbar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  458. package/dist/primitives/toolbar/src/ToolbarSeparator.js +7 -0
  459. package/dist/primitives/toolbar/src/ToolbarSeparator.js.map +1 -0
  460. package/dist/primitives/toolbar/src/ToolbarSeparator.vue_vue_type_script_setup_true_lang.js +40 -0
  461. package/dist/primitives/toolbar/src/ToolbarSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -0
  462. package/dist/primitives/toolbar/src/index.js +3 -0
  463. package/dist/primitives/tooltip/src/Tooltip.js.map +1 -0
  464. package/dist/primitives/tooltip/src/Tooltip.vue_vue_type_script_setup_true_lang.js.map +1 -0
  465. package/dist/primitives/tree-view/src/TreeView.js +7 -0
  466. package/dist/primitives/tree-view/src/TreeView.js.map +1 -0
  467. package/dist/primitives/tree-view/src/TreeView.vue_vue_type_script_setup_true_lang.js +310 -0
  468. package/dist/primitives/tree-view/src/TreeView.vue_vue_type_script_setup_true_lang.js.map +1 -0
  469. package/dist/primitives/tree-view/src/TreeViewNode.js +7 -0
  470. package/dist/primitives/tree-view/src/TreeViewNode.js.map +1 -0
  471. package/dist/primitives/tree-view/src/TreeViewNode.vue_vue_type_script_setup_true_lang.js +103 -0
  472. package/dist/primitives/tree-view/src/TreeViewNode.vue_vue_type_script_setup_true_lang.js.map +1 -0
  473. package/dist/primitives/tree-view/src/context.js +6 -0
  474. package/dist/primitives/tree-view/src/context.js.map +1 -0
  475. package/dist/primitives/tree-view/src/index.js +3 -0
  476. package/dist/primitives/visually-hidden/src/VisuallyHidden.js +7 -0
  477. package/dist/primitives/visually-hidden/src/VisuallyHidden.js.map +1 -0
  478. package/dist/primitives/visually-hidden/src/VisuallyHidden.vue_vue_type_script_setup_true_lang.js +27 -0
  479. package/dist/primitives/visually-hidden/src/VisuallyHidden.vue_vue_type_script_setup_true_lang.js.map +1 -0
  480. package/dist/primitives/visually-hidden/src/index.js +2 -0
  481. package/dist/primitives/window-controls/src/WindowControls.js.map +1 -0
  482. package/dist/primitives/window-controls/src/WindowControls.vue_vue_type_script_setup_true_lang.js +127 -0
  483. package/dist/primitives/window-controls/src/WindowControls.vue_vue_type_script_setup_true_lang.js.map +1 -0
  484. package/dist/styles/theme.css +30 -6
  485. package/dist/theme.js +2 -2
  486. package/package.json +31 -29
  487. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/CalendarDate.js +0 -236
  488. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/CalendarDate.js.map +0 -1
  489. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/calendars/GregorianCalendar.js +0 -117
  490. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/calendars/GregorianCalendar.js.map +0 -1
  491. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/conversion.js +0 -142
  492. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/conversion.js.map +0 -1
  493. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/manipulation.js +0 -280
  494. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/manipulation.js.map +0 -1
  495. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/queries.js +0 -40
  496. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/queries.js.map +0 -1
  497. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/string.js +0 -69
  498. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/string.js.map +0 -1
  499. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/utils.js +0 -8
  500. package/dist/node_modules/.pnpm/@internationalized_date@3.12.3/node_modules/@internationalized/date/dist/private/utils.js.map +0 -1
  501. package/dist/packages/blocks/app-header/src/AppHeader.js +0 -7
  502. package/dist/packages/blocks/app-header/src/AppHeader.js.map +0 -1
  503. package/dist/packages/blocks/app-header/src/AppHeader.vue.d.ts +0 -82
  504. package/dist/packages/blocks/app-header/src/AppHeader.vue.d.ts.map +0 -1
  505. package/dist/packages/blocks/app-header/src/AppHeader.vue_vue_type_script_setup_true_lang.js +0 -96
  506. package/dist/packages/blocks/app-header/src/AppHeader.vue_vue_type_script_setup_true_lang.js.map +0 -1
  507. package/dist/packages/blocks/app-header/src/index.d.ts.map +0 -1
  508. package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.js +0 -7
  509. package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.js.map +0 -1
  510. package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.vue.d.ts +0 -42
  511. package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.vue.d.ts.map +0 -1
  512. package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.vue_vue_type_script_setup_true_lang.js +0 -45
  513. package/dist/packages/blocks/dashboard-grid/src/DashboardGrid.vue_vue_type_script_setup_true_lang.js.map +0 -1
  514. package/dist/packages/blocks/dashboard-grid/src/index.d.ts.map +0 -1
  515. package/dist/packages/blocks/desktop-app-shell/src/DesktopAppShell.js +0 -7
  516. package/dist/packages/blocks/desktop-app-shell/src/DesktopAppShell.js.map +0 -1
  517. package/dist/packages/blocks/desktop-app-shell/src/DesktopAppShell.vue.d.ts +0 -102
  518. package/dist/packages/blocks/desktop-app-shell/src/DesktopAppShell.vue_vue_type_script_setup_true_lang.js +0 -76
  519. package/dist/packages/blocks/desktop-app-shell/src/DesktopAppShell.vue_vue_type_script_setup_true_lang.js.map +0 -1
  520. package/dist/packages/blocks/desktop-app-shell/src/index.d.ts.map +0 -1
  521. package/dist/packages/blocks/empty-state/src/EmptyState.js +0 -7
  522. package/dist/packages/blocks/empty-state/src/EmptyState.js.map +0 -1
  523. package/dist/packages/blocks/empty-state/src/EmptyState.vue.d.ts +0 -50
  524. package/dist/packages/blocks/empty-state/src/EmptyState.vue.d.ts.map +0 -1
  525. package/dist/packages/blocks/empty-state/src/EmptyState.vue_vue_type_script_setup_true_lang.js +0 -71
  526. package/dist/packages/blocks/empty-state/src/EmptyState.vue_vue_type_script_setup_true_lang.js.map +0 -1
  527. package/dist/packages/blocks/empty-state/src/index.d.ts.map +0 -1
  528. package/dist/packages/blocks/error-state/src/ErrorState.js +0 -7
  529. package/dist/packages/blocks/error-state/src/ErrorState.js.map +0 -1
  530. package/dist/packages/blocks/error-state/src/ErrorState.vue.d.ts +0 -44
  531. package/dist/packages/blocks/error-state/src/ErrorState.vue.d.ts.map +0 -1
  532. package/dist/packages/blocks/error-state/src/ErrorState.vue_vue_type_script_setup_true_lang.js +0 -60
  533. package/dist/packages/blocks/error-state/src/ErrorState.vue_vue_type_script_setup_true_lang.js.map +0 -1
  534. package/dist/packages/blocks/error-state/src/index.d.ts.map +0 -1
  535. package/dist/packages/blocks/form-actions/src/FormActions.js +0 -7
  536. package/dist/packages/blocks/form-actions/src/FormActions.js.map +0 -1
  537. package/dist/packages/blocks/form-actions/src/FormActions.vue.d.ts +0 -51
  538. package/dist/packages/blocks/form-actions/src/FormActions.vue.d.ts.map +0 -1
  539. package/dist/packages/blocks/form-actions/src/FormActions.vue_vue_type_script_setup_true_lang.js +0 -22
  540. package/dist/packages/blocks/form-actions/src/FormActions.vue_vue_type_script_setup_true_lang.js.map +0 -1
  541. package/dist/packages/blocks/form-actions/src/index.d.ts.map +0 -1
  542. package/dist/packages/blocks/form-section/src/FormSection.js +0 -7
  543. package/dist/packages/blocks/form-section/src/FormSection.js.map +0 -1
  544. package/dist/packages/blocks/form-section/src/FormSection.vue.d.ts +0 -85
  545. package/dist/packages/blocks/form-section/src/FormSection.vue.d.ts.map +0 -1
  546. package/dist/packages/blocks/form-section/src/FormSection.vue_vue_type_script_setup_true_lang.js +0 -64
  547. package/dist/packages/blocks/form-section/src/FormSection.vue_vue_type_script_setup_true_lang.js.map +0 -1
  548. package/dist/packages/blocks/form-section/src/index.d.ts.map +0 -1
  549. package/dist/packages/blocks/loading-state/src/LoadingState.js +0 -7
  550. package/dist/packages/blocks/loading-state/src/LoadingState.js.map +0 -1
  551. package/dist/packages/blocks/loading-state/src/LoadingState.vue.d.ts.map +0 -1
  552. package/dist/packages/blocks/loading-state/src/LoadingState.vue_vue_type_script_setup_true_lang.js +0 -59
  553. package/dist/packages/blocks/loading-state/src/LoadingState.vue_vue_type_script_setup_true_lang.js.map +0 -1
  554. package/dist/packages/blocks/loading-state/src/index.d.ts.map +0 -1
  555. package/dist/packages/blocks/metric-card/src/MetricCard.js +0 -7
  556. package/dist/packages/blocks/metric-card/src/MetricCard.js.map +0 -1
  557. package/dist/packages/blocks/metric-card/src/MetricCard.vue.d.ts +0 -77
  558. package/dist/packages/blocks/metric-card/src/MetricCard.vue.d.ts.map +0 -1
  559. package/dist/packages/blocks/metric-card/src/MetricCard.vue_vue_type_script_setup_true_lang.js +0 -87
  560. package/dist/packages/blocks/metric-card/src/MetricCard.vue_vue_type_script_setup_true_lang.js.map +0 -1
  561. package/dist/packages/blocks/metric-card/src/index.d.ts.map +0 -1
  562. package/dist/packages/blocks/page-header/src/PageHeader.js +0 -7
  563. package/dist/packages/blocks/page-header/src/PageHeader.js.map +0 -1
  564. package/dist/packages/blocks/page-header/src/PageHeader.vue.d.ts.map +0 -1
  565. package/dist/packages/blocks/page-header/src/PageHeader.vue_vue_type_script_setup_true_lang.js +0 -68
  566. package/dist/packages/blocks/page-header/src/PageHeader.vue_vue_type_script_setup_true_lang.js.map +0 -1
  567. package/dist/packages/blocks/page-header/src/index.d.ts.map +0 -1
  568. package/dist/packages/blocks/row-actions/src/RowActions.js +0 -7
  569. package/dist/packages/blocks/row-actions/src/RowActions.js.map +0 -1
  570. package/dist/packages/blocks/row-actions/src/RowActions.vue.d.ts.map +0 -1
  571. package/dist/packages/blocks/row-actions/src/RowActions.vue_vue_type_script_setup_true_lang.js +0 -47
  572. package/dist/packages/blocks/row-actions/src/RowActions.vue_vue_type_script_setup_true_lang.js.map +0 -1
  573. package/dist/packages/blocks/row-actions/src/index.d.ts.map +0 -1
  574. package/dist/packages/blocks/sidebar-nav/src/SidebarNav.js +0 -7
  575. package/dist/packages/blocks/sidebar-nav/src/SidebarNav.js.map +0 -1
  576. package/dist/packages/blocks/sidebar-nav/src/SidebarNav.vue.d.ts.map +0 -1
  577. package/dist/packages/blocks/sidebar-nav/src/SidebarNav.vue_vue_type_script_setup_true_lang.js +0 -129
  578. package/dist/packages/blocks/sidebar-nav/src/SidebarNav.vue_vue_type_script_setup_true_lang.js.map +0 -1
  579. package/dist/packages/blocks/sidebar-nav/src/index.d.ts.map +0 -1
  580. package/dist/packages/blocks/title-bar/src/TitleBar.js +0 -7
  581. package/dist/packages/blocks/title-bar/src/TitleBar.js.map +0 -1
  582. package/dist/packages/blocks/title-bar/src/TitleBar.vue.d.ts +0 -83
  583. package/dist/packages/blocks/title-bar/src/TitleBar.vue_vue_type_script_setup_true_lang.js +0 -69
  584. package/dist/packages/blocks/title-bar/src/TitleBar.vue_vue_type_script_setup_true_lang.js.map +0 -1
  585. package/dist/packages/blocks/title-bar/src/index.d.ts.map +0 -1
  586. package/dist/packages/blocks/toast-stack/src/ToastStack.js +0 -7
  587. package/dist/packages/blocks/toast-stack/src/ToastStack.js.map +0 -1
  588. package/dist/packages/blocks/toast-stack/src/ToastStack.vue_vue_type_script_setup_true_lang.js +0 -52
  589. package/dist/packages/blocks/toast-stack/src/ToastStack.vue_vue_type_script_setup_true_lang.js.map +0 -1
  590. package/dist/packages/blocks/toast-stack/src/index.d.ts.map +0 -1
  591. package/dist/packages/composition/center/src/Center.js.map +0 -1
  592. package/dist/packages/composition/center/src/Center.vue_vue_type_script_setup_true_lang.js.map +0 -1
  593. package/dist/packages/composition/frame/src/Frame.js.map +0 -1
  594. package/dist/packages/composition/frame/src/Frame.vue_vue_type_script_setup_true_lang.js.map +0 -1
  595. package/dist/packages/composition/grid/src/Grid.js.map +0 -1
  596. package/dist/packages/composition/grid/src/Grid.vue_vue_type_script_setup_true_lang.js.map +0 -1
  597. package/dist/packages/composition/inline/src/Inline.js.map +0 -1
  598. package/dist/packages/composition/inline/src/Inline.vue_vue_type_script_setup_true_lang.js.map +0 -1
  599. package/dist/packages/composition/scroll-reel/src/ScrollReel.js.map +0 -1
  600. package/dist/packages/composition/scroll-reel/src/ScrollReel.vue_vue_type_script_setup_true_lang.js +0 -100
  601. package/dist/packages/composition/scroll-reel/src/ScrollReel.vue_vue_type_script_setup_true_lang.js.map +0 -1
  602. package/dist/packages/composition/sidebar/src/Sidebar.js.map +0 -1
  603. package/dist/packages/composition/sidebar/src/Sidebar.vue_vue_type_script_setup_true_lang.js +0 -37
  604. package/dist/packages/composition/sidebar/src/Sidebar.vue_vue_type_script_setup_true_lang.js.map +0 -1
  605. package/dist/packages/composition/split/src/Split.js.map +0 -1
  606. package/dist/packages/composition/split/src/Split.vue_vue_type_script_setup_true_lang.js +0 -41
  607. package/dist/packages/composition/split/src/Split.vue_vue_type_script_setup_true_lang.js.map +0 -1
  608. package/dist/packages/composition/stack/src/Stack.js.map +0 -1
  609. package/dist/packages/composition/stack/src/Stack.vue_vue_type_script_setup_true_lang.js.map +0 -1
  610. package/dist/packages/core/src/a11y-scope.js +0 -29
  611. package/dist/packages/core/src/a11y-scope.js.map +0 -1
  612. package/dist/packages/core/src/attrs.js.map +0 -1
  613. package/dist/packages/core/src/cn.js +0 -61
  614. package/dist/packages/core/src/cn.js.map +0 -1
  615. package/dist/packages/core/src/icon-defaults.js.map +0 -1
  616. package/dist/packages/core/src/index.js +0 -8
  617. package/dist/packages/core/src/motion.js +0 -27
  618. package/dist/packages/core/src/motion.js.map +0 -1
  619. package/dist/packages/core/src/props.js.map +0 -1
  620. package/dist/packages/core/src/theme.js.map +0 -1
  621. package/dist/packages/labels/src/ancestor-disabled.js.map +0 -1
  622. package/dist/packages/labels/src/count-labels.js.map +0 -1
  623. package/dist/packages/labels/src/date-labels.js +0 -159
  624. package/dist/packages/labels/src/date-labels.js.map +0 -1
  625. package/dist/packages/labels/src/field-context.js.map +0 -1
  626. package/dist/packages/labels/src/index.js +0 -6
  627. package/dist/packages/labels/src/labels.js.map +0 -1
  628. package/dist/packages/layouts/app-shell/src/AppShell.js.map +0 -1
  629. package/dist/packages/layouts/app-shell/src/AppShell.vue_vue_type_script_setup_true_lang.js.map +0 -1
  630. package/dist/packages/layouts/centered/src/Centered.js.map +0 -1
  631. package/dist/packages/layouts/centered/src/Centered.vue_vue_type_script_setup_true_lang.js.map +0 -1
  632. package/dist/packages/layouts/dashboard/src/Dashboard.js.map +0 -1
  633. package/dist/packages/layouts/dashboard/src/Dashboard.vue_vue_type_script_setup_true_lang.js +0 -65
  634. package/dist/packages/layouts/dashboard/src/Dashboard.vue_vue_type_script_setup_true_lang.js.map +0 -1
  635. package/dist/packages/layouts/form-layout/src/FormLayout.js.map +0 -1
  636. package/dist/packages/layouts/form-layout/src/FormLayout.vue_vue_type_script_setup_true_lang.js.map +0 -1
  637. package/dist/packages/layouts/master-detail/src/MasterDetail.js.map +0 -1
  638. package/dist/packages/layouts/master-detail/src/MasterDetail.vue_vue_type_script_setup_true_lang.js.map +0 -1
  639. package/dist/packages/layouts/reading/src/Reading.js.map +0 -1
  640. package/dist/packages/layouts/reading/src/Reading.vue_vue_type_script_setup_true_lang.js.map +0 -1
  641. package/dist/packages/layouts/settings/src/Settings.js.map +0 -1
  642. package/dist/packages/layouts/settings/src/Settings.vue_vue_type_script_setup_true_lang.js.map +0 -1
  643. package/dist/packages/layouts/split-layout/src/SplitLayout.js.map +0 -1
  644. package/dist/packages/layouts/split-layout/src/SplitLayout.vue_vue_type_script_setup_true_lang.js +0 -47
  645. package/dist/packages/layouts/split-layout/src/SplitLayout.vue_vue_type_script_setup_true_lang.js.map +0 -1
  646. package/dist/packages/primitives/accordion/src/Accordion.js.map +0 -1
  647. package/dist/packages/primitives/accordion/src/Accordion.vue_vue_type_script_setup_true_lang.js.map +0 -1
  648. package/dist/packages/primitives/alert/src/Alert.js.map +0 -1
  649. package/dist/packages/primitives/alert/src/Alert.vue_vue_type_script_setup_true_lang.js +0 -127
  650. package/dist/packages/primitives/alert/src/Alert.vue_vue_type_script_setup_true_lang.js.map +0 -1
  651. package/dist/packages/primitives/alert-dialog/src/AlertDialog.js.map +0 -1
  652. package/dist/packages/primitives/alert-dialog/src/AlertDialog.vue_vue_type_script_setup_true_lang.js.map +0 -1
  653. package/dist/packages/primitives/avatar/src/Avatar.js.map +0 -1
  654. package/dist/packages/primitives/avatar/src/Avatar.vue_vue_type_script_setup_true_lang.js +0 -115
  655. package/dist/packages/primitives/avatar/src/Avatar.vue_vue_type_script_setup_true_lang.js.map +0 -1
  656. package/dist/packages/primitives/avatar-group/src/AvatarGroup.js.map +0 -1
  657. package/dist/packages/primitives/avatar-group/src/AvatarGroup.vue_vue_type_script_setup_true_lang.js.map +0 -1
  658. package/dist/packages/primitives/badge/src/Badge.js.map +0 -1
  659. package/dist/packages/primitives/badge/src/Badge.vue_vue_type_script_setup_true_lang.js.map +0 -1
  660. package/dist/packages/primitives/breadcrumb/src/Breadcrumb.js.map +0 -1
  661. package/dist/packages/primitives/breadcrumb/src/Breadcrumb.vue_vue_type_script_setup_true_lang.js.map +0 -1
  662. package/dist/packages/primitives/button/src/Button.js.map +0 -1
  663. package/dist/packages/primitives/button/src/Button.vue_vue_type_script_setup_true_lang.js.map +0 -1
  664. package/dist/packages/primitives/card/src/Card.js.map +0 -1
  665. package/dist/packages/primitives/card/src/Card.vue_vue_type_script_setup_true_lang.js.map +0 -1
  666. package/dist/packages/primitives/carousel/src/Carousel.js.map +0 -1
  667. package/dist/packages/primitives/carousel/src/Carousel.vue_vue_type_script_setup_true_lang.js.map +0 -1
  668. package/dist/packages/primitives/checkbox/src/Checkbox.js.map +0 -1
  669. package/dist/packages/primitives/checkbox/src/Checkbox.vue_vue_type_script_setup_true_lang.js.map +0 -1
  670. package/dist/packages/primitives/chip/src/Chip.js.map +0 -1
  671. package/dist/packages/primitives/chip/src/Chip.vue_vue_type_script_setup_true_lang.js.map +0 -1
  672. package/dist/packages/primitives/collapse/src/Collapse.js.map +0 -1
  673. package/dist/packages/primitives/collapse/src/Collapse.vue_vue_type_script_setup_true_lang.js.map +0 -1
  674. package/dist/packages/primitives/color-picker/src/ColorPicker.js.map +0 -1
  675. package/dist/packages/primitives/color-picker/src/ColorPicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
  676. package/dist/packages/primitives/combobox/src/Combobox.js.map +0 -1
  677. package/dist/packages/primitives/combobox/src/Combobox.vue_vue_type_script_setup_true_lang.js.map +0 -1
  678. package/dist/packages/primitives/context-menu/src/ContextMenu.js.map +0 -1
  679. package/dist/packages/primitives/context-menu/src/ContextMenu.vue_vue_type_script_setup_true_lang.js.map +0 -1
  680. package/dist/packages/primitives/date-picker/src/DatePicker.js.map +0 -1
  681. package/dist/packages/primitives/date-picker/src/DatePicker.vue_vue_type_script_setup_true_lang.js +0 -294
  682. package/dist/packages/primitives/date-picker/src/DatePicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
  683. package/dist/packages/primitives/date-range-picker/src/DateRangePicker.js.map +0 -1
  684. package/dist/packages/primitives/date-range-picker/src/DateRangePicker.vue_vue_type_script_setup_true_lang.js +0 -416
  685. package/dist/packages/primitives/date-range-picker/src/DateRangePicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
  686. package/dist/packages/primitives/date-time-picker/src/DateTimePicker.js.map +0 -1
  687. package/dist/packages/primitives/date-time-picker/src/DateTimePicker.vue_vue_type_script_setup_true_lang.js +0 -360
  688. package/dist/packages/primitives/date-time-picker/src/DateTimePicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
  689. package/dist/packages/primitives/date-time-range-picker/src/DateTimeRangePicker.js.map +0 -1
  690. package/dist/packages/primitives/date-time-range-picker/src/DateTimeRangePicker.vue_vue_type_script_setup_true_lang.js +0 -564
  691. package/dist/packages/primitives/date-time-range-picker/src/DateTimeRangePicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
  692. package/dist/packages/primitives/dialog/src/Dialog.js.map +0 -1
  693. package/dist/packages/primitives/dialog/src/Dialog.vue_vue_type_script_setup_true_lang.js +0 -101
  694. package/dist/packages/primitives/dialog/src/Dialog.vue_vue_type_script_setup_true_lang.js.map +0 -1
  695. package/dist/packages/primitives/drawer/src/Drawer.js.map +0 -1
  696. package/dist/packages/primitives/drawer/src/Drawer.vue_vue_type_script_setup_true_lang.js +0 -227
  697. package/dist/packages/primitives/drawer/src/Drawer.vue_vue_type_script_setup_true_lang.js.map +0 -1
  698. package/dist/packages/primitives/dropdown-menu/src/DropdownMenu.js.map +0 -1
  699. package/dist/packages/primitives/dropdown-menu/src/DropdownMenu.vue_vue_type_script_setup_true_lang.js.map +0 -1
  700. package/dist/packages/primitives/editable/src/Editable.js.map +0 -1
  701. package/dist/packages/primitives/editable/src/Editable.vue_vue_type_script_setup_true_lang.js.map +0 -1
  702. package/dist/packages/primitives/field/src/Field.js.map +0 -1
  703. package/dist/packages/primitives/field/src/Field.vue_vue_type_script_setup_true_lang.js.map +0 -1
  704. package/dist/packages/primitives/fieldset/src/Fieldset.js.map +0 -1
  705. package/dist/packages/primitives/fieldset/src/Fieldset.vue_vue_type_script_setup_true_lang.js.map +0 -1
  706. package/dist/packages/primitives/file-upload/src/FileUpload.js.map +0 -1
  707. package/dist/packages/primitives/file-upload/src/FileUpload.vue_vue_type_script_setup_true_lang.js.map +0 -1
  708. package/dist/packages/primitives/hover-card/src/HoverCard.js.map +0 -1
  709. package/dist/packages/primitives/hover-card/src/HoverCard.vue_vue_type_script_setup_true_lang.js.map +0 -1
  710. package/dist/packages/primitives/icon-button/src/IconButton.js.map +0 -1
  711. package/dist/packages/primitives/icon-button/src/IconButton.vue_vue_type_script_setup_true_lang.js.map +0 -1
  712. package/dist/packages/primitives/indicator/src/Indicator.js.map +0 -1
  713. package/dist/packages/primitives/indicator/src/Indicator.vue_vue_type_script_setup_true_lang.js.map +0 -1
  714. package/dist/packages/primitives/inline-error/src/InlineError.js.map +0 -1
  715. package/dist/packages/primitives/inline-error/src/InlineError.vue_vue_type_script_setup_true_lang.js.map +0 -1
  716. package/dist/packages/primitives/kbd/src/Kbd.js.map +0 -1
  717. package/dist/packages/primitives/kbd/src/Kbd.vue_vue_type_script_setup_true_lang.js.map +0 -1
  718. package/dist/packages/primitives/link/src/Link.js.map +0 -1
  719. package/dist/packages/primitives/link/src/Link.vue_vue_type_script_setup_true_lang.js.map +0 -1
  720. package/dist/packages/primitives/list/src/List.js.map +0 -1
  721. package/dist/packages/primitives/list/src/List.vue_vue_type_script_setup_true_lang.js.map +0 -1
  722. package/dist/packages/primitives/list/src/ListItem.js.map +0 -1
  723. package/dist/packages/primitives/list/src/ListItem.vue_vue_type_script_setup_true_lang.js +0 -101
  724. package/dist/packages/primitives/list/src/ListItem.vue_vue_type_script_setup_true_lang.js.map +0 -1
  725. package/dist/packages/primitives/menubar/src/Menubar.js.map +0 -1
  726. package/dist/packages/primitives/menubar/src/Menubar.vue_vue_type_script_setup_true_lang.js +0 -299
  727. package/dist/packages/primitives/menubar/src/Menubar.vue_vue_type_script_setup_true_lang.js.map +0 -1
  728. package/dist/packages/primitives/number-field/src/NumberField.js.map +0 -1
  729. package/dist/packages/primitives/number-field/src/NumberField.vue_vue_type_script_setup_true_lang.js.map +0 -1
  730. package/dist/packages/primitives/otp-input/src/OtpInput.js.map +0 -1
  731. package/dist/packages/primitives/otp-input/src/OtpInput.vue_vue_type_script_setup_true_lang.js.map +0 -1
  732. package/dist/packages/primitives/pagination/src/Pagination.js.map +0 -1
  733. package/dist/packages/primitives/pagination/src/Pagination.vue_vue_type_script_setup_true_lang.js.map +0 -1
  734. package/dist/packages/primitives/popover/src/Popover.js.map +0 -1
  735. package/dist/packages/primitives/popover/src/Popover.vue_vue_type_script_setup_true_lang.js.map +0 -1
  736. package/dist/packages/primitives/progress/src/Progress.js.map +0 -1
  737. package/dist/packages/primitives/progress/src/Progress.vue_vue_type_script_setup_true_lang.js.map +0 -1
  738. package/dist/packages/primitives/radial-progress/src/RadialProgress.js.map +0 -1
  739. package/dist/packages/primitives/radial-progress/src/RadialProgress.vue_vue_type_script_setup_true_lang.js.map +0 -1
  740. package/dist/packages/primitives/radio-group/src/RadioGroup.js.map +0 -1
  741. package/dist/packages/primitives/radio-group/src/RadioGroup.vue_vue_type_script_setup_true_lang.js.map +0 -1
  742. package/dist/packages/primitives/rating/src/Rating.js.map +0 -1
  743. package/dist/packages/primitives/rating/src/Rating.vue_vue_type_script_setup_true_lang.js.map +0 -1
  744. package/dist/packages/primitives/scroll-area/src/ScrollArea.js.map +0 -1
  745. package/dist/packages/primitives/scroll-area/src/ScrollArea.vue_vue_type_script_setup_true_lang.js.map +0 -1
  746. package/dist/packages/primitives/segmented-control/src/SegmentedControl.js.map +0 -1
  747. package/dist/packages/primitives/segmented-control/src/SegmentedControl.vue_vue_type_script_setup_true_lang.js +0 -133
  748. package/dist/packages/primitives/segmented-control/src/SegmentedControl.vue_vue_type_script_setup_true_lang.js.map +0 -1
  749. package/dist/packages/primitives/select/src/Select.js.map +0 -1
  750. package/dist/packages/primitives/select/src/Select.vue_vue_type_script_setup_true_lang.js.map +0 -1
  751. package/dist/packages/primitives/separator/src/Separator.js.map +0 -1
  752. package/dist/packages/primitives/separator/src/Separator.vue_vue_type_script_setup_true_lang.js.map +0 -1
  753. package/dist/packages/primitives/skeleton/src/Skeleton.js.map +0 -1
  754. package/dist/packages/primitives/skeleton/src/Skeleton.vue_vue_type_script_setup_true_lang.js.map +0 -1
  755. package/dist/packages/primitives/slider/src/Slider.js.map +0 -1
  756. package/dist/packages/primitives/slider/src/Slider.vue_vue_type_script_setup_true_lang.js.map +0 -1
  757. package/dist/packages/primitives/speed-dial/src/SpeedDial.js.map +0 -1
  758. package/dist/packages/primitives/speed-dial/src/SpeedDial.vue_vue_type_script_setup_true_lang.js.map +0 -1
  759. package/dist/packages/primitives/spinner/src/Spinner.js.map +0 -1
  760. package/dist/packages/primitives/spinner/src/Spinner.vue_vue_type_script_setup_true_lang.js.map +0 -1
  761. package/dist/packages/primitives/stepper/src/Stepper.js.map +0 -1
  762. package/dist/packages/primitives/stepper/src/Stepper.vue_vue_type_script_setup_true_lang.js +0 -206
  763. package/dist/packages/primitives/stepper/src/Stepper.vue_vue_type_script_setup_true_lang.js.map +0 -1
  764. package/dist/packages/primitives/surface/src/Surface.js.map +0 -1
  765. package/dist/packages/primitives/surface/src/Surface.vue_vue_type_script_setup_true_lang.js.map +0 -1
  766. package/dist/packages/primitives/switch/src/Switch.js.map +0 -1
  767. package/dist/packages/primitives/switch/src/Switch.vue_vue_type_script_setup_true_lang.js +0 -75
  768. package/dist/packages/primitives/switch/src/Switch.vue_vue_type_script_setup_true_lang.js.map +0 -1
  769. package/dist/packages/primitives/table/src/Table.js.map +0 -1
  770. package/dist/packages/primitives/table/src/Table.vue_vue_type_script_setup_true_lang.js.map +0 -1
  771. package/dist/packages/primitives/table/src/TableCell.js.map +0 -1
  772. package/dist/packages/primitives/table/src/TableCell.vue_vue_type_script_setup_true_lang.js.map +0 -1
  773. package/dist/packages/primitives/table/src/TableHead.js.map +0 -1
  774. package/dist/packages/primitives/table/src/TableHead.vue_vue_type_script_setup_true_lang.js.map +0 -1
  775. package/dist/packages/primitives/table/src/TableRow.js.map +0 -1
  776. package/dist/packages/primitives/table/src/TableRow.vue_vue_type_script_setup_true_lang.js.map +0 -1
  777. package/dist/packages/primitives/table/src/index.js +0 -8
  778. package/dist/packages/primitives/tabs/src/Tabs.js.map +0 -1
  779. package/dist/packages/primitives/tabs/src/Tabs.vue_vue_type_script_setup_true_lang.js.map +0 -1
  780. package/dist/packages/primitives/tags-input/src/TagsInput.js.map +0 -1
  781. package/dist/packages/primitives/tags-input/src/TagsInput.vue_vue_type_script_setup_true_lang.js.map +0 -1
  782. package/dist/packages/primitives/text-field/src/TextField.js.map +0 -1
  783. package/dist/packages/primitives/text-field/src/TextField.vue_vue_type_script_setup_true_lang.js.map +0 -1
  784. package/dist/packages/primitives/textarea/src/Textarea.js.map +0 -1
  785. package/dist/packages/primitives/textarea/src/Textarea.vue_vue_type_script_setup_true_lang.js.map +0 -1
  786. package/dist/packages/primitives/time-picker/src/TimePicker.js.map +0 -1
  787. package/dist/packages/primitives/time-picker/src/TimePicker.vue_vue_type_script_setup_true_lang.js +0 -187
  788. package/dist/packages/primitives/time-picker/src/TimePicker.vue_vue_type_script_setup_true_lang.js.map +0 -1
  789. package/dist/packages/primitives/timeline/src/Timeline.js.map +0 -1
  790. package/dist/packages/primitives/timeline/src/Timeline.vue_vue_type_script_setup_true_lang.js.map +0 -1
  791. package/dist/packages/primitives/timeline/src/TimelineItem.js.map +0 -1
  792. package/dist/packages/primitives/timeline/src/TimelineItem.vue_vue_type_script_setup_true_lang.js.map +0 -1
  793. package/dist/packages/primitives/timeline/src/index.js +0 -5
  794. package/dist/packages/primitives/toast/src/Toast.js.map +0 -1
  795. package/dist/packages/primitives/toast/src/Toast.vue_vue_type_script_setup_true_lang.js.map +0 -1
  796. package/dist/packages/primitives/toast/src/ToastItem.js.map +0 -1
  797. package/dist/packages/primitives/toast/src/ToastItem.vue_vue_type_script_setup_true_lang.js +0 -118
  798. package/dist/packages/primitives/toast/src/ToastItem.vue_vue_type_script_setup_true_lang.js.map +0 -1
  799. package/dist/packages/primitives/tooltip/src/Tooltip.js.map +0 -1
  800. package/dist/packages/primitives/tooltip/src/Tooltip.vue_vue_type_script_setup_true_lang.js.map +0 -1
  801. package/dist/packages/primitives/window-controls/src/WindowControls.js.map +0 -1
  802. package/dist/packages/primitives/window-controls/src/WindowControls.vue_vue_type_script_setup_true_lang.js +0 -124
  803. package/dist/packages/primitives/window-controls/src/WindowControls.vue_vue_type_script_setup_true_lang.js.map +0 -1
  804. /package/dist/{packages/composition → composition}/center/src/Center.js +0 -0
  805. /package/dist/{packages/composition → composition}/center/src/Center.vue_vue_type_script_setup_true_lang.js +0 -0
  806. /package/dist/{packages/composition → composition}/center/src/index.js +0 -0
  807. /package/dist/{packages/blocks → composition}/dashboard-grid/src/index.js +0 -0
  808. /package/dist/{packages/composition → composition}/frame/src/Frame.js +0 -0
  809. /package/dist/{packages/composition → composition}/frame/src/Frame.vue_vue_type_script_setup_true_lang.js +0 -0
  810. /package/dist/{packages/composition → composition}/frame/src/index.js +0 -0
  811. /package/dist/{packages/composition → composition}/grid/src/Grid.js +0 -0
  812. /package/dist/{packages/composition → composition}/grid/src/Grid.vue_vue_type_script_setup_true_lang.js +0 -0
  813. /package/dist/{packages/composition → composition}/grid/src/index.js +0 -0
  814. /package/dist/{packages/composition → composition}/inline/src/Inline.js +0 -0
  815. /package/dist/{packages/composition → composition}/inline/src/Inline.vue_vue_type_script_setup_true_lang.js +0 -0
  816. /package/dist/{packages/composition → composition}/inline/src/index.js +0 -0
  817. /package/dist/{packages/composition → composition}/scroll-reel/src/ScrollReel.js +0 -0
  818. /package/dist/{packages/composition → composition}/scroll-reel/src/index.js +0 -0
  819. /package/dist/{packages/composition → composition}/sidebar/src/Sidebar.js +0 -0
  820. /package/dist/{packages/composition → composition}/sidebar/src/index.js +0 -0
  821. /package/dist/{packages/composition → composition}/split/src/Split.js +0 -0
  822. /package/dist/{packages/composition → composition}/split/src/index.js +0 -0
  823. /package/dist/{packages/composition → composition}/stack/src/Stack.js +0 -0
  824. /package/dist/{packages/composition → composition}/stack/src/Stack.vue_vue_type_script_setup_true_lang.js +0 -0
  825. /package/dist/{packages/composition → composition}/stack/src/index.js +0 -0
  826. /package/dist/{packages/core → core}/src/attrs.js +0 -0
  827. /package/dist/{packages/core → core}/src/icon-defaults.js +0 -0
  828. /package/dist/{packages/core → core}/src/props.js +0 -0
  829. /package/dist/{packages/core → core}/src/theme.js +0 -0
  830. /package/dist/{packages/labels → labels}/src/ancestor-disabled.js +0 -0
  831. /package/dist/{packages/labels → labels}/src/count-labels.js +0 -0
  832. /package/dist/{packages/labels → labels}/src/field-context.js +0 -0
  833. /package/dist/{packages/labels → labels}/src/labels.js +0 -0
  834. /package/dist/{packages/layouts → layouts}/app-shell/src/AppShell.js +0 -0
  835. /package/dist/{packages/layouts → layouts}/app-shell/src/AppShell.vue_vue_type_script_setup_true_lang.js +0 -0
  836. /package/dist/{packages/layouts → layouts}/app-shell/src/index.js +0 -0
  837. /package/dist/{packages/layouts → layouts}/centered/src/Centered.js +0 -0
  838. /package/dist/{packages/layouts → layouts}/centered/src/Centered.vue_vue_type_script_setup_true_lang.js +0 -0
  839. /package/dist/{packages/layouts → layouts}/centered/src/index.js +0 -0
  840. /package/dist/{packages/layouts → layouts}/dashboard/src/Dashboard.js +0 -0
  841. /package/dist/{packages/layouts → layouts}/dashboard/src/index.js +0 -0
  842. /package/dist/{packages/blocks → layouts}/desktop-app-shell/src/index.js +0 -0
  843. /package/dist/{packages/layouts → layouts}/form-layout/src/FormLayout.js +0 -0
  844. /package/dist/{packages/layouts → layouts}/form-layout/src/FormLayout.vue_vue_type_script_setup_true_lang.js +0 -0
  845. /package/dist/{packages/layouts → layouts}/form-layout/src/index.js +0 -0
  846. /package/dist/{packages/layouts → layouts}/master-detail/src/MasterDetail.js +0 -0
  847. /package/dist/{packages/layouts → layouts}/master-detail/src/MasterDetail.vue_vue_type_script_setup_true_lang.js +0 -0
  848. /package/dist/{packages/layouts → layouts}/master-detail/src/index.js +0 -0
  849. /package/dist/{packages/layouts → layouts}/reading/src/Reading.js +0 -0
  850. /package/dist/{packages/layouts → layouts}/reading/src/Reading.vue_vue_type_script_setup_true_lang.js +0 -0
  851. /package/dist/{packages/layouts → layouts}/reading/src/index.js +0 -0
  852. /package/dist/{packages/layouts → layouts}/settings/src/Settings.js +0 -0
  853. /package/dist/{packages/layouts → layouts}/settings/src/Settings.vue_vue_type_script_setup_true_lang.js +0 -0
  854. /package/dist/{packages/layouts → layouts}/settings/src/index.js +0 -0
  855. /package/dist/{packages/layouts → layouts}/split-layout/src/SplitLayout.js +0 -0
  856. /package/dist/{packages/layouts → layouts}/split-layout/src/index.js +0 -0
  857. /package/dist/packages/{blocks → composition}/dashboard-grid/src/index.d.ts +0 -0
  858. /package/dist/packages/{blocks → layouts}/desktop-app-shell/src/index.d.ts +0 -0
  859. /package/dist/packages/{blocks → patterns}/app-header/src/index.d.ts +0 -0
  860. /package/dist/packages/{blocks → patterns}/empty-state/src/index.d.ts +0 -0
  861. /package/dist/packages/{blocks → patterns}/error-state/src/index.d.ts +0 -0
  862. /package/dist/packages/{blocks → patterns}/form-actions/src/index.d.ts +0 -0
  863. /package/dist/packages/{blocks → patterns}/form-section/src/index.d.ts +0 -0
  864. /package/dist/packages/{blocks → patterns}/loading-state/src/LoadingState.vue.d.ts +0 -0
  865. /package/dist/packages/{blocks → patterns}/loading-state/src/index.d.ts +0 -0
  866. /package/dist/packages/{blocks → patterns}/metric-card/src/index.d.ts +0 -0
  867. /package/dist/packages/{blocks → patterns}/page-header/src/PageHeader.vue.d.ts +0 -0
  868. /package/dist/packages/{blocks → patterns}/page-header/src/index.d.ts +0 -0
  869. /package/dist/packages/{blocks → patterns}/row-actions/src/RowActions.vue.d.ts +0 -0
  870. /package/dist/packages/{blocks → patterns}/row-actions/src/index.d.ts +0 -0
  871. /package/dist/packages/{blocks → patterns}/sidebar-nav/src/SidebarNav.vue.d.ts +0 -0
  872. /package/dist/packages/{blocks → patterns}/sidebar-nav/src/index.d.ts +0 -0
  873. /package/dist/packages/{blocks → patterns}/title-bar/src/index.d.ts +0 -0
  874. /package/dist/packages/{blocks → patterns}/toast-stack/src/ToastStack.vue.d.ts +0 -0
  875. /package/dist/packages/{blocks → patterns}/toast-stack/src/index.d.ts +0 -0
  876. /package/dist/{packages/blocks → patterns}/app-header/src/index.js +0 -0
  877. /package/dist/{packages/blocks → patterns}/empty-state/src/index.js +0 -0
  878. /package/dist/{packages/blocks → patterns}/error-state/src/index.js +0 -0
  879. /package/dist/{packages/blocks → patterns}/form-actions/src/index.js +0 -0
  880. /package/dist/{packages/blocks → patterns}/form-section/src/index.js +0 -0
  881. /package/dist/{packages/blocks → patterns}/loading-state/src/index.js +0 -0
  882. /package/dist/{packages/blocks → patterns}/metric-card/src/index.js +0 -0
  883. /package/dist/{packages/blocks → patterns}/page-header/src/index.js +0 -0
  884. /package/dist/{packages/blocks → patterns}/row-actions/src/index.js +0 -0
  885. /package/dist/{packages/blocks → patterns}/sidebar-nav/src/index.js +0 -0
  886. /package/dist/{packages/blocks → patterns}/title-bar/src/index.js +0 -0
  887. /package/dist/{packages/blocks → patterns}/toast-stack/src/index.js +0 -0
  888. /package/dist/{packages/primitives → primitives}/accordion/src/Accordion.js +0 -0
  889. /package/dist/{packages/primitives → primitives}/accordion/src/Accordion.vue_vue_type_script_setup_true_lang.js +0 -0
  890. /package/dist/{packages/primitives → primitives}/accordion/src/index.js +0 -0
  891. /package/dist/{packages/primitives → primitives}/alert/src/Alert.js +0 -0
  892. /package/dist/{packages/primitives → primitives}/alert/src/index.js +0 -0
  893. /package/dist/{packages/primitives → primitives}/alert-dialog/src/AlertDialog.js +0 -0
  894. /package/dist/{packages/primitives → primitives}/alert-dialog/src/AlertDialog.vue_vue_type_script_setup_true_lang.js +0 -0
  895. /package/dist/{packages/primitives → primitives}/alert-dialog/src/index.js +0 -0
  896. /package/dist/{packages/primitives → primitives}/avatar/src/Avatar.js +0 -0
  897. /package/dist/{packages/primitives → primitives}/avatar/src/index.js +0 -0
  898. /package/dist/{packages/primitives → primitives}/avatar-group/src/AvatarGroup.js +0 -0
  899. /package/dist/{packages/primitives → primitives}/avatar-group/src/AvatarGroup.vue_vue_type_script_setup_true_lang.js +0 -0
  900. /package/dist/{packages/primitives → primitives}/avatar-group/src/index.js +0 -0
  901. /package/dist/{packages/primitives → primitives}/badge/src/Badge.js +0 -0
  902. /package/dist/{packages/primitives → primitives}/badge/src/Badge.vue_vue_type_script_setup_true_lang.js +0 -0
  903. /package/dist/{packages/primitives → primitives}/badge/src/index.js +0 -0
  904. /package/dist/{packages/primitives → primitives}/breadcrumb/src/Breadcrumb.js +0 -0
  905. /package/dist/{packages/primitives → primitives}/breadcrumb/src/Breadcrumb.vue_vue_type_script_setup_true_lang.js +0 -0
  906. /package/dist/{packages/primitives → primitives}/breadcrumb/src/index.js +0 -0
  907. /package/dist/{packages/primitives → primitives}/button/src/Button.js +0 -0
  908. /package/dist/{packages/primitives → primitives}/button/src/Button.vue_vue_type_script_setup_true_lang.js +0 -0
  909. /package/dist/{packages/primitives → primitives}/button/src/index.js +0 -0
  910. /package/dist/{packages/primitives → primitives}/card/src/Card.js +0 -0
  911. /package/dist/{packages/primitives → primitives}/card/src/Card.vue_vue_type_script_setup_true_lang.js +0 -0
  912. /package/dist/{packages/primitives → primitives}/card/src/index.js +0 -0
  913. /package/dist/{packages/primitives → primitives}/carousel/src/Carousel.js +0 -0
  914. /package/dist/{packages/primitives → primitives}/carousel/src/Carousel.vue_vue_type_script_setup_true_lang.js +0 -0
  915. /package/dist/{packages/primitives → primitives}/carousel/src/index.js +0 -0
  916. /package/dist/{packages/primitives → primitives}/checkbox/src/Checkbox.js +0 -0
  917. /package/dist/{packages/primitives → primitives}/checkbox/src/Checkbox.vue_vue_type_script_setup_true_lang.js +0 -0
  918. /package/dist/{packages/primitives → primitives}/checkbox/src/index.js +0 -0
  919. /package/dist/{packages/primitives → primitives}/chip/src/Chip.js +0 -0
  920. /package/dist/{packages/primitives → primitives}/chip/src/Chip.vue_vue_type_script_setup_true_lang.js +0 -0
  921. /package/dist/{packages/primitives → primitives}/chip/src/index.js +0 -0
  922. /package/dist/{packages/primitives → primitives}/collapse/src/Collapse.js +0 -0
  923. /package/dist/{packages/primitives → primitives}/collapse/src/Collapse.vue_vue_type_script_setup_true_lang.js +0 -0
  924. /package/dist/{packages/primitives → primitives}/collapse/src/index.js +0 -0
  925. /package/dist/{packages/primitives → primitives}/color-picker/src/ColorPicker.js +0 -0
  926. /package/dist/{packages/primitives → primitives}/color-picker/src/ColorPicker.vue_vue_type_script_setup_true_lang.js +0 -0
  927. /package/dist/{packages/primitives → primitives}/color-picker/src/index.js +0 -0
  928. /package/dist/{packages/primitives → primitives}/combobox/src/Combobox.js +0 -0
  929. /package/dist/{packages/primitives → primitives}/combobox/src/Combobox.vue_vue_type_script_setup_true_lang.js +0 -0
  930. /package/dist/{packages/primitives → primitives}/combobox/src/index.js +0 -0
  931. /package/dist/{packages/primitives → primitives}/context-menu/src/ContextMenu.js +0 -0
  932. /package/dist/{packages/primitives → primitives}/context-menu/src/ContextMenu.vue_vue_type_script_setup_true_lang.js +0 -0
  933. /package/dist/{packages/primitives → primitives}/context-menu/src/index.js +0 -0
  934. /package/dist/{packages/primitives → primitives}/date-picker/src/DatePicker.js +0 -0
  935. /package/dist/{packages/primitives → primitives}/date-picker/src/index.js +0 -0
  936. /package/dist/{packages/primitives → primitives}/date-range-picker/src/DateRangePicker.js +0 -0
  937. /package/dist/{packages/primitives → primitives}/date-range-picker/src/index.js +0 -0
  938. /package/dist/{packages/primitives → primitives}/date-time-picker/src/DateTimePicker.js +0 -0
  939. /package/dist/{packages/primitives → primitives}/date-time-picker/src/index.js +0 -0
  940. /package/dist/{packages/primitives → primitives}/date-time-range-picker/src/DateTimeRangePicker.js +0 -0
  941. /package/dist/{packages/primitives → primitives}/date-time-range-picker/src/index.js +0 -0
  942. /package/dist/{packages/primitives → primitives}/dialog/src/Dialog.js +0 -0
  943. /package/dist/{packages/primitives → primitives}/dialog/src/index.js +0 -0
  944. /package/dist/{packages/primitives → primitives}/drawer/src/Drawer.js +0 -0
  945. /package/dist/{packages/primitives → primitives}/drawer/src/index.js +0 -0
  946. /package/dist/{packages/primitives → primitives}/dropdown-menu/src/DropdownMenu.js +0 -0
  947. /package/dist/{packages/primitives → primitives}/dropdown-menu/src/DropdownMenu.vue_vue_type_script_setup_true_lang.js +0 -0
  948. /package/dist/{packages/primitives → primitives}/dropdown-menu/src/index.js +0 -0
  949. /package/dist/{packages/primitives → primitives}/editable/src/Editable.js +0 -0
  950. /package/dist/{packages/primitives → primitives}/editable/src/Editable.vue_vue_type_script_setup_true_lang.js +0 -0
  951. /package/dist/{packages/primitives → primitives}/editable/src/index.js +0 -0
  952. /package/dist/{packages/primitives → primitives}/field/src/Field.js +0 -0
  953. /package/dist/{packages/primitives → primitives}/field/src/Field.vue_vue_type_script_setup_true_lang.js +0 -0
  954. /package/dist/{packages/primitives → primitives}/field/src/index.js +0 -0
  955. /package/dist/{packages/primitives → primitives}/fieldset/src/Fieldset.js +0 -0
  956. /package/dist/{packages/primitives → primitives}/fieldset/src/Fieldset.vue_vue_type_script_setup_true_lang.js +0 -0
  957. /package/dist/{packages/primitives → primitives}/fieldset/src/index.js +0 -0
  958. /package/dist/{packages/primitives → primitives}/file-upload/src/FileUpload.js +0 -0
  959. /package/dist/{packages/primitives → primitives}/file-upload/src/FileUpload.vue_vue_type_script_setup_true_lang.js +0 -0
  960. /package/dist/{packages/primitives → primitives}/file-upload/src/index.js +0 -0
  961. /package/dist/{packages/primitives → primitives}/hover-card/src/HoverCard.js +0 -0
  962. /package/dist/{packages/primitives → primitives}/hover-card/src/HoverCard.vue_vue_type_script_setup_true_lang.js +0 -0
  963. /package/dist/{packages/primitives → primitives}/hover-card/src/index.js +0 -0
  964. /package/dist/{packages/primitives → primitives}/icon-button/src/IconButton.js +0 -0
  965. /package/dist/{packages/primitives → primitives}/icon-button/src/IconButton.vue_vue_type_script_setup_true_lang.js +0 -0
  966. /package/dist/{packages/primitives → primitives}/icon-button/src/index.js +0 -0
  967. /package/dist/{packages/primitives → primitives}/indicator/src/Indicator.js +0 -0
  968. /package/dist/{packages/primitives → primitives}/indicator/src/Indicator.vue_vue_type_script_setup_true_lang.js +0 -0
  969. /package/dist/{packages/primitives → primitives}/indicator/src/index.js +0 -0
  970. /package/dist/{packages/primitives → primitives}/inline-error/src/InlineError.js +0 -0
  971. /package/dist/{packages/primitives → primitives}/inline-error/src/InlineError.vue_vue_type_script_setup_true_lang.js +0 -0
  972. /package/dist/{packages/primitives → primitives}/inline-error/src/index.js +0 -0
  973. /package/dist/{packages/primitives → primitives}/kbd/src/Kbd.js +0 -0
  974. /package/dist/{packages/primitives → primitives}/kbd/src/Kbd.vue_vue_type_script_setup_true_lang.js +0 -0
  975. /package/dist/{packages/primitives → primitives}/kbd/src/index.js +0 -0
  976. /package/dist/{packages/primitives → primitives}/link/src/Link.js +0 -0
  977. /package/dist/{packages/primitives → primitives}/link/src/Link.vue_vue_type_script_setup_true_lang.js +0 -0
  978. /package/dist/{packages/primitives → primitives}/link/src/index.js +0 -0
  979. /package/dist/{packages/primitives → primitives}/list/src/List.js +0 -0
  980. /package/dist/{packages/primitives → primitives}/list/src/List.vue_vue_type_script_setup_true_lang.js +0 -0
  981. /package/dist/{packages/primitives → primitives}/list/src/ListItem.js +0 -0
  982. /package/dist/{packages/primitives → primitives}/list/src/index.js +0 -0
  983. /package/dist/{packages/primitives → primitives}/menubar/src/Menubar.js +0 -0
  984. /package/dist/{packages/primitives → primitives}/menubar/src/index.js +0 -0
  985. /package/dist/{packages/primitives → primitives}/number-field/src/NumberField.js +0 -0
  986. /package/dist/{packages/primitives → primitives}/number-field/src/NumberField.vue_vue_type_script_setup_true_lang.js +0 -0
  987. /package/dist/{packages/primitives → primitives}/number-field/src/index.js +0 -0
  988. /package/dist/{packages/primitives → primitives}/otp-input/src/OtpInput.js +0 -0
  989. /package/dist/{packages/primitives → primitives}/otp-input/src/OtpInput.vue_vue_type_script_setup_true_lang.js +0 -0
  990. /package/dist/{packages/primitives → primitives}/otp-input/src/index.js +0 -0
  991. /package/dist/{packages/primitives → primitives}/pagination/src/Pagination.js +0 -0
  992. /package/dist/{packages/primitives → primitives}/pagination/src/Pagination.vue_vue_type_script_setup_true_lang.js +0 -0
  993. /package/dist/{packages/primitives → primitives}/pagination/src/index.js +0 -0
  994. /package/dist/{packages/primitives → primitives}/popover/src/Popover.js +0 -0
  995. /package/dist/{packages/primitives → primitives}/popover/src/Popover.vue_vue_type_script_setup_true_lang.js +0 -0
  996. /package/dist/{packages/primitives → primitives}/popover/src/index.js +0 -0
  997. /package/dist/{packages/primitives → primitives}/progress/src/Progress.js +0 -0
  998. /package/dist/{packages/primitives → primitives}/progress/src/Progress.vue_vue_type_script_setup_true_lang.js +0 -0
  999. /package/dist/{packages/primitives → primitives}/progress/src/index.js +0 -0
  1000. /package/dist/{packages/primitives → primitives}/radial-progress/src/RadialProgress.js +0 -0
  1001. /package/dist/{packages/primitives → primitives}/radial-progress/src/RadialProgress.vue_vue_type_script_setup_true_lang.js +0 -0
  1002. /package/dist/{packages/primitives → primitives}/radial-progress/src/index.js +0 -0
  1003. /package/dist/{packages/primitives → primitives}/radio-group/src/RadioGroup.js +0 -0
  1004. /package/dist/{packages/primitives → primitives}/radio-group/src/RadioGroup.vue_vue_type_script_setup_true_lang.js +0 -0
  1005. /package/dist/{packages/primitives → primitives}/radio-group/src/index.js +0 -0
  1006. /package/dist/{packages/primitives → primitives}/rating/src/Rating.js +0 -0
  1007. /package/dist/{packages/primitives → primitives}/rating/src/Rating.vue_vue_type_script_setup_true_lang.js +0 -0
  1008. /package/dist/{packages/primitives → primitives}/rating/src/index.js +0 -0
  1009. /package/dist/{packages/primitives → primitives}/scroll-area/src/ScrollArea.js +0 -0
  1010. /package/dist/{packages/primitives → primitives}/scroll-area/src/ScrollArea.vue_vue_type_script_setup_true_lang.js +0 -0
  1011. /package/dist/{packages/primitives → primitives}/scroll-area/src/index.js +0 -0
  1012. /package/dist/{packages/primitives → primitives}/segmented-control/src/SegmentedControl.js +0 -0
  1013. /package/dist/{packages/primitives → primitives}/segmented-control/src/index.js +0 -0
  1014. /package/dist/{packages/primitives → primitives}/select/src/Select.js +0 -0
  1015. /package/dist/{packages/primitives → primitives}/select/src/Select.vue_vue_type_script_setup_true_lang.js +0 -0
  1016. /package/dist/{packages/primitives → primitives}/select/src/index.js +0 -0
  1017. /package/dist/{packages/primitives → primitives}/separator/src/Separator.js +0 -0
  1018. /package/dist/{packages/primitives → primitives}/separator/src/Separator.vue_vue_type_script_setup_true_lang.js +0 -0
  1019. /package/dist/{packages/primitives → primitives}/separator/src/index.js +0 -0
  1020. /package/dist/{packages/primitives → primitives}/skeleton/src/Skeleton.js +0 -0
  1021. /package/dist/{packages/primitives → primitives}/skeleton/src/Skeleton.vue_vue_type_script_setup_true_lang.js +0 -0
  1022. /package/dist/{packages/primitives → primitives}/skeleton/src/index.js +0 -0
  1023. /package/dist/{packages/primitives → primitives}/slider/src/Slider.js +0 -0
  1024. /package/dist/{packages/primitives → primitives}/slider/src/Slider.vue_vue_type_script_setup_true_lang.js +0 -0
  1025. /package/dist/{packages/primitives → primitives}/slider/src/index.js +0 -0
  1026. /package/dist/{packages/primitives → primitives}/speed-dial/src/SpeedDial.js +0 -0
  1027. /package/dist/{packages/primitives → primitives}/speed-dial/src/SpeedDial.vue_vue_type_script_setup_true_lang.js +0 -0
  1028. /package/dist/{packages/primitives → primitives}/speed-dial/src/index.js +0 -0
  1029. /package/dist/{packages/primitives → primitives}/spinner/src/Spinner.js +0 -0
  1030. /package/dist/{packages/primitives → primitives}/spinner/src/Spinner.vue_vue_type_script_setup_true_lang.js +0 -0
  1031. /package/dist/{packages/primitives → primitives}/spinner/src/index.js +0 -0
  1032. /package/dist/{packages/primitives → primitives}/stepper/src/Stepper.js +0 -0
  1033. /package/dist/{packages/primitives → primitives}/stepper/src/index.js +0 -0
  1034. /package/dist/{packages/primitives → primitives}/surface/src/Surface.js +0 -0
  1035. /package/dist/{packages/primitives → primitives}/surface/src/Surface.vue_vue_type_script_setup_true_lang.js +0 -0
  1036. /package/dist/{packages/primitives → primitives}/surface/src/index.js +0 -0
  1037. /package/dist/{packages/primitives → primitives}/switch/src/Switch.js +0 -0
  1038. /package/dist/{packages/primitives → primitives}/switch/src/index.js +0 -0
  1039. /package/dist/{packages/primitives → primitives}/table/src/Table.js +0 -0
  1040. /package/dist/{packages/primitives → primitives}/table/src/Table.vue_vue_type_script_setup_true_lang.js +0 -0
  1041. /package/dist/{packages/primitives → primitives}/table/src/TableCell.js +0 -0
  1042. /package/dist/{packages/primitives → primitives}/table/src/TableCell.vue_vue_type_script_setup_true_lang.js +0 -0
  1043. /package/dist/{packages/primitives → primitives}/table/src/TableHead.js +0 -0
  1044. /package/dist/{packages/primitives → primitives}/table/src/TableHead.vue_vue_type_script_setup_true_lang.js +0 -0
  1045. /package/dist/{packages/primitives → primitives}/table/src/TableRow.js +0 -0
  1046. /package/dist/{packages/primitives → primitives}/table/src/TableRow.vue_vue_type_script_setup_true_lang.js +0 -0
  1047. /package/dist/{packages/primitives → primitives}/tabs/src/Tabs.js +0 -0
  1048. /package/dist/{packages/primitives → primitives}/tabs/src/Tabs.vue_vue_type_script_setup_true_lang.js +0 -0
  1049. /package/dist/{packages/primitives → primitives}/tabs/src/index.js +0 -0
  1050. /package/dist/{packages/primitives → primitives}/tags-input/src/TagsInput.js +0 -0
  1051. /package/dist/{packages/primitives → primitives}/tags-input/src/TagsInput.vue_vue_type_script_setup_true_lang.js +0 -0
  1052. /package/dist/{packages/primitives → primitives}/tags-input/src/index.js +0 -0
  1053. /package/dist/{packages/primitives → primitives}/text-field/src/TextField.js +0 -0
  1054. /package/dist/{packages/primitives → primitives}/text-field/src/TextField.vue_vue_type_script_setup_true_lang.js +0 -0
  1055. /package/dist/{packages/primitives → primitives}/text-field/src/index.js +0 -0
  1056. /package/dist/{packages/primitives → primitives}/textarea/src/Textarea.js +0 -0
  1057. /package/dist/{packages/primitives → primitives}/textarea/src/Textarea.vue_vue_type_script_setup_true_lang.js +0 -0
  1058. /package/dist/{packages/primitives → primitives}/textarea/src/index.js +0 -0
  1059. /package/dist/{packages/primitives → primitives}/time-picker/src/TimePicker.js +0 -0
  1060. /package/dist/{packages/primitives → primitives}/time-picker/src/index.js +0 -0
  1061. /package/dist/{packages/primitives → primitives}/timeline/src/Timeline.js +0 -0
  1062. /package/dist/{packages/primitives → primitives}/timeline/src/Timeline.vue_vue_type_script_setup_true_lang.js +0 -0
  1063. /package/dist/{packages/primitives → primitives}/timeline/src/TimelineItem.js +0 -0
  1064. /package/dist/{packages/primitives → primitives}/timeline/src/TimelineItem.vue_vue_type_script_setup_true_lang.js +0 -0
  1065. /package/dist/{packages/primitives → primitives}/toast/src/Toast.js +0 -0
  1066. /package/dist/{packages/primitives → primitives}/toast/src/Toast.vue_vue_type_script_setup_true_lang.js +0 -0
  1067. /package/dist/{packages/primitives → primitives}/toast/src/ToastItem.js +0 -0
  1068. /package/dist/{packages/primitives → primitives}/toast/src/index.js +0 -0
  1069. /package/dist/{packages/primitives → primitives}/tooltip/src/Tooltip.js +0 -0
  1070. /package/dist/{packages/primitives → primitives}/tooltip/src/Tooltip.vue_vue_type_script_setup_true_lang.js +0 -0
  1071. /package/dist/{packages/primitives → primitives}/tooltip/src/index.js +0 -0
  1072. /package/dist/{packages/primitives → primitives}/window-controls/src/WindowControls.js +0 -0
  1073. /package/dist/{packages/primitives → primitives}/window-controls/src/index.js +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Chip.js","names":[],"sources":["../../../../packages/primitives/chip/src/Chip.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/**\n * The same eight names Badge carries, deliberately — a chip and a badge sitting\n * in one row are the same object in two moods, so `success` has to mean the\n * same green in both. A ninth name here would be a second vocabulary for one\n * palette.\n */\nexport type ChipVariant =\n \"neutral\" | \"outline\" | \"primary\" | \"success\" | \"warning\" | \"info\" | \"destructive\" | \"accent\";\n\n/**\n * Two heights off the shared control scale (the text input's `sm` and `md`), so\n * a row of chips above a field lines up with it. There is no `lg`: a chip is a\n * token, and one big enough to need the 44px step is a Button.\n */\nexport type ChipSize = \"sm\" | \"md\";\n\n/**\n * The container. It is the coloured pill, and it is deliberately not the\n * interactive node — see the docblock below for why that separation is the\n * whole component.\n *\n * Selection is a state the *edges* deepen: the hue-carrying variants draw a\n * stronger border around the wash they already sit in, the hueless ones swap\n * their fill for the primary wash. It is never any one signal alone that says\n * so — every selected chip also carries `aria-pressed=\"true\"` and a check\n * glyph, which is what keeps the state legible to a reader who cannot resolve\n * a deepened edge from a resting one.\n */\nexport const chipVariants = cva(\n [\n \"group inline-flex max-w-full items-center rounded-full border align-middle font-medium\",\n \"transition-[background-color,border-color,color] duration-fast ease-out\",\n // No `opacity` here, and that is the point. `data-[disabled]:opacity-50`\n // dimmed the pill *and* its label together, taking a 5.01:1 label down to\n // 2.78:1 against its own fill — halving the alpha more than halves the\n // contrast. Unavailability is painted in measured colours instead: the\n // fill and border below, and `disabledText` on the label and the glyph\n // beside it.\n \"data-[disabled]:cursor-not-allowed\",\n ],\n {\n // `satisfies` keeps the two halves honest: the union above is the name a\n // consumer imports and the documentation prints, the map below is the\n // classes. Adding a member to one and not the other stops compiling.\n variants: {\n variant: {\n // The two hueless variants take the primary wash when selected —\n // `--color-primary-muted` is the repository's selected/active fill, the\n // one Select's checked row already uses, so a chosen filter reads as a\n // human decision rather than as a new colour invented here.\n neutral:\n \"border-transparent bg-subtle text-subtle-foreground data-[selected]:border-primary/40 data-[selected]:bg-primary-muted data-[selected]:text-primary-text\",\n outline:\n \"border-border bg-transparent text-muted-foreground data-[selected]:border-primary/40 data-[selected]:bg-primary-muted data-[selected]:text-primary-text\",\n // The hue-carrying variants deepen their own hue instead of jumping to\n // the primary: a reader picked this chip *because* it is the destructive\n // one, and swapping its colour on selection would throw that away.\n // The tinted washes use the opaque `*-muted` tokens, not an alpha of\n // the base hue: `bg-*-/12` composites against the surface behind it, so\n // a chip renders at 4.46:1 on `bg-card` and differently on `bg-sunken`\n // — under the AA floor and inconsistent. `*-muted` is mixed to hold\n // ≥4.5:1 against its own `*-text` in both themes (see theme.css),\n // which is what these variants were named for.\n //\n // Selection deepens the border, not the fill: a `data-[selected]:bg-*-/20`\n // over the wash drops the text to ~4.2:1 in light mode (success, warning,\n // info, destructive), below the same floor the unselected state holds.\n // `*-muted` is the theme's \"selected/active fill\" anyway, so the state is\n // carried by the deeper border, the check glyph and `aria-pressed` — the\n // signals the docblock below already names as what makes selection legible.\n primary:\n \"border-transparent bg-primary-muted text-primary-text data-[selected]:border-primary/45\",\n success:\n \"border-transparent bg-success-muted text-success-text data-[selected]:border-success/45\",\n // `-text`, matching Badge and the other functional siblings: the wash\n // is mixed to hold contrast against the `*-text` rung in both themes,\n // not against the base hue.\n warning:\n \"border-transparent bg-warning-muted text-warning-text data-[selected]:border-warning/45\",\n info: \"border-transparent bg-info-muted text-info-text data-[selected]:border-info/45\",\n destructive:\n \"border-transparent bg-destructive-muted text-destructive-text data-[selected]:border-destructive/45\",\n accent:\n \"border-accent/40 bg-accent-muted text-accent-text data-[selected]:border-accent/70\",\n } satisfies Record<ChipVariant, string>,\n size: {\n sm: \"h-8 text-xs\",\n md: \"h-9 text-sm\",\n } satisfies Record<ChipSize, string>,\n },\n defaultVariants: { variant: \"neutral\", size: \"md\" },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Check, X } from \"@lucide/vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\n\n/**\n * Chip — an interactive token: a filter that switches on, an entity that can be\n * dismissed, a recipient sitting in a picker.\n *\n * The line against Badge is the one worth knowing, because the two look almost\n * identical: **Badge is a status label a reader only looks at; Chip is a\n * control a reader acts on.** A Badge that gained a click handler would be a\n * Chip, and a Chip nobody can toggle or dismiss is a Badge wearing a button's\n * clothes — it takes a Tab stop and announces itself as pressable while doing\n * nothing. Reach for Button when the token *is* the action rather than a\n * standing state, and for SegmentedControl when exactly one of a small set must\n * be chosen; a row of chips is many-of-many, and none-of-them is a valid answer.\n *\n * The structure is the component. A chip that both toggles and dismisses has\n * two controls, and they are **siblings inside a non-interactive container** —\n * never a dismiss `<button>` nested inside a toggle `<button>`. Nested buttons\n * are invalid HTML: the parser reparents them, and screen readers disagree\n * about which one they are on and what a press means. So the pill is a `<span>`\n * that paints, and everything pressable is a child of it.\n *\n * Both controls stay on the natural Tab order rather than roving. They are two\n * different actions on one object, not N instances of one control, and a reader\n * who tabbed to the chip has to be able to reach \"remove\" without guessing an\n * arrow key.\n */\nconst props = withDefaults(\n defineProps<{\n /** Whether the chip is switched on. Binding it is what makes the chip a toggle — leave it unset for a chip that is only dismissable, and the label renders as inert text instead of a press target. */\n selected?: boolean | undefined;\n /** Renders a dismiss control beside the label, as a sibling of the toggle rather than inside it. */\n removable?: boolean;\n /** The accessible name of the dismiss control. Localise it, or qualify it — \"Remove Ana Duarte\" reads far better in a list of recipients. */\n removeLabel?: string;\n /** Unavailable: drains the pill to a neutral fill, mutes the label, and makes both controls inert to pointer and keyboard. */\n disabled?: boolean;\n /** Which status or meta the token carries. The names and colours are Badge's, so a chip and a badge never disagree. */\n variant?: ChipVariant;\n /** Chip height, off the shared control scale so a row of chips lines up with the field above it. */\n size?: ChipSize;\n }>(),\n {\n // Not `false`. `undefined` is the signal that this chip is not a toggle at\n // all, and Vue casts an absent Boolean prop to `false` unless a default\n // says otherwise — without this line every chip would claim to be a toggle\n // that is switched off, and a dismiss-only chip would grow a dead Tab stop.\n selected: undefined,\n removable: false,\n removeLabel: \"Remove\",\n disabled: false,\n variant: \"neutral\",\n size: \"md\",\n },\n);\n\nconst emit = defineEmits<{\n /** The flipped selection. The chip does not update itself: a filter chip's state is the query it stands for, and a chip that switched on locally would keep claiming a result set the host never fetched. */\n \"update:selected\": [value: boolean];\n /** The dismiss control was activated. Removing the chip from the list is the host's to do. */\n remove: [];\n}>();\n\nconst toggleable = computed(() => props.selected !== undefined);\n\n// The label's horizontal padding, shared by both branches below so the pill is\n// the same width whether or not it is pressable. The dismiss control supplies\n// its own trailing room, so the label gives its right side back when one is\n// present.\nconst labelPad = computed(() =>\n cn(props.size === \"sm\" ? \"px-2.5\" : \"px-3\", props.removable && \"pr-1\"),\n);\n\n// Springy transform, steady colour — the same split Button and Checkbox use, so\n// a chip press feels like every other press in the library.\nconst pressStyle =\n \"transition: transform var(--duration-fast) var(--ease-spring), background-color var(--duration-fast) var(--ease-out);\";\n\n// The unavailable label colour, and it belongs on the label rather than on the\n// pill around it. A colour set on the container is only *inherited* here, and\n// the container already carries `data-[selected]:text-primary-text` — an attribute\n// selector no plain class on the same element outranks. On the label itself it\n// is a declaration rather than an inheritance, so it wins whatever the pill\n// resolved to: 4.67:1 over the drained `--color-muted` fill, 4.77:1 over the\n// primary wash a selected chip keeps.\nconst disabledText = \"group-data-[disabled]:text-muted-foreground\";\n\n// Both inner controls are surfaces *inside* a 32px pill, so the standard\n// outward `outline-offset-2` would draw the toggle's ring straight through the\n// dismiss control sitting 4px to its right, and vice versa. Inset instead —\n// the ring lands just inside the pill's own border, which is where the eye\n// already is. WindowControls takes the same offset for the same reason.\nconst focusRing =\n \"focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo\";\n\n// Everything a host passes lands on the container: it is the node with an\n// identity (a data-testid, a key in a list), while the two controls inside it\n// are named by their own content and by `removeLabel`. `class` is pulled out of\n// that spread and merged through `cn()` instead — Vue's own class merge only\n// concatenates, so a caller's `max-w-32` would win or lose against the pill's\n// own utilities depending on Tailwind's emission order rather than on intent.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: containerAttrs } = useSplitAttrs();\n</script>\n\n<template>\n <span\n v-bind=\"containerAttrs\"\n :data-selected=\"selected || undefined\"\n :data-disabled=\"disabled || undefined\"\n :class=\"\n cn(\n chipVariants({ variant, size }),\n // Drained to the neutral well, with the hairline the coloured variants\n // hide: an unavailable chip gives up its hue rather than its legibility.\n // A *selected* one keeps the primary wash — `data-[selected]:bg-primary-muted`\n // outranks a plain class — which is right: switched-on is information,\n // and the label is muted over either fill.\n //\n // `border-border` and not the strong weight it used to take.\n // `theme.css` reserves the strong hairline for a block that must\n // *assert* its edge, which is the opposite of what this state says, and\n // the lighter rim is the same one every other unavailable control in the\n // library slackens to — so a disabled chip in a row of disabled\n // controls is one treatment rather than a second.\n disabled && 'border-border bg-muted',\n removable && 'pr-1',\n attrs.class as string,\n )\n \"\n >\n <button\n v-if=\"toggleable\"\n type=\"button\"\n :aria-pressed=\"selected\"\n :disabled=\"disabled\"\n :style=\"pressStyle\"\n :class=\"\n cn(\n 'inline-flex h-full min-w-0 select-none items-center gap-1 rounded-full',\n labelPad,\n // A neutral darkening rather than a token fill: the pill underneath\n // can be any of eight colours, and a hover state is not an action\n // colour.\n 'hover:bg-foreground/5 active:scale-press',\n focusRing,\n 'disabled:pointer-events-none',\n )\n \"\n @click=\"emit('update:selected', !selected)\"\n >\n <!-- The check is the half of the selected signal that survives a reader\n who cannot tell a 12% wash from a 20% one; `aria-pressed` is the\n other half. It collapses its own width rather than unmounting, so\n the pill grows into the glyph instead of snapping. -->\n <span\n aria-hidden=\"true\"\n class=\"inline-flex w-0 shrink-0 items-center overflow-hidden opacity-0 transition-[width,opacity] duration-fast ease-spring group-data-[selected]:w-4 group-data-[selected]:opacity-100\"\n >\n <Check class=\"h-3.5 w-3.5 shrink-0\" />\n </span>\n <span :class=\"cn('truncate', disabledText)\">\n <!-- @slot The chip's label. Keep it to a word or two — a token that needs a sentence is a row, not a chip. -->\n <slot />\n </span>\n </button>\n <span v-else :class=\"cn('inline-flex min-w-0 items-center', labelPad)\">\n <span :class=\"cn('truncate', disabledText)\"><slot /></span>\n </span>\n\n <!-- A sibling of the toggle, never a child of it. 24px square is the floor\n WCAG 2.2 SC 2.5.8 sets for a target, which is what decides the size\n here rather than the glyph's own 14px. -->\n <button\n v-if=\"removable\"\n type=\"button\"\n :aria-label=\"removeLabel\"\n :disabled=\"disabled\"\n :style=\"pressStyle\"\n :class=\"\n cn(\n 'inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full',\n // Not `hover:bg-subtle`, the usual neutral well: it is opaque, and\n // over a coloured pill it punches a grey hole through the fill\n // instead of darkening it.\n 'hover:bg-foreground/10 active:scale-90',\n focusRing,\n disabledText,\n 'disabled:pointer-events-none',\n )\n \"\n @click=\"emit('remove')\"\n >\n <X class=\"h-3.5 w-3.5\" />\n </button>\n </span>\n</template>\n"],"mappings":""}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Chip.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../packages/primitives/chip/src/Chip.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/**\n * The same eight names Badge carries, deliberately — a chip and a badge sitting\n * in one row are the same object in two moods, so `success` has to mean the\n * same green in both. A ninth name here would be a second vocabulary for one\n * palette.\n */\nexport type ChipVariant =\n \"neutral\" | \"outline\" | \"primary\" | \"success\" | \"warning\" | \"info\" | \"destructive\" | \"accent\";\n\n/**\n * Two heights off the shared control scale (the text input's `sm` and `md`), so\n * a row of chips above a field lines up with it. There is no `lg`: a chip is a\n * token, and one big enough to need the 44px step is a Button.\n */\nexport type ChipSize = \"sm\" | \"md\";\n\n/**\n * The container. It is the coloured pill, and it is deliberately not the\n * interactive node — see the docblock below for why that separation is the\n * whole component.\n *\n * Selection is a state the *edges* deepen: the hue-carrying variants draw a\n * stronger border around the wash they already sit in, the hueless ones swap\n * their fill for the primary wash. It is never any one signal alone that says\n * so — every selected chip also carries `aria-pressed=\"true\"` and a check\n * glyph, which is what keeps the state legible to a reader who cannot resolve\n * a deepened edge from a resting one.\n */\nexport const chipVariants = cva(\n [\n \"group inline-flex max-w-full items-center rounded-full border align-middle font-medium\",\n \"transition-[background-color,border-color,color] duration-fast ease-out\",\n // No `opacity` here, and that is the point. `data-[disabled]:opacity-50`\n // dimmed the pill *and* its label together, taking a 5.01:1 label down to\n // 2.78:1 against its own fill — halving the alpha more than halves the\n // contrast. Unavailability is painted in measured colours instead: the\n // fill and border below, and `disabledText` on the label and the glyph\n // beside it.\n \"data-[disabled]:cursor-not-allowed\",\n ],\n {\n // `satisfies` keeps the two halves honest: the union above is the name a\n // consumer imports and the documentation prints, the map below is the\n // classes. Adding a member to one and not the other stops compiling.\n variants: {\n variant: {\n // The two hueless variants take the primary wash when selected —\n // `--color-primary-muted` is the repository's selected/active fill, the\n // one Select's checked row already uses, so a chosen filter reads as a\n // human decision rather than as a new colour invented here.\n neutral:\n \"border-transparent bg-subtle text-subtle-foreground data-[selected]:border-primary/40 data-[selected]:bg-primary-muted data-[selected]:text-primary-text\",\n outline:\n \"border-border bg-transparent text-muted-foreground data-[selected]:border-primary/40 data-[selected]:bg-primary-muted data-[selected]:text-primary-text\",\n // The hue-carrying variants deepen their own hue instead of jumping to\n // the primary: a reader picked this chip *because* it is the destructive\n // one, and swapping its colour on selection would throw that away.\n // The tinted washes use the opaque `*-muted` tokens, not an alpha of\n // the base hue: `bg-*-/12` composites against the surface behind it, so\n // a chip renders at 4.46:1 on `bg-card` and differently on `bg-sunken`\n // — under the AA floor and inconsistent. `*-muted` is mixed to hold\n // ≥4.5:1 against its own `*-text` in both themes (see theme.css),\n // which is what these variants were named for.\n //\n // Selection deepens the border, not the fill: a `data-[selected]:bg-*-/20`\n // over the wash drops the text to ~4.2:1 in light mode (success, warning,\n // info, destructive), below the same floor the unselected state holds.\n // `*-muted` is the theme's \"selected/active fill\" anyway, so the state is\n // carried by the deeper border, the check glyph and `aria-pressed` — the\n // signals the docblock below already names as what makes selection legible.\n primary:\n \"border-transparent bg-primary-muted text-primary-text data-[selected]:border-primary/45\",\n success:\n \"border-transparent bg-success-muted text-success-text data-[selected]:border-success/45\",\n // `-text`, matching Badge and the other functional siblings: the wash\n // is mixed to hold contrast against the `*-text` rung in both themes,\n // not against the base hue.\n warning:\n \"border-transparent bg-warning-muted text-warning-text data-[selected]:border-warning/45\",\n info: \"border-transparent bg-info-muted text-info-text data-[selected]:border-info/45\",\n destructive:\n \"border-transparent bg-destructive-muted text-destructive-text data-[selected]:border-destructive/45\",\n accent:\n \"border-accent/40 bg-accent-muted text-accent-text data-[selected]:border-accent/70\",\n } satisfies Record<ChipVariant, string>,\n size: {\n sm: \"h-8 text-xs\",\n md: \"h-9 text-sm\",\n } satisfies Record<ChipSize, string>,\n },\n defaultVariants: { variant: \"neutral\", size: \"md\" },\n },\n);\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { Check, X } from \"@lucide/vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\n\n/**\n * Chip — an interactive token: a filter that switches on, an entity that can be\n * dismissed, a recipient sitting in a picker.\n *\n * The line against Badge is the one worth knowing, because the two look almost\n * identical: **Badge is a status label a reader only looks at; Chip is a\n * control a reader acts on.** A Badge that gained a click handler would be a\n * Chip, and a Chip nobody can toggle or dismiss is a Badge wearing a button's\n * clothes — it takes a Tab stop and announces itself as pressable while doing\n * nothing. Reach for Button when the token *is* the action rather than a\n * standing state, and for SegmentedControl when exactly one of a small set must\n * be chosen; a row of chips is many-of-many, and none-of-them is a valid answer.\n *\n * The structure is the component. A chip that both toggles and dismisses has\n * two controls, and they are **siblings inside a non-interactive container** —\n * never a dismiss `<button>` nested inside a toggle `<button>`. Nested buttons\n * are invalid HTML: the parser reparents them, and screen readers disagree\n * about which one they are on and what a press means. So the pill is a `<span>`\n * that paints, and everything pressable is a child of it.\n *\n * Both controls stay on the natural Tab order rather than roving. They are two\n * different actions on one object, not N instances of one control, and a reader\n * who tabbed to the chip has to be able to reach \"remove\" without guessing an\n * arrow key.\n */\nconst props = withDefaults(\n defineProps<{\n /** Whether the chip is switched on. Binding it is what makes the chip a toggle — leave it unset for a chip that is only dismissable, and the label renders as inert text instead of a press target. */\n selected?: boolean | undefined;\n /** Renders a dismiss control beside the label, as a sibling of the toggle rather than inside it. */\n removable?: boolean;\n /** The accessible name of the dismiss control. Localise it, or qualify it — \"Remove Ana Duarte\" reads far better in a list of recipients. */\n removeLabel?: string;\n /** Unavailable: drains the pill to a neutral fill, mutes the label, and makes both controls inert to pointer and keyboard. */\n disabled?: boolean;\n /** Which status or meta the token carries. The names and colours are Badge's, so a chip and a badge never disagree. */\n variant?: ChipVariant;\n /** Chip height, off the shared control scale so a row of chips lines up with the field above it. */\n size?: ChipSize;\n }>(),\n {\n // Not `false`. `undefined` is the signal that this chip is not a toggle at\n // all, and Vue casts an absent Boolean prop to `false` unless a default\n // says otherwise — without this line every chip would claim to be a toggle\n // that is switched off, and a dismiss-only chip would grow a dead Tab stop.\n selected: undefined,\n removable: false,\n removeLabel: \"Remove\",\n disabled: false,\n variant: \"neutral\",\n size: \"md\",\n },\n);\n\nconst emit = defineEmits<{\n /** The flipped selection. The chip does not update itself: a filter chip's state is the query it stands for, and a chip that switched on locally would keep claiming a result set the host never fetched. */\n \"update:selected\": [value: boolean];\n /** The dismiss control was activated. Removing the chip from the list is the host's to do. */\n remove: [];\n}>();\n\nconst toggleable = computed(() => props.selected !== undefined);\n\n// The label's horizontal padding, shared by both branches below so the pill is\n// the same width whether or not it is pressable. The dismiss control supplies\n// its own trailing room, so the label gives its right side back when one is\n// present.\nconst labelPad = computed(() =>\n cn(props.size === \"sm\" ? \"px-2.5\" : \"px-3\", props.removable && \"pr-1\"),\n);\n\n// Springy transform, steady colour — the same split Button and Checkbox use, so\n// a chip press feels like every other press in the library.\nconst pressStyle =\n \"transition: transform var(--duration-fast) var(--ease-spring), background-color var(--duration-fast) var(--ease-out);\";\n\n// The unavailable label colour, and it belongs on the label rather than on the\n// pill around it. A colour set on the container is only *inherited* here, and\n// the container already carries `data-[selected]:text-primary-text` — an attribute\n// selector no plain class on the same element outranks. On the label itself it\n// is a declaration rather than an inheritance, so it wins whatever the pill\n// resolved to: 4.67:1 over the drained `--color-muted` fill, 4.77:1 over the\n// primary wash a selected chip keeps.\nconst disabledText = \"group-data-[disabled]:text-muted-foreground\";\n\n// Both inner controls are surfaces *inside* a 32px pill, so the standard\n// outward `outline-offset-2` would draw the toggle's ring straight through the\n// dismiss control sitting 4px to its right, and vice versa. Inset instead —\n// the ring lands just inside the pill's own border, which is where the eye\n// already is. WindowControls takes the same offset for the same reason.\nconst focusRing =\n \"focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo\";\n\n// Everything a host passes lands on the container: it is the node with an\n// identity (a data-testid, a key in a list), while the two controls inside it\n// are named by their own content and by `removeLabel`. `class` is pulled out of\n// that spread and merged through `cn()` instead — Vue's own class merge only\n// concatenates, so a caller's `max-w-32` would win or lose against the pill's\n// own utilities depending on Tailwind's emission order rather than on intent.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: containerAttrs } = useSplitAttrs();\n</script>\n\n<template>\n <span\n v-bind=\"containerAttrs\"\n :data-selected=\"selected || undefined\"\n :data-disabled=\"disabled || undefined\"\n :class=\"\n cn(\n chipVariants({ variant, size }),\n // Drained to the neutral well, with the hairline the coloured variants\n // hide: an unavailable chip gives up its hue rather than its legibility.\n // A *selected* one keeps the primary wash — `data-[selected]:bg-primary-muted`\n // outranks a plain class — which is right: switched-on is information,\n // and the label is muted over either fill.\n //\n // `border-border` and not the strong weight it used to take.\n // `theme.css` reserves the strong hairline for a block that must\n // *assert* its edge, which is the opposite of what this state says, and\n // the lighter rim is the same one every other unavailable control in the\n // library slackens to — so a disabled chip in a row of disabled\n // controls is one treatment rather than a second.\n disabled && 'border-border bg-muted',\n removable && 'pr-1',\n attrs.class as string,\n )\n \"\n >\n <button\n v-if=\"toggleable\"\n type=\"button\"\n :aria-pressed=\"selected\"\n :disabled=\"disabled\"\n :style=\"pressStyle\"\n :class=\"\n cn(\n 'inline-flex h-full min-w-0 select-none items-center gap-1 rounded-full',\n labelPad,\n // A neutral darkening rather than a token fill: the pill underneath\n // can be any of eight colours, and a hover state is not an action\n // colour.\n 'hover:bg-foreground/5 active:scale-press',\n focusRing,\n 'disabled:pointer-events-none',\n )\n \"\n @click=\"emit('update:selected', !selected)\"\n >\n <!-- The check is the half of the selected signal that survives a reader\n who cannot tell a 12% wash from a 20% one; `aria-pressed` is the\n other half. It collapses its own width rather than unmounting, so\n the pill grows into the glyph instead of snapping. -->\n <span\n aria-hidden=\"true\"\n class=\"inline-flex w-0 shrink-0 items-center overflow-hidden opacity-0 transition-[width,opacity] duration-fast ease-spring group-data-[selected]:w-4 group-data-[selected]:opacity-100\"\n >\n <Check class=\"h-3.5 w-3.5 shrink-0\" />\n </span>\n <span :class=\"cn('truncate', disabledText)\">\n <!-- @slot The chip's label. Keep it to a word or two — a token that needs a sentence is a row, not a chip. -->\n <slot />\n </span>\n </button>\n <span v-else :class=\"cn('inline-flex min-w-0 items-center', labelPad)\">\n <span :class=\"cn('truncate', disabledText)\"><slot /></span>\n </span>\n\n <!-- A sibling of the toggle, never a child of it. 24px square is the floor\n WCAG 2.2 SC 2.5.8 sets for a target, which is what decides the size\n here rather than the glyph's own 14px. -->\n <button\n v-if=\"removable\"\n type=\"button\"\n :aria-label=\"removeLabel\"\n :disabled=\"disabled\"\n :style=\"pressStyle\"\n :class=\"\n cn(\n 'inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full',\n // Not `hover:bg-subtle`, the usual neutral well: it is opaque, and\n // over a coloured pill it punches a grey hole through the fill\n // instead of darkening it.\n 'hover:bg-foreground/10 active:scale-90',\n focusRing,\n disabledText,\n 'disabled:pointer-events-none',\n )\n \"\n @click=\"emit('remove')\"\n >\n <X class=\"h-3.5 w-3.5\" />\n </button>\n </span>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,IAAa,eAAe,IAC1B;CACE;CACA;CAOA;AACF,GACA;CAIE,UAAU;EACR,SAAS;GAKP,SACE;GACF,SACE;GAiBF,SACE;GACF,SACE;GAIF,SACE;GACF,MAAM;GACN,aACE;GACF,QACE;EACJ;EACA,MAAM;GACJ,IAAI;GACJ,IAAI;EACN;CACF;CACA,iBAAiB;EAAE,SAAS;EAAW,MAAM;CAAK;AACpD,CACF;;;;;;;;;;;;;;;;;;;;;;;EAkCA,MAAM,QAAQ;EA6Bd,MAAM,OAAO;EAOb,MAAM,aAAa,eAAe,MAAM,aAAa,KAAA,CAAS;EAM9D,MAAM,WAAW,eACf,GAAG,MAAM,SAAS,OAAO,WAAW,QAAQ,MAAM,aAAa,MAAM,CACvE;EAIA,MAAM,aACJ;EASF,MAAM,eAAe;EAOrB,MAAM,YACJ;EASF,MAAM,EAAE,OAAO,MAAM,mBAAmB,cAAc;;GAIpD,OAAA,UAAA,GAAA,mBAyFO,QAzFP,WACU,MAwFH,cAAA,GAxFiB;IACrB,iBAAe,QAAA,YAAY,KAAA;IAC3B,iBAAe,QAAA,YAAY,KAAA;IAC3B,OAAc,MAAA,EAAA,CAAE,CAAU,MAAA,YAAA,CAAY,CAAA;KAAA,SAAG,QAAA;KAAO,MAAE,QAAA;IAAI,CAAA,GAA60B,QAAA,YAAQ,0BAAsC,QAAA,aAAS,QAAoB,MAAA,KAAA,CAAK,CAAC,KAAA;GAsB78B,CAAA,GAAA,CAAA,WAAA,SADR,UAAA,GAAA,mBAkCS,UAAA;;IAhCP,MAAK;IACJ,gBAAc,QAAA;IACd,UAAU,QAAA;IACV,OAAO;IACP,OAAK,eAAW,MAAA,EAAA,CAAE,CAAA,0EAAgG,SAAA,OAAA,4CAA2P,WAAA,8BAAA,CAAA;IAY7W,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,mBAAA,CAAqB,QAAA,QAAQ;GAMzC,GAAA,CAAA,mBAKO,QALP,YAKO,CADL,YAAsC,MAAA,KAAA,GAAA,EAA/B,OAAM,uBAAsB,CAAA,CAAA,CAAA,GAErC,mBAGO,QAAA,EAHA,OAAK,eAAE,MAAA,EAAA,CAAE,CAAA,YAAa,YAAY,CAAA,EAAA,GAAA,CAEvC,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,IAAA,UAAA,MAGZ,UAAA,GAAA,mBAEO,QAAA;;IAFO,OAAK,eAAE,MAAA,EAAA,CAAE,CAAA,oCAAqC,SAAA,KAAQ,CAAA;GAClE,GAAA,CAAA,mBAA2D,QAAA,EAApD,OAAK,eAAE,MAAA,EAAA,CAAE,CAAA,YAAa,YAAY,CAAA,EAAA,GAAA,CAAG,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,CAAA,IAO9C,QAAA,aADR,UAAA,GAAA,mBAqBS,UAAA;;IAnBP,MAAK;IACJ,cAAY,QAAA;IACZ,UAAU,QAAA;IACV,OAAO;IACP,OAAK,eAAW,MAAA,EAAA,CAAE,CAAA,yEAAA,0CAAiV,WAAqB,cAAA,8BAAA,CAAA;IAYxX,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,QAAA;GAEZ,GAAA,CAAA,YAAyB,MAAA,CAAA,GAAA,EAAtB,OAAM,cAAa,CAAA,CAAA,GAAA,IAAA,UAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,IAAA,UAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Collapse.js","names":[],"sources":["../../../../packages/primitives/collapse/src/Collapse.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Collapse — one disclosure: a trigger that shows and hides a single region\n * of content. The generic primitive under Accordion's row-group; the state\n * machinery is Reka's Collapsible, so controlled and uncontrolled use,\n * aria-expanded/aria-controls wiring and rapid open/close are all owned\n * there rather than reimplemented here.\n *\n * Expansion animates on the shared height pair (`--animate-expand` /\n * `--animate-collapse`) keyed to Reka's measured\n * `--reka-collapsible-content-height`; padding lives on an inner wrapper\n * because a padded outer box would pop at both ends of the animation while\n * its height interpolated.\n */\n</script>\n\n<script setup lang=\"ts\">\nimport { ChevronDown } from \"@lucide/vue\";\nimport { CollapsibleContent, CollapsibleRoot, CollapsibleTrigger } from \"reka-ui\";\nimport { cn, optional } from \"@ecoma-io/loom-core\";\nimport { useId } from \"vue\";\n\nwithDefaults(\n defineProps<{\n /**\n * Controls visibility; pair with `v-model:open`. Omit it and the collapse\n * owns its own state, seeded by `defaultOpen`.\n */\n open?: boolean | undefined;\n /** The uncontrolled starting state. */\n defaultOpen?: boolean;\n /** Unavailable rather than hidden: the trigger stays put and inert. */\n disabled?: boolean;\n }>(),\n {\n // `undefined` is the uncontrolled state, and only an explicit default\n // keeps it reachable past Vue's Boolean casting.\n open: undefined,\n defaultOpen: false,\n disabled: false,\n },\n);\n\ndefineEmits<{ \"update:open\": [value: boolean] }>();\n\n// Reka leaves the trigger's aria-controls pointing at an id its Content only\n// registers non-reactively, so a closed-first render ships an empty IDREF.\n// Both halves get explicit ids here instead; fallthrough attributes merge\n// after Reka's own, which is the same mechanism AlertDialog uses to clear\n// its dangling describedby.\nconst triggerId = useId();\nconst contentId = useId();\n</script>\n\n<template>\n <CollapsibleRoot\n v-slot=\"{ open: state }\"\n v-bind=\"optional({ open })\"\n :default-open=\"defaultOpen\"\n :disabled=\"disabled\"\n :unmount-on-hide=\"false\"\n @update:open=\"$emit('update:open', $event)\"\n >\n <CollapsibleTrigger\n :id=\"triggerId\"\n :aria-controls=\"contentId\"\n :class=\"\n cn(\n 'group flex w-full items-center justify-between gap-3 rounded-md px-4 py-3 text-left text-sm font-medium',\n 'transition-colors duration-fast ease-out hover:bg-subtle',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo',\n 'disabled:pointer-events-none disabled:bg-transparent disabled:text-muted-foreground',\n )\n \"\n >\n <!-- @slot The control's visible face, inside a real `<button>` carrying\n aria-expanded/aria-controls and the canonical focus ring. `open`\n mirrors the real state, controlled or not. -->\n <slot name=\"trigger\" :open=\"state\" />\n <ChevronDown\n class=\"h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-fast ease-out group-data-[state=open]:rotate-180\"\n aria-hidden=\"true\"\n />\n </CollapsibleTrigger>\n <!-- Mounted even while closed: the region id in aria-controls has to\n resolve for a screen reader before the first expansion, and a\n persistent element is what lets the collapse animation actually play\n instead of being unmounted mid-frame. Reka conceals the closed\n region with hidden=\"until-found\". -->\n <CollapsibleContent\n data-loom-collapse=\"\"\n class=\"overflow-hidden data-[state=open]:animate-expand data-[state=closed]:animate-collapse\"\n >\n <!-- The animated box carries no padding of its own: interpolating\n height around fixed padding pops at both ends of the film. This\n inner div also carries the id the trigger references: Reka writes\n its own content id after any we pass, so the reference lands here\n where it actually resolves. -->\n <div :id=\"contentId\" class=\"px-4 pb-4\">\n <!-- @slot The region's content. Nested collapses work unchanged —\n each owns its own region. -->\n <slot />\n </div>\n </CollapsibleContent>\n </CollapsibleRoot>\n</template>\n"],"mappings":""}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Collapse.vue_vue_type_script_setup_true_lang.js","names":["$emit"],"sources":["../../../../packages/primitives/collapse/src/Collapse.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Collapse — one disclosure: a trigger that shows and hides a single region\n * of content. The generic primitive under Accordion's row-group; the state\n * machinery is Reka's Collapsible, so controlled and uncontrolled use,\n * aria-expanded/aria-controls wiring and rapid open/close are all owned\n * there rather than reimplemented here.\n *\n * Expansion animates on the shared height pair (`--animate-expand` /\n * `--animate-collapse`) keyed to Reka's measured\n * `--reka-collapsible-content-height`; padding lives on an inner wrapper\n * because a padded outer box would pop at both ends of the animation while\n * its height interpolated.\n */\n</script>\n\n<script setup lang=\"ts\">\nimport { ChevronDown } from \"@lucide/vue\";\nimport { CollapsibleContent, CollapsibleRoot, CollapsibleTrigger } from \"reka-ui\";\nimport { cn, optional } from \"@ecoma-io/loom-core\";\nimport { useId } from \"vue\";\n\nwithDefaults(\n defineProps<{\n /**\n * Controls visibility; pair with `v-model:open`. Omit it and the collapse\n * owns its own state, seeded by `defaultOpen`.\n */\n open?: boolean | undefined;\n /** The uncontrolled starting state. */\n defaultOpen?: boolean;\n /** Unavailable rather than hidden: the trigger stays put and inert. */\n disabled?: boolean;\n }>(),\n {\n // `undefined` is the uncontrolled state, and only an explicit default\n // keeps it reachable past Vue's Boolean casting.\n open: undefined,\n defaultOpen: false,\n disabled: false,\n },\n);\n\ndefineEmits<{ \"update:open\": [value: boolean] }>();\n\n// Reka leaves the trigger's aria-controls pointing at an id its Content only\n// registers non-reactively, so a closed-first render ships an empty IDREF.\n// Both halves get explicit ids here instead; fallthrough attributes merge\n// after Reka's own, which is the same mechanism AlertDialog uses to clear\n// its dangling describedby.\nconst triggerId = useId();\nconst contentId = useId();\n</script>\n\n<template>\n <CollapsibleRoot\n v-slot=\"{ open: state }\"\n v-bind=\"optional({ open })\"\n :default-open=\"defaultOpen\"\n :disabled=\"disabled\"\n :unmount-on-hide=\"false\"\n @update:open=\"$emit('update:open', $event)\"\n >\n <CollapsibleTrigger\n :id=\"triggerId\"\n :aria-controls=\"contentId\"\n :class=\"\n cn(\n 'group flex w-full items-center justify-between gap-3 rounded-md px-4 py-3 text-left text-sm font-medium',\n 'transition-colors duration-fast ease-out hover:bg-subtle',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo',\n 'disabled:pointer-events-none disabled:bg-transparent disabled:text-muted-foreground',\n )\n \"\n >\n <!-- @slot The control's visible face, inside a real `<button>` carrying\n aria-expanded/aria-controls and the canonical focus ring. `open`\n mirrors the real state, controlled or not. -->\n <slot name=\"trigger\" :open=\"state\" />\n <ChevronDown\n class=\"h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-fast ease-out group-data-[state=open]:rotate-180\"\n aria-hidden=\"true\"\n />\n </CollapsibleTrigger>\n <!-- Mounted even while closed: the region id in aria-controls has to\n resolve for a screen reader before the first expansion, and a\n persistent element is what lets the collapse animation actually play\n instead of being unmounted mid-frame. Reka conceals the closed\n region with hidden=\"until-found\". -->\n <CollapsibleContent\n data-loom-collapse=\"\"\n class=\"overflow-hidden data-[state=open]:animate-expand data-[state=closed]:animate-collapse\"\n >\n <!-- The animated box carries no padding of its own: interpolating\n height around fixed padding pops at both ends of the film. This\n inner div also carries the id the trigger references: Reka writes\n its own content id after any we pass, so the reference lands here\n where it actually resolves. -->\n <div :id=\"contentId\" class=\"px-4 pb-4\">\n <!-- @slot The region's content. Nested collapses work unchanged —\n each owns its own region. -->\n <slot />\n </div>\n </CollapsibleContent>\n </CollapsibleRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkDA,MAAM,YAAY,MAAM;EACxB,MAAM,YAAY,MAAM;;GAItB,OAAA,UAAA,GAAA,YAiDkB,MAAA,eAAA,GAjDlB,WAEU,MA+CQ,QAAA,CA/CA,CAAA,EAAA,MAAG,QAAA,KAAI,CAAA,GAAA;IACtB,gBAAc,QAAA;IACd,UAAU,QAAA;IACV,mBAAiB;IACjB,iBAAW,OAAA,OAAA,OAAA,MAAA,WAAEA,KAAAA,MAAK,eAAgB,MAAM;;IAEzC,SAAA,SAoBqB,EAAA,MA3BL,YAAK,CAOrB,YAoBqB,MAAA,kBAAA,GAAA;KAnBlB,IAAI,MAAA,SAAA;KACJ,iBAAe,MAAA,SAAA;KACf,OAAK,eAAW,MAAA,EAAA,CAAE,CAAA,2GAAA,4DAAA,+GAAA,qFAAA,CAAA;;KAYnB,SAAA,cAAqC,CAArC,WAAqC,KAAA,QAAA,WAAA,EAAf,MAAM,MAAK,CAAA,GACjC,YAGE,MAAA,WAAA,GAAA;MAFA,OAAM;MACN,eAAY;;;;;;;IAQhB,CAAA,GAAA,YAcqB,MAAA,kBAAA,GAAA;KAbnB,sBAAmB;KACnB,OAAM;;KAON,SAAA,cAIM,CAJN,mBAIM,OAAA;MAJA,IAAI,MAAA,SAAA;MAAW,OAAM;KAGzB,GAAA,CAAA,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,GAAA,UAAA,CAAA,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorPicker.js","names":[],"sources":["../../../../packages/primitives/color-picker/src/ColorPicker.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { ColorPickerLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it, and\n * exported so a host can build a partial vocabulary against the real thing.\n */\nexport const COLOR_PICKER_LABELS: ColorPickerLabels = {\n area: \"Saturation and brightness\",\n areaRoleDescription: \"Colour picker\",\n areaThumb: \"Saturation and brightness\",\n areaThumbRoleDescription: \"Colour thumb\",\n // Differs from Reka's own \"Saturation 60, Brightness 80\" by the one capital,\n // which is the same trick the rest of the library uses to let a test assert\n // whose string reached the DOM rather than merely what it said.\n areaValue: ({ saturation, brightness }) =>\n `Saturation ${String(saturation)}, brightness ${String(brightness)}`,\n hue: \"Hue\",\n hex: \"Hex value\",\n presets: \"Presets\",\n swatch: ({ color }) => color,\n swatchRoleDescription: \"Colour swatch\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useTemplateRef, watch } from \"vue\";\nimport {\n ColorAreaRoot,\n ColorAreaArea,\n ColorAreaThumb,\n ColorSliderRoot,\n ColorSliderTrack,\n ColorSliderThumb,\n ColorFieldRoot,\n ColorFieldInput,\n ColorSwatch,\n ColorSwatchPickerRoot,\n ColorSwatchPickerItem,\n colorToString,\n getChannelValue,\n isValidColor,\n normalizeColor,\n type Color,\n} from \"reka-ui\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { optional } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { useAncestorDisabled } from \"@ecoma-io/loom-labels\";\nimport { useFieldControl } from \"@ecoma-io/loom-labels\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\n/**\n * ColorPicker — choose one colour, as `#rrggbb`. A saturation/brightness\n * area, a hue slider, an editable hex field, and an optional row of presets.\n * Reach for it when the colour itself is the value being authored: a label\n * colour, a chart series, a theme override.\n *\n * When the choice is actually a small closed set — a status colour, a brand\n * palette — a Select or a RadioGroup names the options and this does not.\n * A picker offers sixteen million answers, which is the wrong control for a\n * question with six.\n *\n * Built on Reka UI's colour parts, which supply the whole semantic layer:\n * `role=\"slider\"` on both thumbs, the area's two-axis arrow stepping, the\n * listbox roving focus over the presets, and the parsing that turns typed text\n * into a colour. Every part models its value as a colour string and emits hex,\n * which is what lets this expose one plain `#rrggbb` rather than a channel\n * object.\n *\n * **Where the \"no raw colour values\" rule falls here.** The colour a person is\n * picking is *data*: the area's gradient, the hue track and every swatch fill\n * are bound from the model value at run time, and a token could not express\n * them. Everything that is *chrome* — the borders, the focus ring, the field,\n * the labels, the disabled state, the rings that keep the thumbs visible —\n * comes from `theme.css` and nothing else. A literal colour in this file is a\n * defect unless it is a value being picked.\n *\n * **The hex is the non-colour channel.** A control that communicates only in\n * colour is unusable by the readers most likely to need help choosing one, so\n * the hex value is always on screen as text and is itself the edit surface;\n * every swatch is named rather than left a bare square — by its hex unless\n * `labels.swatch` gives it words; and the disabled state is carried by\n * `aria-disabled` as well as by the appearance. It is also why the hex and the\n * saturation area are the parts of an unavailable picker that drain rather\n * than dim, while the hue track and presets keep a documented dim — their\n * fills are data colours no token can express. See the root's class list and\n * the comments on those parts.\n *\n * The event contract matches Slider and NumberField. `update:modelValue` is\n * transient — every position a thumb passes through — and `commit` fires once\n * per gesture, so one drag across the area is one undo entry rather than a\n * hundred.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself through\n * `useFieldControl()`, and the row's answers land on two different nodes — see\n * the comment above `groupFieldAttrs`, which is where that split is decided.\n * **A row's label does not name the picker.** `<label for>` names a labelable\n * element and this renders a `div[role=\"group\"]`, so the row's label resolves\n * to it and announces nobody; `ariaLabel`/`ariaLabelledby` below are what name\n * the picker, exactly as they were before.\n *\n * There is no `readonly`, and a row's is ignored rather than approximated. A\n * colour that may be looked at but not changed is a swatch — the `ColorSwatch`\n * beside the hex value already is one — and none of the four parts has a\n * read-only state to put it in, so the honest options were a picker that looks\n * live and swallows every gesture, or none at all.\n */\nconst props = withDefaults(\n defineProps<{\n /** The chosen colour as `#rrggbb`. There is no alpha channel in this version. */\n modelValue?: string;\n /** Preset colours shown as a row of named swatches. Omit it and no row is rendered. */\n swatches?: string[];\n /** Unavailable: drains the picker's chrome, keeps the colour surfaces readable, and refuses the pointer, the keyboard and the field. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** The accessible name for the picker as a whole, when nothing visible already labels it. */\n ariaLabel?: string;\n /** The id of the visible element that labels the picker (a Field wrapper's label, say). */\n ariaLabelledby?: string;\n /**\n * Names for the parts, as any subset of `ColorPickerLabels` — the rest stay\n * as the host's `provideLoomLabels` vocabulary left them, and then as\n * Loom's English.\n *\n * `ariaLabel` above names the *picker*; this names what is inside it, and\n * six of its nine keys are the only thing standing between a reader and\n * Reka UI's own English.\n */\n labels?: LabelOverrides<ColorPickerLabels>;\n }>(),\n {\n // Not `false`: absent has to stay tellable from `false` for a Field above\n // to disable the row and for `:disabled=\"false\"` to overrule one that does.\n // Vue casts an absent Boolean prop with no declared default to `false`,\n // which would leave the context wired and inert.\n disabled: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** Transient: every colour a drag or an arrow step passes through. Not a checkpoint. */\n \"update:modelValue\": [value: string];\n /** Committed: once per gesture — drag release, arrow step, hex entry, preset click. */\n commit: [value: string];\n}>();\n\n// `text`, not `labels`: the prop of that name is one of the three sources this\n// resolves, and a template reading the raw prop would be reading the overrides\n// rather than the answer.\nconst text = useLabels(\"colorPicker\", COLOR_PICKER_LABELS, () => props.labels);\n\n// The seed for an unset or unparseable model value. Reka's ColorArea, ColorField\n// and ColorSlider each fall back to this same string internally, so matching it\n// is what keeps the four parts agreeing about what \"no colour yet\" looks like\n// rather than each inventing its own. It is picked data, not a theme colour.\nconst FALLBACK = \"#000000\";\n\n// A colour a consumer supplied is parsed by Reka inside a render function, and\n// an unparseable one throws there — taking the host's page down, not just this\n// component. A library cannot do that with a prop, so every value entering\n// `current` is checked first. `isValidColor` is Reka's own parser rather than a\n// regex here, so what this accepts and what the parts accept cannot drift.\nfunction toColor(value: string | undefined): string {\n return value !== undefined && isValidColor(value) ? value : FALLBACK;\n}\n\n// The working colour, fed to all four parts. Seeded from the prop and advanced\n// on every tick, exactly as Slider's `lastValue` is: given a defined model value\n// Reka runs fully controlled, so a host that correctly withholds transient\n// values until commit would otherwise freeze the thumbs at the gesture's start.\nconst current = ref(toColor(props.modelValue));\n\n// The value the host last acknowledged. Every commit path compares against it,\n// which is what makes a gesture that ends where it started — a click that lands\n// on the thumb, an arrow at the edge of the area, the same hex retyped, the\n// already-selected preset clicked again — produce no checkpoint at all.\nconst lastCommitted = ref(current.value);\n\n// An incoming value equal to `current` is this component's own emit echoing\n// back through a `v-model`, and re-baselining on it would swallow the commit at\n// the end of the gesture that produced it. Anything else is the host moving the\n// colour itself, which is a new baseline by definition — which is why this\n// needs no \"is a gesture in flight?\" flag to tell the two apart.\nwatch(\n () => props.modelValue,\n (value) => {\n const next = toColor(value);\n if (next === current.value) return;\n current.value = next;\n lastCommitted.value = next;\n },\n);\n\n// Every one of Reka's parts writes a hex string back into its own model, but\n// each types its update as `string | Color` because that union is what it will\n// *accept* coming in. Narrowing it here rather than casting keeps the object\n// half real: a future part that emits one still resolves to hex instead of\n// stringifying to \"[object Object]\" and failing to parse two frames later.\nfunction applyFromPart(value: string | Color): void {\n apply(typeof value === \"string\" ? value : colorToString(value, \"hex\"));\n}\n\nfunction apply(next: string): void {\n const value = toColor(next);\n if (value === current.value) return;\n current.value = value;\n emit(\"update:modelValue\", value);\n}\n\n/**\n * The area thumb's `aria-valuetext`, which Reka would otherwise build from its\n * own English channel names — \"Saturation 60, Brightness 80\", said again on\n * every arrow key.\n *\n * The two numbers are recomputed here rather than read out of Reka, because\n * Reka exposes neither: `ColorAreaRoot` yields only `style` to its slot and\n * keeps `xValue`/`yValue` in a context this component cannot inject. What it\n * does export is the arithmetic — `getChannelValue` and `normalizeColor` are\n * the same two functions `ColorAreaRoot` calls, applied to the same `current`\n * this component hands it as `model-value`, with the same `Math.round`. So the\n * number here and the `aria-valuenow` beside it agree by construction rather\n * than by coincidence, which is what makes replacing this string safe: Reka\n * re-derives its own pair from the model on the next tick after any gesture,\n * to this identical formula.\n */\nconst areaValueText = computed(() => {\n const color = normalizeColor(current.value);\n return text.value.areaValue({\n saturation: Math.round(getChannelValue(color, \"saturation\")),\n brightness: Math.round(getChannelValue(color, \"brightness\")),\n });\n});\n\nfunction onFieldCommit(value: string | Color): void {\n applyFromPart(value);\n commitCurrent();\n}\n\nfunction commitCurrent(): void {\n if (current.value === lastCommitted.value) return;\n lastCommitted.value = current.value;\n emit(\"commit\", current.value);\n}\n\n// Reka commits the area on pointer release only — `ColorAreaArea` calls its\n// root's `commitValues` from `pointerup` and not from its own key handler — so\n// an arrow-stepped colour would never reach a host's undo stack. Deferring by a\n// tick is what makes this independent of whether Vue runs this listener before\n// or after Reka's on the same element: by then the step has been applied and\n// `current` holds it. `commitCurrent` swallows the no-op at the axis limits.\nconst AREA_STEP_KEYS = new Set([\n \"ArrowLeft\",\n \"ArrowRight\",\n \"ArrowUp\",\n \"ArrowDown\",\n \"PageUp\",\n \"PageDown\",\n \"Home\",\n \"End\",\n]);\n\nfunction onAreaKeydown(event: KeyboardEvent): void {\n if (field.disabled || !AREA_STEP_KEYS.has(event.key)) return;\n void nextTick(commitCurrent);\n}\n\n// A preset that will not parse is dropped rather than rendered: it would be an\n// invisible square that sets an unusable value, and an empty row would leave a\n// `role=\"listbox\"` with no options, which is an ARIA violation of its own. The\n// row is therefore rendered only when something survives this.\nconst presets = computed(() => (props.swatches ?? []).filter((swatch) => isValidColor(swatch)));\n\nfunction onPresetPick(value: unknown): void {\n if (typeof value !== \"string\") return;\n apply(value);\n commitCurrent();\n}\n\n// Unlike Slider and Select, `class` and the remaining fallthrough attributes go\n// to the same node. The picker has four interactive parts and no single one of\n// them is what an `aria-describedby` or a `data-testid` is about — the group\n// around them is. `class` still needs the `cn()` merge rather than Vue's plain\n// concatenation, so it is bound separately from the spread.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: groupAttrs } = useSplitAttrs();\n\n/**\n * Two of this control's four parts are Reka roots that the platform cannot\n * disable: the saturation area and the hue slider render `<span role=\"slider\"\n * tabindex=\"0\">`, and `<fieldset disabled>` reaches only `<input>`, `<button>`,\n * `<select>` and `<textarea>`. Measured in jsdom, both still took an arrow key\n * inside a disabled group and moved the colour — while the hex `<input>` beside\n * them went properly inert, so the picker was half unavailable and half not.\n *\n * Read off the DOM rather than taken from the Field context, which publishes no\n * `disabled` on purpose — see `../../lib/ancestor-disabled.ts`.\n */\nconst root = useTemplateRef<HTMLElement>(\"root\");\nconst groupDisabled = useAncestorDisabled(() => root.value);\n\n// `id` and `aria-describedby` arrive as fallthrough attrs rather than props, so\n// they are handed in as this caller's own values: a caller who sets either\n// still beats the row, and the row's description is merged into theirs rather\n// than replacing it. `name`, `required` and `invalid` are absent because this\n// component has no prop for any of them — the row's answer stands unopposed.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: attrs[\"aria-describedby\"] as string | undefined,\n // The fieldset beats the prop in both directions, exactly as it does for the\n // hex input inside this very control.\n disabled: groupDisabled.value ? true : props.disabled,\n}));\n\n/**\n * The half of the resolved bag the group takes, and the reason there are two\n * halves at all.\n *\n * A row describes *the picker*, and no one of the four parts is the picker —\n * the colour is authored across all of them — so the group around them is what\n * carries the identity and the description, exactly as a `data-testid` does.\n *\n * `name` and `aria-required` cannot follow them there. ARIA allows neither on\n * `role=\"group\"`, and `aria-allowed-attr` is a WCAG 4.1.2 rule\n * `e2e/accessibility.e2e.ts` runs over every docs page, so shipping the whole\n * bag here would turn that gate red. They go to the hex field instead, which is\n * the picker's one real form control: a native `<input>` holding exactly the\n * `#rrggbb` this component emits, so — unlike NumberField's spinbutton, which\n * holds a *formatted* number and would post its grouping separators — a `name`\n * on it submits the model value itself. `aria-invalid` rides along with them,\n * because a state announced on entering a group is a state most readers meet\n * once, while the field is where an error about the value is actually read.\n */\nconst groupFieldAttrs = computed(() =>\n optional({ id: field.id, \"aria-describedby\": field.attrs[\"aria-describedby\"] }),\n);\n\n// Both thumbs sit on a surface whose colour is the value being chosen, so they\n// have to read against white, against black and against every hue in between. A\n// single-colour thumb cannot: the light ring vanishes on a pale fill and the\n// dark one vanishes on a dark fill. The pair — a `background` band inside a\n// `foreground` hairline — always leaves one of the two in contrast.\nconst THUMB =\n \"block size-6 rounded-full border-2 border-background bg-transparent ring-1 ring-foreground shadow-sm \" +\n \"transition-transform duration-fast ease-spring hover:scale-110 active:scale-95 \" +\n \"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo \" +\n \"data-[disabled]:pointer-events-none\";\n</script>\n\n<template>\n <div\n ref=\"root\"\n v-bind=\"{ ...groupAttrs, ...groupFieldAttrs }\"\n role=\"group\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-disabled=\"field.disabled || undefined\"\n :data-disabled=\"field.disabled || undefined\"\n :class=\"\n cn(\n 'flex w-full max-w-xs flex-col gap-3',\n // No `opacity` on the group, and the split below is the whole reason.\n // A dim here ran over everything the picker holds, the hex among it:\n // measured on the built site, `opacity-50` put the hex value at 3.06:1\n // — the same 3.08:1 the text input's own dim produced before it was\n // drained, and the same failure axe does not raise because it exempts\n // a disabled control under 1.4.3.\n //\n // So the parts part ways. The saturation area drains to the neutral\n // well like every other unavailable control (its gradient is this\n // component's own inline binding, so unavailability can withhold it);\n // the hue track and the preset swatches keep a dim because their fills\n // are data colours no token can express; and the hex field takes the\n // drained fill, muted text and slackened rim every other control in\n // the library wears, because it is text and it is the one thing a\n // reader still needs from a picker they cannot use.\n field.disabled && 'cursor-not-allowed',\n attrs.class as string,\n )\n \"\n >\n <!-- Saturation across, brightness up. `style` is Reka's own gradient for\n those two axes at the current hue — the picked colour rendered as a\n surface, which is data and not a token. -->\n <ColorAreaRoot\n v-slot=\"{ style }\"\n :model-value=\"current\"\n color-space=\"hsb\"\n x-channel=\"saturation\"\n y-channel=\"brightness\"\n :disabled=\"field.disabled\"\n @update:model-value=\"applyFromPart\"\n @change-end=\"commitCurrent\"\n >\n <!-- Reka gives this `role=\"application\"`, which hands every key straight\n to the area rather than to the screen reader's own navigation. That\n only works if the region says what it is, so it is named here; the\n thumb inside carries the per-axis values.\n\n Both `aria-roledescription`s below replace one Reka writes in English\n inside its own render function. They reach the DOM as fallthrough\n attributes, which Vue merges last, so each is a replacement rather\n than a second phrase — and removing one falls back to Reka's English\n rather than to nothing, which is the failure no test of Loom's own\n strings would catch.\n\n `aria-valuetext` on the thumb is the third of them and the one a\n reader hears most, since it is re-announced on every arrow key.\n `areaValueText` explains why replacing it does not risk contradicting\n the `aria-valuenow` beside it. -->\n <!-- The gradient is Loom's own inline binding, so unavailability can\n take the surface back: with the picker disabled the gradient is\n withheld and the area falls to the neutral well, drained like every\n other unavailable control rather than faded through. -->\n <ColorAreaArea\n :style=\"field.disabled ? undefined : style\"\n :aria-label=\"text.area\"\n :aria-roledescription=\"text.areaRoleDescription\"\n class=\"relative h-40 w-full rounded-md border border-border bg-background data-[disabled]:bg-muted\"\n @keydown=\"onAreaKeydown\"\n >\n <ColorAreaThumb\n :aria-label=\"text.areaThumb\"\n :aria-roledescription=\"text.areaThumbRoleDescription\"\n :aria-valuetext=\"areaValueText\"\n :class=\"THUMB\"\n />\n </ColorAreaArea>\n </ColorAreaRoot>\n\n <ColorSliderRoot\n :model-value=\"current\"\n channel=\"hue\"\n color-space=\"hsb\"\n :disabled=\"field.disabled\"\n class=\"relative flex w-full touch-none items-center py-1\"\n @update:model-value=\"applyFromPart\"\n @change-end=\"commitCurrent\"\n >\n <!-- The one dim left on a *tokenless* surface, and it stays because it\n must: Reka paints the spectrum as an inline `style` inside its own\n component (verified against its source — the track's background\n never passes through a slot), and no class can outrank an inline\n style. The hue under the thumb is data, not chrome, so draining it\n to a token would be lying about what is there. -->\n <ColorSliderTrack\n class=\"relative h-3 w-full grow rounded-full border border-border data-[disabled]:opacity-50\"\n />\n <!-- Reka names this from its channel — \"Hue\" — so the binding replaces\n that rather than adding to it. -->\n <ColorSliderThumb :aria-label=\"text.hue\" :class=\"THUMB\" />\n </ColorSliderRoot>\n\n <!-- The hex is the picker's text channel, so it is always on screen and it\n is the edit surface too. Typing writes the model on blur and on Enter\n rather than per keystroke, so a half-typed value is never emitted and\n text that will not parse is reverted to the current colour; the arrow\n keys nudge it a step at a time. Both paths arrive here already at a\n boundary, which is why the field's update is itself the checkpoint. -->\n <ColorFieldRoot\n :model-value=\"current\"\n :disabled=\"field.disabled\"\n class=\"flex h-9 items-center gap-2 rounded-md border border-input bg-background px-3 text-sm text-foreground transition-[color,background-color,border-color,box-shadow] duration-fast ease-out focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring focus-within:shadow-halo data-[disabled]:cursor-not-allowed data-[disabled]:border-border data-[disabled]:bg-muted data-[disabled]:text-muted-foreground\"\n @update:model-value=\"onFieldCommit\"\n >\n <!-- `label` is Reka's own documented prop for this, so it is set rather\n than bound over: left unset the swatch names itself through a\n `getColorName` that answers \"vibrant red\" in English and is not\n exported for Loom to delegate to. The roledescription is a\n fallthrough replacement, as on the area above. -->\n <ColorSwatch\n :color=\"current\"\n :label=\"text.swatch({ color: current })\"\n :aria-roledescription=\"text.swatchRoleDescription\"\n :style=\"{ backgroundColor: current }\"\n class=\"size-6 shrink-0 rounded-sm border border-border\"\n />\n <!-- The row's three form-control answers, which the group cannot hold —\n see `groupFieldAttrs`. `aria-label` stays: it names the *field*, not\n the picker, and a row's label never reached this element anyway. -->\n <ColorFieldInput\n :aria-label=\"text.hex\"\n :name=\"field.name\"\n :aria-required=\"field.required || undefined\"\n :aria-invalid=\"field.invalid || undefined\"\n class=\"tabular min-w-0 flex-1 self-stretch bg-transparent outline-none disabled:cursor-not-allowed\"\n />\n </ColorFieldRoot>\n\n <!-- One tab stop, not one per swatch: Reka's swatch picker is a listbox\n with roving focus, so arrows move between presets and Enter or Space\n chooses. `replace` rather than Reka's default `toggle`: a row of\n presets is a choice, not a set of switches, so clicking the one\n already showing must re-affirm the colour rather than clear it to\n nothing. `onPresetPick`'s string check holds the same line from the\n other side, for the empty selection `toggle` would emit. -->\n <ColorSwatchPickerRoot\n v-if=\"presets.length > 0\"\n :model-value=\"current\"\n :disabled=\"field.disabled\"\n :aria-disabled=\"field.disabled || undefined\"\n selection-behavior=\"replace\"\n :aria-label=\"text.presets\"\n class=\"flex flex-wrap gap-2 data-[disabled]:opacity-50\"\n @update:model-value=\"onPresetPick\"\n >\n <!-- Each item names itself from Reka's English `getColorName` unless\n this binding replaces it, so a row of presets is where that\n vocabulary leaks in bulk. -->\n <!-- Each swatch's fill is a preset the host supplied, bound inline right\n here — data colours no token can express (the same constraint as\n the hue track above). Withholding the fill when unavailable would\n blank the palette instead of draining chrome around it, so the row\n keeps the dim: the one honest treatment for content that *is*\n colour. -->\n <ColorSwatchPickerItem\n v-for=\"preset in presets\"\n :key=\"preset\"\n :value=\"preset\"\n :disabled=\"field.disabled\"\n :aria-label=\"text.swatch({ color: preset })\"\n :style=\"{ backgroundColor: preset }\"\n class=\"size-6 cursor-pointer rounded-sm border border-border transition-transform duration-fast ease-spring hover:scale-110 active:scale-95 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo aria-selected:ring-2 aria-selected:ring-primary aria-selected:ring-offset-2 aria-selected:ring-offset-background data-[disabled]:pointer-events-none\"\n />\n </ColorSwatchPickerRoot>\n </div>\n</template>\n"],"mappings":""}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ColorPicker.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../packages/primitives/color-picker/src/ColorPicker.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { ColorPickerLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it, and\n * exported so a host can build a partial vocabulary against the real thing.\n */\nexport const COLOR_PICKER_LABELS: ColorPickerLabels = {\n area: \"Saturation and brightness\",\n areaRoleDescription: \"Colour picker\",\n areaThumb: \"Saturation and brightness\",\n areaThumbRoleDescription: \"Colour thumb\",\n // Differs from Reka's own \"Saturation 60, Brightness 80\" by the one capital,\n // which is the same trick the rest of the library uses to let a test assert\n // whose string reached the DOM rather than merely what it said.\n areaValue: ({ saturation, brightness }) =>\n `Saturation ${String(saturation)}, brightness ${String(brightness)}`,\n hue: \"Hue\",\n hex: \"Hex value\",\n presets: \"Presets\",\n swatch: ({ color }) => color,\n swatchRoleDescription: \"Colour swatch\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useTemplateRef, watch } from \"vue\";\nimport {\n ColorAreaRoot,\n ColorAreaArea,\n ColorAreaThumb,\n ColorSliderRoot,\n ColorSliderTrack,\n ColorSliderThumb,\n ColorFieldRoot,\n ColorFieldInput,\n ColorSwatch,\n ColorSwatchPickerRoot,\n ColorSwatchPickerItem,\n colorToString,\n getChannelValue,\n isValidColor,\n normalizeColor,\n type Color,\n} from \"reka-ui\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { optional } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { useAncestorDisabled } from \"@ecoma-io/loom-labels\";\nimport { useFieldControl } from \"@ecoma-io/loom-labels\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\n/**\n * ColorPicker — choose one colour, as `#rrggbb`. A saturation/brightness\n * area, a hue slider, an editable hex field, and an optional row of presets.\n * Reach for it when the colour itself is the value being authored: a label\n * colour, a chart series, a theme override.\n *\n * When the choice is actually a small closed set — a status colour, a brand\n * palette — a Select or a RadioGroup names the options and this does not.\n * A picker offers sixteen million answers, which is the wrong control for a\n * question with six.\n *\n * Built on Reka UI's colour parts, which supply the whole semantic layer:\n * `role=\"slider\"` on both thumbs, the area's two-axis arrow stepping, the\n * listbox roving focus over the presets, and the parsing that turns typed text\n * into a colour. Every part models its value as a colour string and emits hex,\n * which is what lets this expose one plain `#rrggbb` rather than a channel\n * object.\n *\n * **Where the \"no raw colour values\" rule falls here.** The colour a person is\n * picking is *data*: the area's gradient, the hue track and every swatch fill\n * are bound from the model value at run time, and a token could not express\n * them. Everything that is *chrome* — the borders, the focus ring, the field,\n * the labels, the disabled state, the rings that keep the thumbs visible —\n * comes from `theme.css` and nothing else. A literal colour in this file is a\n * defect unless it is a value being picked.\n *\n * **The hex is the non-colour channel.** A control that communicates only in\n * colour is unusable by the readers most likely to need help choosing one, so\n * the hex value is always on screen as text and is itself the edit surface;\n * every swatch is named rather than left a bare square — by its hex unless\n * `labels.swatch` gives it words; and the disabled state is carried by\n * `aria-disabled` as well as by the appearance. It is also why the hex and the\n * saturation area are the parts of an unavailable picker that drain rather\n * than dim, while the hue track and presets keep a documented dim — their\n * fills are data colours no token can express. See the root's class list and\n * the comments on those parts.\n *\n * The event contract matches Slider and NumberField. `update:modelValue` is\n * transient — every position a thumb passes through — and `commit` fires once\n * per gesture, so one drag across the area is one undo entry rather than a\n * hundred.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself through\n * `useFieldControl()`, and the row's answers land on two different nodes — see\n * the comment above `groupFieldAttrs`, which is where that split is decided.\n * **A row's label does not name the picker.** `<label for>` names a labelable\n * element and this renders a `div[role=\"group\"]`, so the row's label resolves\n * to it and announces nobody; `ariaLabel`/`ariaLabelledby` below are what name\n * the picker, exactly as they were before.\n *\n * There is no `readonly`, and a row's is ignored rather than approximated. A\n * colour that may be looked at but not changed is a swatch — the `ColorSwatch`\n * beside the hex value already is one — and none of the four parts has a\n * read-only state to put it in, so the honest options were a picker that looks\n * live and swallows every gesture, or none at all.\n */\nconst props = withDefaults(\n defineProps<{\n /** The chosen colour as `#rrggbb`. There is no alpha channel in this version. */\n modelValue?: string;\n /** Preset colours shown as a row of named swatches. Omit it and no row is rendered. */\n swatches?: string[];\n /** Unavailable: drains the picker's chrome, keeps the colour surfaces readable, and refuses the pointer, the keyboard and the field. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** The accessible name for the picker as a whole, when nothing visible already labels it. */\n ariaLabel?: string;\n /** The id of the visible element that labels the picker (a Field wrapper's label, say). */\n ariaLabelledby?: string;\n /**\n * Names for the parts, as any subset of `ColorPickerLabels` — the rest stay\n * as the host's `provideLoomLabels` vocabulary left them, and then as\n * Loom's English.\n *\n * `ariaLabel` above names the *picker*; this names what is inside it, and\n * six of its nine keys are the only thing standing between a reader and\n * Reka UI's own English.\n */\n labels?: LabelOverrides<ColorPickerLabels>;\n }>(),\n {\n // Not `false`: absent has to stay tellable from `false` for a Field above\n // to disable the row and for `:disabled=\"false\"` to overrule one that does.\n // Vue casts an absent Boolean prop with no declared default to `false`,\n // which would leave the context wired and inert.\n disabled: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** Transient: every colour a drag or an arrow step passes through. Not a checkpoint. */\n \"update:modelValue\": [value: string];\n /** Committed: once per gesture — drag release, arrow step, hex entry, preset click. */\n commit: [value: string];\n}>();\n\n// `text`, not `labels`: the prop of that name is one of the three sources this\n// resolves, and a template reading the raw prop would be reading the overrides\n// rather than the answer.\nconst text = useLabels(\"colorPicker\", COLOR_PICKER_LABELS, () => props.labels);\n\n// The seed for an unset or unparseable model value. Reka's ColorArea, ColorField\n// and ColorSlider each fall back to this same string internally, so matching it\n// is what keeps the four parts agreeing about what \"no colour yet\" looks like\n// rather than each inventing its own. It is picked data, not a theme colour.\nconst FALLBACK = \"#000000\";\n\n// A colour a consumer supplied is parsed by Reka inside a render function, and\n// an unparseable one throws there — taking the host's page down, not just this\n// component. A library cannot do that with a prop, so every value entering\n// `current` is checked first. `isValidColor` is Reka's own parser rather than a\n// regex here, so what this accepts and what the parts accept cannot drift.\nfunction toColor(value: string | undefined): string {\n return value !== undefined && isValidColor(value) ? value : FALLBACK;\n}\n\n// The working colour, fed to all four parts. Seeded from the prop and advanced\n// on every tick, exactly as Slider's `lastValue` is: given a defined model value\n// Reka runs fully controlled, so a host that correctly withholds transient\n// values until commit would otherwise freeze the thumbs at the gesture's start.\nconst current = ref(toColor(props.modelValue));\n\n// The value the host last acknowledged. Every commit path compares against it,\n// which is what makes a gesture that ends where it started — a click that lands\n// on the thumb, an arrow at the edge of the area, the same hex retyped, the\n// already-selected preset clicked again — produce no checkpoint at all.\nconst lastCommitted = ref(current.value);\n\n// An incoming value equal to `current` is this component's own emit echoing\n// back through a `v-model`, and re-baselining on it would swallow the commit at\n// the end of the gesture that produced it. Anything else is the host moving the\n// colour itself, which is a new baseline by definition — which is why this\n// needs no \"is a gesture in flight?\" flag to tell the two apart.\nwatch(\n () => props.modelValue,\n (value) => {\n const next = toColor(value);\n if (next === current.value) return;\n current.value = next;\n lastCommitted.value = next;\n },\n);\n\n// Every one of Reka's parts writes a hex string back into its own model, but\n// each types its update as `string | Color` because that union is what it will\n// *accept* coming in. Narrowing it here rather than casting keeps the object\n// half real: a future part that emits one still resolves to hex instead of\n// stringifying to \"[object Object]\" and failing to parse two frames later.\nfunction applyFromPart(value: string | Color): void {\n apply(typeof value === \"string\" ? value : colorToString(value, \"hex\"));\n}\n\nfunction apply(next: string): void {\n const value = toColor(next);\n if (value === current.value) return;\n current.value = value;\n emit(\"update:modelValue\", value);\n}\n\n/**\n * The area thumb's `aria-valuetext`, which Reka would otherwise build from its\n * own English channel names — \"Saturation 60, Brightness 80\", said again on\n * every arrow key.\n *\n * The two numbers are recomputed here rather than read out of Reka, because\n * Reka exposes neither: `ColorAreaRoot` yields only `style` to its slot and\n * keeps `xValue`/`yValue` in a context this component cannot inject. What it\n * does export is the arithmetic — `getChannelValue` and `normalizeColor` are\n * the same two functions `ColorAreaRoot` calls, applied to the same `current`\n * this component hands it as `model-value`, with the same `Math.round`. So the\n * number here and the `aria-valuenow` beside it agree by construction rather\n * than by coincidence, which is what makes replacing this string safe: Reka\n * re-derives its own pair from the model on the next tick after any gesture,\n * to this identical formula.\n */\nconst areaValueText = computed(() => {\n const color = normalizeColor(current.value);\n return text.value.areaValue({\n saturation: Math.round(getChannelValue(color, \"saturation\")),\n brightness: Math.round(getChannelValue(color, \"brightness\")),\n });\n});\n\nfunction onFieldCommit(value: string | Color): void {\n applyFromPart(value);\n commitCurrent();\n}\n\nfunction commitCurrent(): void {\n if (current.value === lastCommitted.value) return;\n lastCommitted.value = current.value;\n emit(\"commit\", current.value);\n}\n\n// Reka commits the area on pointer release only — `ColorAreaArea` calls its\n// root's `commitValues` from `pointerup` and not from its own key handler — so\n// an arrow-stepped colour would never reach a host's undo stack. Deferring by a\n// tick is what makes this independent of whether Vue runs this listener before\n// or after Reka's on the same element: by then the step has been applied and\n// `current` holds it. `commitCurrent` swallows the no-op at the axis limits.\nconst AREA_STEP_KEYS = new Set([\n \"ArrowLeft\",\n \"ArrowRight\",\n \"ArrowUp\",\n \"ArrowDown\",\n \"PageUp\",\n \"PageDown\",\n \"Home\",\n \"End\",\n]);\n\nfunction onAreaKeydown(event: KeyboardEvent): void {\n if (field.disabled || !AREA_STEP_KEYS.has(event.key)) return;\n void nextTick(commitCurrent);\n}\n\n// A preset that will not parse is dropped rather than rendered: it would be an\n// invisible square that sets an unusable value, and an empty row would leave a\n// `role=\"listbox\"` with no options, which is an ARIA violation of its own. The\n// row is therefore rendered only when something survives this.\nconst presets = computed(() => (props.swatches ?? []).filter((swatch) => isValidColor(swatch)));\n\nfunction onPresetPick(value: unknown): void {\n if (typeof value !== \"string\") return;\n apply(value);\n commitCurrent();\n}\n\n// Unlike Slider and Select, `class` and the remaining fallthrough attributes go\n// to the same node. The picker has four interactive parts and no single one of\n// them is what an `aria-describedby` or a `data-testid` is about — the group\n// around them is. `class` still needs the `cn()` merge rather than Vue's plain\n// concatenation, so it is bound separately from the spread.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: groupAttrs } = useSplitAttrs();\n\n/**\n * Two of this control's four parts are Reka roots that the platform cannot\n * disable: the saturation area and the hue slider render `<span role=\"slider\"\n * tabindex=\"0\">`, and `<fieldset disabled>` reaches only `<input>`, `<button>`,\n * `<select>` and `<textarea>`. Measured in jsdom, both still took an arrow key\n * inside a disabled group and moved the colour — while the hex `<input>` beside\n * them went properly inert, so the picker was half unavailable and half not.\n *\n * Read off the DOM rather than taken from the Field context, which publishes no\n * `disabled` on purpose — see `../../lib/ancestor-disabled.ts`.\n */\nconst root = useTemplateRef<HTMLElement>(\"root\");\nconst groupDisabled = useAncestorDisabled(() => root.value);\n\n// `id` and `aria-describedby` arrive as fallthrough attrs rather than props, so\n// they are handed in as this caller's own values: a caller who sets either\n// still beats the row, and the row's description is merged into theirs rather\n// than replacing it. `name`, `required` and `invalid` are absent because this\n// component has no prop for any of them — the row's answer stands unopposed.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: attrs[\"aria-describedby\"] as string | undefined,\n // The fieldset beats the prop in both directions, exactly as it does for the\n // hex input inside this very control.\n disabled: groupDisabled.value ? true : props.disabled,\n}));\n\n/**\n * The half of the resolved bag the group takes, and the reason there are two\n * halves at all.\n *\n * A row describes *the picker*, and no one of the four parts is the picker —\n * the colour is authored across all of them — so the group around them is what\n * carries the identity and the description, exactly as a `data-testid` does.\n *\n * `name` and `aria-required` cannot follow them there. ARIA allows neither on\n * `role=\"group\"`, and `aria-allowed-attr` is a WCAG 4.1.2 rule\n * `e2e/accessibility.e2e.ts` runs over every docs page, so shipping the whole\n * bag here would turn that gate red. They go to the hex field instead, which is\n * the picker's one real form control: a native `<input>` holding exactly the\n * `#rrggbb` this component emits, so — unlike NumberField's spinbutton, which\n * holds a *formatted* number and would post its grouping separators — a `name`\n * on it submits the model value itself. `aria-invalid` rides along with them,\n * because a state announced on entering a group is a state most readers meet\n * once, while the field is where an error about the value is actually read.\n */\nconst groupFieldAttrs = computed(() =>\n optional({ id: field.id, \"aria-describedby\": field.attrs[\"aria-describedby\"] }),\n);\n\n// Both thumbs sit on a surface whose colour is the value being chosen, so they\n// have to read against white, against black and against every hue in between. A\n// single-colour thumb cannot: the light ring vanishes on a pale fill and the\n// dark one vanishes on a dark fill. The pair — a `background` band inside a\n// `foreground` hairline — always leaves one of the two in contrast.\nconst THUMB =\n \"block size-6 rounded-full border-2 border-background bg-transparent ring-1 ring-foreground shadow-sm \" +\n \"transition-transform duration-fast ease-spring hover:scale-110 active:scale-95 \" +\n \"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo \" +\n \"data-[disabled]:pointer-events-none\";\n</script>\n\n<template>\n <div\n ref=\"root\"\n v-bind=\"{ ...groupAttrs, ...groupFieldAttrs }\"\n role=\"group\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-disabled=\"field.disabled || undefined\"\n :data-disabled=\"field.disabled || undefined\"\n :class=\"\n cn(\n 'flex w-full max-w-xs flex-col gap-3',\n // No `opacity` on the group, and the split below is the whole reason.\n // A dim here ran over everything the picker holds, the hex among it:\n // measured on the built site, `opacity-50` put the hex value at 3.06:1\n // — the same 3.08:1 the text input's own dim produced before it was\n // drained, and the same failure axe does not raise because it exempts\n // a disabled control under 1.4.3.\n //\n // So the parts part ways. The saturation area drains to the neutral\n // well like every other unavailable control (its gradient is this\n // component's own inline binding, so unavailability can withhold it);\n // the hue track and the preset swatches keep a dim because their fills\n // are data colours no token can express; and the hex field takes the\n // drained fill, muted text and slackened rim every other control in\n // the library wears, because it is text and it is the one thing a\n // reader still needs from a picker they cannot use.\n field.disabled && 'cursor-not-allowed',\n attrs.class as string,\n )\n \"\n >\n <!-- Saturation across, brightness up. `style` is Reka's own gradient for\n those two axes at the current hue — the picked colour rendered as a\n surface, which is data and not a token. -->\n <ColorAreaRoot\n v-slot=\"{ style }\"\n :model-value=\"current\"\n color-space=\"hsb\"\n x-channel=\"saturation\"\n y-channel=\"brightness\"\n :disabled=\"field.disabled\"\n @update:model-value=\"applyFromPart\"\n @change-end=\"commitCurrent\"\n >\n <!-- Reka gives this `role=\"application\"`, which hands every key straight\n to the area rather than to the screen reader's own navigation. That\n only works if the region says what it is, so it is named here; the\n thumb inside carries the per-axis values.\n\n Both `aria-roledescription`s below replace one Reka writes in English\n inside its own render function. They reach the DOM as fallthrough\n attributes, which Vue merges last, so each is a replacement rather\n than a second phrase — and removing one falls back to Reka's English\n rather than to nothing, which is the failure no test of Loom's own\n strings would catch.\n\n `aria-valuetext` on the thumb is the third of them and the one a\n reader hears most, since it is re-announced on every arrow key.\n `areaValueText` explains why replacing it does not risk contradicting\n the `aria-valuenow` beside it. -->\n <!-- The gradient is Loom's own inline binding, so unavailability can\n take the surface back: with the picker disabled the gradient is\n withheld and the area falls to the neutral well, drained like every\n other unavailable control rather than faded through. -->\n <ColorAreaArea\n :style=\"field.disabled ? undefined : style\"\n :aria-label=\"text.area\"\n :aria-roledescription=\"text.areaRoleDescription\"\n class=\"relative h-40 w-full rounded-md border border-border bg-background data-[disabled]:bg-muted\"\n @keydown=\"onAreaKeydown\"\n >\n <ColorAreaThumb\n :aria-label=\"text.areaThumb\"\n :aria-roledescription=\"text.areaThumbRoleDescription\"\n :aria-valuetext=\"areaValueText\"\n :class=\"THUMB\"\n />\n </ColorAreaArea>\n </ColorAreaRoot>\n\n <ColorSliderRoot\n :model-value=\"current\"\n channel=\"hue\"\n color-space=\"hsb\"\n :disabled=\"field.disabled\"\n class=\"relative flex w-full touch-none items-center py-1\"\n @update:model-value=\"applyFromPart\"\n @change-end=\"commitCurrent\"\n >\n <!-- The one dim left on a *tokenless* surface, and it stays because it\n must: Reka paints the spectrum as an inline `style` inside its own\n component (verified against its source — the track's background\n never passes through a slot), and no class can outrank an inline\n style. The hue under the thumb is data, not chrome, so draining it\n to a token would be lying about what is there. -->\n <ColorSliderTrack\n class=\"relative h-3 w-full grow rounded-full border border-border data-[disabled]:opacity-50\"\n />\n <!-- Reka names this from its channel — \"Hue\" — so the binding replaces\n that rather than adding to it. -->\n <ColorSliderThumb :aria-label=\"text.hue\" :class=\"THUMB\" />\n </ColorSliderRoot>\n\n <!-- The hex is the picker's text channel, so it is always on screen and it\n is the edit surface too. Typing writes the model on blur and on Enter\n rather than per keystroke, so a half-typed value is never emitted and\n text that will not parse is reverted to the current colour; the arrow\n keys nudge it a step at a time. Both paths arrive here already at a\n boundary, which is why the field's update is itself the checkpoint. -->\n <ColorFieldRoot\n :model-value=\"current\"\n :disabled=\"field.disabled\"\n class=\"flex h-9 items-center gap-2 rounded-md border border-input bg-background px-3 text-sm text-foreground transition-[color,background-color,border-color,box-shadow] duration-fast ease-out focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring focus-within:shadow-halo data-[disabled]:cursor-not-allowed data-[disabled]:border-border data-[disabled]:bg-muted data-[disabled]:text-muted-foreground\"\n @update:model-value=\"onFieldCommit\"\n >\n <!-- `label` is Reka's own documented prop for this, so it is set rather\n than bound over: left unset the swatch names itself through a\n `getColorName` that answers \"vibrant red\" in English and is not\n exported for Loom to delegate to. The roledescription is a\n fallthrough replacement, as on the area above. -->\n <ColorSwatch\n :color=\"current\"\n :label=\"text.swatch({ color: current })\"\n :aria-roledescription=\"text.swatchRoleDescription\"\n :style=\"{ backgroundColor: current }\"\n class=\"size-6 shrink-0 rounded-sm border border-border\"\n />\n <!-- The row's three form-control answers, which the group cannot hold —\n see `groupFieldAttrs`. `aria-label` stays: it names the *field*, not\n the picker, and a row's label never reached this element anyway. -->\n <ColorFieldInput\n :aria-label=\"text.hex\"\n :name=\"field.name\"\n :aria-required=\"field.required || undefined\"\n :aria-invalid=\"field.invalid || undefined\"\n class=\"tabular min-w-0 flex-1 self-stretch bg-transparent outline-none disabled:cursor-not-allowed\"\n />\n </ColorFieldRoot>\n\n <!-- One tab stop, not one per swatch: Reka's swatch picker is a listbox\n with roving focus, so arrows move between presets and Enter or Space\n chooses. `replace` rather than Reka's default `toggle`: a row of\n presets is a choice, not a set of switches, so clicking the one\n already showing must re-affirm the colour rather than clear it to\n nothing. `onPresetPick`'s string check holds the same line from the\n other side, for the empty selection `toggle` would emit. -->\n <ColorSwatchPickerRoot\n v-if=\"presets.length > 0\"\n :model-value=\"current\"\n :disabled=\"field.disabled\"\n :aria-disabled=\"field.disabled || undefined\"\n selection-behavior=\"replace\"\n :aria-label=\"text.presets\"\n class=\"flex flex-wrap gap-2 data-[disabled]:opacity-50\"\n @update:model-value=\"onPresetPick\"\n >\n <!-- Each item names itself from Reka's English `getColorName` unless\n this binding replaces it, so a row of presets is where that\n vocabulary leaks in bulk. -->\n <!-- Each swatch's fill is a preset the host supplied, bound inline right\n here — data colours no token can express (the same constraint as\n the hue track above). Withholding the fill when unavailable would\n blank the palette instead of draining chrome around it, so the row\n keeps the dim: the one honest treatment for content that *is*\n colour. -->\n <ColorSwatchPickerItem\n v-for=\"preset in presets\"\n :key=\"preset\"\n :value=\"preset\"\n :disabled=\"field.disabled\"\n :aria-label=\"text.swatch({ color: preset })\"\n :style=\"{ backgroundColor: preset }\"\n class=\"size-6 cursor-pointer rounded-sm border border-border transition-transform duration-fast ease-spring hover:scale-110 active:scale-95 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo aria-selected:ring-2 aria-selected:ring-primary aria-selected:ring-offset-2 aria-selected:ring-offset-background data-[disabled]:pointer-events-none\"\n />\n </ColorSwatchPickerRoot>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AASA,IAAa,sBAAyC;CACpD,MAAM;CACN,qBAAqB;CACrB,WAAW;CACX,0BAA0B;CAI1B,YAAY,EAAE,YAAY,iBACxB,cAAc,OAAO,UAAU,EAAE,eAAe,OAAO,UAAU;CACnE,KAAK;CACL,KAAK;CACL,SAAS;CACT,SAAS,EAAE,YAAY;CACvB,uBAAuB;AACzB;;;;;;;;;;;;;;;;;EAsFA,MAAM,QAAQ;EAgCd,MAAM,OAAO;EAUb,MAAM,OAAO,UAAU,eAAe,2BAA2B,MAAM,MAAM;EAM7E,MAAM,WAAW;EAOjB,SAAS,QAAQ,OAAmC;GAClD,OAAO,UAAU,KAAA,KAAa,aAAa,KAAK,IAAI,QAAQ;EAC9D;EAMA,MAAM,UAAU,IAAI,QAAQ,MAAM,UAAU,CAAC;EAM7C,MAAM,gBAAgB,IAAI,QAAQ,KAAK;EAOvC,YACQ,MAAM,aACX,UAAU;GACT,MAAM,OAAO,QAAQ,KAAK;GAC1B,IAAI,SAAS,QAAQ,OAAO;GAC5B,QAAQ,QAAQ;GAChB,cAAc,QAAQ;EACxB,CACF;EAOA,SAAS,cAAc,OAA6B;GAClD,MAAM,OAAO,UAAU,WAAW,QAAQ,cAAc,OAAO,KAAK,CAAC;EACvE;EAEA,SAAS,MAAM,MAAoB;GACjC,MAAM,QAAQ,QAAQ,IAAI;GAC1B,IAAI,UAAU,QAAQ,OAAO;GAC7B,QAAQ,QAAQ;GAChB,KAAK,qBAAqB,KAAK;EACjC;;;;;;;;;;;;;;;;;EAkBA,MAAM,gBAAgB,eAAe;GACnC,MAAM,QAAQ,eAAe,QAAQ,KAAK;GAC1C,OAAO,KAAK,MAAM,UAAU;IAC1B,YAAY,KAAK,MAAM,gBAAgB,OAAO,YAAY,CAAC;IAC3D,YAAY,KAAK,MAAM,gBAAgB,OAAO,YAAY,CAAC;GAC7D,CAAC;EACH,CAAC;EAED,SAAS,cAAc,OAA6B;GAClD,cAAc,KAAK;GACnB,cAAc;EAChB;EAEA,SAAS,gBAAsB;GAC7B,IAAI,QAAQ,UAAU,cAAc,OAAO;GAC3C,cAAc,QAAQ,QAAQ;GAC9B,KAAK,UAAU,QAAQ,KAAK;EAC9B;EAQA,MAAM,iCAAiB,IAAI,IAAI;GAC7B;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC;EAED,SAAS,cAAc,OAA4B;GACjD,IAAI,MAAM,YAAY,CAAC,eAAe,IAAI,MAAM,GAAG,GAAG;GACtD,SAAc,aAAa;EAC7B;EAMA,MAAM,UAAU,gBAAgB,MAAM,YAAY,CAAC,EAAA,CAAG,QAAQ,WAAW,aAAa,MAAM,CAAC,CAAC;EAE9F,SAAS,aAAa,OAAsB;GAC1C,IAAI,OAAO,UAAU,UAAU;GAC/B,MAAM,KAAK;GACX,cAAc;EAChB;EAQA,MAAM,EAAE,OAAO,MAAM,eAAe,cAAc;;;;;;;;;;;;EAalD,MAAM,OAAO,eAA4B,MAAM;EAC/C,MAAM,gBAAgB,0BAA0B,KAAK,KAAK;EAO1D,MAAM,QAAQ,uBAAuB;GACnC,IAAI,MAAM;GACV,aAAa,MAAM;GAGnB,UAAU,cAAc,QAAQ,OAAO,MAAM;EAC/C,EAAE;;;;;;;;;;;;;;;;;;;;EAqBF,MAAM,kBAAkB,eACtB,SAAS;GAAE,IAAI,MAAM;GAAI,oBAAoB,MAAM,MAAM;EAAoB,CAAC,CAChF;EAOA,MAAM,QACJ;;GAOA,OAAA,UAAA,GAAA,mBA+KM,OA/KN,WA+KM;IA9KA,SAAA;IAAJ,KAAI;GACS,GAAA;IAAA,GAAA,MAAA,UAAA;IAAU,GAAK,gBAAA;GAAe,GAAA;IAC3C,MAAK;IACJ,cAAY,QAAA;IACZ,mBAAiB,QAAA;IACjB,iBAAe,MAAA,KAAA,CAAK,CAAC,YAAY,KAAA;IACjC,iBAAe,MAAA,KAAA,CAAK,CAAC,YAAY,KAAA;IACjC,OAAc,MAAA,EAAA,CAAE,CAAA,uCAAklC,MAAA,KAAA,CAAK,CAAC,YAAQ,sBAAkC,MAAA,KAAA,CAAK,CAAC,KAAA;;IA0BzpC,YA4CgB,MAAA,aAAA,GAAA;KA1Cb,eAAa,QAAA;KACd,eAAY;KACZ,aAAU;KACV,aAAU;KACT,UAAU,MAAA,KAAA,CAAK,CAAC;KAChB,uBAAoB;KACpB,aAAY;;KAsBb,SAAA,SAagB,EA1CN,YAAK,CA6Bf,YAagB,MAAA,aAAA,GAAA;MAZb,OAAK,eAAE,MAAA,KAAA,CAAK,CAAC,WAAW,KAAA,IAAY,KAAK;MACzC,cAAY,MAAA,IAAA,CAAI,CAAC;MACjB,wBAAsB,MAAA,IAAA,CAAI,CAAC;MAC5B,OAAM;MACL,WAAS;;MAEV,SAAA,cAKE,CALF,YAKE,MAAA,cAAA,GAAA;OAJC,cAAY,MAAA,IAAA,CAAI,CAAC;OACjB,wBAAsB,MAAA,IAAA,CAAI,CAAC;OAC3B,kBAAgB,cAAA;OAChB,OAAK,eAAE,KAAK;;;;;;;;;;;;;;IAKnB,YAqBkB,MAAA,eAAA,GAAA;KApBf,eAAa,QAAA;KACd,SAAQ;KACR,eAAY;KACX,UAAU,MAAA,KAAA,CAAK,CAAC;KACjB,OAAM;KACL,uBAAoB;KACpB,aAAY;;KAQb,SAAA,cAEE,CAFF,YAEE,MAAA,gBAAA,GAAA,EADA,OAAM,wFAAuF,CAAA,GAI/F,YAA0D,MAAA,gBAAA,GAAA;MAAvC,cAAY,MAAA,IAAA,CAAI,CAAC;MAAM,OAAK,eAAE,KAAK;;;;IASxD,YA4BiB,MAAA,cAAA,GAAA;KA3Bd,eAAa,QAAA;KACb,UAAU,MAAA,KAAA,CAAK,CAAC;KACjB,OAAM;KACL,uBAAoB;;KAOrB,SAAA,cAME,CANF,YAME,MAAA,WAAA,GAAA;MALC,OAAO,QAAA;MACP,OAAO,MAAA,IAAA,CAAI,CAAC,OAAM,EAAA,OAAU,QAAA,MAAO,CAAA;MACnC,wBAAsB,MAAA,IAAA,CAAI,CAAC;MAC3B,OAAK,eAAA,EAAA,iBAAqB,QAAA,MAAO,CAAA;MAClC,OAAM;;;;;;KAKR,CAAA,GAAA,YAME,MAAA,eAAA,GAAA;MALC,cAAY,MAAA,IAAA,CAAI,CAAC;MACjB,MAAM,MAAA,KAAA,CAAK,CAAC;MACZ,iBAAe,MAAA,KAAA,CAAK,CAAC,YAAY,KAAA;MACjC,gBAAc,MAAA,KAAA,CAAK,CAAC,WAAW,KAAA;MAChC,OAAM;;;;;;;;;IAYF,QAAA,MAAQ,SAAM,KADtB,UAAA,GAAA,YA4BwB,MAAA,qBAAA,GAAA;;KA1BrB,eAAa,QAAA;KACb,UAAU,MAAA,KAAA,CAAK,CAAC;KAChB,iBAAe,MAAA,KAAA,CAAK,CAAC,YAAY,KAAA;KAClC,sBAAmB;KAClB,cAAY,MAAA,IAAA,CAAI,CAAC;KAClB,OAAM;KACL,uBAAoB;;KAYnB,SAAA,cAAyB,EAD3B,UAAA,IAAA,GAAA,mBAQE,UAAA,MAAA,WAPiB,QAAA,QAAV,WAAM;MADf,OAAA,UAAA,GAAA,YAQE,MAAA,qBAAA,GAAA;OANC,KAAK;OACL,OAAO;OACP,UAAU,MAAA,KAAA,CAAK,CAAC;OAChB,cAAY,MAAA,IAAA,CAAI,CAAC,OAAM,EAAA,OAAU,OAAM,CAAA;OACvC,OAAK,eAAA,EAAA,iBAAqB,OAAM,CAAA;OACjC,OAAM"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Combobox.js","names":[],"sources":["../../../../packages/primitives/combobox/src/Combobox.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { ComboboxLabels } from \"@ecoma-io/loom-labels\";\nimport { cva } from \"class-variance-authority\";\n\n/**\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it, and\n * exported so a host can build a partial vocabulary against the real thing.\n */\nexport const COMBOBOX_LABELS: ComboboxLabels = {\n trigger: \"Show options\",\n empty: \"No results\",\n count: ({ count }) => `${String(count)} selected`,\n overflow: ({ hidden }) => `+${String(hidden)} more`,\n};\n\n/**\n * One row of the list. `value` is what the model carries; `label` is what a\n * reader sees, what the filter matches, and what the input shows once the row\n * is chosen.\n *\n * Identical to `SelectOption` today, and deliberately not the same\n * declaration: the two surfaces are independent, and the first field either\n * one grows — a secondary line here, a group key there — is a field the other\n * should not inherit by accident. A shared alias would make that change look\n * free when it is not.\n */\nexport interface ComboboxOption {\n /** The value bound to `v-model` when this row is chosen. Unique within the list. */\n value: string;\n /** The text shown on the row, matched by the filter, and put in the input once chosen. */\n label: string;\n /** Present but unchoosable — visible, skipped by the keyboard, unclickable. */\n disabled?: boolean;\n}\n\n/**\n * The control's height scale. It matches the text input and Select scales\n * exactly, so a form row mixing a Combobox beside either never comes out\n * uneven — which is why reaching past `size` for an `h-*` class is always the\n * wrong fix.\n */\nexport type ComboboxSize = \"sm\" | \"md\" | \"lg\";\n\nexport const comboboxVariants = cva(\n [\n \"flex w-full items-center gap-2 rounded-md border border-input bg-background text-foreground\",\n \"transition-[color,background-color,border-color,box-shadow] duration-fast ease-out\",\n // The focusable node is the input *inside* this box, so the ring is drawn\n // with `focus-within` rather than `focus-visible` — the same choice\n // TextField makes for the same reason, and what keeps the two controls\n // lighting up identically in a form row.\n \"focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring\",\n ],\n {\n // `satisfies` keeps the two halves honest: the union above is the name a\n // consumer imports and the documentation prints, the map below is the\n // classes. Adding a member to one and not the other stops compiling.\n variants: {\n size: {\n sm: \"h-8 px-2.5 text-xs\",\n md: \"h-9 px-3 text-sm\",\n lg: \"h-11 px-4 text-base\",\n } satisfies Record<ComboboxSize, string>,\n },\n defaultVariants: { size: \"md\" },\n },\n);\n\n/**\n * The same three numbers as a floor rather than as a fixed height, for the\n * multi-select box only.\n *\n * A box holding tokens is sized by its content, which is TagsInput's call and\n * the reason its field is `min-h-9`. What keeps that from turning into an\n * unbounded control here is `visibleValues`: the token row never wraps, so in\n * practice the box resolves to exactly the height above and a multi-select\n * still lines up with the single-select beside it. The `h-auto` that goes with\n * it in the template is what releases the fixed height `comboboxVariants`\n * already set — Tailwind's merge resolves the two, `min-h-*` does not.\n */\nconst multiSelectHeights = {\n sm: \"min-h-8\",\n md: \"min-h-9\",\n lg: \"min-h-11\",\n} satisfies Record<ComboboxSize, string>;\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from \"vue\";\nimport {\n ComboboxRoot,\n ComboboxAnchor,\n ComboboxInput,\n ComboboxTrigger,\n ComboboxPortal,\n ComboboxContent,\n ComboboxViewport,\n ComboboxItem,\n ComboboxItemIndicator,\n ComboboxEmpty,\n} from \"reka-ui\";\nimport { Check, ChevronDown } from \"@lucide/vue\";\nimport Chip from \"@ecoma-io/loom-chip\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { listStaggerDelay } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { useFieldControl } from \"@ecoma-io/loom-labels\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\nimport { optional } from \"@ecoma-io/loom-core\";\n\n/**\n * Combobox — a text input that narrows a list as you type, for the list too\n * long to scan. Countries, currencies, repositories, people: anywhere a reader\n * knows roughly what they are looking for and would rather type three letters\n * than scroll past two hundred rows.\n *\n * Its neighbour is `Select`, and the boundary is the length of the list rather\n * than the shape of the control. Three to fifteen rows a reader can read\n * through belong in a Select — a search box over eight options is a keystroke\n * charged for nothing. Two to five options that should all be visible at once\n * belong in a segmented control. Past roughly fifteen, searching beats\n * scrolling and this is the control that offers it.\n *\n * Built on Reka UI's Combobox, which supplies the editable-combobox semantics:\n * the `role=\"combobox\"` input wired to the listbox by `aria-expanded` and\n * `aria-controls`, `aria-autocomplete=\"list\"`, and the active row tracked by\n * `aria-activedescendant` while real focus stays in the input. That last part\n * is the one genuine behavioural difference from Select, which moves focus\n * onto the row itself — a combobox cannot, because the reader is still typing.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself: the row's id, the id of\n * its hint or error line, `required`, `invalid`, `disabled` and the name the\n * chosen value is submitted under all arrive through `useFieldControl()`, so\n * `<Field label=\"Country\" error=\"…\"><Combobox … /></Field>` needs no attributes\n * at the call site. Both booleans below still win over the row when they are\n * set, in both directions — which is why they default to `undefined` rather\n * than `false`.\n *\n * A row's `readonly` is deliberately ignored. The text in the box is not the\n * value — it is the chosen option's label, rewritten on every choice — so a\n * `readonly` input here would freeze a caption rather than protect a value,\n * while the list underneath still opened on click. A choice nobody may change\n * is a disabled Combobox, or the label rendered as text.\n *\n * `multiple` turns it into a many-of-many picker. The chosen values render as\n * tokens in the box — the same `Chip` a\n * [TagsInput](../TagsInput/TagsInput.vue) commits its values to, so a selection\n * looks the same wherever a form shows one — and the input goes back to being\n * only a search box. The tokens are **inert**, deliberately: the list is where\n * a choice is made and where it is unmade, so the control stays the single Tab\n * stop it is in single-select, and a value hidden behind the overflow count is\n * reachable by exactly the same gesture as a visible one. That is the one place\n * this diverges from TagsInput, whose tokens carry their own remove control\n * because it has no list to send a reader back to.\n */\nconst props = withDefaults(\n defineProps<{\n /**\n * The chosen option's `value`, or every chosen value when `multiple`.\n *\n * The union is one prop rather than a generic component, and the invariant\n * is the mode: single-select emits and accepts a `string` and never an\n * array, multi-select an array and never a bare string. A generic would\n * express that in the type system and cost more than it buys — it would\n * print a conditional type in the generated API table below, and it would\n * break `InstanceType<typeof Combobox>`, which is how a consumer types a\n * template ref.\n */\n modelValue?: string | string[] | undefined;\n /** The rows, in the order they are shown. */\n options: ComboboxOption[];\n /** Lets several rows be chosen at once: chosen rows toggle instead of closing the list, and the box shows the selection as tokens. */\n multiple?: boolean;\n /**\n * How many tokens the box shows before the rest collapse into a count.\n *\n * The box must not grow with the selection — it sits in a form row beside\n * controls on a fixed height scale — so past this many the tail becomes one\n * `labels.overflow` summary: five chosen shows three and \"+2 more\", fifty\n * shows three and \"+47 more\". Raise it for a wide box; the row never wraps,\n * so a number the box has no room for is a number that truncates.\n */\n visibleValues?: number;\n /** Shown in the empty input, before anything is typed or chosen. */\n placeholder?: string;\n /** Shown as a row of its own when the filter matches nothing. Defaults to `labels.empty`, so say what was searched for rather than restating the default in a second language. */\n emptyMessage?: string | undefined;\n /** Unavailable: dims the control, refuses to open and refuses to take text. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Error state: paints the destructive border and ring, and sets `aria-invalid`. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** Control height. It shares the text input scale so mixed form rows stay aligned. */\n size?: ComboboxSize;\n /**\n * Filter `options` against the typed text. Turn it off when the host is\n * producing the list itself — from a server, in response to\n * `update:query` — so a result that does not literally contain what was\n * typed is not then hidden a second time by a filter running underneath it.\n */\n filter?: boolean;\n /**\n * Names for the two strings this control supplies itself, as any subset of\n * `ComboboxLabels` — the rest stay as the host's `provideLoomLabels`\n * vocabulary left them, and then as Loom's English.\n *\n * This is the per-instance correction, not the place to localise an\n * application. `emptyMessage` is the shorter way to reach `empty` for one\n * box; this is what reaches `trigger`.\n */\n labels?: LabelOverrides<ComboboxLabels>;\n }>(),\n {\n // `modelValue: undefined` is load-bearing rather than redundant: paired\n // with `optional()` below it is what keeps the uncontrolled third state\n // reachable, instead of pinning the control to a value nobody chose.\n modelValue: undefined,\n multiple: false,\n // Three, and the number is a judgement rather than a measurement: two\n // tokens plus a count reads as a control that shows almost nothing, and\n // four leaves a `md` box no room to type in at the default width. It is a\n // prop because the right answer is the box's width, which only the caller\n // knows.\n visibleValues: 3,\n // No English default here any more. The wording moved into `COMBOBOX_LABELS`\n // so a host can set it once for the whole application rather than on every\n // box, and an absent prop is what lets the resolved label through.\n emptyMessage: undefined,\n // Not `false`, for either. `false` is a caller saying \"this control is fine\n // / enabled even though its row is not\"; absent is a caller saying nothing,\n // and only `undefined` survives to mean that past Vue's\n // absent-Boolean-casts-to-false rule — see TextField.vue, which carries the\n // full reasoning.\n disabled: undefined,\n invalid: undefined,\n size: \"md\",\n filter: true,\n },\n);\n\nconst emit = defineEmits<{\n /** The chosen option's `value` — or the whole chosen list, when `multiple`. Single-select fires once per choice and the list closes with it; multi-select fires once per toggle and the list stays open. */\n \"update:modelValue\": [value: string | string[]];\n /** The text now in the input — as the reader types, and again when a choice puts its label there. */\n \"update:query\": [query: string];\n}>();\n\n// `text`, not `labels`: the prop of that name is one of the three sources this\n// resolves, and a template reading the raw prop would be reading the overrides\n// rather than the answer.\nconst text = useLabels(\"combobox\", COMBOBOX_LABELS, () => props.labels);\n\nconst query = ref(\"\");\n\n/**\n * The stagger is the list's *reveal*, and re-filtering is not a reveal. This\n * is true from the moment the list opens until the first keystroke, after\n * which every row arrives immediately.\n *\n * Two things go wrong without it. A delay recomputed per keystroke makes the\n * list feel like it is rebuilding under the reader's fingers — the opposite of\n * what a filter is for. And raising `animation-delay` on a row that survived\n * the keystroke rewinds its entrance: the row is still mounted, so the\n * animation is not restarted, it is re-timed, and a row that had finished\n * fading in drops back to half-opacity. Going the other way — stagger to `0ms`\n * — only ever fast-forwards, which is why this flag falls and does not rise\n * again until the content has unmounted and remounted with the next open.\n */\nconst revealing = ref(true);\n\nconst countId = useId();\n\n/**\n * The multi-select's own copy of the selection, and the reason it keeps one:\n * the tokens have to render whether or not the host bound `v-model`.\n *\n * Left uncontrolled, `modelValue` stays `undefined` while Reka manages the\n * choice internally — which is the third state `optional()` exists to preserve\n * — so a trigger reading the prop would sit empty while the list showed three\n * checked rows. This mirrors rather than drives: it is never fed back into\n * Reka, so nothing about the uncontrolled control changes.\n *\n * Seeded from the prop rather than sanitised, for TagsInput's reason: a list\n * the host already holds is the host's to hold.\n */\nconst selected = ref<string[]>(Array.isArray(props.modelValue) ? [...props.modelValue] : []);\nwatch(\n () => props.modelValue,\n (next) => {\n if (Array.isArray(next)) selected.value = [...next];\n },\n // Shallow, deliberately: the contract is whole-list replacement — Reka hands\n // back the complete selection on every toggle and a host echoes it straight\n // back down — so in-place mutation is not a case this mirror owes anyone.\n);\n\n/**\n * The chosen values as the box shows them, and the fallback is the point: a\n * host driving `options` from a search hands back only the rows matching the\n * current query, so a value chosen from an earlier one has no option to look\n * its label up in. Falling back to the value keeps the token on screen — a\n * chosen value that vanished from the trigger while it was still in the model\n * would be the control lying about what it holds.\n */\nconst tokens = computed(() =>\n selected.value.map((value) => ({\n value,\n label: props.options.find((option) => option.value === value)?.label ?? value,\n })),\n);\n\nconst visibleTokens = computed(() => tokens.value.slice(0, Math.max(0, props.visibleValues)));\nconst hiddenTokens = computed(() => tokens.value.length - visibleTokens.value.length);\n\n/**\n * What the input shows once a row is chosen. Without this Reka falls back to\n * the model value's own `toString()`, which would leave `en` in the box where\n * the reader picked \"English\".\n *\n * A multi-select shows nothing: the tokens are the selection, and the input\n * beside them is a search box. Reka calls this on close rather than on choose,\n * so the query the reader typed survives every toggle and one search can pick\n * several rows — which is the whole reason the list stays open.\n */\nfunction displayValue(value: unknown): string {\n if (props.multiple) return \"\";\n return props.options.find((option) => option.value === value)?.label ?? \"\";\n}\n\n/**\n * Reka hands back the whole selection on every toggle, never a delta, so the\n * emitted array is always the complete list — the same contract TagsInput's\n * `update:modelValue` carries, and the reason a host can assign it straight\n * back.\n */\nfunction onChoice(value: unknown): void {\n if (!props.multiple) {\n emit(\"update:modelValue\", String(value));\n return;\n }\n const values = Array.isArray(value) ? value.map(String) : [];\n selected.value = values;\n emit(\"update:modelValue\", values);\n}\n\nfunction onQuery(text: string): void {\n // Reka rewrites the input's text on its own account — once as the component\n // mounts, and again when a choice puts the chosen label back in the box —\n // and each of those arrives here as an update. Reporting a query that did\n // not change would have a host running the same search twice on mount, so\n // only a real change is passed on.\n if (text === query.value) return;\n query.value = text;\n revealing.value = false;\n emit(\"update:query\", text);\n}\n\n// The root renders no DOM node of its own, so fallthrough attributes would be\n// dropped on the floor. They go to the input, which is the element they\n// describe and the only one a name can land on — the chevron trigger already\n// carries Reka's own `aria-label`, and naming the control means naming the\n// `role=\"combobox\"` node.\n//\n// `class` is pulled out of that spread and merged through `cn()` onto the\n// anchor instead, because the anchor is the box a caller means when they pass\n// `w-64`. Spreading it alongside the anchor's own `:class` would only\n// concatenate the two lists — Vue's merge is generic, not Tailwind-aware — so\n// a caller's width would win or lose depending on which utility Tailwind\n// happened to emit last.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\n\n// `id` and `aria-describedby` reach this control as fallthrough attrs rather\n// than props, so they are read off `attrs` and handed in as this caller's own\n// values — a caller who sets either still beats the row, and the row's\n// description is merged into theirs rather than replacing it. `name`,\n// `readonly` and `required` are absent from this object because there is no\n// prop to oppose the row with; the row's answer stands unopposed, which is\n// what is wanted.\n//\n// The multi-select's count joins that list rather than replacing anything: it\n// is one more thing this control says about itself, and it reads after the\n// caller's own description and before the row's message — the same\n// most-specific-first order `useFieldControl` applies one layer out. Wired\n// through `aria-describedby` rather than announced, which is TagsInput's call\n// for the same fact: it is heard on focus and on every return to the box, which\n// is when the question is asked, and a live region would speak the whole total\n// over the top of the `aria-selected` change the row itself already announces.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [attrs[\"aria-describedby\"] as string | undefined, props.multiple ? countId : \"\"]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n disabled: props.disabled,\n invalid: props.invalid,\n}));\n\n// `name` is the one resolved key that does not travel with the bag, and here\n// it is a defect rather than a nicety: the bag lands on the input, and what\n// the input holds is the chosen option's *label*. A `name` on it would post\n// \"Viet Nam\" where the model carries `vn`. Reka submits the value itself\n// through a hidden control it renders from the root's own `name`, so that is\n// where the row's name goes. Everything else in the bag — the id, the merged\n// description, `aria-required`, `aria-invalid` — belongs on the\n// `role=\"combobox\"` node, which is the input.\nconst inputFieldAttrs = computed(() => {\n // Removed from a copy rather than listed positively, so a key added to the\n // resolved bag later reaches this input without anyone remembering to come\n // back here.\n const aria: Record<string, unknown> = { ...field.attrs };\n delete aria.name;\n return aria;\n});\n</script>\n\n<template>\n <!-- `open-on-click` and not `open-on-focus`: clicking the box is a reader\n asking to see the list, while focus arrives by Tab as often as by\n intent, and a list that unfolds over the next field every time someone\n tabs through a form is an obstruction. Typing opens it either way. -->\n <ComboboxRoot\n v-bind=\"optional({ modelValue, name: field.name })\"\n :multiple=\"multiple\"\n :disabled=\"field.disabled\"\n :ignore-filter=\"!filter\"\n open-on-click\n @update:model-value=\"onChoice\"\n @update:open=\"revealing = true\"\n >\n <ComboboxAnchor\n :data-disabled=\"field.disabled || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :class=\"\n cn(\n comboboxVariants({ size }),\n // A box holding tokens is sized by them — see `multiSelectHeights`.\n // `h-auto` is what releases the fixed height the variant just set;\n // Tailwind's merge resolves two `h-*` utilities and leaves a `min-h-*`\n // beside either of them alone.\n multiple && ['h-auto', multiSelectHeights[size], 'gap-1.5'],\n !field.invalid && 'focus-within:shadow-halo',\n field.invalid && 'border-destructive focus-within:outline-destructive',\n // The box holds the chosen value, so it is drained rather than\n // dimmed: `opacity-50` composited the input's text down to 3.06:1,\n // and what a reader needs from an unavailable Combobox is precisely\n // what it is set to. The neutral well says unavailable on its own —\n // the input's own `disabled:text-muted-foreground` below carries the\n // text to 4.67:1 over it.\n //\n // The hairline recedes with the fill, and that second channel is the\n // point: unavailable is a difference in *shape* as well as in colour,\n // so it survives a reader who cannot resolve `muted` from\n // `background`. This control has no read-only state to be told apart\n // from — see the docblock — so it takes the unavailable row alone.\n field.disabled && 'cursor-not-allowed border-border bg-muted text-muted-foreground',\n attrs.class as string,\n )\n \"\n >\n <!-- The selection, as the tokens a TagsInput commits its values to, so a\n chosen set looks the same wherever a form shows one. Inert on\n purpose: the list is where a value is chosen and where it is\n unchosen, which keeps the whole control one Tab stop and keeps a\n value behind the overflow count reachable by the same gesture as a\n visible one. -->\n <template v-if=\"multiple\">\n <Chip\n v-for=\"token in visibleTokens\"\n :key=\"token.value\"\n size=\"sm\"\n :disabled=\"field.disabled\"\n class=\"min-w-0 animate-fade-rise\"\n >\n {{ token.label }}\n </Chip>\n <!-- Not a token: it stands for values rather than being one, and a\n fourth pill saying \"+47 more\" would read as a forty-eighth\n choice. -->\n <span v-if=\"hiddenTokens > 0\" class=\"tabular shrink-0 text-small text-muted-foreground\">\n {{ text.overflow({ hidden: hiddenTokens }) }}\n </span>\n </template>\n\n <ComboboxInput\n v-bind=\"{ ...inputAttrs, ...inputFieldAttrs }\"\n :model-value=\"query\"\n :display-value=\"displayValue\"\n :placeholder=\"multiple && tokens.length > 0 ? undefined : placeholder\"\n class=\"min-w-6 flex-1 self-stretch bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:text-muted-foreground\"\n @update:model-value=\"onQuery\"\n />\n <!-- Reka takes this button out of the tab order itself, so the whole\n control is one Tab stop: the input. It also names it, in English —\n `aria-label=\"Show popup\"`, written inside its own render function\n with no prop to reach it by — and the binding below replaces that\n rather than competing with it, because Vue merges a fallthrough\n attribute onto the root vnode after the render function produced it.\n Removing it does not fall back to nothing; it falls back to Reka's\n English, which no test of Loom's own strings would catch. -->\n <ComboboxTrigger\n :aria-label=\"text.trigger\"\n class=\"group min-h-6 min-w-6 shrink-0 text-muted-foreground disabled:cursor-not-allowed\"\n >\n <ChevronDown\n class=\"h-4 w-4 transition-transform duration-fast ease-out group-data-[state=open]:rotate-180\"\n />\n </ComboboxTrigger>\n\n <!-- The size of the selection, and the only thing that carries it to a\n reader who cannot see the tokens: the visible row shows the first few\n and a count for the rest, and neither is announced. Reka publishes\n nothing of the sort — the listbox's `aria-multiselectable` says the\n control takes several values, never how many it holds. -->\n <span v-if=\"multiple\" :id=\"countId\" class=\"sr-only\">\n {{ text.count({ count: tokens.length }) }}\n </span>\n </ComboboxAnchor>\n\n <ComboboxPortal>\n <ComboboxContent\n position=\"popper\"\n :side-offset=\"6\"\n :class=\"\n cn(\n 'z-overlay max-h-72 min-w-[var(--reka-combobox-trigger-width)] overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md',\n // Each half of the motion is scoped to its own state, never\n // unconditional. Closing swaps the computed animation-name to\n // fade-fall's, which is what Reka's Presence reads: it holds the\n // panel mounted until that exit's animationend and only then takes\n // it away. Unconditional, a finished entrance animation sat on the\n // closed element and stranded it invisible over the page, eating\n // clicks.\n 'data-[state=open]:animate-fade-rise data-[state=closed]:animate-fade-fall',\n )\n \"\n >\n <ComboboxViewport class=\"p-1\">\n <!-- A filter that matches nothing has to say so. An empty popover\n reads as a broken one, and a screen reader is told nothing at\n all — so the message is a row inside the listbox rather than a\n caption beside it. `role=\"option\"` because a bare div is not a\n legitimate child of `role=\"listbox\"` and is skipped; disabled\n because it is a statement, not a choice. -->\n <ComboboxEmpty\n role=\"option\"\n aria-disabled=\"true\"\n class=\"animate-fade-rise px-3 py-1.5 text-sm text-muted-foreground\"\n >\n {{ emptyMessage ?? text.empty }}\n </ComboboxEmpty>\n\n <!-- Keyed by value rather than by index: a row that survives a\n keystroke keeps its DOM node, so its entrance animation is not\n re-run and the list settles instead of flashing. Keyed by index,\n every row below a filtered-out one would be reused for different\n content while the tail remounted — an animation playing on the\n wrong rows.\n\n `text-value` pins the filter to the label. Left off, Reka falls\n back to whatever the row happens to render, which is the label\n today and the label plus a badge, a hint or a count the first\n time a row grows one. -->\n <ComboboxItem\n v-for=\"(option, index) in options\"\n :key=\"option.value\"\n :value=\"option.value\"\n :text-value=\"option.label\"\n :disabled=\"option.disabled ?? false\"\n :style=\"{ animationDelay: revealing ? listStaggerDelay(index) : '0ms' }\"\n :class=\"\n cn(\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-3 py-1.5 pr-8 text-sm text-foreground outline-none',\n 'transition-colors duration-fast ease-out',\n 'animate-fade-rise',\n 'data-[highlighted]:bg-subtle',\n 'data-[state=checked]:bg-primary-muted data-[state=checked]:text-primary-text',\n // Inert, but still readable. `data-[disabled]:opacity-50` took\n // the label to 3.13:1 on the popover; the colour on the span\n // below leaves it at 5.76:1 and still visibly lighter than the\n // rows around it.\n 'data-[disabled]:pointer-events-none',\n )\n \"\n >\n <!-- The mute lives on this span rather than on the row, and it has\n to. `data-[disabled]:` sorts *before* `data-[state=checked]:`\n in Tailwind's variant order, so a disabled row that is also the\n chosen one would take `text-primary-text` from the container — and a\n container colour is only inherited. Declared here it wins\n whatever the row resolved to. -->\n <span :class=\"option.disabled && 'text-muted-foreground'\">{{ option.label }}</span>\n <ComboboxItemIndicator class=\"absolute right-2 inline-flex items-center\">\n <Check class=\"h-4 w-4\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxViewport>\n </ComboboxContent>\n </ComboboxPortal>\n </ComboboxRoot>\n</template>\n"],"mappings":""}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Combobox.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../packages/primitives/combobox/src/Combobox.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { ComboboxLabels } from \"@ecoma-io/loom-labels\";\nimport { cva } from \"class-variance-authority\";\n\n/**\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it, and\n * exported so a host can build a partial vocabulary against the real thing.\n */\nexport const COMBOBOX_LABELS: ComboboxLabels = {\n trigger: \"Show options\",\n empty: \"No results\",\n count: ({ count }) => `${String(count)} selected`,\n overflow: ({ hidden }) => `+${String(hidden)} more`,\n};\n\n/**\n * One row of the list. `value` is what the model carries; `label` is what a\n * reader sees, what the filter matches, and what the input shows once the row\n * is chosen.\n *\n * Identical to `SelectOption` today, and deliberately not the same\n * declaration: the two surfaces are independent, and the first field either\n * one grows — a secondary line here, a group key there — is a field the other\n * should not inherit by accident. A shared alias would make that change look\n * free when it is not.\n */\nexport interface ComboboxOption {\n /** The value bound to `v-model` when this row is chosen. Unique within the list. */\n value: string;\n /** The text shown on the row, matched by the filter, and put in the input once chosen. */\n label: string;\n /** Present but unchoosable — visible, skipped by the keyboard, unclickable. */\n disabled?: boolean;\n}\n\n/**\n * The control's height scale. It matches the text input and Select scales\n * exactly, so a form row mixing a Combobox beside either never comes out\n * uneven — which is why reaching past `size` for an `h-*` class is always the\n * wrong fix.\n */\nexport type ComboboxSize = \"sm\" | \"md\" | \"lg\";\n\nexport const comboboxVariants = cva(\n [\n \"flex w-full items-center gap-2 rounded-md border border-input bg-background text-foreground\",\n \"transition-[color,background-color,border-color,box-shadow] duration-fast ease-out\",\n // The focusable node is the input *inside* this box, so the ring is drawn\n // with `focus-within` rather than `focus-visible` — the same choice\n // TextField makes for the same reason, and what keeps the two controls\n // lighting up identically in a form row.\n \"focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring\",\n ],\n {\n // `satisfies` keeps the two halves honest: the union above is the name a\n // consumer imports and the documentation prints, the map below is the\n // classes. Adding a member to one and not the other stops compiling.\n variants: {\n size: {\n sm: \"h-8 px-2.5 text-xs\",\n md: \"h-9 px-3 text-sm\",\n lg: \"h-11 px-4 text-base\",\n } satisfies Record<ComboboxSize, string>,\n },\n defaultVariants: { size: \"md\" },\n },\n);\n\n/**\n * The same three numbers as a floor rather than as a fixed height, for the\n * multi-select box only.\n *\n * A box holding tokens is sized by its content, which is TagsInput's call and\n * the reason its field is `min-h-9`. What keeps that from turning into an\n * unbounded control here is `visibleValues`: the token row never wraps, so in\n * practice the box resolves to exactly the height above and a multi-select\n * still lines up with the single-select beside it. The `h-auto` that goes with\n * it in the template is what releases the fixed height `comboboxVariants`\n * already set — Tailwind's merge resolves the two, `min-h-*` does not.\n */\nconst multiSelectHeights = {\n sm: \"min-h-8\",\n md: \"min-h-9\",\n lg: \"min-h-11\",\n} satisfies Record<ComboboxSize, string>;\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from \"vue\";\nimport {\n ComboboxRoot,\n ComboboxAnchor,\n ComboboxInput,\n ComboboxTrigger,\n ComboboxPortal,\n ComboboxContent,\n ComboboxViewport,\n ComboboxItem,\n ComboboxItemIndicator,\n ComboboxEmpty,\n} from \"reka-ui\";\nimport { Check, ChevronDown } from \"@lucide/vue\";\nimport Chip from \"@ecoma-io/loom-chip\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { listStaggerDelay } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { useFieldControl } from \"@ecoma-io/loom-labels\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\nimport { optional } from \"@ecoma-io/loom-core\";\n\n/**\n * Combobox — a text input that narrows a list as you type, for the list too\n * long to scan. Countries, currencies, repositories, people: anywhere a reader\n * knows roughly what they are looking for and would rather type three letters\n * than scroll past two hundred rows.\n *\n * Its neighbour is `Select`, and the boundary is the length of the list rather\n * than the shape of the control. Three to fifteen rows a reader can read\n * through belong in a Select — a search box over eight options is a keystroke\n * charged for nothing. Two to five options that should all be visible at once\n * belong in a segmented control. Past roughly fifteen, searching beats\n * scrolling and this is the control that offers it.\n *\n * Built on Reka UI's Combobox, which supplies the editable-combobox semantics:\n * the `role=\"combobox\"` input wired to the listbox by `aria-expanded` and\n * `aria-controls`, `aria-autocomplete=\"list\"`, and the active row tracked by\n * `aria-activedescendant` while real focus stays in the input. That last part\n * is the one genuine behavioural difference from Select, which moves focus\n * onto the row itself — a combobox cannot, because the reader is still typing.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself: the row's id, the id of\n * its hint or error line, `required`, `invalid`, `disabled` and the name the\n * chosen value is submitted under all arrive through `useFieldControl()`, so\n * `<Field label=\"Country\" error=\"…\"><Combobox … /></Field>` needs no attributes\n * at the call site. Both booleans below still win over the row when they are\n * set, in both directions — which is why they default to `undefined` rather\n * than `false`.\n *\n * A row's `readonly` is deliberately ignored. The text in the box is not the\n * value — it is the chosen option's label, rewritten on every choice — so a\n * `readonly` input here would freeze a caption rather than protect a value,\n * while the list underneath still opened on click. A choice nobody may change\n * is a disabled Combobox, or the label rendered as text.\n *\n * `multiple` turns it into a many-of-many picker. The chosen values render as\n * tokens in the box — the same `Chip` a\n * [TagsInput](../TagsInput/TagsInput.vue) commits its values to, so a selection\n * looks the same wherever a form shows one — and the input goes back to being\n * only a search box. The tokens are **inert**, deliberately: the list is where\n * a choice is made and where it is unmade, so the control stays the single Tab\n * stop it is in single-select, and a value hidden behind the overflow count is\n * reachable by exactly the same gesture as a visible one. That is the one place\n * this diverges from TagsInput, whose tokens carry their own remove control\n * because it has no list to send a reader back to.\n */\nconst props = withDefaults(\n defineProps<{\n /**\n * The chosen option's `value`, or every chosen value when `multiple`.\n *\n * The union is one prop rather than a generic component, and the invariant\n * is the mode: single-select emits and accepts a `string` and never an\n * array, multi-select an array and never a bare string. A generic would\n * express that in the type system and cost more than it buys — it would\n * print a conditional type in the generated API table below, and it would\n * break `InstanceType<typeof Combobox>`, which is how a consumer types a\n * template ref.\n */\n modelValue?: string | string[] | undefined;\n /** The rows, in the order they are shown. */\n options: ComboboxOption[];\n /** Lets several rows be chosen at once: chosen rows toggle instead of closing the list, and the box shows the selection as tokens. */\n multiple?: boolean;\n /**\n * How many tokens the box shows before the rest collapse into a count.\n *\n * The box must not grow with the selection — it sits in a form row beside\n * controls on a fixed height scale — so past this many the tail becomes one\n * `labels.overflow` summary: five chosen shows three and \"+2 more\", fifty\n * shows three and \"+47 more\". Raise it for a wide box; the row never wraps,\n * so a number the box has no room for is a number that truncates.\n */\n visibleValues?: number;\n /** Shown in the empty input, before anything is typed or chosen. */\n placeholder?: string;\n /** Shown as a row of its own when the filter matches nothing. Defaults to `labels.empty`, so say what was searched for rather than restating the default in a second language. */\n emptyMessage?: string | undefined;\n /** Unavailable: dims the control, refuses to open and refuses to take text. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Error state: paints the destructive border and ring, and sets `aria-invalid`. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** Control height. It shares the text input scale so mixed form rows stay aligned. */\n size?: ComboboxSize;\n /**\n * Filter `options` against the typed text. Turn it off when the host is\n * producing the list itself — from a server, in response to\n * `update:query` — so a result that does not literally contain what was\n * typed is not then hidden a second time by a filter running underneath it.\n */\n filter?: boolean;\n /**\n * Names for the two strings this control supplies itself, as any subset of\n * `ComboboxLabels` — the rest stay as the host's `provideLoomLabels`\n * vocabulary left them, and then as Loom's English.\n *\n * This is the per-instance correction, not the place to localise an\n * application. `emptyMessage` is the shorter way to reach `empty` for one\n * box; this is what reaches `trigger`.\n */\n labels?: LabelOverrides<ComboboxLabels>;\n }>(),\n {\n // `modelValue: undefined` is load-bearing rather than redundant: paired\n // with `optional()` below it is what keeps the uncontrolled third state\n // reachable, instead of pinning the control to a value nobody chose.\n modelValue: undefined,\n multiple: false,\n // Three, and the number is a judgement rather than a measurement: two\n // tokens plus a count reads as a control that shows almost nothing, and\n // four leaves a `md` box no room to type in at the default width. It is a\n // prop because the right answer is the box's width, which only the caller\n // knows.\n visibleValues: 3,\n // No English default here any more. The wording moved into `COMBOBOX_LABELS`\n // so a host can set it once for the whole application rather than on every\n // box, and an absent prop is what lets the resolved label through.\n emptyMessage: undefined,\n // Not `false`, for either. `false` is a caller saying \"this control is fine\n // / enabled even though its row is not\"; absent is a caller saying nothing,\n // and only `undefined` survives to mean that past Vue's\n // absent-Boolean-casts-to-false rule — see TextField.vue, which carries the\n // full reasoning.\n disabled: undefined,\n invalid: undefined,\n size: \"md\",\n filter: true,\n },\n);\n\nconst emit = defineEmits<{\n /** The chosen option's `value` — or the whole chosen list, when `multiple`. Single-select fires once per choice and the list closes with it; multi-select fires once per toggle and the list stays open. */\n \"update:modelValue\": [value: string | string[]];\n /** The text now in the input — as the reader types, and again when a choice puts its label there. */\n \"update:query\": [query: string];\n}>();\n\n// `text`, not `labels`: the prop of that name is one of the three sources this\n// resolves, and a template reading the raw prop would be reading the overrides\n// rather than the answer.\nconst text = useLabels(\"combobox\", COMBOBOX_LABELS, () => props.labels);\n\nconst query = ref(\"\");\n\n/**\n * The stagger is the list's *reveal*, and re-filtering is not a reveal. This\n * is true from the moment the list opens until the first keystroke, after\n * which every row arrives immediately.\n *\n * Two things go wrong without it. A delay recomputed per keystroke makes the\n * list feel like it is rebuilding under the reader's fingers — the opposite of\n * what a filter is for. And raising `animation-delay` on a row that survived\n * the keystroke rewinds its entrance: the row is still mounted, so the\n * animation is not restarted, it is re-timed, and a row that had finished\n * fading in drops back to half-opacity. Going the other way — stagger to `0ms`\n * — only ever fast-forwards, which is why this flag falls and does not rise\n * again until the content has unmounted and remounted with the next open.\n */\nconst revealing = ref(true);\n\nconst countId = useId();\n\n/**\n * The multi-select's own copy of the selection, and the reason it keeps one:\n * the tokens have to render whether or not the host bound `v-model`.\n *\n * Left uncontrolled, `modelValue` stays `undefined` while Reka manages the\n * choice internally — which is the third state `optional()` exists to preserve\n * — so a trigger reading the prop would sit empty while the list showed three\n * checked rows. This mirrors rather than drives: it is never fed back into\n * Reka, so nothing about the uncontrolled control changes.\n *\n * Seeded from the prop rather than sanitised, for TagsInput's reason: a list\n * the host already holds is the host's to hold.\n */\nconst selected = ref<string[]>(Array.isArray(props.modelValue) ? [...props.modelValue] : []);\nwatch(\n () => props.modelValue,\n (next) => {\n if (Array.isArray(next)) selected.value = [...next];\n },\n // Shallow, deliberately: the contract is whole-list replacement — Reka hands\n // back the complete selection on every toggle and a host echoes it straight\n // back down — so in-place mutation is not a case this mirror owes anyone.\n);\n\n/**\n * The chosen values as the box shows them, and the fallback is the point: a\n * host driving `options` from a search hands back only the rows matching the\n * current query, so a value chosen from an earlier one has no option to look\n * its label up in. Falling back to the value keeps the token on screen — a\n * chosen value that vanished from the trigger while it was still in the model\n * would be the control lying about what it holds.\n */\nconst tokens = computed(() =>\n selected.value.map((value) => ({\n value,\n label: props.options.find((option) => option.value === value)?.label ?? value,\n })),\n);\n\nconst visibleTokens = computed(() => tokens.value.slice(0, Math.max(0, props.visibleValues)));\nconst hiddenTokens = computed(() => tokens.value.length - visibleTokens.value.length);\n\n/**\n * What the input shows once a row is chosen. Without this Reka falls back to\n * the model value's own `toString()`, which would leave `en` in the box where\n * the reader picked \"English\".\n *\n * A multi-select shows nothing: the tokens are the selection, and the input\n * beside them is a search box. Reka calls this on close rather than on choose,\n * so the query the reader typed survives every toggle and one search can pick\n * several rows — which is the whole reason the list stays open.\n */\nfunction displayValue(value: unknown): string {\n if (props.multiple) return \"\";\n return props.options.find((option) => option.value === value)?.label ?? \"\";\n}\n\n/**\n * Reka hands back the whole selection on every toggle, never a delta, so the\n * emitted array is always the complete list — the same contract TagsInput's\n * `update:modelValue` carries, and the reason a host can assign it straight\n * back.\n */\nfunction onChoice(value: unknown): void {\n if (!props.multiple) {\n emit(\"update:modelValue\", String(value));\n return;\n }\n const values = Array.isArray(value) ? value.map(String) : [];\n selected.value = values;\n emit(\"update:modelValue\", values);\n}\n\nfunction onQuery(text: string): void {\n // Reka rewrites the input's text on its own account — once as the component\n // mounts, and again when a choice puts the chosen label back in the box —\n // and each of those arrives here as an update. Reporting a query that did\n // not change would have a host running the same search twice on mount, so\n // only a real change is passed on.\n if (text === query.value) return;\n query.value = text;\n revealing.value = false;\n emit(\"update:query\", text);\n}\n\n// The root renders no DOM node of its own, so fallthrough attributes would be\n// dropped on the floor. They go to the input, which is the element they\n// describe and the only one a name can land on — the chevron trigger already\n// carries Reka's own `aria-label`, and naming the control means naming the\n// `role=\"combobox\"` node.\n//\n// `class` is pulled out of that spread and merged through `cn()` onto the\n// anchor instead, because the anchor is the box a caller means when they pass\n// `w-64`. Spreading it alongside the anchor's own `:class` would only\n// concatenate the two lists — Vue's merge is generic, not Tailwind-aware — so\n// a caller's width would win or lose depending on which utility Tailwind\n// happened to emit last.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\n\n// `id` and `aria-describedby` reach this control as fallthrough attrs rather\n// than props, so they are read off `attrs` and handed in as this caller's own\n// values — a caller who sets either still beats the row, and the row's\n// description is merged into theirs rather than replacing it. `name`,\n// `readonly` and `required` are absent from this object because there is no\n// prop to oppose the row with; the row's answer stands unopposed, which is\n// what is wanted.\n//\n// The multi-select's count joins that list rather than replacing anything: it\n// is one more thing this control says about itself, and it reads after the\n// caller's own description and before the row's message — the same\n// most-specific-first order `useFieldControl` applies one layer out. Wired\n// through `aria-describedby` rather than announced, which is TagsInput's call\n// for the same fact: it is heard on focus and on every return to the box, which\n// is when the question is asked, and a live region would speak the whole total\n// over the top of the `aria-selected` change the row itself already announces.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [attrs[\"aria-describedby\"] as string | undefined, props.multiple ? countId : \"\"]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n disabled: props.disabled,\n invalid: props.invalid,\n}));\n\n// `name` is the one resolved key that does not travel with the bag, and here\n// it is a defect rather than a nicety: the bag lands on the input, and what\n// the input holds is the chosen option's *label*. A `name` on it would post\n// \"Viet Nam\" where the model carries `vn`. Reka submits the value itself\n// through a hidden control it renders from the root's own `name`, so that is\n// where the row's name goes. Everything else in the bag — the id, the merged\n// description, `aria-required`, `aria-invalid` — belongs on the\n// `role=\"combobox\"` node, which is the input.\nconst inputFieldAttrs = computed(() => {\n // Removed from a copy rather than listed positively, so a key added to the\n // resolved bag later reaches this input without anyone remembering to come\n // back here.\n const aria: Record<string, unknown> = { ...field.attrs };\n delete aria.name;\n return aria;\n});\n</script>\n\n<template>\n <!-- `open-on-click` and not `open-on-focus`: clicking the box is a reader\n asking to see the list, while focus arrives by Tab as often as by\n intent, and a list that unfolds over the next field every time someone\n tabs through a form is an obstruction. Typing opens it either way. -->\n <ComboboxRoot\n v-bind=\"optional({ modelValue, name: field.name })\"\n :multiple=\"multiple\"\n :disabled=\"field.disabled\"\n :ignore-filter=\"!filter\"\n open-on-click\n @update:model-value=\"onChoice\"\n @update:open=\"revealing = true\"\n >\n <ComboboxAnchor\n :data-disabled=\"field.disabled || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :class=\"\n cn(\n comboboxVariants({ size }),\n // A box holding tokens is sized by them — see `multiSelectHeights`.\n // `h-auto` is what releases the fixed height the variant just set;\n // Tailwind's merge resolves two `h-*` utilities and leaves a `min-h-*`\n // beside either of them alone.\n multiple && ['h-auto', multiSelectHeights[size], 'gap-1.5'],\n !field.invalid && 'focus-within:shadow-halo',\n field.invalid && 'border-destructive focus-within:outline-destructive',\n // The box holds the chosen value, so it is drained rather than\n // dimmed: `opacity-50` composited the input's text down to 3.06:1,\n // and what a reader needs from an unavailable Combobox is precisely\n // what it is set to. The neutral well says unavailable on its own —\n // the input's own `disabled:text-muted-foreground` below carries the\n // text to 4.67:1 over it.\n //\n // The hairline recedes with the fill, and that second channel is the\n // point: unavailable is a difference in *shape* as well as in colour,\n // so it survives a reader who cannot resolve `muted` from\n // `background`. This control has no read-only state to be told apart\n // from — see the docblock — so it takes the unavailable row alone.\n field.disabled && 'cursor-not-allowed border-border bg-muted text-muted-foreground',\n attrs.class as string,\n )\n \"\n >\n <!-- The selection, as the tokens a TagsInput commits its values to, so a\n chosen set looks the same wherever a form shows one. Inert on\n purpose: the list is where a value is chosen and where it is\n unchosen, which keeps the whole control one Tab stop and keeps a\n value behind the overflow count reachable by the same gesture as a\n visible one. -->\n <template v-if=\"multiple\">\n <Chip\n v-for=\"token in visibleTokens\"\n :key=\"token.value\"\n size=\"sm\"\n :disabled=\"field.disabled\"\n class=\"min-w-0 animate-fade-rise\"\n >\n {{ token.label }}\n </Chip>\n <!-- Not a token: it stands for values rather than being one, and a\n fourth pill saying \"+47 more\" would read as a forty-eighth\n choice. -->\n <span v-if=\"hiddenTokens > 0\" class=\"tabular shrink-0 text-small text-muted-foreground\">\n {{ text.overflow({ hidden: hiddenTokens }) }}\n </span>\n </template>\n\n <ComboboxInput\n v-bind=\"{ ...inputAttrs, ...inputFieldAttrs }\"\n :model-value=\"query\"\n :display-value=\"displayValue\"\n :placeholder=\"multiple && tokens.length > 0 ? undefined : placeholder\"\n class=\"min-w-6 flex-1 self-stretch bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:text-muted-foreground\"\n @update:model-value=\"onQuery\"\n />\n <!-- Reka takes this button out of the tab order itself, so the whole\n control is one Tab stop: the input. It also names it, in English —\n `aria-label=\"Show popup\"`, written inside its own render function\n with no prop to reach it by — and the binding below replaces that\n rather than competing with it, because Vue merges a fallthrough\n attribute onto the root vnode after the render function produced it.\n Removing it does not fall back to nothing; it falls back to Reka's\n English, which no test of Loom's own strings would catch. -->\n <ComboboxTrigger\n :aria-label=\"text.trigger\"\n class=\"group min-h-6 min-w-6 shrink-0 text-muted-foreground disabled:cursor-not-allowed\"\n >\n <ChevronDown\n class=\"h-4 w-4 transition-transform duration-fast ease-out group-data-[state=open]:rotate-180\"\n />\n </ComboboxTrigger>\n\n <!-- The size of the selection, and the only thing that carries it to a\n reader who cannot see the tokens: the visible row shows the first few\n and a count for the rest, and neither is announced. Reka publishes\n nothing of the sort — the listbox's `aria-multiselectable` says the\n control takes several values, never how many it holds. -->\n <span v-if=\"multiple\" :id=\"countId\" class=\"sr-only\">\n {{ text.count({ count: tokens.length }) }}\n </span>\n </ComboboxAnchor>\n\n <ComboboxPortal>\n <ComboboxContent\n position=\"popper\"\n :side-offset=\"6\"\n :class=\"\n cn(\n 'z-overlay max-h-72 min-w-[var(--reka-combobox-trigger-width)] overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md',\n // Each half of the motion is scoped to its own state, never\n // unconditional. Closing swaps the computed animation-name to\n // fade-fall's, which is what Reka's Presence reads: it holds the\n // panel mounted until that exit's animationend and only then takes\n // it away. Unconditional, a finished entrance animation sat on the\n // closed element and stranded it invisible over the page, eating\n // clicks.\n 'data-[state=open]:animate-fade-rise data-[state=closed]:animate-fade-fall',\n )\n \"\n >\n <ComboboxViewport class=\"p-1\">\n <!-- A filter that matches nothing has to say so. An empty popover\n reads as a broken one, and a screen reader is told nothing at\n all — so the message is a row inside the listbox rather than a\n caption beside it. `role=\"option\"` because a bare div is not a\n legitimate child of `role=\"listbox\"` and is skipped; disabled\n because it is a statement, not a choice. -->\n <ComboboxEmpty\n role=\"option\"\n aria-disabled=\"true\"\n class=\"animate-fade-rise px-3 py-1.5 text-sm text-muted-foreground\"\n >\n {{ emptyMessage ?? text.empty }}\n </ComboboxEmpty>\n\n <!-- Keyed by value rather than by index: a row that survives a\n keystroke keeps its DOM node, so its entrance animation is not\n re-run and the list settles instead of flashing. Keyed by index,\n every row below a filtered-out one would be reused for different\n content while the tail remounted — an animation playing on the\n wrong rows.\n\n `text-value` pins the filter to the label. Left off, Reka falls\n back to whatever the row happens to render, which is the label\n today and the label plus a badge, a hint or a count the first\n time a row grows one. -->\n <ComboboxItem\n v-for=\"(option, index) in options\"\n :key=\"option.value\"\n :value=\"option.value\"\n :text-value=\"option.label\"\n :disabled=\"option.disabled ?? false\"\n :style=\"{ animationDelay: revealing ? listStaggerDelay(index) : '0ms' }\"\n :class=\"\n cn(\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-3 py-1.5 pr-8 text-sm text-foreground outline-none',\n 'transition-colors duration-fast ease-out',\n 'animate-fade-rise',\n 'data-[highlighted]:bg-subtle',\n 'data-[state=checked]:bg-primary-muted data-[state=checked]:text-primary-text',\n // Inert, but still readable. `data-[disabled]:opacity-50` took\n // the label to 3.13:1 on the popover; the colour on the span\n // below leaves it at 5.76:1 and still visibly lighter than the\n // rows around it.\n 'data-[disabled]:pointer-events-none',\n )\n \"\n >\n <!-- The mute lives on this span rather than on the row, and it has\n to. `data-[disabled]:` sorts *before* `data-[state=checked]:`\n in Tailwind's variant order, so a disabled row that is also the\n chosen one would take `text-primary-text` from the container — and a\n container colour is only inherited. Declared here it wins\n whatever the row resolved to. -->\n <span :class=\"option.disabled && 'text-muted-foreground'\">{{ option.label }}</span>\n <ComboboxItemIndicator class=\"absolute right-2 inline-flex items-center\">\n <Check class=\"h-4 w-4\" />\n </ComboboxItemIndicator>\n </ComboboxItem>\n </ComboboxViewport>\n </ComboboxContent>\n </ComboboxPortal>\n </ComboboxRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,IAAa,kBAAkC;CAC7C,SAAS;CACT,OAAO;CACP,QAAQ,EAAE,YAAY,GAAG,OAAO,KAAK,EAAE;CACvC,WAAW,EAAE,aAAa,IAAI,OAAO,MAAM,EAAE;AAC/C;AA8BA,IAAa,mBAAmB,IAC9B;CACE;CACA;CAKA;AACF,GACA;CAIE,UAAU,EACR,MAAM;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;CACN,EACF;CACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CACF;;;;;;;;;;;;;AAcA,IAAM,qBAAqB;CACzB,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuEA,MAAM,QAAQ;EAoFd,MAAM,OAAO;EAUb,MAAM,OAAO,UAAU,YAAY,uBAAuB,MAAM,MAAM;EAEtE,MAAM,QAAQ,IAAI,EAAE;;;;;;;;;;;;;;;EAgBpB,MAAM,YAAY,IAAI,IAAI;EAE1B,MAAM,UAAU,MAAM;;;;;;;;;;;;;;EAetB,MAAM,WAAW,IAAc,MAAM,QAAQ,MAAM,UAAU,IAAI,CAAC,GAAG,MAAM,UAAU,IAAI,CAAC,CAAC;EAC3F,YACQ,MAAM,aACX,SAAS;GACR,IAAI,MAAM,QAAQ,IAAI,GAAG,SAAS,QAAQ,CAAC,GAAG,IAAI;EACpD,CAIF;;;;;;;;;EAUA,MAAM,SAAS,eACb,SAAS,MAAM,KAAK,WAAW;GAC7B;GACA,OAAO,MAAM,QAAQ,MAAM,WAAW,OAAO,UAAU,KAAK,CAAC,EAAE,SAAS;EAC1E,EAAE,CACJ;EAEA,MAAM,gBAAgB,eAAe,OAAO,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC;EAC5F,MAAM,eAAe,eAAe,OAAO,MAAM,SAAS,cAAc,MAAM,MAAM;;;;;;;;;;;EAYpF,SAAS,aAAa,OAAwB;GAC5C,IAAI,MAAM,UAAU,OAAO;GAC3B,OAAO,MAAM,QAAQ,MAAM,WAAW,OAAO,UAAU,KAAK,CAAC,EAAE,SAAS;EAC1E;;;;;;;EAQA,SAAS,SAAS,OAAsB;GACtC,IAAI,CAAC,MAAM,UAAU;IACnB,KAAK,qBAAqB,OAAO,KAAK,CAAC;IACvC;GACF;GACA,MAAM,SAAS,MAAM,QAAQ,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,CAAC;GAC3D,SAAS,QAAQ;GACjB,KAAK,qBAAqB,MAAM;EAClC;EAEA,SAAS,QAAQ,MAAoB;GAMnC,IAAI,SAAS,MAAM,OAAO;GAC1B,MAAM,QAAQ;GACd,UAAU,QAAQ;GAClB,KAAK,gBAAgB,IAAI;EAC3B;EAeA,MAAM,EAAE,OAAO,MAAM,eAAe,cAAc;EAkBlD,MAAM,QAAQ,uBAAuB;GACnC,IAAI,MAAM;GACV,aAAa,CAAC,MAAM,qBAA2C,MAAM,WAAW,UAAU,EAAE,CAAA,CACzF,QAAQ,OAAqB,OAAO,OAAO,YAAY,GAAG,SAAS,CAAC,CAAA,CACpE,KAAK,GAAG;GACX,UAAU,MAAM;GAChB,SAAS,MAAM;EACjB,EAAE;EAUF,MAAM,kBAAkB,eAAe;GAIrC,MAAM,OAAgC,EAAE,GAAG,MAAM,MAAM;GACvD,OAAO,KAAK;GACZ,OAAO;EACT,CAAC;;GAQC,OAAA,UAAA,GAAA,YAkLe,MAAA,YAAA,GAlLf,WACU,MAiLK,QAAA,CAjLG,CAAA;IAAA,YAAG,QAAA;IAAU,MAAQ,MAAA,KAAA,CAAK,CAAC;GAAI,CAAA,GAAA;IAC9C,UAAU,QAAA;IACV,UAAU,MAAA,KAAA,CAAK,CAAC;IAChB,iBAAa,CAAG,QAAA;IACjB,iBAAA;IACC,uBAAoB;IACpB,iBAAW,OAAA,OAAA,OAAA,MAAA,WAAE,UAAA,QAAS;;IAEvB,SAAA,cAuFiB,CAvFjB,YAuFiB,MAAA,cAAA,GAAA;KAtFd,iBAAe,MAAA,KAAA,CAAK,CAAC,YAAY,KAAA;KACjC,gBAAc,MAAA,KAAA,CAAK,CAAC,WAAW,KAAA;KAC/B,OAAK,eAAW,MAAA,EAAA,CAAE,CAAY,MAAA,gBAAA,CAAgB,CAAA,EAAA,MAAG,QAAA,KAAI,CAAA,GAAwS,QAAA,YAAQ;MAAA;MAAe,mBAAmB,QAAA;MAAI;KAAA,GAA0B,CAAA,MAAA,KAAA,CAAK,CAAC,WAAO,4BAA0C,MAAA,KAAA,CAAK,CAAC,WAAO,uDAAi4B,MAAA,KAAA,CAAK,CAAC,YAAQ,mEAAiF,MAAA,KAAA,CAAK,CAAC,KAAA,CAAA;;KAiCh9C,SAAA,cAgBW;MAhBK,QAAA,YAAhB,UAAA,GAAA,mBAgBW,UAAA,EAAA,KAAA,EAAA,GAAA,EAfT,UAAA,IAAA,GAAA,mBAQO,UAAA,MAAA,WAPW,cAAA,QAAT,UAAK;OADd,OAAA,UAAA,GAAA,YAQO,MAAA,YAAA,GAAA;QANJ,KAAK,MAAM;QACZ,MAAK;QACJ,UAAU,MAAA,KAAA,CAAK,CAAC;QACjB,OAAM;;QAEN,SAAA,cAAiB,CAAd,gBAAA,gBAAA,MAAM,KAAK,GAAA,CAAA,CAAA,CAAA;;;MAKJ,CAAA,GAAA,GAAA,IAAA,aAAA,QAAY,KAAxB,UAAA,GAAA,mBAEO,QAFP,YAEO,gBADF,MAAA,IAAA,CAAI,CAAC,SAAQ,EAAA,QAAW,aAAA,MAAY,CAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,EAAA,KAAA,mBAAA,IAAA,IAAA;MAI3C,YAOE,MAAA,aAAA,GAPF,WAOE;OAAA,GANa,MAAA,UAAA;OAAU,GAAK,gBAAA;MAAe,GAAA;OAC1C,eAAa,MAAA;OACb,iBAAe;OACf,aAAa,QAAA,YAAY,OAAA,MAAO,SAAM,IAAO,KAAA,IAAY,QAAA;OAC1D,OAAM;OACL,uBAAoB;;MAUvB,YAOkB,MAAA,eAAA,GAAA;OANf,cAAY,MAAA,IAAA,CAAI,CAAC;OAClB,OAAM;;OAEN,SAAA,cAEE,CAFF,YAEE,MAAA,WAAA,GAAA,EADA,OAAM,yFAAwF,CAAA,CAAA,CAAA;;;MAStF,QAAA,YAAZ,UAAA,GAAA,mBAEO,QAAA;;OAFgB,IAAI,MAAA,OAAA;OAAS,OAAM;MACrC,GAAA,gBAAA,MAAA,IAAA,CAAI,CAAC,MAAK,EAAA,OAAU,OAAA,MAAO,OAAM,CAAA,CAAA,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA;;;;;;;IAIxC,CAAA,GAAA,YA+EiB,MAAA,cAAA,GAAA,MAAA;KA9Ef,SAAA,cA6EkB,CA7ElB,YA6EkB,MAAA,eAAA,GAAA;MA5EhB,UAAS;MACR,eAAa;MACb,OAAK,eAAa,MAAA,EAAA,CAAE,CAAA,8JAAA,2EAAA,CAAA;;MAcrB,SAAA,cA2DmB,CA3DnB,YA2DmB,MAAA,gBAAA,GAAA,EA3DD,OAAM,MAAK,GAAA;OAO3B,SAAA,cAMgB,CANhB,YAMgB,MAAA,aAAA,GAAA;QALd,MAAK;QACL,iBAAc;QACd,OAAM;;QAEN,SAAA,cAAgC,CAA7B,gBAAA,gBAAA,QAAA,gBAAgB,MAAA,IAAA,CAAI,CAAC,KAAK,GAAA,CAAA,CAAA,CAAA;;OAc/B,CAAA,IAAA,UAAA,IAAA,GAAA,mBAgCe,UAAA,MAAA,WA/Ba,QAAA,UAAlB,QAAQ,UAAK;QADvB,OAAA,UAAA,GAAA,YAgCe,MAAA,YAAA,GAAA;SA9BZ,KAAK,OAAO;SACZ,OAAO,OAAO;SACd,cAAY,OAAO;SACnB,UAAU,OAAO,YAAQ;SACzB,OAAK,eAAA,EAAA,gBAAoB,UAAA,QAAY,MAAA,gBAAA,CAAgB,CAAC,KAAK,IAAA,MAAA,CAAA;SAC3D,OAAK,eAAiB,MAAA,EAAA,CAAE,CAAA,gIAAA,4CAAA,qBAAA,gCAAA,gFAAA,qCAAA,CAAA;;SAqBzB,SAAA,cAAmF,CAAnF,mBAAmF,QAAA,EAA5E,OAAK,eAAE,OAAO,YAAQ,uBAAA,EAAgC,GAAA,gBAAA,OAAO,KAAK,GAAA,CAAA,GACzE,YAEwB,MAAA,qBAAA,GAAA,EAFD,OAAM,4CAA2C,GAAA;UACtE,SAAA,cAAyB,CAAzB,YAAyB,MAAA,KAAA,GAAA,EAAlB,OAAM,UAAS,CAAA,CAAA,CAAA"}
@@ -0,0 +1,7 @@
1
+ import Command_vue_vue_type_script_setup_true_lang_default, { COMMAND_LABELS } from "./Command.vue_vue_type_script_setup_true_lang.js";
2
+ //#region packages/primitives/command/src/Command.vue
3
+ var Command_default = Command_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { COMMAND_LABELS, Command_default as default };
6
+
7
+ //# sourceMappingURL=Command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Command.js","names":[],"sources":["../../../../packages/primitives/command/src/Command.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { CommandLabels, LabelOverrides } from \"@ecoma-io/loom-labels\";\n/**\n * One searchable item in the command list. `value` is what the host receives on\n * select; `label` is what the reader sees and what the filter matches against.\n *\n * Deliberately not `ComboboxOption` or `DropdownMenuEntry`: those shapes carry\n * `modelValue` and `separator` fields respectively, and either would be\n * dead weight here — a command is an action, not a value or a menu row.\n */\nexport interface CommandItem {\n /** Unique key. */\n value: string;\n /** Visible label. */\n label: string;\n /** Optional description shown below the label. */\n description?: string;\n /** Group heading this item belongs to. */\n group?: string;\n /** Disabled state. */\n disabled?: boolean;\n}\n\n/**\n * A named section heading above a run of items. Only rendered when the group\n * contains at least one item that survived the current filter.\n */\nexport interface CommandGroup {\n /** Group heading text. */\n heading: string;\n}\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it.\n * Every string a Command actually says is the chrome around the host's items,\n * so the whole slot is here and none of it hides in the template.\n */\nexport const COMMAND_LABELS: CommandLabels = {\n placeholder: \"Type to search…\",\n emptyMessage: \"No results found.\",\n searchLabel: \"Search\",\n resultSingular: \"{count} result available\",\n resultPlural: \"{count} results available\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useId, watch } from \"vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { useLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n * Command — a keyboard-driven command search, the universal \"Cmd+K\" pattern.\n *\n * A text input that narrows a grouped list as you type, for executing actions\n * rather than selecting values. Its neighbour is `Combobox`, which selects a\n * value for a form field; this control runs an action and has no `modelValue`.\n *\n * The two are one family in the same way a Combobox and a Select are: the same\n * surface vocabulary, the same tokens, the same keyboard model. What differs is\n * intent — \"open settings\" is not a value you could submit in a form — and that\n * intent shapes the API: `onSelect` rather than `v-model`.\n *\n * Built from native ARIA roles rather than Reka UI, because Reka ships no\n * Command primitive. The semantics follow the WAI-ARIA combobox pattern with\n * `aria-activedescendant` navigation: focus stays in the input while the\n * highlighted item moves, which is the only model that keeps typing fluid.\n *\n * `aria-expanded` is deliberately absent. The input is a fixed searchbox, not\n * a popover trigger, so it has no collapsed state to announce: the listbox is\n * visible on mount and returns on any interaction after Escape closes it.\n */\nconst props = withDefaults(\n defineProps<{\n /** The items to search through. */\n items: CommandItem[];\n /** Optional group definitions for section headers. */\n groups?: CommandGroup[];\n /** Controlled search query. */\n query?: string | undefined;\n /** Whether the command menu is open. */\n open?: boolean | undefined;\n /** Names for the strings this control supplies itself. */\n labels?: LabelOverrides<CommandLabels> | undefined;\n /** Accessible label by reference for the search input. */\n ariaLabelledby?: string;\n }>(),\n {\n query: undefined,\n open: undefined,\n labels: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** Fired when an item is selected. */\n select: [value: string];\n /** Fired when the query changes. */\n \"update:query\": [value: string];\n /** Fired when open state changes. */\n \"update:open\": [value: boolean];\n}>();\n\nconst resolvedLabels = useLabels(\"command\", COMMAND_LABELS, () => props.labels);\n\nconst inputId = useId();\nconst listboxId = useId();\nconst liveRegionId = useId();\n\n/**\n * The controlled/uncontrolled query. When `query` is bound from outside, the\n * prop wins; otherwise the component owns its own state.\n */\nconst internalQuery = ref(\"\");\nconst queryValue = computed(() => props.query ?? internalQuery.value);\n\nfunction setQuery(value: string): void {\n internalQuery.value = value;\n emit(\"update:query\", value);\n}\n\n/**\n * The controlled/uncontrolled open state. `true` when the listbox is visible.\n */\nconst internalOpen = ref(true);\nconst isOpen = computed(() => props.open ?? internalOpen.value);\n\nfunction setOpen(value: boolean): void {\n if (props.open !== undefined) {\n emit(\"update:open\", value);\n } else {\n internalOpen.value = value;\n }\n}\n\n/**\n * Bring the listbox back after Escape closed it. Focus never leaves the\n * search input, so without this a closed Command is a dead end — the only\n * escape, before this fix, was unmounting the component. Controlled mode is\n * untouched: the emit the host chose stays with the host, and this rewrites\n * only the fallback state a host never bound.\n */\nfunction restoreOpen(): void {\n if (props.open === undefined) internalOpen.value = true;\n}\n\n/**\n * The index of the highlighted item within the filtered list. Reset to `0`\n * whenever the query changes so the first match is always ready to select.\n */\nconst highlightedIndex = ref(0);\n\nconst listboxRef = ref<HTMLElement | null>(null);\n\n// Arrow-key focus never leaves the input (aria-activedescendant), so the\n// scrollable listbox must be tab-reachable itself — an overflow container no\n// keyboard can reach is the scrollable-region-focusable violation the harness\n// axe gate exists to catch. Scrolling the highlighted option into view is the\n// other half: an active item moved off-screen is navigation the user cannot\n// see. jsdom has no scrollIntoView, hence the optional call.\nwatch([highlightedIndex, isOpen], async () => {\n if (!isOpen.value) return;\n await nextTick();\n listboxRef.value?.querySelector(\"[data-active]\")?.scrollIntoView?.({ block: \"nearest\" });\n});\n\n/**\n * Items filtered by the current query. Case-insensitive substring match\n * across `label`, `description` and `value`.\n */\nconst filteredItems = computed(() => {\n const needle = queryValue.value.trim().toLowerCase();\n if (!needle) return props.items;\n return props.items.filter((item) => {\n const haystack = [item.label, item.description ?? \"\", item.value].join(\" \").toLowerCase();\n return haystack.includes(needle);\n });\n});\n\n/**\n * Items grouped for rendering. Each entry is either a group heading or a flat\n * item. Groups with no matching items are omitted entirely.\n */\ninterface GroupedEntry {\n kind: \"heading\";\n heading: string;\n groupId: string;\n}\n\ninterface GroupedItem {\n kind: \"item\";\n item: CommandItem;\n globalIndex: number;\n}\n\ntype RenderEntry = GroupedEntry | GroupedItem;\n\nconst renderEntries = computed<RenderEntry[]>(() => {\n if (filteredItems.value.length === 0) return [];\n\n const groupDefs = props.groups;\n if (!groupDefs || groupDefs.length === 0) {\n return filteredItems.value.map((item, i) => ({ kind: \"item\", item, globalIndex: i }));\n }\n\n const ungrouped: CommandItem[] = [];\n const grouped = new Map<string, CommandItem[]>();\n\n for (const item of filteredItems.value) {\n if (item.group) {\n const list = grouped.get(item.group) ?? [];\n list.push(item);\n grouped.set(item.group, list);\n } else {\n ungrouped.push(item);\n }\n }\n\n const entries: RenderEntry[] = [];\n let globalIndex = 0;\n\n for (const def of groupDefs) {\n const items = grouped.get(def.heading);\n if (!items || items.length === 0) continue;\n entries.push({\n kind: \"heading\",\n heading: def.heading,\n groupId: `${inputId}-group-${def.heading}`,\n });\n for (const item of items) {\n entries.push({ kind: \"item\", item, globalIndex });\n globalIndex++;\n }\n }\n\n for (const item of ungrouped) {\n entries.push({ kind: \"item\", item, globalIndex });\n globalIndex++;\n }\n\n return entries;\n});\n\n/**\n * The item list for the non-grouped case, used by keyboard navigation. Derived\n * from `renderEntries` so the two are always in sync.\n */\nconst flatItems = computed(() =>\n renderEntries.value.filter((e): e is GroupedItem => e.kind === \"item\"),\n);\n\n/**\n * Keep the highlight within bounds. A filter that removes items can strand the\n * index past the end.\n */\nwatch(flatItems, (items) => {\n if (highlightedIndex.value >= items.length) {\n highlightedIndex.value = Math.max(0, items.length - 1);\n }\n});\n\n/**\n * The documented reset: the highlight returns to the first match whenever the\n * query changes — whether the query came from typing or from a parent updating\n * the controlled `query` prop. Typing reaches this watcher through `setQuery`,\n * which is why onInput no longer resets the highlight itself.\n */\nwatch(queryValue, () => {\n highlightedIndex.value = 0;\n});\n\n/**\n * The total number of results, announced to assistive technology through a live\n * region. Changes only when the filtered set changes, not on every keystroke.\n */\nconst resultCount = computed(() => filteredItems.value.length);\nconst announcement = ref(\"\");\nwatch(resultCount, (count) => {\n const template =\n count === 1 ? resolvedLabels.value.resultSingular : resolvedLabels.value.resultPlural;\n announcement.value = template.replace(\"{count}\", String(count));\n});\n\n/**\n * The currently highlighted item, or `undefined` when the list is empty.\n */\nconst highlightedItem = computed(() => flatItems.value[highlightedIndex.value]?.item);\n\nfunction highlightUp(): void {\n if (flatItems.value.length === 0) return;\n highlightedIndex.value =\n highlightedIndex.value <= 0 ? flatItems.value.length - 1 : highlightedIndex.value - 1;\n}\n\nfunction highlightDown(): void {\n if (flatItems.value.length === 0) return;\n highlightedIndex.value =\n highlightedIndex.value >= flatItems.value.length - 1 ? 0 : highlightedIndex.value + 1;\n}\n\nfunction selectHighlighted(): void {\n const item = highlightedItem.value;\n if (!item || item.disabled) return;\n emit(\"select\", item.value);\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n // A closed Command returns on any interaction except the two that leave it —\n // Escape (the key that closed it, still under the same finger) and Tab\n // (which moves focus elsewhere). Keydown fires before the input event, so\n // typing also lands on an open list.\n if (!isOpen.value && event.key !== \"Escape\" && event.key !== \"Tab\") restoreOpen();\n switch (event.key) {\n case \"ArrowDown\": {\n event.preventDefault();\n highlightDown();\n break;\n }\n case \"ArrowUp\": {\n event.preventDefault();\n highlightUp();\n break;\n }\n case \"Enter\": {\n event.preventDefault();\n selectHighlighted();\n break;\n }\n case \"Escape\": {\n event.preventDefault();\n if (queryValue.value.length > 0) {\n setQuery(\"\");\n } else {\n setOpen(false);\n }\n break;\n }\n case \"Home\": {\n event.preventDefault();\n if (flatItems.value.length > 0) highlightedIndex.value = 0;\n break;\n }\n case \"End\": {\n event.preventDefault();\n if (flatItems.value.length > 0) highlightedIndex.value = flatItems.value.length - 1;\n break;\n }\n }\n}\n\nfunction onInput(event: Event): void {\n const value = (event.target as HTMLInputElement).value;\n setQuery(value);\n}\n\nfunction selectItem(item: CommandItem): void {\n if (item.disabled) return;\n emit(\"select\", item.value);\n}\n\nfunction itemId(index: number): string {\n return `${inputId}-option-${String(index)}`;\n}\n</script>\n\n<template>\n <div\n :data-state=\"isOpen ? 'open' : 'closed'\"\n :class=\"\n cn(\n 'rounded-md border border-border bg-popover text-popover-foreground shadow-md overflow-hidden',\n 'outline-none',\n )\n \"\n >\n <div class=\"flex items-center border-b border-border\">\n <input\n :id=\"inputId\"\n type=\"text\"\n role=\"searchbox\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n :aria-controls=\"listboxId\"\n :aria-activedescendant=\"highlightedItem ? itemId(highlightedIndex) : undefined\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-label=\"ariaLabelledby ? undefined : resolvedLabels.searchLabel\"\n :placeholder=\"resolvedLabels.placeholder\"\n :value=\"queryValue\"\n class=\"w-full px-3 py-2 text-sm bg-transparent text-foreground border-none outline-none placeholder:text-muted-foreground\"\n @input=\"onInput\"\n @keydown=\"onKeydown\"\n @focus=\"restoreOpen\"\n @click=\"restoreOpen\"\n />\n </div>\n <div\n v-if=\"isOpen\"\n :id=\"listboxId\"\n ref=\"listboxRef\"\n role=\"listbox\"\n tabindex=\"0\"\n :aria-labelledby=\"inputId\"\n class=\"max-h-[300px] overflow-y-auto p-1\"\n >\n <template\n v-for=\"entry in renderEntries\"\n :key=\"entry.kind === 'heading' ? entry.groupId : entry.item.value\"\n >\n <div\n v-if=\"entry.kind === 'heading'\"\n :id=\"entry.groupId\"\n role=\"presentation\"\n class=\"px-2 py-1.5 text-micro font-medium uppercase tracking-wide text-muted-foreground\"\n >\n {{ entry.heading }}\n </div>\n <!-- eslint-disable vuejs-accessibility/click-events-have-key-events, vuejs-accessibility/interactive-supports-focus, vuejs-accessibility/mouse-events-have-key-events -->\n <div\n v-else\n :id=\"itemId(entry.globalIndex)\"\n role=\"option\"\n :aria-selected=\"highlightedIndex === entry.globalIndex\"\n :aria-disabled=\"entry.item.disabled || undefined\"\n :data-active=\"highlightedIndex === entry.globalIndex || undefined\"\n class=\"flex flex-col gap-0.5 rounded-sm px-2 py-1.5 text-sm cursor-pointer outline-none transition-colors duration-fast ease-out data-[active]:bg-primary-muted data-[active]:text-primary-text\"\n @mouseenter=\"highlightedIndex = entry.globalIndex\"\n @click=\"selectItem(entry.item)\"\n >\n <span>{{ entry.item.label }}</span>\n <span v-if=\"entry.item.description\" class=\"text-xs text-muted-foreground\">\n {{ entry.item.description }}\n </span>\n </div>\n </template>\n\n <div\n v-if=\"filteredItems.length === 0\"\n role=\"option\"\n aria-selected=\"false\"\n aria-disabled=\"true\"\n class=\"px-2 py-6 text-center text-sm text-muted-foreground\"\n >\n {{ resolvedLabels.emptyMessage }}\n </div>\n </div>\n\n <span :id=\"liveRegionId\" role=\"status\" aria-live=\"polite\" class=\"sr-only\">\n {{ announcement }}\n </span>\n </div>\n</template>\n"],"mappings":""}