@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
@@ -1 +0,0 @@
1
- {"version":3,"file":"TagsInput.js","names":[],"sources":["../../../../../packages/primitives/tags-input/src/TagsInput.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type {\n TagsInputLabels,\n TagsInputRejectReason,\n TagsInputRejection,\n} from \"@ecoma-io/loom-labels\";\n\n/**\n * Every refusal names the value, because a reader looking at eight tokens\n * cannot tell which \"that one\" is.\n *\n * Loom's English does not name the limit, though `rejected` is handed it: a\n * `max` refusal only ever happens when a limit is set, so a sentence that also\n * had to word the limitless case would be a branch nothing can reach. The\n * number is there for a host that wants \"only 3 can be added\" — and the count\n * description already reads \"3 of 3 tags\" on focus either way.\n */\nfunction describeRejection(rejection: TagsInputRejection): string {\n switch (rejection.reason) {\n case \"duplicate\":\n return `${rejection.value} has already been added.`;\n case \"max\":\n return `${rejection.value} was not added — the field is full.`;\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 * rather than a transcription of it.\n */\nexport const TAGS_INPUT_LABELS: TagsInputLabels = {\n remove: ({ value }) => `Remove ${value}`,\n count: ({ count, max }) =>\n max === undefined\n ? `${String(count)} ${count === 1 ? \"tag\" : \"tags\"}`\n : `${String(count)} of ${String(max)} tags`,\n rejected: ({ rejections }) => rejections.map(describeRejection).join(\" \"),\n clear: \"Clear all tags\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useId, useTemplateRef, watch } from \"vue\";\nimport {\n TagsInputRoot,\n TagsInputInput,\n TagsInputItem,\n TagsInputItemText,\n TagsInputClear,\n} from \"reka-ui\";\nimport { TriangleAlert, X } from \"@lucide/vue\";\nimport Chip from \"@ecoma-io/loom-chip\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { optional } from \"@ecoma-io/loom-core\";\nimport { useFieldControl } from \"@ecoma-io/loom-labels\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\n/**\n * TagsInput — several values typed into one field, each committed to a\n * removable token: keywords on an article, recipients on a message, labels on\n * an issue.\n *\n * The line against its neighbours is what the values *are*. A\n * [Select](../Select/Select.vue) or a [Combobox](../Combobox/Combobox.vue)\n * picks from a list somebody else wrote, and cannot produce a value that is not\n * already in it; this field's whole point is that the reader invents the\n * values. A [TextField](../TextField/TextField.vue) holds one value, and a\n * comma-separated string in one is a list the application has to parse and the\n * reader has to punctuate correctly. Reach for\n * [Chip](@ecoma-io/loom-chip) alone when the tokens are a display of something\n * already decided — a chip row nobody types into is not a field.\n *\n * Each token *is* a Chip, in the removable shape Chip already ships, so a token\n * here and a chip elsewhere in the same form are the same object. The remove\n * control is Chip's own rather than Reka's `TagsInputItemDelete`, which is\n * `tabindex=\"-1\"` by design: Reka pairs it with an arrow-key selection that\n * moves no focus and sets no `aria-activedescendant`, so the token it\n * highlights is announced to nobody. Loom keeps the buttons on the tab order\n * and replaces the selection outright — see `onKeydownCapture`.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself: the row's id, the id of\n * the hint or error line, and `required` / `invalid` / `disabled` / `readonly` /\n * `name` all arrive through `useFieldControl()`. Every prop below still wins\n * over the row when it is set, in both directions — which is why the four\n * booleans default to `undefined` rather than `false`.\n *\n * `readonly` and `disabled` are different states here as everywhere else, and\n * the difference is larger than usual because there are two things to freeze. A\n * read-only field shows its tokens, refuses to grow one and drops every remove\n * control, while staying a tab stop and staying in the submitted data. A\n * disabled field is unavailable: not a tab stop, not submitted, and its tokens\n * drain to the neutral fill.\n *\n * That makes **three** resting appearances rather than two, and each is three\n * changes rather than one — fill, text colour and border weight together. See\n * the box's class list for why one channel is not enough.\n */\nconst props = withDefaults(\n defineProps<{\n /** The committed tokens. Pair with `@update:modelValue` for `v-model`. */\n modelValue?: string[] | undefined;\n /** Text shown in the empty text box. It is hidden once a token exists, where it would sit beside the tokens claiming the field is empty. */\n placeholder?: string;\n /** The most tokens the field will hold. Anything past it is refused and reported rather than dropped. */\n max?: number;\n /** Whether the same value may be committed twice. Off, so a repeated value is refused and says so. */\n duplicates?: boolean;\n /** What commits a token besides Enter. Typing it, or pasting text containing it, splits at it. */\n delimiter?: string;\n /** Renders a control that empties the field in one press. */\n clearable?: boolean;\n /** Disables the field: no tab stop, no editing, no remove controls, nothing submitted. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Shows the tokens without allowing an edit, while staying focusable and still submitted. Unset defers to a wrapping Field. */\n readonly?: boolean | undefined;\n /** Error state: paints the destructive border/ring and sets aria-invalid. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** Marks the field mandatory to assistive tech (`aria-required`). Unset defers to a wrapping Field. */\n required?: boolean | undefined;\n /** The field name for a native form post. Each token is submitted as `name[0]`, `name[1]`, … Unset defers to a wrapping Field. */\n name?: string;\n /** The accessible name of the text box, when no visible element already labels it. */\n ariaLabel?: string;\n /** The id of the visible element that labels the text box (e.g. a Field wrapper's label). */\n ariaLabelledby?: string;\n /**\n * Names for everything this control says out loud, as any subset of\n * `TagsInputLabels` — 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: the case it exists for is a field whose tokens are people,\n * where \"Remove Ana Duarte\" reads and \"Remove tag\" does not.\n */\n labels?: LabelOverrides<TagsInputLabels>;\n }>(),\n {\n // Not `[]`. An empty array is a concrete value, so it would say \"the host\n // owns this list\", and a host that binds nothing would watch every token it\n // typed vanish on the next render. `undefined` is what leaves the control\n // managing its own — the same distinction `src/lib/props.ts` exists to\n // preserve for the Reka-backed primitives.\n modelValue: undefined,\n duplicates: false,\n delimiter: \",\",\n clearable: false,\n // Not `false`, for any of the four. `false` is a caller saying \"this field\n // is fine / enabled / editable even though its row is not\"; absent is a\n // caller saying nothing, and only `undefined` survives to mean that past\n // Vue's absent-Boolean-casts-to-false rule. TextField.vue carries the full\n // reasoning.\n disabled: undefined,\n readonly: undefined,\n invalid: undefined,\n required: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** The full token list after the change, trimmed and de-duplicated. Never a partial list. */\n \"update:modelValue\": [values: string[]];\n /** Every value refused by this one interaction, each with the rule that refused it. Fires once per interaction, not once per value. */\n reject: [rejections: TagsInputRejection[]];\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(\"tagsInput\", TAGS_INPUT_LABELS, () => props.labels);\n\n// `class` sizes the whole control and lands on the outer element; everything\n// else a caller passes — `id`, `data-testid`, `aria-describedby`,\n// `autocomplete` — describes the real `<input>` and lands there. The outer\n// element is not a form control and the input is not the box a caller lays out,\n// so there is no one node both belong on.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\n\nconst generatedId = useId();\nconst countId = useId();\nconst messageId = useId();\n\nconst inputRef = useTemplateRef<{ $el: HTMLInputElement }>(\"input\");\n\n/**\n * The committed tokens, and the reason this control keeps its own copy rather\n * than forwarding `modelValue` into Reka and letting it manage the state.\n *\n * Loom applies four rules Reka has no notion of — trim, drop the blanks a paste\n * leaves behind, refuse a duplicate, refuse anything past `max` — so Reka is\n * configured to accept everything (`duplicate`, no `max`) and *propose*, and\n * `onProposed` decides. That needs a value flowing back down, which means a\n * `:model-value` that is always defined and always ours.\n *\n * It is `useVModel(…, { passive: true })` written out, and behaves the same way\n * Reka's own would: the change is taken locally and emitted, and a controlled\n * host that declines it is honoured on the next value it does send. Seeded from\n * the prop rather than sanitised, because a list the host already holds is the\n * host's to hold — the rules above are about what this field *accepts*.\n */\nconst tokens = ref<string[]>([...(props.modelValue ?? [])]);\nwatch(\n () => props.modelValue,\n (next) => {\n if (next !== undefined) tokens.value = [...next];\n },\n // Shallow, deliberately: the contract is whole-list replacement — `commit`\n // emits the complete token list on every change and a host echoes it\n // straight back down — so in-place mutation is not a case this mirror owes\n // anyone. Same reasoning as Combobox's mirror of its selection.\n);\n\nconst rejections = ref<TagsInputRejection[]>([]);\nconst message = computed(() =>\n rejections.value.length > 0\n ? text.value.rejected({ rejections: rejections.value, max: props.max })\n : \"\",\n);\n\n// The refusal message reads first and the count second: both describe the\n// field, and the one that just changed is the more specific thing to say. A\n// wrapping Field's own hint or error is merged in after both by\n// `useFieldControl`, never in place of them.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [\n message.value.length > 0 ? messageId : undefined,\n countId,\n attrs[\"aria-describedby\"],\n ]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n name: props.name,\n disabled: props.disabled,\n readonly: props.readonly,\n invalid: props.invalid,\n required: props.required,\n}));\n\n// The `<label for>` a Field renders has to resolve to the text box, and a\n// caller passing their own id must not end up with a label pointing at nothing.\nconst inputId = computed(() => field.id ?? generatedId);\n\n/**\n * A stable key per token, since the token itself cannot be one: `duplicates`\n * makes two identical strings legal and Vue warns on the collision.\n *\n * The n-th occurrence of a value keys as `n:value`, so removing one of two\n * identical tokens unmounts exactly one node and the survivor keeps the other —\n * indistinguishable, because the two say the same thing. Keying by index\n * instead would re-key every row after the one removed, which patches text into\n * nodes that belong to other tokens.\n */\nconst rows = computed(() => {\n const seen = new Map<string, number>();\n return tokens.value.map((value) => {\n const ordinal = seen.get(value) ?? 0;\n seen.set(value, ordinal + 1);\n return { value, key: `${String(ordinal)}:${value}` };\n });\n});\n\n/**\n * Every rule this field applies to a value, in the order a reader meets them,\n * over the *whole* proposal rather than only its tail — the list on screen can\n * never hold a token the box would have refused, whatever a host seeded it with.\n *\n * `settled` is how many entries were already committed, and only what lies past\n * it is *reported*. Everything before it is normalised in silence: a host that\n * seeded two identical values while asking for none is corrected, but saying\n * \"design has already been added\" about a token that was there when the page\n * loaded, at the moment the reader adds something else entirely, describes\n * nothing they did.\n */\nfunction reduce(\n proposed: readonly string[],\n settled: number,\n): { kept: string[]; refused: TagsInputRejection[] } {\n const kept: string[] = [];\n const refused: TagsInputRejection[] = [];\n\n proposed.forEach((raw, index) => {\n const value = raw.trim();\n // Skipped rather than refused. A blank is what a trailing delimiter leaves\n // behind — \"a, b, c,\" pastes as four segments — and a reader who pasted\n // three values did not ask about a fourth.\n if (value === \"\") return;\n\n const reason: TagsInputRejectReason | undefined =\n props.max !== undefined && kept.length >= props.max\n ? \"max\"\n : !props.duplicates && kept.includes(value)\n ? \"duplicate\"\n : undefined;\n\n if (reason === undefined) kept.push(value);\n else if (index >= settled) refused.push({ value, reason });\n });\n\n return { kept, refused };\n}\n\nfunction same(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((value, index) => value === b[index]);\n}\n\nfunction focusInput(): void {\n void nextTick(() => inputRef.value?.$el.focus());\n}\n\nfunction commit(next: string[]): void {\n // The message named values the reader has since edited past. An error sitting\n // under a field somebody is actively fixing reads as an error about the fix.\n rejections.value = [];\n tokens.value = next;\n emit(\"update:modelValue\", next);\n}\n\n/**\n * Reka has already written `proposed` into its own model by the time this runs.\n * `tokens.value` is assigned on every path, including the one where nothing\n * changed, and that is load-bearing: `reduce` returns a fresh array, and only a\n * new reference on the prop Reka watches puts its internal copy back in step\n * with what this field actually accepted. Skip the assignment and a refused\n * value stays in Reka's model — invisible on screen, and submitted by the\n * hidden inputs it renders for `name`.\n */\nfunction onProposed(proposed: string[]): void {\n const { kept, refused } = reduce(proposed, tokens.value.length);\n const changed = !same(kept, tokens.value);\n\n if (changed) commit(kept);\n else tokens.value = kept;\n\n if (refused.length === 0) return;\n rejections.value = refused;\n emit(\"reject\", refused);\n\n // One refusal from one typed commit is the reader's own draft, and Reka has\n // just cleared the box under them. Put it back: a field that eats what it\n // will not take leaves the reader retyping a value they can no longer see.\n // Only the single case — restoring one of three pasted values would be\n // choosing between them.\n const only = refused.length === 1 ? refused[0] : undefined;\n if (only === undefined) return;\n void nextTick(() => {\n const input = inputRef.value?.$el;\n if (!input || input.value !== \"\") return;\n input.value = only.value;\n input.setSelectionRange(only.value.length, only.value.length);\n });\n}\n\nfunction removeAt(index: number): void {\n if (field.disabled || field.readonly) return;\n commit(tokens.value.filter((_, at) => at !== index));\n // The button that was pressed has just unmounted, and a browser drops focus\n // to `<body>` when it does. The text box is where the reader was heading\n // anyway, and it is the one node in this control that never goes away.\n focusInput();\n}\n\n/**\n * The keys Reka's `onInputKeydown` claims once the caret sits at the very\n * start of the text box, and the reason this handler runs in the capture phase\n * on the way down rather than as a listener on the input itself: a fallthrough\n * handler is merged *after* Reka's and cannot stop it.\n *\n * What Reka does with them is a virtual selection — Backspace marks the last\n * token, arrows walk it, a second Backspace deletes it — that moves no focus\n * and publishes no `aria-activedescendant`. On screen it is a highlight; to a\n * screen reader it is nothing at all, so the second Backspace destroys a value\n * the reader was never told was chosen. That is the failure this control is\n * most likely to ship, so the whole mechanism is stopped here.\n *\n * In its place, one rule: **Backspace on an empty box lifts the last token back\n * into it**, as editable text with the caret at the end. Nothing is destroyed —\n * the value is on screen, in a box the reader is already focused on, and Enter\n * puts it straight back. The token that left is a `commit`, so a host watching\n * `update:modelValue` sees the edit begin.\n */\nconst CARET_KEYS = new Set([\"Backspace\", \"Delete\", \"ArrowLeft\", \"ArrowRight\", \"Home\", \"End\"]);\n\nfunction onKeydownCapture(event: KeyboardEvent): void {\n // An IME's own Backspace edits the composition, and Reka's handlers bail on\n // the same flag for the same reason.\n if (event.isComposing) return;\n const input = event.target;\n if (!(input instanceof HTMLInputElement)) return;\n if (!CARET_KEYS.has(event.key)) return;\n if (input.selectionStart !== 0 || input.selectionEnd !== 0) return;\n\n // Stopped only for the keys and only at the caret position where Reka would\n // have acted. Everything else — Enter, the delimiter, every printable\n // character — reaches its handlers untouched.\n event.stopPropagation();\n\n if (event.key !== \"Backspace\" || input.value !== \"\") return;\n if (field.disabled || field.readonly) return;\n const last = tokens.value.at(-1);\n if (last === undefined) return;\n\n event.preventDefault();\n commit(tokens.value.slice(0, -1));\n input.value = last;\n input.setSelectionRange(last.length, last.length);\n}\n\n/**\n * A read-only field takes nothing, and the native `readonly` attribute is not\n * enough to say so. Reka's paste handler reads the clipboard and commits from\n * it directly, without ever consulting the input it fired on, so a paste into a\n * read-only field would grow tokens the reader cannot then remove.\n */\nfunction onPasteCapture(event: ClipboardEvent): void {\n if (!field.readonly && !field.disabled) return;\n event.preventDefault();\n event.stopPropagation();\n}\n</script>\n\n<template>\n <TagsInputRoot\n as=\"div\"\n v-bind=\"optional({ name: field.name })\"\n :model-value=\"tokens\"\n :delimiter=\"delimiter\"\n :disabled=\"field.disabled\"\n :required=\"field.required\"\n add-on-paste\n duplicate\n :class=\"cn('flex flex-col', attrs.class as string)\"\n @update:model-value=\"onProposed\"\n @keydown.capture=\"onKeydownCapture\"\n @paste.capture=\"onPasteCapture\"\n >\n <!-- `duplicate` and the absent `max` above are deliberate: Reka is told to\n accept every value it is offered, so that one place — `reduce` —\n decides what a token is. Two refusal ladders would be two answers to\n `duplicates`, and only one would be the one `reject` reports.\n\n The state markers live on the box rather than on the root, and not by\n preference: an attribute bound on `TagsInputRoot` is a fallthrough\n attr, and the root renders through Reka's `CollectionSlot`, which does\n not carry one to the element underneath. The box is also the honest\n node for them — it is what the state is painted on. -->\n <div\n :data-disabled=\"field.disabled || undefined\"\n :data-readonly=\"field.readonly || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :class=\"\n cn(\n 'flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-input bg-background px-2 py-0.5 text-sm text-foreground',\n 'transition-[color,background-color,border-color,box-shadow] duration-fast ease-out',\n // Rim-lit at rest, the weave blooms on focus, exactly as TextField's\n // does — a field holding tokens is still a field, and a form row\n // should not have two focus languages in it.\n 'focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring',\n !field.invalid && 'focus-within:shadow-halo',\n // Lifted rather than dimmed, and it keeps its focus ring: a read-only\n // field is a value **on show**, not an unavailable control. The fill\n // rises off `background` to `subtle` so the box reads as settled, and\n // the text stays full strength — 13.45:1 over that fill — because\n // being read is the entire purpose of the state. The border does not\n // move, because nothing about the field's reach has: it is still a\n // tab stop and still submitted.\n field.readonly && 'bg-subtle',\n // Unavailable is a step further down all three channels: the fill\n // drains to `muted`, the text follows to `muted-foreground` (4.67:1\n // over it) and the rim slackens from `input` to the lighter `border`.\n //\n // Read-only and disabled used to share `bg-muted` and part on the\n // text colour alone, which is a distinction made in hue and nothing\n // else — the one thing a reader with a colour deficiency does not\n // receive. Three channels is what makes available → on show →\n // unavailable legible without it.\n //\n // No `opacity-50` anywhere in that, and that is the point. Every\n // token inside is a Chip that has already drained itself to a\n // measured unavailable fill; halving the alpha over the top of that\n // takes its label below the contrast floor. `border-border` and not\n // the strong weight, for the reason `theme.css` gives the strong one:\n // it is for a block that must **assert** its edge, and an unavailable\n // field is the one thing that must not.\n field.disabled && 'cursor-not-allowed border-border bg-muted text-muted-foreground',\n // The same appearance, reached from the other direction: a\n // `<fieldset disabled>` above this field disables the `<input>` and\n // every token's remove button natively and never touches\n // `field.disabled`, so the rule above cannot fire and the box\n // rendered byte-identical to an editable one.\n //\n // `in-[fieldset:disabled]:` reads the attribute that did the\n // disabling, so the fill and the native inertness cannot disagree.\n // See TextField.vue for why it is preferred to a `has-[:disabled]:`\n // rule reading this box's own contents.\n 'in-[fieldset:disabled]:cursor-not-allowed in-[fieldset:disabled]:bg-muted in-[fieldset:disabled]:text-muted-foreground',\n // Gated for the reason the two rules below are ordered: Tailwind\n // emits the ancestor half of `in-*` inside `:where()`, so this\n // carries no more specificity than `border-destructive` and would\n // win on emission order alone.\n !field.invalid && 'in-[fieldset:disabled]:border-border',\n // Last of the rules that name a border colour, and the order is\n // load-bearing: `cn()` resolves a border colour by whichever class it\n // saw last, so a field that is both in error and unavailable would\n // lose its destructive rim to the disabled one if this sat above it.\n field.invalid && 'border-destructive focus-within:outline-destructive',\n )\n \"\n >\n <!-- A real list, so a reader browsing the field meets the tokens as\n items rather than as a run of buttons. It is not where the count\n comes from, though: Tailwind's preflight sets `list-style: none` on\n every `ul`, and Safari drops the list role from a list styled that\n way — which is why the count below is published in words instead of\n left to the browser. -->\n <ul v-if=\"tokens.length > 0\" class=\"flex min-w-0 flex-wrap items-center gap-1.5\">\n <TagsInputItem\n v-for=\"(row, index) in rows\"\n :key=\"row.key\"\n as=\"li\"\n :value=\"row.value\"\n class=\"flex animate-fade-rise\"\n >\n <Chip\n size=\"sm\"\n :removable=\"!field.readonly\"\n :disabled=\"field.disabled\"\n :remove-label=\"text.remove({ value: row.value })\"\n @remove=\"removeAt(index)\"\n >\n <TagsInputItemText />\n </Chip>\n </TagsInputItem>\n </ul>\n\n <!-- `field.attrs` spreads **after** the fallthrough attrs, and that\n position is the contract: the bag has already resolved the caller's\n own `id` and `aria-describedby`, and it drops every key that resolved\n to nothing, so it can only add.\n\n `:id` restates what the bag already holds, or supplies the id a\n Field's `<label for>` needs when it holds none. `:name` undoes one\n key of it on purpose — the text box holds a draft, not the value, and\n a `name` on it would post whatever was half-typed instead of the\n tokens. The value is posted by the hidden inputs the root renders. -->\n <TagsInputInput\n :id=\"inputId\"\n ref=\"input\"\n v-bind=\"{\n ...inputAttrs,\n ...field.attrs,\n ...optional({ placeholder: tokens.length === 0 ? placeholder : undefined }),\n }\"\n :name=\"undefined\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :readonly=\"field.readonly\"\n class=\"h-8 min-w-24 flex-1 bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed\"\n />\n\n <TagsInputClear\n v-if=\"clearable && tokens.length > 0 && !field.readonly\"\n :aria-label=\"text.clear\"\n :disabled=\"field.disabled\"\n class=\"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-sm text-muted-foreground transition-colors duration-fast ease-out hover:bg-subtle hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo data-[disabled]:cursor-not-allowed\"\n @click=\"focusInput\"\n >\n <X class=\"h-4 w-4\" />\n </TagsInputClear>\n\n <!-- The count, and the only thing that tells a reader how many tokens are\n in the field without walking them. Reka publishes nothing of the\n sort: its root is an unlabelled `div`. It is wired through\n `aria-describedby` rather than announced, so it is heard on focus and\n on every return to the field, which is when the question is asked. -->\n <span :id=\"countId\" class=\"sr-only\">\n {{ text.count({ count: tokens.length, max }) }}\n </span>\n </div>\n\n <!-- The region is in the DOM from the first render, empty. A live region\n mounted at the same moment as its text is a region assistive tech was\n not yet watching, so the first refusal — the one that matters most — is\n the one it announces least reliably. -->\n <div aria-live=\"polite\" aria-atomic=\"true\">\n <p\n v-if=\"message.length > 0\"\n :id=\"messageId\"\n class=\"mt-1.5 flex animate-fade-rise items-start gap-2 text-small text-destructive-text\"\n >\n <TriangleAlert class=\"mt-0.5 h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n <span>{{ message }}</span>\n </p>\n </div>\n </TagsInputRoot>\n</template>\n"],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"TagsInput.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../../packages/primitives/tags-input/src/TagsInput.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type {\n TagsInputLabels,\n TagsInputRejectReason,\n TagsInputRejection,\n} from \"@ecoma-io/loom-labels\";\n\n/**\n * Every refusal names the value, because a reader looking at eight tokens\n * cannot tell which \"that one\" is.\n *\n * Loom's English does not name the limit, though `rejected` is handed it: a\n * `max` refusal only ever happens when a limit is set, so a sentence that also\n * had to word the limitless case would be a branch nothing can reach. The\n * number is there for a host that wants \"only 3 can be added\" — and the count\n * description already reads \"3 of 3 tags\" on focus either way.\n */\nfunction describeRejection(rejection: TagsInputRejection): string {\n switch (rejection.reason) {\n case \"duplicate\":\n return `${rejection.value} has already been added.`;\n case \"max\":\n return `${rejection.value} was not added — the field is full.`;\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 * rather than a transcription of it.\n */\nexport const TAGS_INPUT_LABELS: TagsInputLabels = {\n remove: ({ value }) => `Remove ${value}`,\n count: ({ count, max }) =>\n max === undefined\n ? `${String(count)} ${count === 1 ? \"tag\" : \"tags\"}`\n : `${String(count)} of ${String(max)} tags`,\n rejected: ({ rejections }) => rejections.map(describeRejection).join(\" \"),\n clear: \"Clear all tags\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useId, useTemplateRef, watch } from \"vue\";\nimport {\n TagsInputRoot,\n TagsInputInput,\n TagsInputItem,\n TagsInputItemText,\n TagsInputClear,\n} from \"reka-ui\";\nimport { TriangleAlert, X } from \"@lucide/vue\";\nimport Chip from \"@ecoma-io/loom-chip\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { optional } from \"@ecoma-io/loom-core\";\nimport { useFieldControl } from \"@ecoma-io/loom-labels\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\n/**\n * TagsInput — several values typed into one field, each committed to a\n * removable token: keywords on an article, recipients on a message, labels on\n * an issue.\n *\n * The line against its neighbours is what the values *are*. A\n * [Select](../Select/Select.vue) or a [Combobox](../Combobox/Combobox.vue)\n * picks from a list somebody else wrote, and cannot produce a value that is not\n * already in it; this field's whole point is that the reader invents the\n * values. A [TextField](../TextField/TextField.vue) holds one value, and a\n * comma-separated string in one is a list the application has to parse and the\n * reader has to punctuate correctly. Reach for\n * [Chip](@ecoma-io/loom-chip) alone when the tokens are a display of something\n * already decided — a chip row nobody types into is not a field.\n *\n * Each token *is* a Chip, in the removable shape Chip already ships, so a token\n * here and a chip elsewhere in the same form are the same object. The remove\n * control is Chip's own rather than Reka's `TagsInputItemDelete`, which is\n * `tabindex=\"-1\"` by design: Reka pairs it with an arrow-key selection that\n * moves no focus and sets no `aria-activedescendant`, so the token it\n * highlights is announced to nobody. Loom keeps the buttons on the tab order\n * and replaces the selection outright — see `onKeydownCapture`.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself: the row's id, the id of\n * the hint or error line, and `required` / `invalid` / `disabled` / `readonly` /\n * `name` all arrive through `useFieldControl()`. Every prop below still wins\n * over the row when it is set, in both directions — which is why the four\n * booleans default to `undefined` rather than `false`.\n *\n * `readonly` and `disabled` are different states here as everywhere else, and\n * the difference is larger than usual because there are two things to freeze. A\n * read-only field shows its tokens, refuses to grow one and drops every remove\n * control, while staying a tab stop and staying in the submitted data. A\n * disabled field is unavailable: not a tab stop, not submitted, and its tokens\n * drain to the neutral fill.\n *\n * That makes **three** resting appearances rather than two, and each is three\n * changes rather than one — fill, text colour and border weight together. See\n * the box's class list for why one channel is not enough.\n */\nconst props = withDefaults(\n defineProps<{\n /** The committed tokens. Pair with `@update:modelValue` for `v-model`. */\n modelValue?: string[] | undefined;\n /** Text shown in the empty text box. It is hidden once a token exists, where it would sit beside the tokens claiming the field is empty. */\n placeholder?: string;\n /** The most tokens the field will hold. Anything past it is refused and reported rather than dropped. */\n max?: number;\n /** Whether the same value may be committed twice. Off, so a repeated value is refused and says so. */\n duplicates?: boolean;\n /** What commits a token besides Enter. Typing it, or pasting text containing it, splits at it. */\n delimiter?: string;\n /** Renders a control that empties the field in one press. */\n clearable?: boolean;\n /** Disables the field: no tab stop, no editing, no remove controls, nothing submitted. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Shows the tokens without allowing an edit, while staying focusable and still submitted. Unset defers to a wrapping Field. */\n readonly?: boolean | undefined;\n /** Error state: paints the destructive border/ring and sets aria-invalid. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** Marks the field mandatory to assistive tech (`aria-required`). Unset defers to a wrapping Field. */\n required?: boolean | undefined;\n /** The field name for a native form post. Each token is submitted as `name[0]`, `name[1]`, … Unset defers to a wrapping Field. */\n name?: string;\n /** The accessible name of the text box, when no visible element already labels it. */\n ariaLabel?: string;\n /** The id of the visible element that labels the text box (e.g. a Field wrapper's label). */\n ariaLabelledby?: string;\n /**\n * Names for everything this control says out loud, as any subset of\n * `TagsInputLabels` — 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: the case it exists for is a field whose tokens are people,\n * where \"Remove Ana Duarte\" reads and \"Remove tag\" does not.\n */\n labels?: LabelOverrides<TagsInputLabels>;\n }>(),\n {\n // Not `[]`. An empty array is a concrete value, so it would say \"the host\n // owns this list\", and a host that binds nothing would watch every token it\n // typed vanish on the next render. `undefined` is what leaves the control\n // managing its own — the same distinction `src/lib/props.ts` exists to\n // preserve for the Reka-backed primitives.\n modelValue: undefined,\n duplicates: false,\n delimiter: \",\",\n clearable: false,\n // Not `false`, for any of the four. `false` is a caller saying \"this field\n // is fine / enabled / editable even though its row is not\"; absent is a\n // caller saying nothing, and only `undefined` survives to mean that past\n // Vue's absent-Boolean-casts-to-false rule. TextField.vue carries the full\n // reasoning.\n disabled: undefined,\n readonly: undefined,\n invalid: undefined,\n required: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** The full token list after the change, trimmed and de-duplicated. Never a partial list. */\n \"update:modelValue\": [values: string[]];\n /** Every value refused by this one interaction, each with the rule that refused it. Fires once per interaction, not once per value. */\n reject: [rejections: TagsInputRejection[]];\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(\"tagsInput\", TAGS_INPUT_LABELS, () => props.labels);\n\n// `class` sizes the whole control and lands on the outer element; everything\n// else a caller passes — `id`, `data-testid`, `aria-describedby`,\n// `autocomplete` — describes the real `<input>` and lands there. The outer\n// element is not a form control and the input is not the box a caller lays out,\n// so there is no one node both belong on.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\n\nconst generatedId = useId();\nconst countId = useId();\nconst messageId = useId();\n\nconst inputRef = useTemplateRef<{ $el: HTMLInputElement }>(\"input\");\n\n/**\n * The committed tokens, and the reason this control keeps its own copy rather\n * than forwarding `modelValue` into Reka and letting it manage the state.\n *\n * Loom applies four rules Reka has no notion of — trim, drop the blanks a paste\n * leaves behind, refuse a duplicate, refuse anything past `max` — so Reka is\n * configured to accept everything (`duplicate`, no `max`) and *propose*, and\n * `onProposed` decides. That needs a value flowing back down, which means a\n * `:model-value` that is always defined and always ours.\n *\n * It is `useVModel(…, { passive: true })` written out, and behaves the same way\n * Reka's own would: the change is taken locally and emitted, and a controlled\n * host that declines it is honoured on the next value it does send. Seeded from\n * the prop rather than sanitised, because a list the host already holds is the\n * host's to hold — the rules above are about what this field *accepts*.\n */\nconst tokens = ref<string[]>([...(props.modelValue ?? [])]);\nwatch(\n () => props.modelValue,\n (next) => {\n if (next !== undefined) tokens.value = [...next];\n },\n // Shallow, deliberately: the contract is whole-list replacement — `commit`\n // emits the complete token list on every change and a host echoes it\n // straight back down — so in-place mutation is not a case this mirror owes\n // anyone. Same reasoning as Combobox's mirror of its selection.\n);\n\nconst rejections = ref<TagsInputRejection[]>([]);\nconst message = computed(() =>\n rejections.value.length > 0\n ? text.value.rejected({ rejections: rejections.value, max: props.max })\n : \"\",\n);\n\n// The refusal message reads first and the count second: both describe the\n// field, and the one that just changed is the more specific thing to say. A\n// wrapping Field's own hint or error is merged in after both by\n// `useFieldControl`, never in place of them.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [\n message.value.length > 0 ? messageId : undefined,\n countId,\n attrs[\"aria-describedby\"],\n ]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n name: props.name,\n disabled: props.disabled,\n readonly: props.readonly,\n invalid: props.invalid,\n required: props.required,\n}));\n\n// The `<label for>` a Field renders has to resolve to the text box, and a\n// caller passing their own id must not end up with a label pointing at nothing.\nconst inputId = computed(() => field.id ?? generatedId);\n\n/**\n * A stable key per token, since the token itself cannot be one: `duplicates`\n * makes two identical strings legal and Vue warns on the collision.\n *\n * The n-th occurrence of a value keys as `n:value`, so removing one of two\n * identical tokens unmounts exactly one node and the survivor keeps the other —\n * indistinguishable, because the two say the same thing. Keying by index\n * instead would re-key every row after the one removed, which patches text into\n * nodes that belong to other tokens.\n */\nconst rows = computed(() => {\n const seen = new Map<string, number>();\n return tokens.value.map((value) => {\n const ordinal = seen.get(value) ?? 0;\n seen.set(value, ordinal + 1);\n return { value, key: `${String(ordinal)}:${value}` };\n });\n});\n\n/**\n * Every rule this field applies to a value, in the order a reader meets them,\n * over the *whole* proposal rather than only its tail — the list on screen can\n * never hold a token the box would have refused, whatever a host seeded it with.\n *\n * `settled` is how many entries were already committed, and only what lies past\n * it is *reported*. Everything before it is normalised in silence: a host that\n * seeded two identical values while asking for none is corrected, but saying\n * \"design has already been added\" about a token that was there when the page\n * loaded, at the moment the reader adds something else entirely, describes\n * nothing they did.\n */\nfunction reduce(\n proposed: readonly string[],\n settled: number,\n): { kept: string[]; refused: TagsInputRejection[] } {\n const kept: string[] = [];\n const refused: TagsInputRejection[] = [];\n\n proposed.forEach((raw, index) => {\n const value = raw.trim();\n // Skipped rather than refused. A blank is what a trailing delimiter leaves\n // behind — \"a, b, c,\" pastes as four segments — and a reader who pasted\n // three values did not ask about a fourth.\n if (value === \"\") return;\n\n const reason: TagsInputRejectReason | undefined =\n props.max !== undefined && kept.length >= props.max\n ? \"max\"\n : !props.duplicates && kept.includes(value)\n ? \"duplicate\"\n : undefined;\n\n if (reason === undefined) kept.push(value);\n else if (index >= settled) refused.push({ value, reason });\n });\n\n return { kept, refused };\n}\n\nfunction same(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((value, index) => value === b[index]);\n}\n\nfunction focusInput(): void {\n void nextTick(() => inputRef.value?.$el.focus());\n}\n\nfunction commit(next: string[]): void {\n // The message named values the reader has since edited past. An error sitting\n // under a field somebody is actively fixing reads as an error about the fix.\n rejections.value = [];\n tokens.value = next;\n emit(\"update:modelValue\", next);\n}\n\n/**\n * Reka has already written `proposed` into its own model by the time this runs.\n * `tokens.value` is assigned on every path, including the one where nothing\n * changed, and that is load-bearing: `reduce` returns a fresh array, and only a\n * new reference on the prop Reka watches puts its internal copy back in step\n * with what this field actually accepted. Skip the assignment and a refused\n * value stays in Reka's model — invisible on screen, and submitted by the\n * hidden inputs it renders for `name`.\n */\nfunction onProposed(proposed: string[]): void {\n const { kept, refused } = reduce(proposed, tokens.value.length);\n const changed = !same(kept, tokens.value);\n\n if (changed) commit(kept);\n else tokens.value = kept;\n\n if (refused.length === 0) return;\n rejections.value = refused;\n emit(\"reject\", refused);\n\n // One refusal from one typed commit is the reader's own draft, and Reka has\n // just cleared the box under them. Put it back: a field that eats what it\n // will not take leaves the reader retyping a value they can no longer see.\n // Only the single case — restoring one of three pasted values would be\n // choosing between them.\n const only = refused.length === 1 ? refused[0] : undefined;\n if (only === undefined) return;\n void nextTick(() => {\n const input = inputRef.value?.$el;\n if (!input || input.value !== \"\") return;\n input.value = only.value;\n input.setSelectionRange(only.value.length, only.value.length);\n });\n}\n\nfunction removeAt(index: number): void {\n if (field.disabled || field.readonly) return;\n commit(tokens.value.filter((_, at) => at !== index));\n // The button that was pressed has just unmounted, and a browser drops focus\n // to `<body>` when it does. The text box is where the reader was heading\n // anyway, and it is the one node in this control that never goes away.\n focusInput();\n}\n\n/**\n * The keys Reka's `onInputKeydown` claims once the caret sits at the very\n * start of the text box, and the reason this handler runs in the capture phase\n * on the way down rather than as a listener on the input itself: a fallthrough\n * handler is merged *after* Reka's and cannot stop it.\n *\n * What Reka does with them is a virtual selection — Backspace marks the last\n * token, arrows walk it, a second Backspace deletes it — that moves no focus\n * and publishes no `aria-activedescendant`. On screen it is a highlight; to a\n * screen reader it is nothing at all, so the second Backspace destroys a value\n * the reader was never told was chosen. That is the failure this control is\n * most likely to ship, so the whole mechanism is stopped here.\n *\n * In its place, one rule: **Backspace on an empty box lifts the last token back\n * into it**, as editable text with the caret at the end. Nothing is destroyed —\n * the value is on screen, in a box the reader is already focused on, and Enter\n * puts it straight back. The token that left is a `commit`, so a host watching\n * `update:modelValue` sees the edit begin.\n */\nconst CARET_KEYS = new Set([\"Backspace\", \"Delete\", \"ArrowLeft\", \"ArrowRight\", \"Home\", \"End\"]);\n\nfunction onKeydownCapture(event: KeyboardEvent): void {\n // An IME's own Backspace edits the composition, and Reka's handlers bail on\n // the same flag for the same reason.\n if (event.isComposing) return;\n const input = event.target;\n if (!(input instanceof HTMLInputElement)) return;\n if (!CARET_KEYS.has(event.key)) return;\n if (input.selectionStart !== 0 || input.selectionEnd !== 0) return;\n\n // Stopped only for the keys and only at the caret position where Reka would\n // have acted. Everything else — Enter, the delimiter, every printable\n // character — reaches its handlers untouched.\n event.stopPropagation();\n\n if (event.key !== \"Backspace\" || input.value !== \"\") return;\n if (field.disabled || field.readonly) return;\n const last = tokens.value.at(-1);\n if (last === undefined) return;\n\n event.preventDefault();\n commit(tokens.value.slice(0, -1));\n input.value = last;\n input.setSelectionRange(last.length, last.length);\n}\n\n/**\n * A read-only field takes nothing, and the native `readonly` attribute is not\n * enough to say so. Reka's paste handler reads the clipboard and commits from\n * it directly, without ever consulting the input it fired on, so a paste into a\n * read-only field would grow tokens the reader cannot then remove.\n */\nfunction onPasteCapture(event: ClipboardEvent): void {\n if (!field.readonly && !field.disabled) return;\n event.preventDefault();\n event.stopPropagation();\n}\n</script>\n\n<template>\n <TagsInputRoot\n as=\"div\"\n v-bind=\"optional({ name: field.name })\"\n :model-value=\"tokens\"\n :delimiter=\"delimiter\"\n :disabled=\"field.disabled\"\n :required=\"field.required\"\n add-on-paste\n duplicate\n :class=\"cn('flex flex-col', attrs.class as string)\"\n @update:model-value=\"onProposed\"\n @keydown.capture=\"onKeydownCapture\"\n @paste.capture=\"onPasteCapture\"\n >\n <!-- `duplicate` and the absent `max` above are deliberate: Reka is told to\n accept every value it is offered, so that one place — `reduce` —\n decides what a token is. Two refusal ladders would be two answers to\n `duplicates`, and only one would be the one `reject` reports.\n\n The state markers live on the box rather than on the root, and not by\n preference: an attribute bound on `TagsInputRoot` is a fallthrough\n attr, and the root renders through Reka's `CollectionSlot`, which does\n not carry one to the element underneath. The box is also the honest\n node for them — it is what the state is painted on. -->\n <div\n :data-disabled=\"field.disabled || undefined\"\n :data-readonly=\"field.readonly || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :class=\"\n cn(\n 'flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border border-input bg-background px-2 py-0.5 text-sm text-foreground',\n 'transition-[color,background-color,border-color,box-shadow] duration-fast ease-out',\n // Rim-lit at rest, the weave blooms on focus, exactly as TextField's\n // does — a field holding tokens is still a field, and a form row\n // should not have two focus languages in it.\n 'focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring',\n !field.invalid && 'focus-within:shadow-halo',\n // Lifted rather than dimmed, and it keeps its focus ring: a read-only\n // field is a value **on show**, not an unavailable control. The fill\n // rises off `background` to `subtle` so the box reads as settled, and\n // the text stays full strength — 13.45:1 over that fill — because\n // being read is the entire purpose of the state. The border does not\n // move, because nothing about the field's reach has: it is still a\n // tab stop and still submitted.\n field.readonly && 'bg-subtle',\n // Unavailable is a step further down all three channels: the fill\n // drains to `muted`, the text follows to `muted-foreground` (4.67:1\n // over it) and the rim slackens from `input` to the lighter `border`.\n //\n // Read-only and disabled used to share `bg-muted` and part on the\n // text colour alone, which is a distinction made in hue and nothing\n // else — the one thing a reader with a colour deficiency does not\n // receive. Three channels is what makes available → on show →\n // unavailable legible without it.\n //\n // No `opacity-50` anywhere in that, and that is the point. Every\n // token inside is a Chip that has already drained itself to a\n // measured unavailable fill; halving the alpha over the top of that\n // takes its label below the contrast floor. `border-border` and not\n // the strong weight, for the reason `theme.css` gives the strong one:\n // it is for a block that must **assert** its edge, and an unavailable\n // field is the one thing that must not.\n field.disabled && 'cursor-not-allowed border-border bg-muted text-muted-foreground',\n // The same appearance, reached from the other direction: a\n // `<fieldset disabled>` above this field disables the `<input>` and\n // every token's remove button natively and never touches\n // `field.disabled`, so the rule above cannot fire and the box\n // rendered byte-identical to an editable one.\n //\n // `in-[fieldset:disabled]:` reads the attribute that did the\n // disabling, so the fill and the native inertness cannot disagree.\n // See TextField.vue for why it is preferred to a `has-[:disabled]:`\n // rule reading this box's own contents.\n 'in-[fieldset:disabled]:cursor-not-allowed in-[fieldset:disabled]:bg-muted in-[fieldset:disabled]:text-muted-foreground',\n // Gated for the reason the two rules below are ordered: Tailwind\n // emits the ancestor half of `in-*` inside `:where()`, so this\n // carries no more specificity than `border-destructive` and would\n // win on emission order alone.\n !field.invalid && 'in-[fieldset:disabled]:border-border',\n // Last of the rules that name a border colour, and the order is\n // load-bearing: `cn()` resolves a border colour by whichever class it\n // saw last, so a field that is both in error and unavailable would\n // lose its destructive rim to the disabled one if this sat above it.\n field.invalid && 'border-destructive focus-within:outline-destructive',\n )\n \"\n >\n <!-- A real list, so a reader browsing the field meets the tokens as\n items rather than as a run of buttons. It is not where the count\n comes from, though: Tailwind's preflight sets `list-style: none` on\n every `ul`, and Safari drops the list role from a list styled that\n way — which is why the count below is published in words instead of\n left to the browser. -->\n <ul v-if=\"tokens.length > 0\" class=\"flex min-w-0 flex-wrap items-center gap-1.5\">\n <TagsInputItem\n v-for=\"(row, index) in rows\"\n :key=\"row.key\"\n as=\"li\"\n :value=\"row.value\"\n class=\"flex animate-fade-rise\"\n >\n <Chip\n size=\"sm\"\n :removable=\"!field.readonly\"\n :disabled=\"field.disabled\"\n :remove-label=\"text.remove({ value: row.value })\"\n @remove=\"removeAt(index)\"\n >\n <TagsInputItemText />\n </Chip>\n </TagsInputItem>\n </ul>\n\n <!-- `field.attrs` spreads **after** the fallthrough attrs, and that\n position is the contract: the bag has already resolved the caller's\n own `id` and `aria-describedby`, and it drops every key that resolved\n to nothing, so it can only add.\n\n `:id` restates what the bag already holds, or supplies the id a\n Field's `<label for>` needs when it holds none. `:name` undoes one\n key of it on purpose — the text box holds a draft, not the value, and\n a `name` on it would post whatever was half-typed instead of the\n tokens. The value is posted by the hidden inputs the root renders. -->\n <TagsInputInput\n :id=\"inputId\"\n ref=\"input\"\n v-bind=\"{\n ...inputAttrs,\n ...field.attrs,\n ...optional({ placeholder: tokens.length === 0 ? placeholder : undefined }),\n }\"\n :name=\"undefined\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :readonly=\"field.readonly\"\n class=\"h-8 min-w-24 flex-1 bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed\"\n />\n\n <TagsInputClear\n v-if=\"clearable && tokens.length > 0 && !field.readonly\"\n :aria-label=\"text.clear\"\n :disabled=\"field.disabled\"\n class=\"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-sm text-muted-foreground transition-colors duration-fast ease-out hover:bg-subtle hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo data-[disabled]:cursor-not-allowed\"\n @click=\"focusInput\"\n >\n <X class=\"h-4 w-4\" />\n </TagsInputClear>\n\n <!-- The count, and the only thing that tells a reader how many tokens are\n in the field without walking them. Reka publishes nothing of the\n sort: its root is an unlabelled `div`. It is wired through\n `aria-describedby` rather than announced, so it is heard on focus and\n on every return to the field, which is when the question is asked. -->\n <span :id=\"countId\" class=\"sr-only\">\n {{ text.count({ count: tokens.length, max }) }}\n </span>\n </div>\n\n <!-- The region is in the DOM from the first render, empty. A live region\n mounted at the same moment as its text is a region assistive tech was\n not yet watching, so the first refusal — the one that matters most — is\n the one it announces least reliably. -->\n <div aria-live=\"polite\" aria-atomic=\"true\">\n <p\n v-if=\"message.length > 0\"\n :id=\"messageId\"\n class=\"mt-1.5 flex animate-fade-rise items-start gap-2 text-small text-destructive-text\"\n >\n <TriangleAlert class=\"mt-0.5 h-4 w-4 shrink-0\" aria-hidden=\"true\" />\n <span>{{ message }}</span>\n </p>\n </div>\n </TagsInputRoot>\n</template>\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"TextField.js","names":[],"sources":["../../../../../packages/primitives/text-field/src/TextField.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { TextFieldLabels } from \"@ecoma-io/loom-labels\";\nimport { COUNT_LABELS, warningWindow, type CountBand } from \"@ecoma-io/loom-labels\";\n\nexport type TextFieldType = \"text\" | \"email\" | \"password\" | \"search\" | \"url\" | \"tel\";\n\nexport type TextFieldSize = \"sm\" | \"md\" | \"lg\";\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 * rather than a transcription of it.\n */\nexport const TEXT_FIELD_LABELS: TextFieldLabels = {\n ...COUNT_LABELS,\n reveal: \"Show password\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useId, useTemplateRef, watch } from \"vue\";\nimport { Eye, EyeOff } from \"@lucide/vue\";\nimport { cn } 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\";\n\n/**\n * TextField — single-line text entry (text · email · password · search · url ·\n * tel). The border, focus ring and invalid state live on the wrapper so\n * optional `#leading`/`#trailing` adornments (a search icon, a unit suffix)\n * sit *inside* the field and share its focus bloom, instead of every caller\n * re-inventing an icon-inside-input layout. For numeric entry reach for a\n * number field; for a bounded continuous value, a slider.\n *\n * Wrapping a rendered structure means the fallthrough `class` must land on\n * the wrapper (so a caller's `w-64`/`flex-1` sizes the whole field) while the\n * rest of the attrs (`id`, `name`, `data-testid`, `aria-describedby`,\n * `autocomplete`) belong on the real `<input>` — the split-attrs convention\n * shared with the other bare controls. The accessible name is a first-class\n * prop pair (`aria-label`/`aria-labelledby`, camelized by Vue) rather than a\n * loose fallthrough attr, so it is bound onto the input explicitly and shows\n * up in the props table — a bare input primitive can only be named by its\n * host.\n *\n * That same wrapper is why `revealable` and the character counter are props\n * here rather than a `PasswordField` and a `CountedField` beside it. `password`\n * is already a `TextFieldType` and the adornment row already exists, so a\n * second component would duplicate an entire input, its Field wiring and its\n * three sizes to add one button; and a counter rendered *below* the field\n * would have to move the fallthrough `class` off the box a caller sizes with\n * it. Both live inside the border, where the adornments already live.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself: the row's id, the id\n * of the hint or error line, and `required` / `invalid` / `disabled` /\n * `readonly` / `name` all arrive through `useFieldControl()`, so\n * `<Field label=\"Email\" error=\"…\"><TextField /></Field>` needs no attributes at\n * the call site. Every prop below still wins over the row when it is set, in\n * both directions — which is why the four booleans default to `undefined`\n * rather than `false`.\n *\n * `readonly` and `disabled` are different states, not two dials on one, so the\n * field has **three** resting appearances rather than two. A read-only field\n * is a value the reader may see and copy but not change: it stays a Tab stop,\n * stays in the form's submitted data, and takes a lifted fill with its text at\n * full strength. A disabled field is unavailable: no Tab stop, not submitted,\n * and drained a step further, in fill, in text colour and in border weight\n * together. Three channels rather than one is the point — see the class list.\n */\nconst props = withDefaults(\n defineProps<{\n /** The current value. Pair with `@update:modelValue` for `v-model`. */\n modelValue?: string;\n /** The native input type — also the on-screen keyboard hint on mobile. */\n type?: TextFieldType;\n /** Text shown in the empty field. */\n placeholder?: string;\n /** Disables the field and blocks pointer and keyboard input. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Shows the value without allowing an edit, while staying focusable and still submitted. Unset defers to a wrapping Field. */\n readonly?: boolean | undefined;\n /** Error state: paints the destructive border/ring and sets aria-invalid. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** Marks the field mandatory to assistive tech (`aria-required`). Unset defers to a wrapping Field. */\n required?: boolean | undefined;\n /** The field name for a native form post or `FormData`. Unset defers to a wrapping Field. */\n name?: string;\n /** Control height. */\n size?: TextFieldSize;\n /** The accessible name, when no visible element already labels the field. */\n ariaLabel?: string;\n /** The id of the visible element that labels the field (e.g. a Field wrapper's label). */\n ariaLabelledby?: string;\n /**\n * Adds a toggle that shows the typed password in place, for\n * `type=\"password\"` **and nothing else** — on any other type it renders\n * nothing at all, because there is nothing to reveal.\n */\n revealable?: boolean;\n /**\n * The character limit the counter reports against, and the point past\n * which it reads as over-limit.\n *\n * Advisory, exactly as `required` is: it does **not** set the native\n * `maxlength`, which silently truncates a paste and tells the reader\n * nothing. Pass `maxlength` yourself as a plain attribute where you want\n * the browser to enforce it too.\n */\n maxLength?: number;\n /**\n * Forces the counter on or off. Left unset it follows `maxLength` — a\n * limit the reader is never shown is one they can only discover by\n * exceeding it — so set it `true` for a running total with no limit, and\n * `false` to hold a limit the field reports nowhere.\n */\n showCount?: boolean | undefined;\n /**\n * Names for everything this control says out loud, as any subset of\n * `TextFieldLabels` — 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: the case it exists for is a field counting something other\n * than characters, where \"80 words left\" is the true sentence.\n */\n labels?: LabelOverrides<TextFieldLabels>;\n }>(),\n {\n type: \"text\",\n // Not `false`, for any of the four. `false` is a caller saying \"this field\n // is fine / enabled / editable even though its row is not\"; absent is a\n // caller saying nothing, and only `undefined` survives to mean that. The\n // explicit default is also what beats Vue's absent-Boolean-casts-to-false\n // rule — the same reason Checkbox's `modelValue` carries one.\n disabled: undefined,\n readonly: undefined,\n invalid: undefined,\n required: undefined,\n size: \"md\",\n revealable: false,\n // `undefined` for the same Boolean-cast reason, and here it is the whole\n // feature: `showCount ?? (maxLength !== undefined)` would be a dead branch\n // if an absent prop arrived as `false`.\n showCount: undefined,\n },\n);\n\nconst emit = defineEmits<{ \"update:modelValue\": [value: string] }>();\n\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\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(\"textField\", TEXT_FIELD_LABELS, () => props.labels);\n\nconst inputRef = useTemplateRef<HTMLInputElement>(\"input\");\nconst countId = useId();\n\n/**\n * What is actually in the box, which is not always `modelValue`.\n *\n * Used without `v-model` this component is uncontrolled — `modelValue` stays\n * `undefined` while the reader types — and the counter still has to count. So\n * the last typed value is kept here and `currentValue` prefers the prop: a\n * controlled host that *declines* an update keeps the count honest, and an\n * uncontrolled one gets the text in front of it.\n *\n * Binding `:value=\"currentValue\"` rather than `:value=\"modelValue\"` is\n * load-bearing and not cosmetic. Vue's `value` patch coerces `null`/`undefined`\n * to `\"\"`, so any re-render of an uncontrolled field wipes the input — a defect\n * nothing had met only because nothing in this component re-rendered on a\n * keystroke until the counter did.\n */\nconst typed = ref(props.modelValue ?? \"\");\nconst currentValue = computed(() => props.modelValue ?? typed.value);\n\nfunction onInput(event: Event): void {\n const value = (event.target as HTMLInputElement).value;\n typed.value = value;\n emit(\"update:modelValue\", value);\n}\n\n/**\n * The reveal, and the two guards that make `revealable` inert rather than\n * surprising on a non-password field: the toggle is not rendered, and the type\n * cannot flip. A `type` that stops being `password` also drops the reveal —\n * coming back as a password already revealed would put a secret on screen that\n * nobody asked for a second time.\n */\nconst canReveal = computed(() => props.revealable && props.type === \"password\");\nconst revealed = ref(false);\nwatch(canReveal, (able) => {\n if (!able) revealed.value = false;\n});\n\nconst inputType = computed(() => (canReveal.value && revealed.value ? \"text\" : props.type));\n\n/**\n * Flipping `type` is what loses the caret: the input is re-created enough,\n * engine by engine, that the selection lands back at 0 or at the end, and a\n * reader who was fixing the third character of a long passphrase is now\n * somewhere else with no way to tell where. So the range is read before the\n * flip and written back after the DOM has it.\n *\n * Both `password` and `text` support the selection API (`email`, `url` and\n * `number` do not, and throw), and this path is unreachable for any other type\n * by construction — see `canReveal`.\n *\n * Focus is deliberately *not* moved back to the input. A reader who pressed\n * this with the keyboard is standing on the toggle and will very often press\n * it again; dropping them into the field would make hiding the password a\n * Shift+Tab away. The restored range is what greets them when they do return.\n */\nfunction toggleReveal(): void {\n const input = inputRef.value;\n const start = input?.selectionStart ?? null;\n const end = input?.selectionEnd ?? null;\n const direction = input?.selectionDirection ?? \"none\";\n\n revealed.value = !revealed.value;\n\n if (input === null || start === null || end === null) return;\n void nextTick(() => {\n input.setSelectionRange(start, end, direction);\n });\n}\n\n/**\n * Length in UTF-16 code units, which is what the platform's own `maxlength`\n * counts. `[...value].length` would count code points and disagree with the\n * browser on any astral character, so a caller who pairs this with a native\n * `maxlength` would watch the counter and the enforcement drift apart.\n */\nconst count = computed(() => currentValue.value.length);\nconst showsCount = computed(() => props.showCount ?? props.maxLength !== undefined);\n\nconst band = computed<CountBand>(() => {\n const max = props.maxLength;\n if (max === undefined) return \"under\";\n const remaining = max - count.value;\n if (remaining < 0) return \"over\";\n return remaining <= warningWindow(max) ? \"near\" : \"under\";\n});\n\nconst countText = computed(() => {\n const max = props.maxLength;\n if (max === undefined) return text.value.count({ count: count.value });\n const over = count.value - max;\n return over > 0\n ? text.value.countOverMax({ count: count.value, max, over })\n : text.value.countOfMax({ count: count.value, max });\n});\n\n/**\n * What the live region says, and it changes **only when the band changes**.\n *\n * A region holding the counter itself would speak on every keystroke, which is\n * worse than silence: it buries the field's own echo of the character just\n * typed under a number nobody asked for. What a reader needs is the two facts\n * they cannot see coming — the limit is close, and the limit is passed — so\n * this fires once at each crossing and goes quiet again on the way back down.\n *\n * The numbers are therefore true at the moment they are spoken and not after.\n * That is the deliberate trade: the visible counter carries the live figure,\n * and it is wired into `aria-describedby`, so the exact count is one\n * re-read away whenever the reader wants it rather than pushed at them.\n */\nconst announcement = ref(\"\");\nwatch(band, (now) => {\n const max = props.maxLength;\n if (max === undefined || now === \"under\") {\n announcement.value = \"\";\n return;\n }\n announcement.value =\n now === \"over\"\n ? text.value.limitExceeded({ over: count.value - max, max })\n : text.value.approachingLimit({ remaining: max - count.value, max });\n});\n\n// `id` and `aria-describedby` reach a bare 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. The counter joins\n// that list rather than replacing anything: it is one more thing this field\n// says about itself, and it reads after the caller's own description and before\n// the row's message, which is the same most-specific-first order\n// `useFieldControl` applies one layer out.\n//\n// `field.attrs` then spreads onto the `<input>` **after** `inputAttrs`, and\n// that position is the contract: the bag has already resolved the caller's own\n// values, and it drops every key that resolved to nothing, so it can only add.\n// The `:aria-invalid` binding that used to sit on the input is gone with it —\n// an individual attribute written after a `v-bind` wins, so keeping one would\n// overwrite the resolved value with the raw prop and quietly re-break the link\n// to the row.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [attrs[\"aria-describedby\"] as string | undefined, showsCount.value ? countId : \"\"]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n name: props.name,\n disabled: props.disabled,\n readonly: props.readonly,\n invalid: props.invalid,\n required: props.required,\n}));\n</script>\n\n<template>\n <div\n :data-disabled=\"field.disabled || undefined\"\n :data-readonly=\"field.readonly || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :class=\"\n cn(\n 'group flex 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 // Rim-lit at rest, the weave blooms on focus (Signature law): the field\n // catches light instead of casting a shadow, and focus draws it tight.\n 'focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring',\n !field.invalid && 'focus-within:shadow-halo',\n size === 'sm' && 'h-8 px-2.5 text-xs',\n size === 'md' && 'h-9 px-3 text-sm',\n size === 'lg' && 'h-11 px-4 text-base',\n // The three resting appearances, and each is three changes rather than\n // one. Read-only and disabled used to share `bg-muted` and part only on\n // the text colour, which is a distinction carried by hue alone — the\n // one thing a reader with a colour deficiency, or a low-quality\n // display, or forced-colors, does not get. The fill separates them and\n // the border weight separates them again, so the progression\n // available → on show → unavailable is legible on three channels.\n //\n // Read-only is a value **on show**: the fill lifts off `background` to\n // `subtle` so the row reads as settled rather than editable, and the\n // text stays full strength — 13.46:1 over that fill — because being\n // read is the entire purpose of the state. The border does not move,\n // because nothing about the control's reach has: it is still a Tab stop\n // and still submitted. The native `readonly` attribute below carries\n // the same fact to assistive tech, so nothing here rests on colour.\n field.readonly && 'bg-subtle',\n // Disabled is **unavailable**: the fill drains one step further to\n // `muted`, the text follows it down to `muted-foreground` (4.68:1 over\n // it, still AA), and the rim slackens from `input` to the lighter\n // `border`.\n //\n // Drained rather than faded, and `opacity` is never the mechanism. The\n // element a dim would sit on is the box, and the box is wrapped around\n // the one thing a reader still needs: measured on the built site,\n // `opacity-50` put a disabled field's value at 3.08:1 and its\n // placeholder — already the muted colour before the fade — at 2.07:1.\n // The text colour is declared here rather than on the `<input>` because\n // the input sets no resting colour of its own and inherits this one,\n // which also carries it to the counter and the adornments in the same\n // box.\n field.disabled && 'cursor-not-allowed border-border bg-muted text-muted-foreground',\n // The same appearance, reached from the other direction: a\n // `<fieldset disabled>` above this field disables the `<input>` inside\n // it natively and never touches `field.disabled`, so the rule above\n // cannot fire and the field rendered byte-identical to an editable one.\n //\n // `in-[fieldset:disabled]:` is a *read* of the attribute that did the\n // disabling, so the fill and the native inertness cannot disagree — the\n // fieldset element is still the only place the fact is written. It is\n // preferred to `has-[:disabled]:` (a wrapper reading its own contents)\n // because that proxy is wrong wherever a control holds a part that\n // disables itself: measured on this branch, NumberField's increment\n // button goes `:disabled` at `max`, so a `has-` rule would drain a\n // perfectly editable field the moment its value reached the top.\n // Nothing about this field is a proxy — the fieldset either disabled it\n // or it did not.\n 'in-[fieldset:disabled]:cursor-not-allowed in-[fieldset:disabled]:bg-muted in-[fieldset:disabled]:text-muted-foreground',\n // Gated where the two rules below are ordered, and for the same reason.\n // Tailwind emits the ancestor half of `in-*` inside `:where()`, so this\n // carries no more specificity than `border-destructive` and would win\n // on emission order alone — an unavailable field that is also in error\n // would quietly lose its destructive rim.\n !field.invalid && 'in-[fieldset:disabled]:border-border',\n // Last of the three rules that name a border colour, and the order is\n // load-bearing: `cn()` resolves a border colour by whichever class it\n // saw last, so a field that is both in error and unavailable would lose\n // its destructive rim to the disabled one if this sat above it.\n field.invalid && 'border-destructive focus-within:outline-destructive',\n attrs.class as string,\n )\n \"\n >\n <span\n v-if=\"$slots.leading\"\n class=\"inline-flex shrink-0 text-muted-foreground transition-colors duration-fast ease-out group-focus-within:text-foreground\"\n >\n <slot name=\"leading\" />\n </span>\n <input\n ref=\"input\"\n v-bind=\"{ ...inputAttrs, ...field.attrs }\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :type=\"inputType\"\n :value=\"currentValue\"\n :placeholder=\"placeholder\"\n :disabled=\"field.disabled\"\n :readonly=\"field.readonly\"\n class=\"min-w-0 flex-1 self-stretch bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed\"\n @input=\"onInput\"\n />\n <!-- The counter is an adornment like any other, and it renders inside the\n border for the reason the icons do: the box is what a caller's `class`\n sizes, so a readout hung underneath it would need an outer element and\n `w-64` would then size something other than the field. Absent, both\n nodes are gone and the box is exactly what it was.\n\n `tabular` because the number changes under itself on every keystroke,\n and proportional digits would shuffle the whole readout sideways as\n they do. -->\n <span\n v-if=\"showsCount\"\n :id=\"countId\"\n :data-over-limit=\"band === 'over' || undefined\"\n :class=\"\n cn(\n 'tabular shrink-0 select-none text-small',\n band === 'under' && 'text-muted-foreground',\n // Colour, and never only colour: `countOverMax` says the limit is\n // passed in words as well, and `approachingLimit` announces the near\n // band once. The digits themselves are the third reading — 21/20 is\n // over the limit whatever it is painted.\n band === 'near' && 'text-warning-text',\n band === 'over' && 'text-destructive-text',\n )\n \"\n >\n {{ countText }}\n </span>\n <!-- In the DOM from the first render, empty. A live region mounted at the\n same moment as its text is a region assistive tech was not yet\n watching, so the first warning — the one that matters most — is the one\n it announces least reliably. -->\n <span v-if=\"showsCount && maxLength !== undefined\" role=\"status\" class=\"sr-only\">\n {{ announcement }}\n </span>\n <span\n v-if=\"$slots.trailing || canReveal\"\n class=\"inline-flex shrink-0 items-center gap-1 text-muted-foreground transition-colors duration-fast ease-out group-focus-within:text-foreground\"\n >\n <slot name=\"trailing\" />\n <!-- Last in the row and last in the tab order, which is the requirement:\n a control that acts on the input must never stand between the reader\n and the input itself.\n\n `aria-pressed` rather than a name that changes with the state, and\n the two are not interchangeable. A name alone can only say what\n pressing will do, so a reader arriving on \"Hide password\" has to\n infer the state from the offer — and on activation the announcement\n is a *rename*, which some screen readers re-read and some do not, so\n the state change can pass in silence. A pressed state changes under a\n stable name, which every major screen reader announces as a state\n change, and it leaves the control findable by voice under the one\n name it always had. The glyph swap is the sighted half of the same\n fact.\n\n It stays available while the field is read-only: `readonly` is about\n changing the value, and revealing does not. -->\n <button\n v-if=\"canReveal\"\n type=\"button\"\n :aria-label=\"text.reveal\"\n :aria-pressed=\"revealed\"\n :disabled=\"field.disabled\"\n class=\"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-sm text-muted-foreground transition-colors duration-fast ease-out hover:bg-subtle hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo disabled:cursor-not-allowed\"\n @click=\"toggleReveal\"\n >\n <EyeOff v-if=\"revealed\" class=\"h-4 w-4\" aria-hidden=\"true\" />\n <Eye v-else class=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n </span>\n </div>\n</template>\n"],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"TextField.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../../../packages/primitives/text-field/src/TextField.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { TextFieldLabels } from \"@ecoma-io/loom-labels\";\nimport { COUNT_LABELS, warningWindow, type CountBand } from \"@ecoma-io/loom-labels\";\n\nexport type TextFieldType = \"text\" | \"email\" | \"password\" | \"search\" | \"url\" | \"tel\";\n\nexport type TextFieldSize = \"sm\" | \"md\" | \"lg\";\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 * rather than a transcription of it.\n */\nexport const TEXT_FIELD_LABELS: TextFieldLabels = {\n ...COUNT_LABELS,\n reveal: \"Show password\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useId, useTemplateRef, watch } from \"vue\";\nimport { Eye, EyeOff } from \"@lucide/vue\";\nimport { cn } 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\";\n\n/**\n * TextField — single-line text entry (text · email · password · search · url ·\n * tel). The border, focus ring and invalid state live on the wrapper so\n * optional `#leading`/`#trailing` adornments (a search icon, a unit suffix)\n * sit *inside* the field and share its focus bloom, instead of every caller\n * re-inventing an icon-inside-input layout. For numeric entry reach for a\n * number field; for a bounded continuous value, a slider.\n *\n * Wrapping a rendered structure means the fallthrough `class` must land on\n * the wrapper (so a caller's `w-64`/`flex-1` sizes the whole field) while the\n * rest of the attrs (`id`, `name`, `data-testid`, `aria-describedby`,\n * `autocomplete`) belong on the real `<input>` — the split-attrs convention\n * shared with the other bare controls. The accessible name is a first-class\n * prop pair (`aria-label`/`aria-labelledby`, camelized by Vue) rather than a\n * loose fallthrough attr, so it is bound onto the input explicitly and shows\n * up in the props table — a bare input primitive can only be named by its\n * host.\n *\n * That same wrapper is why `revealable` and the character counter are props\n * here rather than a `PasswordField` and a `CountedField` beside it. `password`\n * is already a `TextFieldType` and the adornment row already exists, so a\n * second component would duplicate an entire input, its Field wiring and its\n * three sizes to add one button; and a counter rendered *below* the field\n * would have to move the fallthrough `class` off the box a caller sizes with\n * it. Both live inside the border, where the adornments already live.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself: the row's id, the id\n * of the hint or error line, and `required` / `invalid` / `disabled` /\n * `readonly` / `name` all arrive through `useFieldControl()`, so\n * `<Field label=\"Email\" error=\"…\"><TextField /></Field>` needs no attributes at\n * the call site. Every prop below still wins over the row when it is set, in\n * both directions — which is why the four booleans default to `undefined`\n * rather than `false`.\n *\n * `readonly` and `disabled` are different states, not two dials on one, so the\n * field has **three** resting appearances rather than two. A read-only field\n * is a value the reader may see and copy but not change: it stays a Tab stop,\n * stays in the form's submitted data, and takes a lifted fill with its text at\n * full strength. A disabled field is unavailable: no Tab stop, not submitted,\n * and drained a step further, in fill, in text colour and in border weight\n * together. Three channels rather than one is the point — see the class list.\n */\nconst props = withDefaults(\n defineProps<{\n /** The current value. Pair with `@update:modelValue` for `v-model`. */\n modelValue?: string;\n /** The native input type — also the on-screen keyboard hint on mobile. */\n type?: TextFieldType;\n /** Text shown in the empty field. */\n placeholder?: string;\n /** Disables the field and blocks pointer and keyboard input. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Shows the value without allowing an edit, while staying focusable and still submitted. Unset defers to a wrapping Field. */\n readonly?: boolean | undefined;\n /** Error state: paints the destructive border/ring and sets aria-invalid. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** Marks the field mandatory to assistive tech (`aria-required`). Unset defers to a wrapping Field. */\n required?: boolean | undefined;\n /** The field name for a native form post or `FormData`. Unset defers to a wrapping Field. */\n name?: string;\n /** Control height. */\n size?: TextFieldSize;\n /** The accessible name, when no visible element already labels the field. */\n ariaLabel?: string;\n /** The id of the visible element that labels the field (e.g. a Field wrapper's label). */\n ariaLabelledby?: string;\n /**\n * Adds a toggle that shows the typed password in place, for\n * `type=\"password\"` **and nothing else** — on any other type it renders\n * nothing at all, because there is nothing to reveal.\n */\n revealable?: boolean;\n /**\n * The character limit the counter reports against, and the point past\n * which it reads as over-limit.\n *\n * Advisory, exactly as `required` is: it does **not** set the native\n * `maxlength`, which silently truncates a paste and tells the reader\n * nothing. Pass `maxlength` yourself as a plain attribute where you want\n * the browser to enforce it too.\n */\n maxLength?: number;\n /**\n * Forces the counter on or off. Left unset it follows `maxLength` — a\n * limit the reader is never shown is one they can only discover by\n * exceeding it — so set it `true` for a running total with no limit, and\n * `false` to hold a limit the field reports nowhere.\n */\n showCount?: boolean | undefined;\n /**\n * Names for everything this control says out loud, as any subset of\n * `TextFieldLabels` — 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: the case it exists for is a field counting something other\n * than characters, where \"80 words left\" is the true sentence.\n */\n labels?: LabelOverrides<TextFieldLabels>;\n }>(),\n {\n type: \"text\",\n // Not `false`, for any of the four. `false` is a caller saying \"this field\n // is fine / enabled / editable even though its row is not\"; absent is a\n // caller saying nothing, and only `undefined` survives to mean that. The\n // explicit default is also what beats Vue's absent-Boolean-casts-to-false\n // rule — the same reason Checkbox's `modelValue` carries one.\n disabled: undefined,\n readonly: undefined,\n invalid: undefined,\n required: undefined,\n size: \"md\",\n revealable: false,\n // `undefined` for the same Boolean-cast reason, and here it is the whole\n // feature: `showCount ?? (maxLength !== undefined)` would be a dead branch\n // if an absent prop arrived as `false`.\n showCount: undefined,\n },\n);\n\nconst emit = defineEmits<{ \"update:modelValue\": [value: string] }>();\n\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\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(\"textField\", TEXT_FIELD_LABELS, () => props.labels);\n\nconst inputRef = useTemplateRef<HTMLInputElement>(\"input\");\nconst countId = useId();\n\n/**\n * What is actually in the box, which is not always `modelValue`.\n *\n * Used without `v-model` this component is uncontrolled — `modelValue` stays\n * `undefined` while the reader types — and the counter still has to count. So\n * the last typed value is kept here and `currentValue` prefers the prop: a\n * controlled host that *declines* an update keeps the count honest, and an\n * uncontrolled one gets the text in front of it.\n *\n * Binding `:value=\"currentValue\"` rather than `:value=\"modelValue\"` is\n * load-bearing and not cosmetic. Vue's `value` patch coerces `null`/`undefined`\n * to `\"\"`, so any re-render of an uncontrolled field wipes the input — a defect\n * nothing had met only because nothing in this component re-rendered on a\n * keystroke until the counter did.\n */\nconst typed = ref(props.modelValue ?? \"\");\nconst currentValue = computed(() => props.modelValue ?? typed.value);\n\nfunction onInput(event: Event): void {\n const value = (event.target as HTMLInputElement).value;\n typed.value = value;\n emit(\"update:modelValue\", value);\n}\n\n/**\n * The reveal, and the two guards that make `revealable` inert rather than\n * surprising on a non-password field: the toggle is not rendered, and the type\n * cannot flip. A `type` that stops being `password` also drops the reveal —\n * coming back as a password already revealed would put a secret on screen that\n * nobody asked for a second time.\n */\nconst canReveal = computed(() => props.revealable && props.type === \"password\");\nconst revealed = ref(false);\nwatch(canReveal, (able) => {\n if (!able) revealed.value = false;\n});\n\nconst inputType = computed(() => (canReveal.value && revealed.value ? \"text\" : props.type));\n\n/**\n * Flipping `type` is what loses the caret: the input is re-created enough,\n * engine by engine, that the selection lands back at 0 or at the end, and a\n * reader who was fixing the third character of a long passphrase is now\n * somewhere else with no way to tell where. So the range is read before the\n * flip and written back after the DOM has it.\n *\n * Both `password` and `text` support the selection API (`email`, `url` and\n * `number` do not, and throw), and this path is unreachable for any other type\n * by construction — see `canReveal`.\n *\n * Focus is deliberately *not* moved back to the input. A reader who pressed\n * this with the keyboard is standing on the toggle and will very often press\n * it again; dropping them into the field would make hiding the password a\n * Shift+Tab away. The restored range is what greets them when they do return.\n */\nfunction toggleReveal(): void {\n const input = inputRef.value;\n const start = input?.selectionStart ?? null;\n const end = input?.selectionEnd ?? null;\n const direction = input?.selectionDirection ?? \"none\";\n\n revealed.value = !revealed.value;\n\n if (input === null || start === null || end === null) return;\n void nextTick(() => {\n input.setSelectionRange(start, end, direction);\n });\n}\n\n/**\n * Length in UTF-16 code units, which is what the platform's own `maxlength`\n * counts. `[...value].length` would count code points and disagree with the\n * browser on any astral character, so a caller who pairs this with a native\n * `maxlength` would watch the counter and the enforcement drift apart.\n */\nconst count = computed(() => currentValue.value.length);\nconst showsCount = computed(() => props.showCount ?? props.maxLength !== undefined);\n\nconst band = computed<CountBand>(() => {\n const max = props.maxLength;\n if (max === undefined) return \"under\";\n const remaining = max - count.value;\n if (remaining < 0) return \"over\";\n return remaining <= warningWindow(max) ? \"near\" : \"under\";\n});\n\nconst countText = computed(() => {\n const max = props.maxLength;\n if (max === undefined) return text.value.count({ count: count.value });\n const over = count.value - max;\n return over > 0\n ? text.value.countOverMax({ count: count.value, max, over })\n : text.value.countOfMax({ count: count.value, max });\n});\n\n/**\n * What the live region says, and it changes **only when the band changes**.\n *\n * A region holding the counter itself would speak on every keystroke, which is\n * worse than silence: it buries the field's own echo of the character just\n * typed under a number nobody asked for. What a reader needs is the two facts\n * they cannot see coming — the limit is close, and the limit is passed — so\n * this fires once at each crossing and goes quiet again on the way back down.\n *\n * The numbers are therefore true at the moment they are spoken and not after.\n * That is the deliberate trade: the visible counter carries the live figure,\n * and it is wired into `aria-describedby`, so the exact count is one\n * re-read away whenever the reader wants it rather than pushed at them.\n */\nconst announcement = ref(\"\");\nwatch(band, (now) => {\n const max = props.maxLength;\n if (max === undefined || now === \"under\") {\n announcement.value = \"\";\n return;\n }\n announcement.value =\n now === \"over\"\n ? text.value.limitExceeded({ over: count.value - max, max })\n : text.value.approachingLimit({ remaining: max - count.value, max });\n});\n\n// `id` and `aria-describedby` reach a bare 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. The counter joins\n// that list rather than replacing anything: it is one more thing this field\n// says about itself, and it reads after the caller's own description and before\n// the row's message, which is the same most-specific-first order\n// `useFieldControl` applies one layer out.\n//\n// `field.attrs` then spreads onto the `<input>` **after** `inputAttrs`, and\n// that position is the contract: the bag has already resolved the caller's own\n// values, and it drops every key that resolved to nothing, so it can only add.\n// The `:aria-invalid` binding that used to sit on the input is gone with it —\n// an individual attribute written after a `v-bind` wins, so keeping one would\n// overwrite the resolved value with the raw prop and quietly re-break the link\n// to the row.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [attrs[\"aria-describedby\"] as string | undefined, showsCount.value ? countId : \"\"]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n name: props.name,\n disabled: props.disabled,\n readonly: props.readonly,\n invalid: props.invalid,\n required: props.required,\n}));\n</script>\n\n<template>\n <div\n :data-disabled=\"field.disabled || undefined\"\n :data-readonly=\"field.readonly || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :class=\"\n cn(\n 'group flex 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 // Rim-lit at rest, the weave blooms on focus (Signature law): the field\n // catches light instead of casting a shadow, and focus draws it tight.\n 'focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring',\n !field.invalid && 'focus-within:shadow-halo',\n size === 'sm' && 'h-8 px-2.5 text-xs',\n size === 'md' && 'h-9 px-3 text-sm',\n size === 'lg' && 'h-11 px-4 text-base',\n // The three resting appearances, and each is three changes rather than\n // one. Read-only and disabled used to share `bg-muted` and part only on\n // the text colour, which is a distinction carried by hue alone — the\n // one thing a reader with a colour deficiency, or a low-quality\n // display, or forced-colors, does not get. The fill separates them and\n // the border weight separates them again, so the progression\n // available → on show → unavailable is legible on three channels.\n //\n // Read-only is a value **on show**: the fill lifts off `background` to\n // `subtle` so the row reads as settled rather than editable, and the\n // text stays full strength — 13.46:1 over that fill — because being\n // read is the entire purpose of the state. The border does not move,\n // because nothing about the control's reach has: it is still a Tab stop\n // and still submitted. The native `readonly` attribute below carries\n // the same fact to assistive tech, so nothing here rests on colour.\n field.readonly && 'bg-subtle',\n // Disabled is **unavailable**: the fill drains one step further to\n // `muted`, the text follows it down to `muted-foreground` (4.68:1 over\n // it, still AA), and the rim slackens from `input` to the lighter\n // `border`.\n //\n // Drained rather than faded, and `opacity` is never the mechanism. The\n // element a dim would sit on is the box, and the box is wrapped around\n // the one thing a reader still needs: measured on the built site,\n // `opacity-50` put a disabled field's value at 3.08:1 and its\n // placeholder — already the muted colour before the fade — at 2.07:1.\n // The text colour is declared here rather than on the `<input>` because\n // the input sets no resting colour of its own and inherits this one,\n // which also carries it to the counter and the adornments in the same\n // box.\n field.disabled && 'cursor-not-allowed border-border bg-muted text-muted-foreground',\n // The same appearance, reached from the other direction: a\n // `<fieldset disabled>` above this field disables the `<input>` inside\n // it natively and never touches `field.disabled`, so the rule above\n // cannot fire and the field rendered byte-identical to an editable one.\n //\n // `in-[fieldset:disabled]:` is a *read* of the attribute that did the\n // disabling, so the fill and the native inertness cannot disagree — the\n // fieldset element is still the only place the fact is written. It is\n // preferred to `has-[:disabled]:` (a wrapper reading its own contents)\n // because that proxy is wrong wherever a control holds a part that\n // disables itself: measured on this branch, NumberField's increment\n // button goes `:disabled` at `max`, so a `has-` rule would drain a\n // perfectly editable field the moment its value reached the top.\n // Nothing about this field is a proxy — the fieldset either disabled it\n // or it did not.\n 'in-[fieldset:disabled]:cursor-not-allowed in-[fieldset:disabled]:bg-muted in-[fieldset:disabled]:text-muted-foreground',\n // Gated where the two rules below are ordered, and for the same reason.\n // Tailwind emits the ancestor half of `in-*` inside `:where()`, so this\n // carries no more specificity than `border-destructive` and would win\n // on emission order alone — an unavailable field that is also in error\n // would quietly lose its destructive rim.\n !field.invalid && 'in-[fieldset:disabled]:border-border',\n // Last of the three rules that name a border colour, and the order is\n // load-bearing: `cn()` resolves a border colour by whichever class it\n // saw last, so a field that is both in error and unavailable would lose\n // its destructive rim to the disabled one if this sat above it.\n field.invalid && 'border-destructive focus-within:outline-destructive',\n attrs.class as string,\n )\n \"\n >\n <span\n v-if=\"$slots.leading\"\n class=\"inline-flex shrink-0 text-muted-foreground transition-colors duration-fast ease-out group-focus-within:text-foreground\"\n >\n <slot name=\"leading\" />\n </span>\n <input\n ref=\"input\"\n v-bind=\"{ ...inputAttrs, ...field.attrs }\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :type=\"inputType\"\n :value=\"currentValue\"\n :placeholder=\"placeholder\"\n :disabled=\"field.disabled\"\n :readonly=\"field.readonly\"\n class=\"min-w-0 flex-1 self-stretch bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed\"\n @input=\"onInput\"\n />\n <!-- The counter is an adornment like any other, and it renders inside the\n border for the reason the icons do: the box is what a caller's `class`\n sizes, so a readout hung underneath it would need an outer element and\n `w-64` would then size something other than the field. Absent, both\n nodes are gone and the box is exactly what it was.\n\n `tabular` because the number changes under itself on every keystroke,\n and proportional digits would shuffle the whole readout sideways as\n they do. -->\n <span\n v-if=\"showsCount\"\n :id=\"countId\"\n :data-over-limit=\"band === 'over' || undefined\"\n :class=\"\n cn(\n 'tabular shrink-0 select-none text-small',\n band === 'under' && 'text-muted-foreground',\n // Colour, and never only colour: `countOverMax` says the limit is\n // passed in words as well, and `approachingLimit` announces the near\n // band once. The digits themselves are the third reading — 21/20 is\n // over the limit whatever it is painted.\n band === 'near' && 'text-warning-text',\n band === 'over' && 'text-destructive-text',\n )\n \"\n >\n {{ countText }}\n </span>\n <!-- In the DOM from the first render, empty. A live region mounted at the\n same moment as its text is a region assistive tech was not yet\n watching, so the first warning — the one that matters most — is the one\n it announces least reliably. -->\n <span v-if=\"showsCount && maxLength !== undefined\" role=\"status\" class=\"sr-only\">\n {{ announcement }}\n </span>\n <span\n v-if=\"$slots.trailing || canReveal\"\n class=\"inline-flex shrink-0 items-center gap-1 text-muted-foreground transition-colors duration-fast ease-out group-focus-within:text-foreground\"\n >\n <slot name=\"trailing\" />\n <!-- Last in the row and last in the tab order, which is the requirement:\n a control that acts on the input must never stand between the reader\n and the input itself.\n\n `aria-pressed` rather than a name that changes with the state, and\n the two are not interchangeable. A name alone can only say what\n pressing will do, so a reader arriving on \"Hide password\" has to\n infer the state from the offer — and on activation the announcement\n is a *rename*, which some screen readers re-read and some do not, so\n the state change can pass in silence. A pressed state changes under a\n stable name, which every major screen reader announces as a state\n change, and it leaves the control findable by voice under the one\n name it always had. The glyph swap is the sighted half of the same\n fact.\n\n It stays available while the field is read-only: `readonly` is about\n changing the value, and revealing does not. -->\n <button\n v-if=\"canReveal\"\n type=\"button\"\n :aria-label=\"text.reveal\"\n :aria-pressed=\"revealed\"\n :disabled=\"field.disabled\"\n class=\"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-sm text-muted-foreground transition-colors duration-fast ease-out hover:bg-subtle hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo disabled:cursor-not-allowed\"\n @click=\"toggleReveal\"\n >\n <EyeOff v-if=\"revealed\" class=\"h-4 w-4\" aria-hidden=\"true\" />\n <Eye v-else class=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n </span>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Textarea.js","names":[],"sources":["../../../../../packages/primitives/textarea/src/Textarea.vue"],"sourcesContent":["<script lang=\"ts\">\nimport {\n COUNT_LABELS,\n warningWindow,\n type CountBand,\n type TextareaLabels,\n} from \"@ecoma-io/loom-labels\";\n\nexport type TextareaResize = \"none\" | \"vertical\";\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 * rather than a transcription of it.\n */\nexport const TEXTAREA_LABELS: TextareaLabels = COUNT_LABELS;\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from \"vue\";\nimport { cn } 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\";\n\n/**\n * Textarea — multi-line text entry, around a native `<textarea>`. The\n * accessible name is a first-class prop pair (`aria-label`/`aria-labelledby`,\n * camelized by Vue) bound onto the textarea explicitly, the same contract as\n * TextField.\n *\n * The border, focus ring and invalid state live on the wrapper so optional\n * `#leading`/`#trailing` adornments sit *inside* the field and share its focus\n * bloom, instead of every caller re-inventing an icon-inside-input layout.\n * The slot names and positions match TextField's, and the vertical alignment\n * differs — `items-start` for multi-line, where the text begins, versus\n * `items-center` for single-line — because a five-row box with a centered icon\n * mid-field reads as a mistake rather than a choice.\n *\n * Wrapping a rendered structure means the fallthrough `class` must land on the\n * wrapper (so a caller's `w-64`/`flex-1` sizes the whole field) while the rest\n * of the attrs (`id`, `name`, `data-testid`, `aria-describedby`) belong on the\n * real `<textarea>` — the split-attrs convention shared with TextField.\n *\n * That same wrapper is why the character counter is a prop here rather than a\n * `CountedField` beside this one. A counter rendered *below* the field would\n * have to move the fallthrough `class` off the box a caller sizes with it, and\n * a textarea has no free column to hang one in — the value fills the box and\n * scrolls, and the bottom-right corner belongs to the native resize grabber.\n * The counter sits below the border, where `resize` moves the box's bottom\n * edge and the counter travels with it rather than floating over the text.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself through\n * `useFieldControl()` — the row's id, the id of its hint or error line, and\n * `required` / `invalid` / `disabled` / `readonly` / `name` — so\n * `<Field label=\"Bio\" hint=\"…\"><Textarea /></Field>` needs no attributes at the\n * call site. Every prop below still wins over the row when it is set, in both\n * directions, which is why the four booleans default to `undefined` rather\n * than `false`.\n *\n * `readonly` and `disabled` are different states, and they are told apart on\n * three channels rather than one. A read-only field is a value on show: the\n * subtle fill, the text at full strength, the input hairline, still a Tab stop\n * and still submitted. A disabled one is unavailable: the deeper neutral fill,\n * the muted text, and the hairline receding to the plain border — a difference\n * in shape as well as in colour, which is what survives a reader who cannot\n * resolve the two fills apart.\n */\nconst props = withDefaults(\n defineProps<{\n /** The current value. Pair with `@update:modelValue` for `v-model`. */\n modelValue?: string;\n /** Text shown in the empty field. */\n placeholder?: string;\n /** Disables the field and blocks pointer and keyboard input. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Shows the value without allowing an edit, while staying focusable and still submitted. Unset defers to a wrapping Field. */\n readonly?: boolean | undefined;\n /** Error state: paints the destructive border/ring and sets aria-invalid. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** Marks the field mandatory to assistive tech (`aria-required`). Unset defers to a wrapping Field. */\n required?: boolean | undefined;\n /** The field name for a native form post or `FormData`. Unset defers to a wrapping Field. */\n name?: string;\n /** Initial height in text rows. */\n rows?: number;\n /** Whether a person can drag-resize the field; `none` locks it to `rows`. The counter sits below the box either way, so a drag never moves it onto the value. */\n resize?: TextareaResize;\n /** The accessible name, when no visible element already labels the field. */\n ariaLabel?: string;\n /** The id of the visible element that labels the field (e.g. a Field wrapper's label). */\n ariaLabelledby?: string;\n /**\n * The character limit the counter reports against, and the point past\n * which it reads as over-limit.\n *\n * Advisory, exactly as `required` is: it does **not** set the native\n * `maxlength`, which silently truncates a paste and tells the reader\n * nothing. Pass `maxlength` yourself as a plain attribute where you want\n * the browser to enforce it too.\n */\n maxLength?: number;\n /**\n * Forces the counter on or off. Left unset it follows `maxLength` — a\n * limit the reader is never shown is one they can only discover by\n * exceeding it — so set it `true` for a running total with no limit, and\n * `false` to hold a limit the field reports nowhere.\n */\n showCount?: boolean | undefined;\n /**\n * Names for everything this control says out loud, as any subset of\n * `TextareaLabels` — 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: the case it exists for is a field counting something other\n * than characters, where \"80 words left\" is the true sentence.\n */\n labels?: LabelOverrides<TextareaLabels>;\n }>(),\n {\n // Not `false`, for any of the four — see TextField.vue, which carries the\n // full reasoning. `false` is a caller's decision that must beat the row;\n // absent is a caller saying nothing, and only `undefined` survives to mean\n // that past Vue's absent-Boolean-casts-to-false rule.\n disabled: undefined,\n readonly: undefined,\n invalid: undefined,\n required: undefined,\n rows: 3,\n resize: \"vertical\",\n // `undefined` for the same Boolean-cast reason, and here it is the whole\n // feature: `showCount ?? (maxLength !== undefined)` would be a dead branch\n // if an absent prop arrived as `false`.\n showCount: undefined,\n },\n);\n\nconst emit = defineEmits<{ \"update:modelValue\": [value: string] }>();\n\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: textareaAttrs } = useSplitAttrs();\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(\"textarea\", TEXTAREA_LABELS, () => props.labels);\n\nconst countId = useId();\n\n/**\n * What is actually in the box, which is not always `modelValue` — TextField's\n * reasoning, and the same defect waiting on this side of it.\n *\n * Used without `v-model` this component is uncontrolled, so `modelValue` stays\n * `undefined` while the reader types and the counter still has to count. And\n * binding `:value=\"currentValue\"` rather than `:value=\"modelValue\"` is\n * load-bearing rather than cosmetic: Vue's `value` patch coerces\n * `null`/`undefined` to `\"\"`, so any re-render of an uncontrolled field wipes\n * it — a defect nothing had met only because nothing in this component\n * re-rendered on a keystroke until the counter did.\n */\nconst typed = ref(props.modelValue ?? \"\");\nconst currentValue = computed(() => props.modelValue ?? typed.value);\n\nfunction onInput(event: Event): void {\n const value = (event.target as HTMLTextAreaElement).value;\n typed.value = value;\n emit(\"update:modelValue\", value);\n}\n\n/**\n * Length in UTF-16 code units, which is what the platform's own `maxlength`\n * counts. `[...value].length` would count code points and disagree with the\n * browser on any astral character, so a caller who pairs this with a native\n * `maxlength` would watch the counter and the enforcement drift apart.\n */\nconst count = computed(() => currentValue.value.length);\nconst showsCount = computed(() => props.showCount ?? props.maxLength !== undefined);\n\nconst band = computed<CountBand>(() => {\n const max = props.maxLength;\n if (max === undefined) return \"under\";\n const remaining = max - count.value;\n if (remaining < 0) return \"over\";\n return remaining <= warningWindow(max) ? \"near\" : \"under\";\n});\n\nconst countText = computed(() => {\n const max = props.maxLength;\n if (max === undefined) return text.value.count({ count: count.value });\n const over = count.value - max;\n return over > 0\n ? text.value.countOverMax({ count: count.value, max, over })\n : text.value.countOfMax({ count: count.value, max });\n});\n\n/**\n * What the live region says, and it changes **only when the band changes** —\n * TextField's decision, taken once for the pair rather than re-litigated here.\n *\n * A region holding the counter itself would speak on every keystroke, burying\n * the field's own echo of the character just typed under a number nobody asked\n * for. What a reader needs is the two facts they cannot see coming — the limit\n * is close, and the limit is passed — so this fires once at each crossing and\n * goes quiet again on the way back down. The numbers are therefore true at the\n * moment they are spoken and not after; the visible counter carries the live\n * figure, and it is wired into `aria-describedby`, so the exact count is one\n * re-read away whenever the reader wants it rather than pushed at them.\n */\nconst announcement = ref(\"\");\nwatch(band, (now) => {\n const max = props.maxLength;\n if (max === undefined || now === \"under\") {\n announcement.value = \"\";\n return;\n }\n announcement.value =\n now === \"over\"\n ? text.value.limitExceeded({ over: count.value - max, max })\n : text.value.approachingLimit({ remaining: max - count.value, max });\n});\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. The\n// counter joins that list rather than replacing anything — it reads after the\n// caller's own description and before the row's message, which is the same\n// most-specific-first order `useFieldControl` applies one layer out.\n//\n// `field.attrs` then spreads **after** `textareaAttrs`, and that position is\n// the contract — see TextField.vue, which carries the full reasoning. The\n// `:aria-invalid` binding that used to sit below went with it: an individual\n// attribute written after a `v-bind` wins, so keeping one would overwrite the\n// resolved value with the raw prop.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [attrs[\"aria-describedby\"] as string | undefined, showsCount.value ? countId : \"\"]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n name: props.name,\n disabled: props.disabled,\n readonly: props.readonly,\n invalid: props.invalid,\n required: props.required,\n}));\n</script>\n\n<template>\n <!-- Layout, and nothing else: no fallthrough attribute lands here and nothing\n is painted on it. `inline-flex` is what makes it shrink-wrap the field\n frame — a block wrapper would be as wide as the column, and the counter\n would right-align to that column rather than to the field's own edge. -->\n <div class=\"inline-flex max-w-full flex-col align-top\">\n <!-- The field frame: border, focus, state. Like TextField, the border lives\n here so optional #leading/#trailing adornments sit inside the field and\n share its focus bloom, instead of every caller re-inventing an\n icon-inside-input layout. -->\n <div\n :data-disabled=\"field.disabled || undefined\"\n :data-readonly=\"field.readonly || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :class=\"\n cn(\n 'group flex items-start gap-2 rounded-md border border-input bg-background text-foreground px-3 py-2 text-sm',\n 'transition-[color,background-color,border-color,box-shadow] duration-fast ease-out',\n // Rim-lit at rest, the weave blooms on focus (Signature law): the field\n // catches light instead of casting a shadow, and focus draws it tight.\n 'focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring',\n !field.invalid && 'focus-within:shadow-halo',\n // The three resting appearances, and each is three changes rather than\n // one. Read-only and disabled used to share `bg-muted` and part only on\n // the text colour, which is a distinction carried by hue alone — the\n // one thing a reader with a colour deficiency, or a low-quality\n // display, or forced-colors, does not get. The fill separates them and\n // the border weight separates them again, so the progression\n // available → on show → unavailable is legible on three channels.\n //\n // Read-only is a value **on show**: the fill lifts off `background` to\n // `subtle` so the row reads as settled rather than editable, and the\n // text stays full strength — 13.46:1 over that fill — because being\n // read is the entire purpose of the state. The border does not move,\n // because nothing about the control's reach has: it is still a Tab stop\n // and still submitted. The native `readonly` attribute below carries\n // the same fact to assistive tech, so nothing here rests on colour.\n field.readonly && 'bg-subtle',\n // Disabled is **unavailable**: the fill drains one step further to\n // `muted`, the text follows it down to `muted-foreground` (4.68:1 over\n // it, still AA), and the rim slackens from `input` to the lighter\n // `border`.\n //\n // Drained rather than faded, and `opacity` is never the mechanism. The\n // element a dim would sit on is the box, and the box is wrapped around\n // the one thing a reader still needs: measured on the built site,\n // `opacity-50` put a disabled field's value at 3.08:1 and its\n // placeholder — already the muted colour before the fade — at 2.07:1.\n // The text colour is declared here rather than on the `<textarea>` because\n // the textarea sets no resting colour of its own and inherits this one,\n // which also carries it to the adornments in the same box.\n field.disabled && 'cursor-not-allowed border-border bg-muted text-muted-foreground',\n // The same appearance, reached from the other direction: a\n // `<fieldset disabled>` above this field disables the `<textarea>` inside\n // it natively and never touches `field.disabled`, so the rule above\n // cannot fire and the field rendered byte-identical to an editable one.\n //\n // `in-[fieldset:disabled]:` is a *read* of the attribute that did the\n // disabling, so the fill and the native inertness cannot disagree — the\n // fieldset element is still the only place the fact is written. It is\n // preferred to `has-[:disabled]:` (a wrapper reading its own contents)\n // because that proxy is wrong wherever a control holds a part that\n // disables itself.\n 'in-[fieldset:disabled]:cursor-not-allowed in-[fieldset:disabled]:bg-muted in-[fieldset:disabled]:text-muted-foreground',\n // Gated where the two rules below are ordered, and for the same reason.\n // Tailwind emits the ancestor half of `in-*` inside `:where()`, so this\n // carries no more specificity than `border-destructive` and would win\n // on emission order alone — an unavailable field that is also in error\n // would quietly lose its destructive rim.\n !field.invalid && 'in-[fieldset:disabled]:border-border',\n // Last of the three rules that name a border colour, and the order is\n // load-bearing: `cn()` resolves a border colour by whichever class it\n // saw last, so a field that is both in error and unavailable would lose\n // its destructive rim to the disabled one if this sat above it.\n field.invalid && 'border-destructive focus-within:outline-destructive',\n attrs.class as string,\n )\n \"\n >\n <span\n v-if=\"$slots.leading\"\n class=\"inline-flex shrink-0 text-muted-foreground transition-colors duration-fast ease-out group-focus-within:text-foreground\"\n >\n <slot name=\"leading\" />\n </span>\n <textarea\n v-bind=\"{ ...textareaAttrs, ...field.attrs }\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :value=\"currentValue\"\n :placeholder=\"placeholder\"\n :disabled=\"field.disabled\"\n :readonly=\"field.readonly\"\n :rows=\"rows\"\n :class=\"\n cn(\n 'min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed',\n resize === 'none' ? 'resize-none' : 'resize-y',\n )\n \"\n @input=\"onInput\"\n />\n <span\n v-if=\"$slots.trailing\"\n class=\"inline-flex shrink-0 items-center gap-1 text-muted-foreground transition-colors duration-fast ease-out group-focus-within:text-foreground\"\n >\n <slot name=\"trailing\" />\n </span>\n </div>\n <!-- Below the box, never inside it. A textarea's value fills its box and\n scrolls, so there is no free column to hang a readout in, and the\n bottom-right corner belongs to the native resize grabber — an inset\n counter would sit on top of the one affordance that says the field can\n be dragged. Here it travels with the bottom edge instead, so `resize`\n moves it rather than moving the box out from under it.\n\n `tabular` because the number changes under itself on every keystroke,\n and proportional digits would shuffle the whole readout sideways as\n they do. -->\n <span\n v-if=\"showsCount\"\n :id=\"countId\"\n :data-over-limit=\"band === 'over' || undefined\"\n :class=\"\n cn(\n 'tabular mt-1 select-none self-end text-small',\n band === 'under' && 'text-muted-foreground',\n // Colour, and never only colour: `countOverMax` says the limit is\n // passed in words as well, and `approachingLimit` announces the near\n // band once. The digits themselves are the third reading — 21/20 is\n // over the limit whatever it is painted.\n band === 'near' && 'text-warning-text',\n band === 'over' && 'text-destructive-text',\n )\n \"\n >\n {{ countText }}\n </span>\n <!-- In the DOM from the first render, empty. A live region mounted at the\n same moment as its text is a region assistive tech was not yet\n watching, so the first warning — the one that matters most — is the one\n it announces least reliably. -->\n <span v-if=\"showsCount && maxLength !== undefined\" role=\"status\" class=\"sr-only\">\n {{ announcement }}\n </span>\n </div>\n</template>\n"],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Textarea.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../../../packages/primitives/textarea/src/Textarea.vue"],"sourcesContent":["<script lang=\"ts\">\nimport {\n COUNT_LABELS,\n warningWindow,\n type CountBand,\n type TextareaLabels,\n} from \"@ecoma-io/loom-labels\";\n\nexport type TextareaResize = \"none\" | \"vertical\";\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 * rather than a transcription of it.\n */\nexport const TEXTAREA_LABELS: TextareaLabels = COUNT_LABELS;\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useId, watch } from \"vue\";\nimport { cn } 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\";\n\n/**\n * Textarea — multi-line text entry, around a native `<textarea>`. The\n * accessible name is a first-class prop pair (`aria-label`/`aria-labelledby`,\n * camelized by Vue) bound onto the textarea explicitly, the same contract as\n * TextField.\n *\n * The border, focus ring and invalid state live on the wrapper so optional\n * `#leading`/`#trailing` adornments sit *inside* the field and share its focus\n * bloom, instead of every caller re-inventing an icon-inside-input layout.\n * The slot names and positions match TextField's, and the vertical alignment\n * differs — `items-start` for multi-line, where the text begins, versus\n * `items-center` for single-line — because a five-row box with a centered icon\n * mid-field reads as a mistake rather than a choice.\n *\n * Wrapping a rendered structure means the fallthrough `class` must land on the\n * wrapper (so a caller's `w-64`/`flex-1` sizes the whole field) while the rest\n * of the attrs (`id`, `name`, `data-testid`, `aria-describedby`) belong on the\n * real `<textarea>` — the split-attrs convention shared with TextField.\n *\n * That same wrapper is why the character counter is a prop here rather than a\n * `CountedField` beside this one. A counter rendered *below* the field would\n * have to move the fallthrough `class` off the box a caller sizes with it, and\n * a textarea has no free column to hang one in — the value fills the box and\n * scrolls, and the bottom-right corner belongs to the native resize grabber.\n * The counter sits below the border, where `resize` moves the box's bottom\n * edge and the counter travels with it rather than floating over the text.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself through\n * `useFieldControl()` — the row's id, the id of its hint or error line, and\n * `required` / `invalid` / `disabled` / `readonly` / `name` — so\n * `<Field label=\"Bio\" hint=\"…\"><Textarea /></Field>` needs no attributes at the\n * call site. Every prop below still wins over the row when it is set, in both\n * directions, which is why the four booleans default to `undefined` rather\n * than `false`.\n *\n * `readonly` and `disabled` are different states, and they are told apart on\n * three channels rather than one. A read-only field is a value on show: the\n * subtle fill, the text at full strength, the input hairline, still a Tab stop\n * and still submitted. A disabled one is unavailable: the deeper neutral fill,\n * the muted text, and the hairline receding to the plain border — a difference\n * in shape as well as in colour, which is what survives a reader who cannot\n * resolve the two fills apart.\n */\nconst props = withDefaults(\n defineProps<{\n /** The current value. Pair with `@update:modelValue` for `v-model`. */\n modelValue?: string;\n /** Text shown in the empty field. */\n placeholder?: string;\n /** Disables the field and blocks pointer and keyboard input. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Shows the value without allowing an edit, while staying focusable and still submitted. Unset defers to a wrapping Field. */\n readonly?: boolean | undefined;\n /** Error state: paints the destructive border/ring and sets aria-invalid. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** Marks the field mandatory to assistive tech (`aria-required`). Unset defers to a wrapping Field. */\n required?: boolean | undefined;\n /** The field name for a native form post or `FormData`. Unset defers to a wrapping Field. */\n name?: string;\n /** Initial height in text rows. */\n rows?: number;\n /** Whether a person can drag-resize the field; `none` locks it to `rows`. The counter sits below the box either way, so a drag never moves it onto the value. */\n resize?: TextareaResize;\n /** The accessible name, when no visible element already labels the field. */\n ariaLabel?: string;\n /** The id of the visible element that labels the field (e.g. a Field wrapper's label). */\n ariaLabelledby?: string;\n /**\n * The character limit the counter reports against, and the point past\n * which it reads as over-limit.\n *\n * Advisory, exactly as `required` is: it does **not** set the native\n * `maxlength`, which silently truncates a paste and tells the reader\n * nothing. Pass `maxlength` yourself as a plain attribute where you want\n * the browser to enforce it too.\n */\n maxLength?: number;\n /**\n * Forces the counter on or off. Left unset it follows `maxLength` — a\n * limit the reader is never shown is one they can only discover by\n * exceeding it — so set it `true` for a running total with no limit, and\n * `false` to hold a limit the field reports nowhere.\n */\n showCount?: boolean | undefined;\n /**\n * Names for everything this control says out loud, as any subset of\n * `TextareaLabels` — 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: the case it exists for is a field counting something other\n * than characters, where \"80 words left\" is the true sentence.\n */\n labels?: LabelOverrides<TextareaLabels>;\n }>(),\n {\n // Not `false`, for any of the four — see TextField.vue, which carries the\n // full reasoning. `false` is a caller's decision that must beat the row;\n // absent is a caller saying nothing, and only `undefined` survives to mean\n // that past Vue's absent-Boolean-casts-to-false rule.\n disabled: undefined,\n readonly: undefined,\n invalid: undefined,\n required: undefined,\n rows: 3,\n resize: \"vertical\",\n // `undefined` for the same Boolean-cast reason, and here it is the whole\n // feature: `showCount ?? (maxLength !== undefined)` would be a dead branch\n // if an absent prop arrived as `false`.\n showCount: undefined,\n },\n);\n\nconst emit = defineEmits<{ \"update:modelValue\": [value: string] }>();\n\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: textareaAttrs } = useSplitAttrs();\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(\"textarea\", TEXTAREA_LABELS, () => props.labels);\n\nconst countId = useId();\n\n/**\n * What is actually in the box, which is not always `modelValue` — TextField's\n * reasoning, and the same defect waiting on this side of it.\n *\n * Used without `v-model` this component is uncontrolled, so `modelValue` stays\n * `undefined` while the reader types and the counter still has to count. And\n * binding `:value=\"currentValue\"` rather than `:value=\"modelValue\"` is\n * load-bearing rather than cosmetic: Vue's `value` patch coerces\n * `null`/`undefined` to `\"\"`, so any re-render of an uncontrolled field wipes\n * it — a defect nothing had met only because nothing in this component\n * re-rendered on a keystroke until the counter did.\n */\nconst typed = ref(props.modelValue ?? \"\");\nconst currentValue = computed(() => props.modelValue ?? typed.value);\n\nfunction onInput(event: Event): void {\n const value = (event.target as HTMLTextAreaElement).value;\n typed.value = value;\n emit(\"update:modelValue\", value);\n}\n\n/**\n * Length in UTF-16 code units, which is what the platform's own `maxlength`\n * counts. `[...value].length` would count code points and disagree with the\n * browser on any astral character, so a caller who pairs this with a native\n * `maxlength` would watch the counter and the enforcement drift apart.\n */\nconst count = computed(() => currentValue.value.length);\nconst showsCount = computed(() => props.showCount ?? props.maxLength !== undefined);\n\nconst band = computed<CountBand>(() => {\n const max = props.maxLength;\n if (max === undefined) return \"under\";\n const remaining = max - count.value;\n if (remaining < 0) return \"over\";\n return remaining <= warningWindow(max) ? \"near\" : \"under\";\n});\n\nconst countText = computed(() => {\n const max = props.maxLength;\n if (max === undefined) return text.value.count({ count: count.value });\n const over = count.value - max;\n return over > 0\n ? text.value.countOverMax({ count: count.value, max, over })\n : text.value.countOfMax({ count: count.value, max });\n});\n\n/**\n * What the live region says, and it changes **only when the band changes** —\n * TextField's decision, taken once for the pair rather than re-litigated here.\n *\n * A region holding the counter itself would speak on every keystroke, burying\n * the field's own echo of the character just typed under a number nobody asked\n * for. What a reader needs is the two facts they cannot see coming — the limit\n * is close, and the limit is passed — so this fires once at each crossing and\n * goes quiet again on the way back down. The numbers are therefore true at the\n * moment they are spoken and not after; the visible counter carries the live\n * figure, and it is wired into `aria-describedby`, so the exact count is one\n * re-read away whenever the reader wants it rather than pushed at them.\n */\nconst announcement = ref(\"\");\nwatch(band, (now) => {\n const max = props.maxLength;\n if (max === undefined || now === \"under\") {\n announcement.value = \"\";\n return;\n }\n announcement.value =\n now === \"over\"\n ? text.value.limitExceeded({ over: count.value - max, max })\n : text.value.approachingLimit({ remaining: max - count.value, max });\n});\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. The\n// counter joins that list rather than replacing anything — it reads after the\n// caller's own description and before the row's message, which is the same\n// most-specific-first order `useFieldControl` applies one layer out.\n//\n// `field.attrs` then spreads **after** `textareaAttrs`, and that position is\n// the contract — see TextField.vue, which carries the full reasoning. The\n// `:aria-invalid` binding that used to sit below went with it: an individual\n// attribute written after a `v-bind` wins, so keeping one would overwrite the\n// resolved value with the raw prop.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [attrs[\"aria-describedby\"] as string | undefined, showsCount.value ? countId : \"\"]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n name: props.name,\n disabled: props.disabled,\n readonly: props.readonly,\n invalid: props.invalid,\n required: props.required,\n}));\n</script>\n\n<template>\n <!-- Layout, and nothing else: no fallthrough attribute lands here and nothing\n is painted on it. `inline-flex` is what makes it shrink-wrap the field\n frame — a block wrapper would be as wide as the column, and the counter\n would right-align to that column rather than to the field's own edge. -->\n <div class=\"inline-flex max-w-full flex-col align-top\">\n <!-- The field frame: border, focus, state. Like TextField, the border lives\n here so optional #leading/#trailing adornments sit inside the field and\n share its focus bloom, instead of every caller re-inventing an\n icon-inside-input layout. -->\n <div\n :data-disabled=\"field.disabled || undefined\"\n :data-readonly=\"field.readonly || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :class=\"\n cn(\n 'group flex items-start gap-2 rounded-md border border-input bg-background text-foreground px-3 py-2 text-sm',\n 'transition-[color,background-color,border-color,box-shadow] duration-fast ease-out',\n // Rim-lit at rest, the weave blooms on focus (Signature law): the field\n // catches light instead of casting a shadow, and focus draws it tight.\n 'focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring',\n !field.invalid && 'focus-within:shadow-halo',\n // The three resting appearances, and each is three changes rather than\n // one. Read-only and disabled used to share `bg-muted` and part only on\n // the text colour, which is a distinction carried by hue alone — the\n // one thing a reader with a colour deficiency, or a low-quality\n // display, or forced-colors, does not get. The fill separates them and\n // the border weight separates them again, so the progression\n // available → on show → unavailable is legible on three channels.\n //\n // Read-only is a value **on show**: the fill lifts off `background` to\n // `subtle` so the row reads as settled rather than editable, and the\n // text stays full strength — 13.46:1 over that fill — because being\n // read is the entire purpose of the state. The border does not move,\n // because nothing about the control's reach has: it is still a Tab stop\n // and still submitted. The native `readonly` attribute below carries\n // the same fact to assistive tech, so nothing here rests on colour.\n field.readonly && 'bg-subtle',\n // Disabled is **unavailable**: the fill drains one step further to\n // `muted`, the text follows it down to `muted-foreground` (4.68:1 over\n // it, still AA), and the rim slackens from `input` to the lighter\n // `border`.\n //\n // Drained rather than faded, and `opacity` is never the mechanism. The\n // element a dim would sit on is the box, and the box is wrapped around\n // the one thing a reader still needs: measured on the built site,\n // `opacity-50` put a disabled field's value at 3.08:1 and its\n // placeholder — already the muted colour before the fade — at 2.07:1.\n // The text colour is declared here rather than on the `<textarea>` because\n // the textarea sets no resting colour of its own and inherits this one,\n // which also carries it to the adornments in the same box.\n field.disabled && 'cursor-not-allowed border-border bg-muted text-muted-foreground',\n // The same appearance, reached from the other direction: a\n // `<fieldset disabled>` above this field disables the `<textarea>` inside\n // it natively and never touches `field.disabled`, so the rule above\n // cannot fire and the field rendered byte-identical to an editable one.\n //\n // `in-[fieldset:disabled]:` is a *read* of the attribute that did the\n // disabling, so the fill and the native inertness cannot disagree — the\n // fieldset element is still the only place the fact is written. It is\n // preferred to `has-[:disabled]:` (a wrapper reading its own contents)\n // because that proxy is wrong wherever a control holds a part that\n // disables itself.\n 'in-[fieldset:disabled]:cursor-not-allowed in-[fieldset:disabled]:bg-muted in-[fieldset:disabled]:text-muted-foreground',\n // Gated where the two rules below are ordered, and for the same reason.\n // Tailwind emits the ancestor half of `in-*` inside `:where()`, so this\n // carries no more specificity than `border-destructive` and would win\n // on emission order alone — an unavailable field that is also in error\n // would quietly lose its destructive rim.\n !field.invalid && 'in-[fieldset:disabled]:border-border',\n // Last of the three rules that name a border colour, and the order is\n // load-bearing: `cn()` resolves a border colour by whichever class it\n // saw last, so a field that is both in error and unavailable would lose\n // its destructive rim to the disabled one if this sat above it.\n field.invalid && 'border-destructive focus-within:outline-destructive',\n attrs.class as string,\n )\n \"\n >\n <span\n v-if=\"$slots.leading\"\n class=\"inline-flex shrink-0 text-muted-foreground transition-colors duration-fast ease-out group-focus-within:text-foreground\"\n >\n <slot name=\"leading\" />\n </span>\n <textarea\n v-bind=\"{ ...textareaAttrs, ...field.attrs }\"\n :aria-label=\"ariaLabel\"\n :aria-labelledby=\"ariaLabelledby\"\n :value=\"currentValue\"\n :placeholder=\"placeholder\"\n :disabled=\"field.disabled\"\n :readonly=\"field.readonly\"\n :rows=\"rows\"\n :class=\"\n cn(\n 'min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed',\n resize === 'none' ? 'resize-none' : 'resize-y',\n )\n \"\n @input=\"onInput\"\n />\n <span\n v-if=\"$slots.trailing\"\n class=\"inline-flex shrink-0 items-center gap-1 text-muted-foreground transition-colors duration-fast ease-out group-focus-within:text-foreground\"\n >\n <slot name=\"trailing\" />\n </span>\n </div>\n <!-- Below the box, never inside it. A textarea's value fills its box and\n scrolls, so there is no free column to hang a readout in, and the\n bottom-right corner belongs to the native resize grabber — an inset\n counter would sit on top of the one affordance that says the field can\n be dragged. Here it travels with the bottom edge instead, so `resize`\n moves it rather than moving the box out from under it.\n\n `tabular` because the number changes under itself on every keystroke,\n and proportional digits would shuffle the whole readout sideways as\n they do. -->\n <span\n v-if=\"showsCount\"\n :id=\"countId\"\n :data-over-limit=\"band === 'over' || undefined\"\n :class=\"\n cn(\n 'tabular mt-1 select-none self-end text-small',\n band === 'under' && 'text-muted-foreground',\n // Colour, and never only colour: `countOverMax` says the limit is\n // passed in words as well, and `approachingLimit` announces the near\n // band once. The digits themselves are the third reading — 21/20 is\n // over the limit whatever it is painted.\n band === 'near' && 'text-warning-text',\n band === 'over' && 'text-destructive-text',\n )\n \"\n >\n {{ countText }}\n </span>\n <!-- In the DOM from the first render, empty. A live region mounted at the\n same moment as its text is a region assistive tech was not yet\n watching, so the first warning — the one that matters most — is the one\n it announces least reliably. -->\n <span v-if=\"showsCount && maxLength !== undefined\" role=\"status\" class=\"sr-only\">\n {{ announcement }}\n </span>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"TimePicker.js","names":[],"sources":["../../../../../packages/primitives/time-picker/src/TimePicker.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { TimeSegmentLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n * Everything this control publishes to assistive technology: the four names\n * Reka UI would otherwise give the segments in English of its own accord.\n * There is nothing else — the icon is decoration and hidden, and the field\n * group takes its name from the caller or from a wrapping Field.\n *\n * An alias for the shared slice rather than a fifth interface. The same four\n * names are said by `DateTimePicker` and `DateTimeRangePicker`, they come from\n * one Reka implementation, and `src/lib/date-labels.ts` carries why they are\n * declared once. The alias exists so this control's `labels` prop reads like\n * every other one's; annotate with `LabelOverrides<TimePickerLabels>` rather\n * than with this, which is total.\n */\nexport type TimePickerLabels = TimeSegmentLabels;\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useTemplateRef } from \"vue\";\nimport { TimeFieldInput, TimeFieldRoot, type TimeValue } from \"reka-ui\";\nimport { Clock } from \"@lucide/vue\";\nimport { parseTime } from \"@internationalized/date\";\nimport { cn } 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 { optional } from \"@ecoma-io/loom-core\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\nimport {\n TIME_SEGMENT_LABELS,\n emptySegmentValueText,\n isTimeSegmentPart,\n} from \"@ecoma-io/loom-labels\";\n\n/**\n * TimePicker — a time of day, typed into a segmented field. Reach for it\n * wherever a clock time is a value: a meeting start, a reminder, opening hours.\n *\n * **There is no clock face and no dropdown, deliberately.** A clock dial is\n * slower than typing for every reader who can type, and unusable for several\n * who cannot; a 96-row list of quarter hours is worse again. The segmented\n * field already is the control — arrow keys change the segment under the\n * cursor, digits fill it and advance — so a panel would only be a second, worse\n * path to the same value. That is the one place this diverges from DatePicker,\n * where the calendar earns its panel by answering \"which Tuesday?\", a question\n * a time never has.\n *\n * **The model value is a plain `\"HH:mm\"` string in 24-hour time**, or\n * `\"HH:mm:ss\"` when `granularity` asks for seconds — the same boundary\n * DatePicker draws for `\"YYYY-MM-DD\"`, and drawn here for the same reason: a\n * host has a string from its API and should not have to learn a date library to\n * bind a time. `hourCycle` moves the *display* to 12-hour and never the value,\n * because conflating the two is how a 12-hour locale ends up storing `\"01:30\"`\n * for half past one in the afternoon.\n *\n * **A time is not a date.** There is no timezone here, no offset, and no `Date`\n * anywhere near the public surface: `\"09:00\"` is nine in the morning wherever\n * it is read, and the moment that turns into is the host's question, not this\n * component's. Pair it with a DatePicker when an instant is what is wanted.\n *\n * Unlike DatePicker there are no `min`/`max` bounds. A time of day has no\n * ordering that survives midnight — a night shift is \"not before 22:00\" *and*\n * \"not after 02:00\", two bounds that cross rather than fence — so a min/max\n * pair would quietly call 01:00 out of range for the exact case it was reached\n * for. A window like that belongs to the host, which knows which day each end\n * is on.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself through\n * `useFieldControl()` — the row's id, the id of its hint or error line, and\n * `required` / `invalid` / `disabled` / `readonly` / `name` — so `<Field\n * label=\"Starts at\" error=\"…\"><TimePicker /></Field>` needs no attributes at the\n * call site. Every prop below still wins over the row when it is set, in both\n * directions, which is why the four booleans default to `undefined` rather than\n * `false`. `readonly` and `disabled` are different states, so the field rests in\n * three appearances rather than two: read-only is a time on show — still a Tab\n * stop, still submitted, a lifted fill with the segments at full strength —\n * where disabled is unavailable and drained a step further, in fill, text\n * colour and border weight together.\n */\nconst props = withDefaults(\n defineProps<{\n /**\n * The chosen time as `\"HH:mm\"`, or `\"HH:mm:ss\"` at second granularity, in\n * 24-hour time whatever the field displays. Unset, empty or unparseable\n * means no time is chosen. The explicit `| undefined` is what lets\n * `v-model` bind a ref that clears — the emitted value drops to `undefined`\n * when the field is emptied, and a plain optional prop refuses to take it\n * back.\n */\n modelValue?: string | undefined;\n /**\n * Whether the field reads as 12-hour with an AM/PM segment or as 24-hour.\n * Display only: the value stays 24-hour either way. Unset follows `locale`,\n * which is what a reader of that locale expects to see.\n */\n hourCycle?: 12 | 24;\n /** How far down the field goes. `\"hour\"` and `\"minute\"` report `\"HH:mm\"`; `\"second\"` adds a seconds segment and reports `\"HH:mm:ss\"`. */\n granularity?: \"hour\" | \"minute\" | \"second\";\n /** BCP 47 tag driving the order of the segments, the separator between them, and the 12-or-24-hour default. */\n locale?: string;\n /** Unavailable: dims the control and takes the field out of the tab order. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Shows the time without allowing an edit: the field stays a Tab stop, stays submitted, and is filled rather than dimmed. Unset defers to a wrapping Field. */\n readonly?: 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 /** Marks the field mandatory to assistive tech (`aria-required` on the segment group). Unset defers to a wrapping Field. */\n required?: boolean | undefined;\n /** The field name for a native form post or `FormData`, carried on the hidden input Reka submits the time through. Unset defers to a wrapping Field. */\n name?: string;\n /**\n * Names for the four segments, as any subset of `TimePickerLabels` — the\n * rest stay as the host's `provideLoomLabels` vocabulary left them, and then\n * as Loom's English.\n *\n * Every one of them replaces a literal Reka writes itself, so this is not\n * decoration: leave the vocabulary unset and the segments are named in\n * English rather than named not at all.\n */\n labels?: LabelOverrides<TimePickerLabels>;\n }>(),\n {\n granularity: \"minute\",\n locale: \"en\",\n // Not `false`, for any of the four — TextField.vue carries the full\n // reasoning: `false` is a caller's decision that must beat the row, absent\n // is a caller saying nothing, and only `undefined` survives to mean that\n // past Vue's absent-Boolean-casts-to-false rule.\n disabled: undefined,\n readonly: undefined,\n invalid: undefined,\n required: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** The chosen time as `\"HH:mm\"` (or `\"HH:mm:ss\"`), or `undefined` once the field has been cleared. */\n \"update:modelValue\": [value: string | undefined];\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(\"timeSegments\", TIME_SEGMENT_LABELS, () => props.labels);\n\n// Read through the ref on every call rather than resolved into a lookup table\n// once: a table built in `setup` freezes the first language and every later\n// switch silently does nothing. `undefined` for the `literal` separators, which\n// Reka renders `aria-hidden` and which must stay unnamed.\nfunction segmentLabel(part: string): string | undefined {\n return isTimeSegmentPart(part) ? text.value[part] : undefined;\n}\n\n// The companion to `segmentLabel`, and the reason it returns an object rather\n// than a string is in `emptySegmentValueText`: Reka's `aria-valuetext` is a\n// hard-coded \"Empty\" only while the segment holds nothing, so this replaces\n// that case and leaves the filled one — a number — exactly as Reka wrote it.\n//\n// The dayPeriod is the exception. Reka writes `\"AM\"` or `\"PM\"` from its own\n// hour-cycle logic, not from `Intl.DateTimeFormat`, so a localised field\n// still announces the period in English. `filledDayPeriod` lets a host replace\n// those with the locale's own period names (Arabic `\"ص\"`/`\"م\"`, Japanese\n// `\"午前\"`/`\"午後\"`).\nfunction segmentValueText(part: string, value: string): { \"aria-valuetext\"?: string } {\n const empty = emptySegmentValueText(part, value, text.value.empty);\n if (empty[\"aria-valuetext\"]) return empty;\n if (part === \"dayPeriod\") {\n return { \"aria-valuetext\": text.value.filledDayPeriod({ dayPeriod: value }) };\n }\n return {};\n}\n\n// One rendered node, so both halves of the fallthrough land on it — the split\n// exists only because `class` needs the Tailwind-aware merge and Vue's own\n// fallthrough would concatenate a caller's `h-11` after our `h-9` instead of\n// replacing it. That node is Reka's `role=\"group\"`, which is also where\n// `aria-label` belongs: a screen reader announces a group's name once on\n// entering it, rather than once per segment.\n//\n// It is also why `invalid` is announced with `aria-invalid` and nothing else.\n// DatePicker moves its `data-invalid` marker onto the anchor because the field\n// group already spells that attribute with Reka's own meaning; here there is no\n// second element to move it to, and an attribute Reka binds itself wins outright\n// — its template merges `$attrs` first and its own bindings after, so a\n// `data-invalid` passed in from out here is overwritten by Reka's own\n// `undefined` before it reaches the DOM. Setting it would look like it worked\n// and silently do nothing.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: fieldAttrs } = useSplitAttrs();\n\n/**\n * The time segments are `<div role=\"spinbutton\" tabindex=\"0\">`, and\n * `<fieldset disabled>` reaches only `<input>`, `<button>`, `<select>` and\n * `<textarea>` — so Reka's hidden input went inert inside a disabled group\n * while the segments a reader actually uses still typed. Measured in jsdom: an\n * empty hour segment became `12` on an arrow key.\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<{ $el?: Element }>(\"root\");\nconst groupDisabled = useAncestorDisabled(() => root.value?.$el);\n\n// `id` and `aria-describedby` reach this control as fallthrough attrs rather\n// than props, so they are handed in as this caller's own values: a caller who\n// sets either still beats the row, and the row's description is merged into\n// theirs rather than replacing it. `field.attrs` then spreads onto\n// `TimeFieldRoot` **after** `fieldAttrs`, which is the node both were already\n// landing on.\n//\n// **Where each key ends up was checked rather than assumed**, given what the\n// note above says about attributes this node overwrites. The set Reka spells\n// itself is `role`, `aria-disabled`, `data-disabled`, `data-readonly`,\n// `data-invalid` and `dir`, and `field.attrs` spells none of them:\n// `aria-describedby`, `aria-required` and `aria-invalid` are undeclared and land\n// on the `role=\"group\"` as intended, while `id` and `name` are declared props\n// and land on the visually-hidden `<input>` the field submits through — which is\n// the element a `<label for>` can actually name, a `role=\"group\"` div not being\n// labelable.\n//\n// The `:aria-invalid` binding that used to sit on the root is gone with it: an\n// individual attribute written after a `v-bind` wins, so keeping one would\n// overwrite the resolved value with the raw prop.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: attrs[\"aria-describedby\"] as string | undefined,\n ariaLabelledby: attrs[\"aria-labelledby\"] as string | undefined,\n name: props.name,\n // The fieldset beats the prop in both directions, exactly as it does for the\n // native input Reka renders inside this very control.\n disabled: groupDisabled.value ? true : props.disabled,\n readonly: props.readonly,\n invalid: props.invalid,\n required: props.required,\n}));\n\n// `aria-labelledby` for the group, resolved against the row — DatePicker's\n// reasoning, and the same three-way guard.\nconst groupLabelledBy = computed(() =>\n attrs[\"aria-label\"] || attrs[\"aria-labelledby\"] ? undefined : field.labelledBy,\n);\n\nfunction fromClock(value: string | undefined): TimeValue | undefined {\n if (!value) return undefined;\n try {\n return parseTime(value);\n } catch {\n // Same contract as DatePicker: a half-typed or wrongly-shaped value is read\n // as no time chosen. A component library cannot decide that a host's bad\n // data is fatal.\n return undefined;\n }\n}\n\nfunction pad(value: number): string {\n return String(value).padStart(2, \"0\");\n}\n\n// Written out rather than taken from `Time.toString()`, which always prints\n// seconds and appends a fractional part when the value carries one — so a\n// minute-granularity field would report `\"09:30:00\"`, and a value the host\n// parsed from `\"09:30:00.5\"` would round-trip a half second the field never\n// showed. The string that comes back is the string the segments are showing.\nfunction toClock(time: TimeValue): string {\n const hhmm = `${pad(time.hour)}:${pad(time.minute)}`;\n return props.granularity === \"second\" ? `${hhmm}:${pad(time.second)}` : hhmm;\n}\n\n// `optional()` rather than plain bindings: Reka reads an explicit `undefined`\n// `modelValue` as a value the host owns and is holding empty, which turns an\n// uncontrolled field into a permanently empty one, and an `hourCycle` of\n// `undefined` is how it is told to follow the locale. Dropping the keys says\n// what is true.\nconst rootValue = computed(() =>\n optional({ modelValue: fromClock(props.modelValue), hourCycle: props.hourCycle }),\n);\n\nfunction onTimeChange(time: TimeValue | undefined) {\n emit(\"update:modelValue\", time ? toClock(time) : undefined);\n}\n\n// The field is one Tab stop, not four. The reasoning, and the reason Reka's own\n// ArrowLeft/ArrowRight handling survives it untouched, is written out in\n// DatePicker — it moves focus with `focus()` directly, which ignores tabindex.\n// It matters more here: a 12-hour field with seconds is four segments, so\n// leaving Reka's default in place costs a keyboard reader four Tab presses to\n// cross one control.\nconst focusedPart = ref<string>();\n\nfunction segmentTabIndex(part: string, segments: readonly { part: string }[]): number | undefined {\n // Read-only keeps every stop it had, unlike disabled: the time is on show and\n // a reader still arrows across the segments to read it.\n if (field.disabled || part === \"literal\") return undefined;\n const editable = segments.filter((segment) => segment.part !== \"literal\");\n // The remembered segment is dropped when a granularity or locale change takes\n // it away — a field whose only tab stop is a seconds segment that no longer\n // exists is a field nothing can reach.\n const active =\n focusedPart.value !== undefined &&\n editable.some((segment) => segment.part === focusedPart.value)\n ? focusedPart.value\n : editable[0]?.part;\n return part === active ? 0 : -1;\n}\n\n// Reka reads `hourCycle` once, when it builds its formatter, and seeds its\n// segment values from the granularity in the same breath — neither is watched.\n// Observed: a field showing 13:30 that is moved to a 12-hour cycle relabels\n// itself \"1:30 AM\", half a day wrong, because the AM/PM segment appears with\n// its initial value and nothing recomputes it from the hour. Widening the\n// granularity on an empty field is the same fault with a different symptom: the\n// new seconds segment arrives with no entry to read, so it renders without a\n// role at all.\n//\n// Both are structural changes — they add and remove segments — so keying the\n// field on them rebuilds it rather than patching a half-migrated one. `locale`\n// is deliberately not in the key: Reka does watch that, and rebuilding on it\n// would throw away focus mid-edit for a change it handles correctly.\nconst shape = computed(() => `${props.granularity}-${props.hourCycle}`);\n\n/**\n * Reka's hour segment publishes `aria-valuenow` and `aria-valuetext` straight\n * off the internal 24-hour value while publishing `aria-valuemin`/`max` as\n * 1–12, so half past one in the afternoon announces itself as \"13 PM\", out of\n * its own declared range. The displayed hour is the one the reader is being\n * asked about, so the announcement is rebuilt from what the segment actually\n * shows. Only under an explicit 12-hour cycle: left to the locale, Reka defers\n * to the formatter and the pair is already consistent.\n */\nfunction hourAnnouncement(\n segments: readonly { part: string; value: string }[],\n): Record<string, string | number> | undefined {\n if (props.hourCycle !== 12) return undefined;\n const shown = Number(segments.find((segment) => segment.part === \"hour\")?.value);\n const period = segments.find((segment) => segment.part === \"dayPeriod\")?.value;\n // An unfilled hour reads as its placeholder rather than a number, and there is\n // no number to announce for it. The empty case is not left to Reka's English\n // \"Empty\" either — `segmentValueText` binds the vocabulary's word for it on\n // the same element, and the two never collide: this returns a value only for\n // a filled hour and that one only for an empty segment.\n if (!Number.isInteger(shown) || period === undefined) return undefined;\n return { \"aria-valuenow\": shown, \"aria-valuetext\": `${shown} ${period}` };\n}\n</script>\n\n<template>\n <TimeFieldRoot\n ref=\"root\"\n :key=\"shape\"\n v-slot=\"{ segments }\"\n v-bind=\"{ ...rootValue, ...fieldAttrs, ...field.attrs }\"\n :aria-labelledby=\"groupLabelledBy\"\n :locale=\"locale\"\n :granularity=\"granularity\"\n :disabled=\"field.disabled\"\n :readonly=\"field.readonly\"\n :class=\"\n cn(\n // The text input's own height scale, so a time sitting in a form row\n // beside a text field lines up rather than nearly lining up. No gap:\n // the colon between two segments is itself a segment, so spacing them\n // apart writes the time as `09 : 30`.\n 'flex h-9 w-full items-center rounded-md border border-input bg-background px-3 text-sm text-foreground',\n 'transition-[color,background-color,border-color,box-shadow] duration-fast ease-out',\n // The box carries the ring and the focused segment below carries a fill\n // instead of a second outline, exactly as DatePicker's field does — a\n // ring drawn inside a ring reads as a rendering fault.\n 'focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring',\n !field.invalid && 'focus-within:shadow-halo',\n // Three resting appearances, and each is painted on this group rather\n // than on the segments inside it: a per-segment fill leaves the colon\n // between them on `background`, and the time comes out striped.\n //\n // Read-only lifts to `subtle` and keeps its focus ring and its\n // full-strength segments — 13.46:1 over that fill — because a read-only\n // time is a value on show, not an unavailable control. The rim stays\n // `input`: the field is still a Tab stop and still submitted. Reka's own\n // `data-readonly` on this node carries the same state to assistive tech,\n // so nothing here rests on colour.\n field.readonly && 'bg-subtle',\n // Drained rather than faded, for the reason DatePicker and\n // DateTimePicker both write out — this control was the one member of\n // the family the sweep still caught. `opacity-50` took the segments\n // down with the box: measured on the built site, the hour and the\n // period read 3.08:1 and the colon between them 2.07:1, and those\n // segments *are* the value. The fill drains one step past read-only,\n // the muted text over it is 4.68:1, and the rim slackens from `input`\n // to `border` — three channels, so the two states do not part on hue\n // alone. Set on the group because no segment declares a resting colour\n // of its own, so each inherits this one.\n field.disabled && 'cursor-not-allowed border-border bg-muted text-muted-foreground',\n // Last of the rules that name a border colour: `cn()` resolves one by\n // whichever class it saw last, so a field both in error and unavailable\n // would otherwise lose its destructive rim to the disabled one.\n field.invalid && 'border-destructive focus-within:outline-destructive',\n attrs.class as string,\n )\n \"\n @update:model-value=\"onTimeChange\"\n >\n <!-- Leading, where DatePicker's calendar button is trailing: that trailing\n slot is a button in every other member of this family, and a glyph\n sitting in it that opens nothing would promise a panel this control\n does not have. Decoration, so it is hidden from the accessibility\n tree — the group's own name says what the field is. -->\n <Clock aria-hidden=\"true\" class=\"mr-2 h-4 w-4 shrink-0 text-muted-foreground\" />\n\n <!-- The `:aria-label` replaces the one Reka writes in English inside its\n own render function. It reaches the DOM node as a fallthrough\n attribute, which Vue merges last, so it is a replacement rather than a\n second name. Removing it does not fall back to nothing; it falls back\n to Reka's English. -->\n <TimeFieldInput\n v-for=\"(item, index) in segments\"\n :key=\"index\"\n :part=\"item.part\"\n :tabindex=\"segmentTabIndex(item.part, segments)\"\n :aria-label=\"segmentLabel(item.part)\"\n v-bind=\"{\n ...segmentValueText(item.part, item.value),\n ...(item.part === 'hour' ? hourAnnouncement(segments) : undefined),\n }\"\n :class=\"\n cn(\n 'tabular rounded-sm px-0.5 outline-none',\n 'transition-colors duration-instant ease-out',\n 'focus:bg-primary-muted focus:text-primary-text',\n 'data-[placeholder]:text-muted-foreground',\n item.part === 'literal' && 'text-muted-foreground',\n )\n \"\n @focusin=\"focusedPart = item.part\"\n >\n {{ item.value }}\n </TimeFieldInput>\n </TimeFieldRoot>\n</template>\n"],"mappings":""}