@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":"Drawer.vue_vue_type_script_setup_true_lang.js","names":["$emit","$slots"],"sources":["../../../../../packages/primitives/drawer/src/Drawer.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { DrawerLabels } from \"@ecoma-io/loom-labels\";\n/**\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it, and\n * exported so a host can build a partial vocabulary against the real thing.\n */\nexport const DRAWER_LABELS: DrawerLabels = {\n close: \"Close\",\n};\n\n/**\n * Which edge of the viewport the panel is anchored to. `right` is the default\n * because a drawer is most often opened *from* a row or a toolbar to show more\n * about what is already on screen, and left-to-right readers expect that\n * detail to arrive on the trailing edge. `left` is where navigation lives,\n * `bottom` is the sheet a narrow screen gets, and `top` is the rare one — a\n * command surface dropping in over the header.\n */\nexport type DrawerSide = \"left\" | \"right\" | \"top\" | \"bottom\";\n\n/**\n * How far the panel reaches along its own axis — width for a `left`/`right`\n * drawer, height for a `top`/`bottom` one. Like Dialog's width, this is the\n * primitive's decision rather than a class a caller passes, so two drawers\n * opened from two screens cannot be two different sizes: `sm` for a filter rail\n * or a navigation sheet, `md` for a record's detail, `lg` for a working surface\n * with a table or a multi-section form in it.\n */\nexport type DrawerSize = \"sm\" | \"md\" | \"lg\";\n\n/**\n * One row per edge, because `side` is not one decision but four made together —\n * which edge the panel is pinned to, which way it slides in from, which\n * dimension `size` then means, and which pair of corners is rounded — plus the\n * direction a dismissing swipe has to travel. Split across a `cva` map and\n * three lookups they drift, and the drift is invisible: a panel pinned to the\n * left that slides in from the right still renders, still passes its own tests,\n * and looks like a rendering bug nobody can name. `satisfies` is the other half\n * — adding a member to `DrawerSide` and not to this table stops compiling.\n *\n * `slide` and `exit` are the same motion in two directions and deliberately not\n * the same mechanism, which is worth reading before either is \"unified\".\n *\n * `slide` is a `starting:` variant rather than a keyframe, and it is a\n * transform rather than an inset or a width. A full-height panel animated on\n * `width`/`right` relayouts the document on every frame; `translate` runs on\n * the compositor. `@starting-style` supplies the before-value for the entry\n * transition at the moment Reka's `Presence` inserts the node, which is the one\n * thing a plain class cannot do. It also composes with the live swipe below:\n * the gesture writes `transform` while the entry owns `translate`, and a\n * keyframe on `transform` would overwrite a drag mid-finger.\n *\n * `exit` has to be a keyframe, for the opposite reason. `Presence` decides how\n * long to keep a closing panel mounted by reading `animation-name` and waiting\n * for `animationend` — it never observes `transitionend`. So a closed panel\n * carrying only a transition is removed from the DOM in the same frame and the\n * transition never runs, which is exactly what a drawer did until these tokens\n * existed: a 320ms slide in, answered by a hard cut. The keyframes animate\n * `translate` rather than `transform` for the same composition reason the entry\n * does, so a panel released mid-swipe leaves from where the finger left it.\n *\n * `handle` positions the grab affordance on the panel's *inner* edge, running\n * along it: a vertical pill on a side drawer, a horizontal one on a sheet.\n */\nconst SIDES = {\n left: {\n edge: \"inset-y-0 left-0 border-r\",\n corners: \"rounded-r-lg\",\n slide: \"starting:-translate-x-full\",\n exit: \"data-[state=closed]:animate-slide-out-to-left\",\n extent: \"width\",\n swipe: \"left\",\n handle: \"right-1.5 top-1/2 h-10 w-1.5 -translate-y-1/2\",\n },\n right: {\n edge: \"inset-y-0 right-0 border-l\",\n corners: \"rounded-l-lg\",\n slide: \"starting:translate-x-full\",\n exit: \"data-[state=closed]:animate-slide-out-to-right\",\n extent: \"width\",\n swipe: \"right\",\n handle: \"left-1.5 top-1/2 h-10 w-1.5 -translate-y-1/2\",\n },\n top: {\n edge: \"inset-x-0 top-0 border-b\",\n corners: \"rounded-b-lg\",\n slide: \"starting:-translate-y-full\",\n exit: \"data-[state=closed]:animate-slide-out-to-top\",\n extent: \"height\",\n swipe: \"up\",\n handle: \"bottom-1.5 left-1/2 h-1.5 w-10 -translate-x-1/2\",\n },\n bottom: {\n edge: \"inset-x-0 bottom-0 border-t\",\n corners: \"rounded-t-lg\",\n slide: \"starting:translate-y-full\",\n exit: \"data-[state=closed]:animate-slide-out-to-bottom\",\n extent: \"height\",\n swipe: \"down\",\n handle: \"top-1.5 left-1/2 h-1.5 w-10 -translate-x-1/2\",\n },\n} satisfies Record<\n DrawerSide,\n {\n edge: string;\n corners: string;\n slide: string;\n exit: string;\n extent: \"width\" | \"height\";\n swipe: \"left\" | \"right\" | \"up\" | \"down\";\n handle: string;\n }\n>;\n\n/**\n * The size scale, indexed by the dimension the anchored edge turned it into.\n * Two maps rather than twelve rows on `SIDES`, because `left` and `right` want\n * the same widths and `top` and `bottom` the same heights — duplicating them\n * per edge is four places for a size to be adjusted in three of.\n *\n * Each is capped against the viewport, so a `lg` drawer on a laptop still\n * leaves the page it is anchored over visible behind it. That gap is the whole\n * difference between a drawer and a full-screen takeover.\n */\nconst EXTENT = {\n width: {\n sm: \"w-[min(90vw,20rem)]\",\n md: \"w-[min(92vw,26rem)]\",\n lg: \"w-[min(94vw,40rem)]\",\n },\n height: {\n sm: \"h-[min(90vh,16rem)]\",\n md: \"h-[min(92vh,24rem)]\",\n lg: \"h-[min(94vh,36rem)]\",\n },\n} satisfies Record<\"width\" | \"height\", Record<DrawerSize, string>>;\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, useId } from \"vue\";\nimport {\n DrawerRoot,\n DrawerTrigger,\n DrawerPortal,\n DrawerOverlay,\n DrawerContent,\n DrawerHandle,\n DrawerTitle,\n DrawerDescription,\n DrawerClose,\n} from \"reka-ui\";\nimport { X } from \"@lucide/vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { optional } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\n/**\n * Drawer — a panel anchored to an edge of the viewport that slides in over the\n * page: a filter rail tuned while a table stays visible behind it, a record's\n * detail opened from a row, a navigation sheet on a narrow screen.\n *\n * **Drawer against Dialog**, because this is the pair most often picked wrongly.\n * `Dialog` is a centred task surface for a decision or a short form: it\n * interrupts, it sits in the middle of the screen, and the page behind it is\n * context rather than something to look at. A Drawer is edge-anchored and\n * deliberately leaves the page visible along its open side, because the work\n * happens *alongside* that content — you tune a filter and watch the rows\n * change. If the user cannot proceed until they answer, that is a Dialog. If\n * they are reading or adjusting something about what is already on screen, it\n * is a Drawer.\n *\n * **It is still modal**, and that is a deliberate choice rather than an\n * oversight: focus is trapped in the panel, Tab never reaches the page behind,\n * everything outside is hidden from assistive technology, and the page does not\n * scroll. Visible is not the same as reachable — a panel you can Tab out of\n * silently strands a keyboard user behind a scrim they cannot see past. One\n * consequence to know about is in `docs/components/drawer.md`: locking the body\n * removes the scrollbar, and Reka compensates with a `padding-right` that\n * viewport-pinned furniture does not inherit.\n *\n * **The way out is never a gesture alone.** Esc closes, the close control in the\n * corner closes, and either one returns focus to whatever opened it. The drag\n * handle is a pointer affordance sitting on top of those, never instead of\n * them — it does not exist for a keyboard, and on a desktop pointer it is a\n * hint rather than a route.\n *\n * `title` is required for the same reason it is on `Dialog`: it is the panel's\n * accessible name, and a drawer without one announces itself as a dialog that\n * says nothing about what it holds.\n *\n * Reach for `Dialog` when the answer must come before anything else happens,\n * `Popover` when the content is small, non-blocking and belongs next to its\n * trigger, and a transient notification when the user need not act at all.\n */\nconst props = withDefaults(\n defineProps<{\n /** Drive the drawer from the host with `v-model:open`; omit it and the drawer owns its own state. */\n open?: boolean | undefined;\n /** The accessible name, and the panel's heading. Name what is in it (\"Filters\", \"Scene 12\"), not the verb that opened it. */\n title: string;\n /** Wired as the drawer's accessible description — one line on what the panel is for, announced with the title. */\n description?: string;\n /** Which edge the panel is anchored to. `right` for detail, `left` for navigation, `bottom` for a sheet. */\n side?: DrawerSide;\n /** How far the panel reaches along its own axis — width on a side drawer, height on a sheet. */\n size?: DrawerSize;\n /** Whether a press outside the panel dismisses it, and whether the drag handle is offered. Esc and the close control work either way. */\n dismissible?: boolean;\n /**\n * The name on the close control, as any subset of `DrawerLabels` — what it\n * leaves out stays as the host's `provideLoomLabels` vocabulary left it,\n * and then as Loom's English.\n *\n * A whole application's language belongs in that vocabulary rather than\n * here. This is the per-instance correction, for the drawer whose close\n * means something more specific than \"Close\" — \"Close filters\", say, on a\n * page carrying two of them.\n */\n labels?: LabelOverrides<DrawerLabels>;\n }>(),\n // `open: undefined` is load-bearing, not a redundant default — it is what\n // keeps the uncontrolled third state reachable past Vue's absent-Boolean\n // casting. `optional()` in the template is the other half; its docblock\n // carries the reasoning for both. `description` needs no such entry: a\n // string prop is already `undefined` when absent.\n { open: undefined, side: \"right\", size: \"md\", dismissible: true },\n);\n\ndefineEmits<{\n /** The drawer opened or closed, for `v-model:open`. The host stays the source of truth — the drawer reports the request and waits. */\n \"update:open\": [value: boolean];\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(\"drawer\", DRAWER_LABELS, () => props.labels);\n\nconst anchor = computed(() => SIDES[props.side]);\n\n// `DrawerRoot` renders no DOM node at all, so fallthrough attributes would be\n// dropped on the floor rather than landing anywhere. They go to the panel,\n// which is the element they actually describe — a `data-testid` or an\n// `aria-*` on `<Drawer>` reads as being about the drawer, not about the button\n// that happens to open it.\n//\n// `class` is pulled out of that spread and merged through `cn()` instead:\n// spreading it alongside the panel's own `:class` only concatenates the two\n// lists — Vue's merge is generic, not Tailwind-aware — so a caller's\n// `w-[30rem]` would lose to the size scale's own width depending on which\n// utility Tailwind happened to emit last.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: panelAttrs } = useSplitAttrs();\n\n/**\n * The `dismissible: false` half. Reka reads a prevented `interactOutside` as\n * \"this layer declines to be dismissed\", which covers the pointer press and the\n * focus that follows it in one place. Esc is deliberately untouched: a panel\n * with no keyboard exit is a trap, and \"do not close this by accident\" is a\n * different request from \"do not let this be closed\".\n */\nfunction guardOutsidePress(event: Event): void {\n if (!props.dismissible) event.preventDefault();\n}\n\n// The `dismissible: false` other half — the swipe. Reka wires\n// `useSwipeDismiss` unconditionally inside `DrawerContentImpl` with\n// `enabled: open` and exposes no prop to turn it off, so a drag on the panel\n// body toward the anchored edge used to dismiss a drawer whose `dismissible`\n// was `false` — defeating exactly the case the prop exists for, on touch,\n// where the reader is least likely to have meant it.\n//\n// There is no event Reka emits for the gesture that a handler could veto\n// from outside; the only lever is stopping its pointer handlers before they\n// start a swipe. Reka listens on the panel in the bubble phase, so a\n// capture-phase listener on `document` runs first for every event that\n// reaches the panel, and `stopImmediatePropagation` clears the rest of the\n// path — Reka's listener included — while leaving click, focus, scroll and\n// selection alone, which are separate events.\n//\n// Two costs are accepted rather than designed around. A consumer's own\n// pointerdown handler inside a non-dismissible drawer is stopped too, which\n// is the same neighbourhood as `interact-outside` vetoing their outside\n// press: `dismissible: false` declines pointer gestures, full stop. And a\n// non-dismissible drawer nested inside another non-dismissible one vetoes\n// gestures for both, which is the direction the pointer would have to travel\n// anyway.\n//\n// Pointer and touch are two paths in Reka (`onPointerDown` returns early for\n// touch pointers, which arrive via `onTouchStart`), so both events are\n// watched. The `data-loom-drawer-panel` marker scopes the veto to this\n// drawer's panel — and to nobody else's. That last half is the part that\n// bites: the marker is on every panel, so a naive `closest` check makes one\n// non-dismissible drawer on a page veto the gestures of every drawer on it,\n// dismissing nothing but the sibling's ability to be swiped. The marker\n// therefore carries this instance's own id, and the veto demands a match on\n// the value, not just the attribute. The attribute itself still has to\n// survive the panel being portalled away from the drawer's own subtree,\n// which an element-membership check would not.\nconst PANEL_MARKER = \"data-loom-drawer-panel\";\n// `useId` like the rest of the library: stable across server and client, so\n// the marker value a listener armed during hydration checks is the value the\n// portalled panel renders with.\nconst panelMarkerId = useId();\n\nfunction vetoSwipeStart(event: PointerEvent | TouchEvent): void {\n if (props.dismissible) return;\n const target = event.target;\n if (!(target instanceof Element)) return;\n const panel = target.closest(`[${PANEL_MARKER}]`);\n if (!(panel instanceof Element) || panel.getAttribute(PANEL_MARKER) !== panelMarkerId) return;\n event.stopImmediatePropagation();\n}\n\n// The listeners are on `document`, not the panel, because the panel's whole\n// lifecycle is Reka's — the portal content mounts with the drawer and is\n// removed with it, so a listener attached to the panel would need re-arming\n// on every open. A document listener is armed once for the component's own\n// lifetime, and `onBeforeUnmount` is the pairing that keeps it from leaking\n// into the next drawer or the host's page.\nonMounted(() => {\n document.addEventListener(\"pointerdown\", vetoSwipeStart, { capture: true });\n document.addEventListener(\"touchstart\", vetoSwipeStart, { capture: true, passive: true });\n});\nonBeforeUnmount(() => {\n document.removeEventListener(\"pointerdown\", vetoSwipeStart, { capture: true });\n document.removeEventListener(\"touchstart\", vetoSwipeStart, { capture: true });\n});\n</script>\n\n<template>\n <DrawerRoot\n v-bind=\"optional({ open })\"\n :swipe-direction=\"anchor.swipe\"\n @update:open=\"$emit('update:open', $event)\"\n >\n <!-- @slot The control that opens the drawer. Optional — omit it and drive\n the drawer entirely from the host with `v-model:open`. -->\n <DrawerTrigger v-if=\"$slots.trigger\" as-child>\n <slot name=\"trigger\" />\n </DrawerTrigger>\n\n <DrawerPortal>\n <!-- `scrim-light` rather than Dialog's `scrim`, and the token now carries\n the reason: a drawer's page is still the thing being worked on. It\n fades rather than moves, so nothing behind the panel appears to\n shift.\n\n Both states are scoped, never unconditional. Reka's Presence keeps\n closed content mounted until an animationend arrives, and a\n mount-only animation never fires a second one — which here would\n strand a full-screen, input-blocking scrim over a page with no drawer\n on it. The paired exit is what makes the close a timed fade instead\n of a cut, and it keeps that guarantee: `fade-out` ends, so Presence\n unmounts on its own animationend rather than on the absence of one. -->\n <DrawerOverlay\n class=\"fixed inset-0 z-overlay bg-foreground/scrim-light data-[state=open]:animate-fade data-[state=closed]:animate-fade-out\"\n />\n\n <DrawerContent\n v-bind=\"panelAttrs\"\n :data-loom-drawer-panel=\"panelMarkerId\"\n :class=\"\n cn(\n 'fixed z-overlay flex flex-col border-border bg-popover text-popover-foreground shadow-lg outline-none',\n anchor.edge,\n anchor.corners,\n EXTENT[anchor.extent][size],\n // `slow`, and this is the one place this component reaches past the\n // `--duration-normal` feedback ceiling. The motion foundations page\n // names a panel taking over the screen as exactly what the\n // unhurried lane is for, and a full-height panel crossing the\n // viewport at 200ms reads as a flinch rather than a slide.\n 'transition-transform duration-slow ease-out',\n anchor.slide,\n // The other half of the same gesture. `SIDES` carries why the two\n // directions are a transition and a keyframe rather than one\n // mechanism run both ways; the short version is that Presence\n // watches `animationend` and nothing else, so a transition on the\n // way out never gets a frame to run in.\n anchor.exit,\n // Reka's swipe-to-dismiss writes the live drag onto the panel as\n // CSS custom properties and leaves the rendering to us. Applying\n // them as `transform` keeps them off `translate`, which the slide\n // above owns — the two properties compose instead of overwriting\n // each other, so a half-finished swipe is not fighting the entry\n // transition. The `0px` fallbacks cover the browsers where\n // `CSS.registerProperty` is unavailable and the vars have no\n // registered initial value.\n '[transform:translate(var(--drawer-swipe-movement-x,0px),var(--drawer-swipe-movement-y,0px))]',\n // While a finger is down the panel must track it exactly; a 320ms\n // ease on every pointermove is a panel lagging behind the hand.\n 'data-[swiping]:transition-none',\n attrs.class as string,\n )\n \"\n @interact-outside=\"guardOutsidePress\"\n >\n <!-- Reka renders the handle `aria-hidden` and unfocusable, which is\n correct and is why it can never become the only exit: it is not on\n the keyboard's path at all. It is drawn only where it means\n something — with `dismissible` off there is nothing to drag towards. -->\n <DrawerHandle\n v-if=\"dismissible\"\n :class=\"cn('absolute rounded-full bg-border-strong', anchor.handle)\"\n />\n\n <!-- The header is `shrink-0` and lives outside the scrolling region on\n purpose: a drawer taller than its content's needs scrolls its body\n while the title — the panel's accessible name and the only thing\n saying what is on screen — stays put. `pr-12` keeps a long title\n clear of the close control. -->\n <div class=\"shrink-0 px-6 pb-4 pr-12 pt-6\">\n <DrawerTitle class=\"text-base font-semibold\">{{ title }}</DrawerTitle>\n <DrawerDescription v-if=\"description\" class=\"mt-1 text-sm text-muted-foreground\">\n {{ description }}\n </DrawerDescription>\n </div>\n\n <!-- `min-h-0` is what makes `flex-1` able to shrink below its content's\n height; without it a flex item's automatic minimum size wins and the\n body grows the panel past the viewport instead of scrolling.\n `overscroll-contain` stops a scroll that reaches the end of this\n region from chaining out to the locked page behind. -->\n <div class=\"min-h-0 flex-1 overflow-y-auto overscroll-contain px-6 pb-6\">\n <!-- @slot The drawer body. -->\n <slot />\n </div>\n\n <!-- @slot The action row, aligned to the trailing edge. Pinned below the\n scrolling body so its actions stay reachable in a long panel. -->\n <div\n v-if=\"$slots.footer\"\n class=\"flex shrink-0 items-center justify-end gap-2 border-t border-border px-6 py-4\"\n >\n <slot name=\"footer\" />\n </div>\n\n <!-- Unconditional, unlike Dialog's `closable`. A dialog can drop its\n corner button because the footer already carries an explicit\n decision; a drawer often has no footer at all, and one of its two\n keyboard-independent exits must always be visible. -->\n <DrawerClose\n :aria-label=\"text.close\"\n class=\"absolute right-4 top-4 inline-flex h-7 w-7 items-center justify-center rounded-md 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\"\n >\n <X class=\"h-4 w-4\" />\n </DrawerClose>\n </DrawerContent>\n </DrawerPortal>\n </DrawerRoot>\n</template>\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"DropdownMenu.js","names":[],"sources":["../../../../../packages/primitives/dropdown-menu/src/DropdownMenu.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * One row of the menu, and the three kinds a menu is built from are told apart\n * by which fields are set rather than by a `kind` discriminator: a `separator`\n * is a rule, a `heading` is a non-interactive group label, and anything else\n * is a command.\n *\n * The list is data rather than markup because the primitive stays free of app\n * logic — selecting a row emits its `value` and the host decides what that\n * command means.\n */\nexport interface DropdownMenuEntry {\n /** The visible text of a command or a heading. */\n label?: string;\n /** The command id emitted on select. An entry without one is not selectable. */\n value?: string;\n /** Accelerator hint shown at the trailing edge, e.g. `⌘S`. Display only — the primitive binds no keys. */\n shortcut?: string;\n /** Render a divider. Every other field is ignored. */\n separator?: boolean;\n /** Render a non-interactive section heading rather than a command. */\n heading?: boolean;\n /** A destructive command — painted in the destructive token so it is not one indistinguishable row. */\n danger?: boolean;\n /** Visible but inert: announced as disabled, and selecting it emits nothing. */\n disabled?: boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n DropdownMenuRoot,\n DropdownMenuTrigger,\n DropdownMenuPortal,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n} from \"reka-ui\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { listStaggerDelay } from \"@ecoma-io/loom-core\";\nimport { optional } from \"@ecoma-io/loom-core\";\n\n/**\n * DropdownMenu — one button that opens a list of commands, with roving focus,\n * typeahead and arrow-key navigation.\n *\n * The escape contract: opening moves focus into the menu and onto the first\n * command; Esc and an outside click both close it; closing returns focus to the\n * trigger. The menu is modal, so while it is open the page behind does not\n * scroll and the rest of the page is hidden from assistive technology — a\n * command list is never scrolled out from under the pointer mid-choice. Focus\n * stays in the menu while it is open, but not the way `Dialog` traps it: a menu\n * has no internal tab order at all. Tab is inert, and the arrow keys plus\n * typeahead are how a row is reached.\n *\n * Selecting an entry emits `select` with its `value`; the host maps that id to\n * an action, which is what keeps the primitive free of app logic.\n *\n * Reach for `Popover` when the panel is interactive content rather than a\n * command list, and for a select control when the list *is* a field's value.\n */\nwithDefaults(\n defineProps<{\n /** The rows, in order. Three kinds, told apart by which fields are set. */\n items: DropdownMenuEntry[];\n /**\n * Let the arrow keys wrap at the ends of the list. Off by default — a\n * cursor that stops at the last row reads as \"there is nothing further\",\n * which is the honest answer for most command lists; long lists are where\n * cycling back to the top pays for itself.\n */\n loop?: boolean;\n /** Drive the menu from the host with `v-model:open`; omit it and the menu owns its own state. */\n open?: boolean | undefined;\n /**\n * Reading direction for the menu and its arrow-key navigation. Reka\n * mirrors traversal from this; without forwarding it a right-to-left\n * host gets left-to-right menus no matter what the page declares.\n */\n dir?: \"ltr\" | \"rtl\";\n }>(),\n // `open: undefined` is load-bearing, not a redundant default — it is what\n // keeps the uncontrolled third state reachable past Vue's absent-Boolean\n // casting. `optional()` in the template is the other half; its docblock\n // carries the reasoning for both.\n { open: undefined },\n);\nconst emit = defineEmits<{ select: [value: string]; \"update:open\": [value: boolean] }>();\n\n/**\n * A disabled entry, and an entry with no command id, select nothing. Reka\n * already blocks pointer events on the disabled row; this is the second half,\n * for the keyboard path that reaches it anyway.\n */\nfunction choose(item: DropdownMenuEntry): void {\n if (item.disabled || item.value === undefined) return;\n emit(\"select\", item.value);\n}\n</script>\n\n<template>\n <DropdownMenuRoot v-bind=\"optional({ open, dir })\" @update:open=\"$emit('update:open', $event)\">\n <!-- @slot The button that opens the menu. Rendered `as-child`, so the\n caller's own element *is* the trigger. -->\n <DropdownMenuTrigger as-child>\n <slot name=\"trigger\" />\n </DropdownMenuTrigger>\n\n <DropdownMenuPortal>\n <DropdownMenuContent\n :side-offset=\"6\"\n align=\"start\"\n :loop=\"loop ?? false\"\n :class=\"\n cn(\n 'z-overlay min-w-[12rem] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md outline-none',\n // Both states scoped, never unconditional. Reka's Presence\n // keeps closed content mounted until an animationend arrives, and a\n // mount-only animation never fires a second one — so an\n // unconditional animation class strands an invisible menu over the\n // page, catching clicks meant for what is behind it. Scoped, the\n // closed element computes `animation-name: none` and Presence\n // unmounts it at once; the paired exit is precisely what Presence\n // is waiting to hold it for. The origin below makes the menu grow\n // out of its trigger rather than out of its own centre — on the\n // way out as well as in.\n 'data-[state=open]:animate-scale-in data-[state=closed]:animate-scale-out',\n )\n \"\n style=\"transform-origin: var(--reka-popper-transform-origin)\"\n >\n <template v-for=\"(item, i) in items\" :key=\"i\">\n <DropdownMenuSeparator v-if=\"item.separator\" class=\"my-1 h-px bg-border\" />\n <DropdownMenuLabel\n v-else-if=\"item.heading\"\n class=\"px-2 py-1.5 text-micro font-medium uppercase tracking-wide text-muted-foreground\"\n >\n {{ item.label }}\n </DropdownMenuLabel>\n <!-- The reveal delay comes from the shared stagger vocabulary, capped\n there so a long menu does not tail off, rather than from a\n per-menu number written by hand.\n\n `disabled` is coerced rather than forwarded raw: an entry that\n simply omits the field is not disabled, and Reka's own prop does\n not accept `undefined` as a way of saying so. -->\n <DropdownMenuItem\n v-else\n :disabled=\"item.disabled ?? false\"\n :class=\"\n cn(\n 'flex cursor-pointer items-center justify-between gap-6 rounded-sm px-2 py-1.5 text-sm text-foreground outline-none',\n 'transition-colors duration-fast ease-out',\n // The rows reveal in sequence as the menu opens, which reads as\n // a list arriving rather than a block appearing. The hover\n // colour transition above is a separate channel, so a row\n // highlighted mid-reveal still responds at once.\n 'animate-fade-rise',\n 'data-[highlighted]:bg-subtle',\n // The row's colour, not its alpha. A menu row is nothing but\n // its label, and `data-[disabled]:opacity-40` composited that\n // label to 2.40:1 on the popover and its shortcut to 1.79:1 —\n // a disabled row a reader cannot make out tells them nothing\n // about what is unavailable, which is the only thing it is\n // there to say. Muted instead: 5.76:1, and a clear drop from\n // the 15.46:1 an available row wears.\n //\n // It takes the danger colour with it, deliberately. An\n // attribute selector outranks the plain `text-destructive-text`\n // below whatever order Tailwind emits them in, and that is the\n // right way round: red is a warning about an action, and there\n // is no action here to warn about.\n 'data-[disabled]:pointer-events-none data-[disabled]:text-muted-foreground',\n item.danger &&\n 'text-destructive-text data-[highlighted]:bg-destructive/10 data-[highlighted]:text-destructive-text',\n )\n \"\n :style=\"{ animationDelay: listStaggerDelay(i) }\"\n @select=\"choose(item)\"\n >\n <span>{{ item.label }}</span>\n <span v-if=\"item.shortcut\" class=\"tabular text-micro text-muted-foreground\">\n {{ item.shortcut }}\n </span>\n </DropdownMenuItem>\n </template>\n </DropdownMenuContent>\n </DropdownMenuPortal>\n </DropdownMenuRoot>\n</template>\n"],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"DropdownMenu.vue_vue_type_script_setup_true_lang.js","names":["$emit"],"sources":["../../../../../packages/primitives/dropdown-menu/src/DropdownMenu.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * One row of the menu, and the three kinds a menu is built from are told apart\n * by which fields are set rather than by a `kind` discriminator: a `separator`\n * is a rule, a `heading` is a non-interactive group label, and anything else\n * is a command.\n *\n * The list is data rather than markup because the primitive stays free of app\n * logic — selecting a row emits its `value` and the host decides what that\n * command means.\n */\nexport interface DropdownMenuEntry {\n /** The visible text of a command or a heading. */\n label?: string;\n /** The command id emitted on select. An entry without one is not selectable. */\n value?: string;\n /** Accelerator hint shown at the trailing edge, e.g. `⌘S`. Display only — the primitive binds no keys. */\n shortcut?: string;\n /** Render a divider. Every other field is ignored. */\n separator?: boolean;\n /** Render a non-interactive section heading rather than a command. */\n heading?: boolean;\n /** A destructive command — painted in the destructive token so it is not one indistinguishable row. */\n danger?: boolean;\n /** Visible but inert: announced as disabled, and selecting it emits nothing. */\n disabled?: boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n DropdownMenuRoot,\n DropdownMenuTrigger,\n DropdownMenuPortal,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n} from \"reka-ui\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { listStaggerDelay } from \"@ecoma-io/loom-core\";\nimport { optional } from \"@ecoma-io/loom-core\";\n\n/**\n * DropdownMenu — one button that opens a list of commands, with roving focus,\n * typeahead and arrow-key navigation.\n *\n * The escape contract: opening moves focus into the menu and onto the first\n * command; Esc and an outside click both close it; closing returns focus to the\n * trigger. The menu is modal, so while it is open the page behind does not\n * scroll and the rest of the page is hidden from assistive technology — a\n * command list is never scrolled out from under the pointer mid-choice. Focus\n * stays in the menu while it is open, but not the way `Dialog` traps it: a menu\n * has no internal tab order at all. Tab is inert, and the arrow keys plus\n * typeahead are how a row is reached.\n *\n * Selecting an entry emits `select` with its `value`; the host maps that id to\n * an action, which is what keeps the primitive free of app logic.\n *\n * Reach for `Popover` when the panel is interactive content rather than a\n * command list, and for a select control when the list *is* a field's value.\n */\nwithDefaults(\n defineProps<{\n /** The rows, in order. Three kinds, told apart by which fields are set. */\n items: DropdownMenuEntry[];\n /**\n * Let the arrow keys wrap at the ends of the list. Off by default — a\n * cursor that stops at the last row reads as \"there is nothing further\",\n * which is the honest answer for most command lists; long lists are where\n * cycling back to the top pays for itself.\n */\n loop?: boolean;\n /** Drive the menu from the host with `v-model:open`; omit it and the menu owns its own state. */\n open?: boolean | undefined;\n /**\n * Reading direction for the menu and its arrow-key navigation. Reka\n * mirrors traversal from this; without forwarding it a right-to-left\n * host gets left-to-right menus no matter what the page declares.\n */\n dir?: \"ltr\" | \"rtl\";\n }>(),\n // `open: undefined` is load-bearing, not a redundant default — it is what\n // keeps the uncontrolled third state reachable past Vue's absent-Boolean\n // casting. `optional()` in the template is the other half; its docblock\n // carries the reasoning for both.\n { open: undefined },\n);\nconst emit = defineEmits<{ select: [value: string]; \"update:open\": [value: boolean] }>();\n\n/**\n * A disabled entry, and an entry with no command id, select nothing. Reka\n * already blocks pointer events on the disabled row; this is the second half,\n * for the keyboard path that reaches it anyway.\n */\nfunction choose(item: DropdownMenuEntry): void {\n if (item.disabled || item.value === undefined) return;\n emit(\"select\", item.value);\n}\n</script>\n\n<template>\n <DropdownMenuRoot v-bind=\"optional({ open, dir })\" @update:open=\"$emit('update:open', $event)\">\n <!-- @slot The button that opens the menu. Rendered `as-child`, so the\n caller's own element *is* the trigger. -->\n <DropdownMenuTrigger as-child>\n <slot name=\"trigger\" />\n </DropdownMenuTrigger>\n\n <DropdownMenuPortal>\n <DropdownMenuContent\n :side-offset=\"6\"\n align=\"start\"\n :loop=\"loop ?? false\"\n :class=\"\n cn(\n 'z-overlay min-w-[12rem] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md outline-none',\n // Both states scoped, never unconditional. Reka's Presence\n // keeps closed content mounted until an animationend arrives, and a\n // mount-only animation never fires a second one — so an\n // unconditional animation class strands an invisible menu over the\n // page, catching clicks meant for what is behind it. Scoped, the\n // closed element computes `animation-name: none` and Presence\n // unmounts it at once; the paired exit is precisely what Presence\n // is waiting to hold it for. The origin below makes the menu grow\n // out of its trigger rather than out of its own centre — on the\n // way out as well as in.\n 'data-[state=open]:animate-scale-in data-[state=closed]:animate-scale-out',\n )\n \"\n style=\"transform-origin: var(--reka-popper-transform-origin)\"\n >\n <template v-for=\"(item, i) in items\" :key=\"i\">\n <DropdownMenuSeparator v-if=\"item.separator\" class=\"my-1 h-px bg-border\" />\n <DropdownMenuLabel\n v-else-if=\"item.heading\"\n class=\"px-2 py-1.5 text-micro font-medium uppercase tracking-wide text-muted-foreground\"\n >\n {{ item.label }}\n </DropdownMenuLabel>\n <!-- The reveal delay comes from the shared stagger vocabulary, capped\n there so a long menu does not tail off, rather than from a\n per-menu number written by hand.\n\n `disabled` is coerced rather than forwarded raw: an entry that\n simply omits the field is not disabled, and Reka's own prop does\n not accept `undefined` as a way of saying so. -->\n <DropdownMenuItem\n v-else\n :disabled=\"item.disabled ?? false\"\n :class=\"\n cn(\n 'flex cursor-pointer items-center justify-between gap-6 rounded-sm px-2 py-1.5 text-sm text-foreground outline-none',\n 'transition-colors duration-fast ease-out',\n // The rows reveal in sequence as the menu opens, which reads as\n // a list arriving rather than a block appearing. The hover\n // colour transition above is a separate channel, so a row\n // highlighted mid-reveal still responds at once.\n 'animate-fade-rise',\n 'data-[highlighted]:bg-subtle',\n // The row's colour, not its alpha. A menu row is nothing but\n // its label, and `data-[disabled]:opacity-40` composited that\n // label to 2.40:1 on the popover and its shortcut to 1.79:1 —\n // a disabled row a reader cannot make out tells them nothing\n // about what is unavailable, which is the only thing it is\n // there to say. Muted instead: 5.76:1, and a clear drop from\n // the 15.46:1 an available row wears.\n //\n // It takes the danger colour with it, deliberately. An\n // attribute selector outranks the plain `text-destructive-text`\n // below whatever order Tailwind emits them in, and that is the\n // right way round: red is a warning about an action, and there\n // is no action here to warn about.\n 'data-[disabled]:pointer-events-none data-[disabled]:text-muted-foreground',\n item.danger &&\n 'text-destructive-text data-[highlighted]:bg-destructive/10 data-[highlighted]:text-destructive-text',\n )\n \"\n :style=\"{ animationDelay: listStaggerDelay(i) }\"\n @select=\"choose(item)\"\n >\n <span>{{ item.label }}</span>\n <span v-if=\"item.shortcut\" class=\"tabular text-micro text-muted-foreground\">\n {{ item.shortcut }}\n </span>\n </DropdownMenuItem>\n </template>\n </DropdownMenuContent>\n </DropdownMenuPortal>\n </DropdownMenuRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;EAwFA,MAAM,OAAO;;;;;;EAOb,SAAS,OAAO,MAA+B;GAC7C,IAAI,KAAK,YAAY,KAAK,UAAU,KAAA,GAAW;GAC/C,KAAK,UAAU,KAAK,KAAK;EAC3B;;GAIE,OAAA,UAAA,GAAA,YAuFmB,MAAA,gBAAA,GAvFnB,WAA0B,MAuFP,QAAA,CAvFe,CAAA;IAAA,MAAG,QAAA;IAAI,KAAE,QAAA;GAAG,CAAA,GAAA,EAAM,iBAAW,OAAA,OAAA,OAAA,MAAA,WAAEA,KAAAA,MAAK,eAAgB,MAAM,GAAA,CAAA,GAAA;IAG1F,SAAA,cAEsB,CAFtB,YAEsB,MAAA,mBAAA,GAAA,EAFD,YAAA,GAAQ,GAAA;KAC3B,SAAA,cAAuB,CAAvB,WAAuB,KAAA,QAAA,SAAA,CAAA,CAAA;;IAGzB,CAAA,GAAA,YA+EqB,MAAA,kBAAA,GAAA,MAAA;KA9EnB,SAAA,cA6EsB,CA7EtB,YA6EsB,MAAA,mBAAA,GAAA;MA5EnB,eAAa;MACd,OAAM;MACL,MAAM,QAAA,QAAI;MACV,OAAK,eAAa,MAAA,EAAA,CAAE,CAAA,yHAAA,0EAAA,CAAA;MAgBrB,OAAA,EAAA,oBAAA,sCAAA;;MAEU,SAAA,cAA0B,EAApC,UAAA,IAAA,GAAA,mBAsDW,UAAA,MAAA,WAtDmB,QAAA,QAAZ,MAAM,MAAC;OAAkB,OAAA,UAAA,GAAA,mBAAA,UAAA,EAAA,KAAA,EAAC,GAAA,CACb,KAAK,aAAlC,UAAA,GAAA,YAA2E,MAAA,qBAAA,GAAA;;QAA9B,OAAM;OAEtC,CAAA,KAAA,KAAK,WADlB,UAAA,GAAA,YAKoB,MAAA,iBAAA,GAAA;;QAHlB,OAAM;;QAEN,SAAA,cAAgB,CAAb,gBAAA,gBAAA,KAAK,KAAK,GAAA,CAAA,CAAA,CAAA;;OASf,GAAA,IAAA,MAAA,UAAA,GAAA,YAsCmB,MAAA,gBAAA,GAAA;;QApChB,UAAU,KAAK,YAAQ;QACvB,OAAK,eAAiB,MAAA,EAAA,CAAE,CAAA,sHAAA,4CAAA,qBAAA,gCAAA,6EAA2jD,KAAK,UAAA,qGAAA,CAAA;QA4BxlD,OAAK,eAAA,EAAA,gBAAoB,MAAA,gBAAA,CAAgB,CAAC,CAAC,EAAA,CAAA;QAC3C,WAAM,WAAE,OAAO,IAAI;;QAEpB,SAAA,cAA6B,CAA7B,mBAA6B,QAAA,MAAA,gBAApB,KAAK,KAAK,GAAA,CAAA,GACP,KAAK,YAAjB,UAAA,GAAA,mBAEO,QAFP,YAEO,gBADF,KAAK,QAAQ,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Editable.js","names":[],"sources":["../../../../../packages/primitives/editable/src/Editable.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { EditableLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it: a\n * consumer who never imports Editable ships none of these bytes.\n *\n * Exported so a host can build a partial vocabulary against the real thing\n * rather than a transcription of it.\n */\nexport const EDITABLE_LABELS: EditableLabels = {\n edit: \"Edit\",\n input: \"Editable text\",\n submit: \"Save\",\n cancel: \"Cancel\",\n restored: ({ value }) => `Empty value discarded, ${value} restored`,\n};\n\n/**\n * What a pointer has to do to open the editor. The keyboard is deliberately\n * not on this axis — Enter and Space open it in all three, because a mode a\n * reader cannot reach by keyboard is a control they cannot use.\n *\n * • `click` — one click on the text opens it. The default: it is the whole\n * promise of edit-in-place, and the only mode a touch reader can perform.\n * • `dblclick` — for a row or a cell where a single click already means\n * something else, selecting it.\n * • `focus` — landing on it opens it, so Tab walks straight into the\n * editor. For a column of fields being filled in order, and the mode that\n * makes Escape's restore-and-hand-focus-back path load-bearing.\n */\nexport type EditableActivationMode = \"click\" | \"dblclick\" | \"focus\";\n\n/**\n * What commits the edit.\n *\n * • `both` — Enter, or focus leaving the control. The default: a reader who\n * typed a value and clicked away meant to keep it.\n * • `enter` — Enter alone; leaving discards, which suits an edit that is a\n * deliberate act rather than an incidental one.\n * • `blur` — leaving alone, for a control inside something that has its own\n * Enter.\n *\n * Escape abandons under all three.\n */\nexport type EditableSubmitMode = \"blur\" | \"enter\" | \"both\";\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, watch, type ComponentPublicInstance } from \"vue\";\nimport {\n EditableRoot,\n EditableArea,\n EditablePreview,\n EditableInput,\n EditableSubmitTrigger,\n EditableCancelTrigger,\n} from \"reka-ui\";\nimport { Check, Pencil, X } from \"@lucide/vue\";\nimport { buttonVariants } from \"@ecoma-io/loom-button\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { optional } 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 * Editable — text that becomes an input where it stands: a record's title, a\n * name on a card, a cell in a table. It is the control that makes an\n * operations screen feel direct, because the value is edited where it is read\n * rather than in a dialog opened to hold one field.\n *\n * Reach for a [TextField](../TextField/TextField.vue) instead whenever the\n * value is being *entered* rather than corrected — a form is a set of empty\n * boxes and should look like one. This is for a value that already exists,\n * that is usually right, and that is occasionally wrong.\n *\n * **It takes no `size`, and that is the point.** Every other control in the\n * library picks a height off the shared scale; this one inherits the\n * typography around it, so an editable page title stays the size of a page\n * title and an editable table cell stays the size of a cell. What it pins\n * instead is that the two states are the same size as each other: the preview\n * and the editor are the only two children of one padded box, both single-line\n * and both inheriting that box's type, so the swap cannot move the row below\n * it. The box carries a transparent border at rest and a visible one while\n * editing — the same border width either way, for the same reason.\n *\n * **Escape restores and hands focus back.** Ending an edit hides the editor,\n * and a browser drops focus to `<body>` when the focused node goes away, so\n * without the hand-off a reader who abandoned an edit would lose their place\n * in the document. With `activationMode: \"focus\"` that hand-off would then\n * re-open the editor it just closed, which is why activation is Loom's rather\n * than Reka's here — the returning focus is suppressed exactly once, until the\n * reader leaves and comes back deliberately.\n *\n * **The model moves on submit, not on keystrokes.** `update:modelValue` fires\n * once, with the committed value, alongside `submit`; `cancel` fires when an\n * edit is abandoned. A control whose whole purpose is that an edit can be\n * taken back cannot publish every intermediate character as though it were\n * the value.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself: the row's id, the id\n * of its hint or error line, `required`, `invalid`, `disabled`, `readonly` and\n * the name the value is submitted under all arrive through `useFieldControl()`.\n * Every prop below still wins over the row when it is set, in both directions\n * — which is why the four booleans default to `undefined` rather than `false`.\n *\n * `readonly` and `disabled` are different states, so the box has **three**\n * resting appearances rather than two. Read-only is a value on show: still\n * focusable, still copyable, still submitted, and lifted onto a fill with its\n * text at full strength. Disabled is unavailable, and drained a step further in\n * fill, in text colour and in border weight together. Three channels rather\n * than one is the point — see `areaClass`.\n *\n * Built on Reka UI's Editable, which owns the state machine — what is showing,\n * what the editor holds before it is committed, and what a dismiss means under\n * each submit mode.\n */\nconst props = withDefaults(\n defineProps<{\n /** The committed value. Pair with `@update:modelValue` for `v-model`. */\n modelValue?: string;\n /** Shown in place of an empty value, in both the preview and the editor. */\n placeholder?: string;\n /** What a pointer does to open the editor. The keyboard opens it in every mode. */\n activationMode?: EditableActivationMode;\n /** What commits the edit. Escape abandons it under all three. */\n submitMode?: EditableSubmitMode;\n /**\n * Sizes the control to its own text and stacks the two states in one grid\n * cell, for an editable sitting inline in a sentence rather than in a\n * column. It measures the committed value, not what is being typed.\n */\n autoResize?: boolean;\n /** The longest value the editor will accept, in characters. */\n maxLength?: number;\n /**\n * Lets a submitted empty value through. Off by default: an empty submit\n * restores the previous value and reports `cancel` instead, because the\n * damage is asymmetric — a value wrongly kept is on screen and can be\n * edited again, a title wrongly emptied is gone.\n */\n allowEmpty?: boolean;\n /** Unavailable: the preview drops out of the tab order and refuses to open. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Shows the value without allowing an edit, while staying focusable. 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 value 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 /** The editor's accessible name, when no visible element already labels it. */\n ariaLabel?: string;\n /**\n * Names for everything this control says out loud, as any subset of\n * `EditableLabels` — 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 `edit`, where a page of\n * editables reads better as \"Rename\" or \"Correct\" than as the same verb\n * five times.\n */\n labels?: LabelOverrides<EditableLabels>;\n }>(),\n {\n activationMode: \"click\",\n submitMode: \"both\",\n autoResize: false,\n allowEmpty: false,\n // Not `false`, for any of the four. `false` is a caller saying \"this value\n // is fine / available / 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 — see TextField.vue, which\n // carries the full reasoning.\n disabled: undefined,\n readonly: undefined,\n invalid: undefined,\n required: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** The committed value. Fires on submit only, never per keystroke. */\n \"update:modelValue\": [value: string];\n /** The edit was committed, with the value that was accepted. */\n submit: [value: string];\n /** The edit was abandoned — Escape, the cancel button, or a refused empty submit. */\n cancel: [];\n}>();\n\ndefineOptions({ inheritAttrs: false });\n\n// `class` lands on the root rather than on the bordered box inside it: the\n// root is what participates in the caller's layout, and it holds the box and\n// the two commit controls beside it, so a caller's `w-64` has to size all\n// three. Everything else — `id`, `aria-describedby`, `aria-labelledby`,\n// `data-testid`, `autocomplete` — describes the *editor*, and lands there.\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\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.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: attrs[\"aria-describedby\"] as string | undefined,\n name: props.name,\n disabled: props.disabled,\n readonly: props.readonly,\n invalid: props.invalid,\n required: props.required,\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(\"editable\", EDITABLE_LABELS, () => props.labels);\n\n// The value as this component knows it, which is also what Reka is fed. Two\n// things need it. A defined `model-value` is what puts Reka in controlled\n// mode, and controlled is what lets a submit be *refused* — Reka's own commit\n// then only announces the new value rather than adopting it, so the preview\n// keeps showing the old one with nothing to undo. And a host using this\n// without `v-model` still needs the value to move, which is what the\n// optimistic write in `onSubmit` is for.\nconst value = ref(props.modelValue ?? \"\");\nwatch(\n () => props.modelValue,\n (next) => {\n // `undefined` is a host that never controlled the value, not a host\n // clearing it — adopting it would blank the box on any unrelated re-render.\n if (next !== undefined) value.value = next;\n },\n);\n\n// Mirrors Reka's own `isEditing`, off the state event rather than out of the\n// slot, because the class bindings and the activation guard both need it in\n// the script half as well as in the template.\nconst editing = ref(false);\n\nconst previewRef = ref<ComponentPublicInstance | null>(null);\nconst rootRef = ref<ComponentPublicInstance | null>(null);\n\n// Reka's parts are components, so the only handle on their DOM node is `$el`,\n// which Vue types as `any`. Narrowing through `unknown` keeps that `any` from\n// spreading into everything it touches — and answers the SSR case honestly,\n// where there is no element at all.\nfunction elementOf(instance: ComponentPublicInstance | null): HTMLElement | null {\n const el = instance?.$el as unknown;\n return el instanceof HTMLElement ? el : null;\n}\n\n// Set only when focus was actually handed back to the preview, and cleared the\n// moment the reader leaves it. Without it, `activationMode: \"focus\"` would\n// read that hand-off as a fresh arrival and re-open the editor the reader just\n// escaped from — a control that cannot be abandoned, which is precisely the\n// trap Escape exists to avoid.\nlet suppressFocusActivation = false;\n\nfunction activate(edit: () => void): void {\n if (field.disabled || field.readonly || editing.value) return;\n edit();\n}\n\n// Reka's own activation is switched off in the template\n// (`activation-mode=\"none\"`) and rebuilt in these three handlers, rather than\n// passed through. Two things need that. Reka has no click mode at all and no\n// keyboard path on its preview, so two of the three modes this component\n// publishes would be unreachable without a pointer. And its focus mode cannot\n// tell a reader arriving on the control from the focus this component hands\n// back after an Escape — which would re-open the editor that Escape just\n// abandoned, forever.\n//\n// A `<button>` turns Enter and Space into a click carrying `detail === 0`,\n// which is what lets one handler serve the keyboard in every activation mode:\n// `dblclick` cannot be typed, and `focus` must not be the only way in for a\n// reader who arrived on the control without meaning to edit yet. `detail` is\n// the same signal Pagination reads to tell a synthesised click from a pointer\n// one.\nfunction onPreviewClick(event: MouseEvent, edit: () => void): void {\n if (props.activationMode === \"dblclick\" && event.detail !== 0) return;\n activate(edit);\n}\n\nfunction onPreviewDoubleClick(edit: () => void): void {\n if (props.activationMode !== \"dblclick\") return;\n activate(edit);\n}\n\nfunction onPreviewFocus(edit: () => void): void {\n if (props.activationMode !== \"focus\" || suppressFocusActivation) return;\n activate(edit);\n}\n\nfunction onPreviewBlur(): void {\n suppressFocusActivation = false;\n}\n\n// The editor is hidden the instant an edit ends, and a browser drops focus to\n// `<body>` when the focused node goes away — so a reader who pressed Escape or\n// Enter would be left with no position in the document at all.\n//\n// Only focus that was actually lost is rescued. A submit caused by clicking\n// somewhere else has already put the reader where they meant to be, and\n// stealing focus back from them would be the worse bug; the same reasoning,\n// and the same `<body>` check, as Pagination's edge-control hand-off. jsdom\n// leaves focus on the hidden node rather than dropping it, and a click on the\n// commit button leaves it on a button that is about to be hidden too, so\n// anything still inside this control counts as lost.\nfunction restoreFocus(): void {\n void nextTick(() => {\n const preview = elementOf(previewRef.value);\n const root = elementOf(rootRef.value);\n if (preview === null) return;\n\n const active = document.activeElement;\n const lost = active === null || active === document.body || (root?.contains(active) ?? false);\n if (!lost) return;\n\n suppressFocusActivation = true;\n preview.focus();\n });\n}\n\nfunction onState(state: \"edit\" | \"submit\" | \"cancel\"): void {\n editing.value = state === \"edit\";\n if (state === \"edit\") return;\n if (state === \"cancel\") emit(\"cancel\");\n restoreFocus();\n}\n\n// The refusal, held for one announcement rather than derived, so the live\n// region says something only when a submit was actually turned away — and is\n// cleared when the next edit opens, so a second identical refusal is still a\n// change to the region and still gets announced.\nconst restored = ref(\"\");\nwatch(editing, (isEditing) => {\n if (isEditing) restored.value = \"\";\n});\n\n// Reka's `submit` is an announcement rather than a request — in controlled\n// mode it has already told us what it would like the value to be and left the\n// deciding here, which is what makes the empty case answerable at all.\nfunction onSubmit(submitted: string | null | undefined): void {\n const next = submitted ?? \"\";\n\n // An empty submit is the one genuinely ambiguous outcome: a reader who\n // cleared the box and pressed Enter may have meant to blank the value, and\n // under `submitMode: \"blur\"` may have meant nothing at all. Loom restores\n // rather than clears, and `allowEmpty` is how a field that can legitimately\n // be emptied says so. `restored` announces it, because a refusal that only\n // shows up as text snapping back is a refusal a screen reader never hears.\n if (next === \"\" && !props.allowEmpty) {\n restored.value = text.value.restored({ value: value.value });\n emit(\"cancel\");\n return;\n }\n\n // Optimistic only while uncontrolled. With a `modelValue` prop the host owns\n // the value, and echoing it here would show a value they may be about to\n // reject — the prop watcher above is what applies the one they accept.\n if (props.modelValue === undefined) value.value = next;\n emit(\"update:modelValue\", next);\n emit(\"submit\", next);\n}\n\n// A read-only preview is not a control, so it is not rendered as one: a\n// `<button>` that refuses to act is worse than plain text. It keeps a\n// `tabindex` of its own instead — a read-only value is one a reader may reach\n// and copy, the same contract TextField's read-only input keeps — while the\n// button state drops Reka's hardcoded `tabindex=\"0\"` entirely, because a\n// `<button>` is focusable without it and a *disabled* one carrying it is\n// focusable when it should not be.\nconst previewAs = computed(() => (field.readonly ? \"span\" : \"button\"));\n\nconst rootProps = computed(() => optional({ name: field.name, maxLength: props.maxLength }));\n\n// `name` is dropped from the bag before it reaches the editor. Reka already\n// renders a hidden input under that name for any Editable inside a `<form>`,\n// and an editor carrying it as well would post the field twice — once with the\n// committed value and once with whatever the box held. Removed from a copy\n// rather than listed positively, so a key added to the resolved bag later\n// reaches this input without anyone remembering to come back here.\nconst editorAttrs = computed(() => {\n const aria: Record<string, unknown> = { ...field.attrs };\n delete aria.name;\n return aria;\n});\n\n// `aria-label` outranks a `<label for>` in the accessible-name order, so a\n// generic fallback would silently replace the name a Field row already gives\n// the editor. It is supplied only where nothing else names it at all — which\n// is also the state Reka would otherwise fill with \"editable input\".\nconst editorLabel = computed<string | undefined>(() => {\n if (props.ariaLabel !== undefined) return props.ariaLabel;\n if (field.id !== undefined) return undefined;\n if (attrs[\"aria-label\"] !== undefined || attrs[\"aria-labelledby\"] !== undefined) return undefined;\n return text.value.input;\n});\n\nconst areaClass = computed(() =>\n cn(\n // One box, two children. The border is present in both states and only\n // changes colour, the padding never changes, and the floor height keeps an\n // empty value from collapsing the row it sits in — between them, nothing\n // below this control moves when it switches.\n \"flex min-h-9 min-w-0 items-center rounded-md border border-transparent px-2 py-1\",\n // A control that sizes to its own text cannot also fill its parent: under\n // `autoResize` Reka makes this box an `inline-grid` measured by the two\n // states stacked inside it, and a width of 100% would measure the row\n // instead.\n props.autoResize ? \"w-auto\" : \"w-full\",\n \"text-inherit transition-[color,background-color,border-color,box-shadow] duration-fast ease-out\",\n // Rim-lit at rest, the weave blooms on focus (Signature law), and it blooms\n // for the preview as much as for the editor: at rest the preview is the\n // focusable node, and a control a reader can tab to has to show it.\n \"focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring\",\n !field.invalid && \"focus-within:shadow-halo\",\n editing.value && \"border-input bg-background\",\n // The affordance for a pointer, since the resting state is deliberately\n // just text: the box lights under the cursor and the caret says the text\n // can be typed into. Never the only signal — the preview announces itself,\n // and carries a glyph.\n !editing.value && !field.disabled && !field.readonly && \"cursor-text hover:bg-subtle\",\n // Lifted rather than dimmed, exactly as a read-only text field is: the\n // value is the whole reason the control is on the page, so it stays at\n // full contrast — 13.45:1 over this fill — whether or not it can be\n // changed. The rim comes up with it, from the resting `transparent` to\n // `input`: at rest this control is deliberately just text, so without a\n // border there is nothing but hue to say the value is on show, and the box\n // was already reserving the width for one.\n field.readonly && \"border-input bg-subtle\",\n // Drained, not faded, and a step further down all three channels: the fill\n // to `muted`, the text to `muted-foreground` (4.67:1 over it) and the rim\n // to the lighter `border`. Half-opacity text on this box measures under\n // 4.5:1, and a value nobody can read is worse than one nobody can edit.\n //\n // Read-only and disabled used to share `bg-muted` and part on the text\n // colour alone — a distinction made in hue and nothing else, which is the\n // one a reader with a colour deficiency does not receive.\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 control disables the preview `<button>`\n // and the `<input>` behind it natively — both are on the list a fieldset\n // reaches — and never touches `field.disabled`, so the rule above cannot\n // fire and the value rendered byte-identical to an editable one.\n //\n // `in-[fieldset:disabled]:` reads the attribute that did the disabling, so\n // the fill and the native inertness cannot disagree. See TextField.vue for\n // why it is preferred to a `has-[:disabled]:` rule reading this box's own\n // 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 rule below is ordered: Tailwind emits the\n // ancestor half of `in-*` inside `:where()`, so this carries no more\n // specificity than `border-destructive` and would win on emission order\n // alone.\n !field.invalid && \"in-[fieldset:disabled]:border-border\",\n // Last of the rules naming a border colour: `cn()` resolves one by\n // whichever class it saw last, so a control both in error and unavailable\n // would lose its destructive rim if this sat above them.\n field.invalid && \"border-destructive focus-within:outline-destructive\",\n ),\n);\n\n// The submit/cancel triggers are glyph-only, so the drained treatment they\n// take is the transparent control's: the neutral well under a glyph that is\n// already `text-muted-foreground`. `opacity-50` used to fade that glyph below\n// contrast — the failure Button records for its own dim — and the native\n// `disabled` attribute these Reka triggers carry already tells assistive tech.\nconst triggerClass = cn(\n buttonVariants({ variant: \"ghost\", size: \"icon-sm\" }),\n \"disabled:cursor-not-allowed disabled:bg-muted disabled:shadow-none\",\n);\n</script>\n\n<template>\n <EditableRoot\n ref=\"rootRef\"\n v-slot=\"{ edit }\"\n v-bind=\"rootProps\"\n :model-value=\"value\"\n :placeholder=\"placeholder ?? ''\"\n activation-mode=\"none\"\n :disabled=\"field.disabled\"\n :readonly=\"field.readonly\"\n :required=\"field.required\"\n :submit-mode=\"submitMode\"\n :auto-resize=\"autoResize\"\n :data-editing=\"editing || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :data-readonly=\"field.readonly || undefined\"\n :data-disabled=\"field.disabled || undefined\"\n :class=\"\n cn(\n 'inline-flex items-center gap-1',\n autoResize ? 'w-auto align-baseline' : 'w-full',\n attrs.class as string,\n )\n \"\n @update:state=\"onState\"\n @submit=\"onSubmit\"\n >\n <EditableArea :class=\"areaClass\">\n <!-- The preview is the control, and Reka's `EditableEditTrigger` is\n deliberately not rendered beside it: a second button doing the same\n job costs a second Tab stop on one value, and its click handler\n fires in every activation mode, which would make `dblclick` and\n `focus` lies. A real `<button>` rather than a `role`, so Enter and\n Space are the browser's job and the affordance survives\n forced-colors mode. -->\n <EditablePreview\n ref=\"previewRef\"\n :as=\"previewAs\"\n :type=\"field.readonly ? undefined : 'button'\"\n :tabindex=\"field.readonly ? 0 : undefined\"\n :disabled=\"!field.readonly && field.disabled ? true : undefined\"\n :aria-describedby=\"field.attrs['aria-describedby']\"\n :aria-invalid=\"field.attrs['aria-invalid']\"\n class=\"flex min-w-0 flex-1 items-center gap-1.5 text-start outline-none\"\n @click=\"(event: MouseEvent) => onPreviewClick(event, edit)\"\n @dblclick=\"() => onPreviewDoubleClick(edit)\"\n @focus=\"() => onPreviewFocus(edit)\"\n @blur=\"onPreviewBlur\"\n >\n <!-- Single-line and truncated, because the editor it swaps with is a\n single-line input: a preview that wrapped would be a taller box\n than the thing replacing it. -->\n <span :class=\"cn('truncate', !value && 'text-muted-foreground')\">\n {{ value || placeholder }}\n </span>\n <template v-if=\"!field.readonly\">\n <!-- The affordance for a sighted reader, and the counterpart to the\n span below it: the resting state is text, so something has to\n say it is more than text. Hidden from assistive tech, which is\n told the same thing in words. -->\n <Pencil class=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <!-- The whole accessibility problem of edit-in-place, in one span.\n The value reads first so it stays the start of the accessible\n name (WCAG 2.5.3, and what a voice-control reader says out\n loud); the verb follows, so the text announces as something\n that can be acted on rather than as prose. -->\n <span class=\"sr-only\">{{ text.edit }}</span>\n </template>\n </EditablePreview>\n\n <EditableInput\n v-bind=\"{ ...inputAttrs, ...editorAttrs }\"\n :aria-label=\"editorLabel\"\n class=\"min-w-0 flex-1 bg-transparent text-inherit outline-none placeholder:text-muted-foreground\"\n />\n </EditableArea>\n\n <!-- Both triggers hide themselves while the preview is showing, so there\n is nothing to guard here. They exist for the reader who has no way to\n know that Enter commits and Escape abandons — an invisible keyboard\n contract is not an affordance. -->\n <EditableSubmitTrigger :aria-label=\"text.submit\" :class=\"triggerClass\">\n <Check class=\"h-4 w-4\" aria-hidden=\"true\" />\n </EditableSubmitTrigger>\n <EditableCancelTrigger :aria-label=\"text.cancel\" :class=\"triggerClass\">\n <X class=\"h-4 w-4\" aria-hidden=\"true\" />\n </EditableCancelTrigger>\n\n <!-- A refused empty submit changes the screen without moving focus or\n opening anything, which a screen reader would otherwise never\n announce. Empty until there is something to say, so it never repeats\n itself on an unrelated re-render. -->\n <span role=\"status\" class=\"sr-only\">{{ restored }}</span>\n </EditableRoot>\n</template>\n"],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Editable.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../../packages/primitives/editable/src/Editable.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { EditableLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it: a\n * consumer who never imports Editable ships none of these bytes.\n *\n * Exported so a host can build a partial vocabulary against the real thing\n * rather than a transcription of it.\n */\nexport const EDITABLE_LABELS: EditableLabels = {\n edit: \"Edit\",\n input: \"Editable text\",\n submit: \"Save\",\n cancel: \"Cancel\",\n restored: ({ value }) => `Empty value discarded, ${value} restored`,\n};\n\n/**\n * What a pointer has to do to open the editor. The keyboard is deliberately\n * not on this axis — Enter and Space open it in all three, because a mode a\n * reader cannot reach by keyboard is a control they cannot use.\n *\n * • `click` — one click on the text opens it. The default: it is the whole\n * promise of edit-in-place, and the only mode a touch reader can perform.\n * • `dblclick` — for a row or a cell where a single click already means\n * something else, selecting it.\n * • `focus` — landing on it opens it, so Tab walks straight into the\n * editor. For a column of fields being filled in order, and the mode that\n * makes Escape's restore-and-hand-focus-back path load-bearing.\n */\nexport type EditableActivationMode = \"click\" | \"dblclick\" | \"focus\";\n\n/**\n * What commits the edit.\n *\n * • `both` — Enter, or focus leaving the control. The default: a reader who\n * typed a value and clicked away meant to keep it.\n * • `enter` — Enter alone; leaving discards, which suits an edit that is a\n * deliberate act rather than an incidental one.\n * • `blur` — leaving alone, for a control inside something that has its own\n * Enter.\n *\n * Escape abandons under all three.\n */\nexport type EditableSubmitMode = \"blur\" | \"enter\" | \"both\";\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, watch, type ComponentPublicInstance } from \"vue\";\nimport {\n EditableRoot,\n EditableArea,\n EditablePreview,\n EditableInput,\n EditableSubmitTrigger,\n EditableCancelTrigger,\n} from \"reka-ui\";\nimport { Check, Pencil, X } from \"@lucide/vue\";\nimport { buttonVariants } from \"@ecoma-io/loom-button\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { optional } 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 * Editable — text that becomes an input where it stands: a record's title, a\n * name on a card, a cell in a table. It is the control that makes an\n * operations screen feel direct, because the value is edited where it is read\n * rather than in a dialog opened to hold one field.\n *\n * Reach for a [TextField](../TextField/TextField.vue) instead whenever the\n * value is being *entered* rather than corrected — a form is a set of empty\n * boxes and should look like one. This is for a value that already exists,\n * that is usually right, and that is occasionally wrong.\n *\n * **It takes no `size`, and that is the point.** Every other control in the\n * library picks a height off the shared scale; this one inherits the\n * typography around it, so an editable page title stays the size of a page\n * title and an editable table cell stays the size of a cell. What it pins\n * instead is that the two states are the same size as each other: the preview\n * and the editor are the only two children of one padded box, both single-line\n * and both inheriting that box's type, so the swap cannot move the row below\n * it. The box carries a transparent border at rest and a visible one while\n * editing — the same border width either way, for the same reason.\n *\n * **Escape restores and hands focus back.** Ending an edit hides the editor,\n * and a browser drops focus to `<body>` when the focused node goes away, so\n * without the hand-off a reader who abandoned an edit would lose their place\n * in the document. With `activationMode: \"focus\"` that hand-off would then\n * re-open the editor it just closed, which is why activation is Loom's rather\n * than Reka's here — the returning focus is suppressed exactly once, until the\n * reader leaves and comes back deliberately.\n *\n * **The model moves on submit, not on keystrokes.** `update:modelValue` fires\n * once, with the committed value, alongside `submit`; `cancel` fires when an\n * edit is abandoned. A control whose whole purpose is that an edit can be\n * taken back cannot publish every intermediate character as though it were\n * the value.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself: the row's id, the id\n * of its hint or error line, `required`, `invalid`, `disabled`, `readonly` and\n * the name the value is submitted under all arrive through `useFieldControl()`.\n * Every prop below still wins over the row when it is set, in both directions\n * — which is why the four booleans default to `undefined` rather than `false`.\n *\n * `readonly` and `disabled` are different states, so the box has **three**\n * resting appearances rather than two. Read-only is a value on show: still\n * focusable, still copyable, still submitted, and lifted onto a fill with its\n * text at full strength. Disabled is unavailable, and drained a step further in\n * fill, in text colour and in border weight together. Three channels rather\n * than one is the point — see `areaClass`.\n *\n * Built on Reka UI's Editable, which owns the state machine — what is showing,\n * what the editor holds before it is committed, and what a dismiss means under\n * each submit mode.\n */\nconst props = withDefaults(\n defineProps<{\n /** The committed value. Pair with `@update:modelValue` for `v-model`. */\n modelValue?: string;\n /** Shown in place of an empty value, in both the preview and the editor. */\n placeholder?: string;\n /** What a pointer does to open the editor. The keyboard opens it in every mode. */\n activationMode?: EditableActivationMode;\n /** What commits the edit. Escape abandons it under all three. */\n submitMode?: EditableSubmitMode;\n /**\n * Sizes the control to its own text and stacks the two states in one grid\n * cell, for an editable sitting inline in a sentence rather than in a\n * column. It measures the committed value, not what is being typed.\n */\n autoResize?: boolean;\n /** The longest value the editor will accept, in characters. */\n maxLength?: number;\n /**\n * Lets a submitted empty value through. Off by default: an empty submit\n * restores the previous value and reports `cancel` instead, because the\n * damage is asymmetric — a value wrongly kept is on screen and can be\n * edited again, a title wrongly emptied is gone.\n */\n allowEmpty?: boolean;\n /** Unavailable: the preview drops out of the tab order and refuses to open. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Shows the value without allowing an edit, while staying focusable. 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 value 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 /** The editor's accessible name, when no visible element already labels it. */\n ariaLabel?: string;\n /**\n * Names for everything this control says out loud, as any subset of\n * `EditableLabels` — 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 `edit`, where a page of\n * editables reads better as \"Rename\" or \"Correct\" than as the same verb\n * five times.\n */\n labels?: LabelOverrides<EditableLabels>;\n }>(),\n {\n activationMode: \"click\",\n submitMode: \"both\",\n autoResize: false,\n allowEmpty: false,\n // Not `false`, for any of the four. `false` is a caller saying \"this value\n // is fine / available / 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 — see TextField.vue, which\n // carries the full reasoning.\n disabled: undefined,\n readonly: undefined,\n invalid: undefined,\n required: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** The committed value. Fires on submit only, never per keystroke. */\n \"update:modelValue\": [value: string];\n /** The edit was committed, with the value that was accepted. */\n submit: [value: string];\n /** The edit was abandoned — Escape, the cancel button, or a refused empty submit. */\n cancel: [];\n}>();\n\ndefineOptions({ inheritAttrs: false });\n\n// `class` lands on the root rather than on the bordered box inside it: the\n// root is what participates in the caller's layout, and it holds the box and\n// the two commit controls beside it, so a caller's `w-64` has to size all\n// three. Everything else — `id`, `aria-describedby`, `aria-labelledby`,\n// `data-testid`, `autocomplete` — describes the *editor*, and lands there.\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\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.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: attrs[\"aria-describedby\"] as string | undefined,\n name: props.name,\n disabled: props.disabled,\n readonly: props.readonly,\n invalid: props.invalid,\n required: props.required,\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(\"editable\", EDITABLE_LABELS, () => props.labels);\n\n// The value as this component knows it, which is also what Reka is fed. Two\n// things need it. A defined `model-value` is what puts Reka in controlled\n// mode, and controlled is what lets a submit be *refused* — Reka's own commit\n// then only announces the new value rather than adopting it, so the preview\n// keeps showing the old one with nothing to undo. And a host using this\n// without `v-model` still needs the value to move, which is what the\n// optimistic write in `onSubmit` is for.\nconst value = ref(props.modelValue ?? \"\");\nwatch(\n () => props.modelValue,\n (next) => {\n // `undefined` is a host that never controlled the value, not a host\n // clearing it — adopting it would blank the box on any unrelated re-render.\n if (next !== undefined) value.value = next;\n },\n);\n\n// Mirrors Reka's own `isEditing`, off the state event rather than out of the\n// slot, because the class bindings and the activation guard both need it in\n// the script half as well as in the template.\nconst editing = ref(false);\n\nconst previewRef = ref<ComponentPublicInstance | null>(null);\nconst rootRef = ref<ComponentPublicInstance | null>(null);\n\n// Reka's parts are components, so the only handle on their DOM node is `$el`,\n// which Vue types as `any`. Narrowing through `unknown` keeps that `any` from\n// spreading into everything it touches — and answers the SSR case honestly,\n// where there is no element at all.\nfunction elementOf(instance: ComponentPublicInstance | null): HTMLElement | null {\n const el = instance?.$el as unknown;\n return el instanceof HTMLElement ? el : null;\n}\n\n// Set only when focus was actually handed back to the preview, and cleared the\n// moment the reader leaves it. Without it, `activationMode: \"focus\"` would\n// read that hand-off as a fresh arrival and re-open the editor the reader just\n// escaped from — a control that cannot be abandoned, which is precisely the\n// trap Escape exists to avoid.\nlet suppressFocusActivation = false;\n\nfunction activate(edit: () => void): void {\n if (field.disabled || field.readonly || editing.value) return;\n edit();\n}\n\n// Reka's own activation is switched off in the template\n// (`activation-mode=\"none\"`) and rebuilt in these three handlers, rather than\n// passed through. Two things need that. Reka has no click mode at all and no\n// keyboard path on its preview, so two of the three modes this component\n// publishes would be unreachable without a pointer. And its focus mode cannot\n// tell a reader arriving on the control from the focus this component hands\n// back after an Escape — which would re-open the editor that Escape just\n// abandoned, forever.\n//\n// A `<button>` turns Enter and Space into a click carrying `detail === 0`,\n// which is what lets one handler serve the keyboard in every activation mode:\n// `dblclick` cannot be typed, and `focus` must not be the only way in for a\n// reader who arrived on the control without meaning to edit yet. `detail` is\n// the same signal Pagination reads to tell a synthesised click from a pointer\n// one.\nfunction onPreviewClick(event: MouseEvent, edit: () => void): void {\n if (props.activationMode === \"dblclick\" && event.detail !== 0) return;\n activate(edit);\n}\n\nfunction onPreviewDoubleClick(edit: () => void): void {\n if (props.activationMode !== \"dblclick\") return;\n activate(edit);\n}\n\nfunction onPreviewFocus(edit: () => void): void {\n if (props.activationMode !== \"focus\" || suppressFocusActivation) return;\n activate(edit);\n}\n\nfunction onPreviewBlur(): void {\n suppressFocusActivation = false;\n}\n\n// The editor is hidden the instant an edit ends, and a browser drops focus to\n// `<body>` when the focused node goes away — so a reader who pressed Escape or\n// Enter would be left with no position in the document at all.\n//\n// Only focus that was actually lost is rescued. A submit caused by clicking\n// somewhere else has already put the reader where they meant to be, and\n// stealing focus back from them would be the worse bug; the same reasoning,\n// and the same `<body>` check, as Pagination's edge-control hand-off. jsdom\n// leaves focus on the hidden node rather than dropping it, and a click on the\n// commit button leaves it on a button that is about to be hidden too, so\n// anything still inside this control counts as lost.\nfunction restoreFocus(): void {\n void nextTick(() => {\n const preview = elementOf(previewRef.value);\n const root = elementOf(rootRef.value);\n if (preview === null) return;\n\n const active = document.activeElement;\n const lost = active === null || active === document.body || (root?.contains(active) ?? false);\n if (!lost) return;\n\n suppressFocusActivation = true;\n preview.focus();\n });\n}\n\nfunction onState(state: \"edit\" | \"submit\" | \"cancel\"): void {\n editing.value = state === \"edit\";\n if (state === \"edit\") return;\n if (state === \"cancel\") emit(\"cancel\");\n restoreFocus();\n}\n\n// The refusal, held for one announcement rather than derived, so the live\n// region says something only when a submit was actually turned away — and is\n// cleared when the next edit opens, so a second identical refusal is still a\n// change to the region and still gets announced.\nconst restored = ref(\"\");\nwatch(editing, (isEditing) => {\n if (isEditing) restored.value = \"\";\n});\n\n// Reka's `submit` is an announcement rather than a request — in controlled\n// mode it has already told us what it would like the value to be and left the\n// deciding here, which is what makes the empty case answerable at all.\nfunction onSubmit(submitted: string | null | undefined): void {\n const next = submitted ?? \"\";\n\n // An empty submit is the one genuinely ambiguous outcome: a reader who\n // cleared the box and pressed Enter may have meant to blank the value, and\n // under `submitMode: \"blur\"` may have meant nothing at all. Loom restores\n // rather than clears, and `allowEmpty` is how a field that can legitimately\n // be emptied says so. `restored` announces it, because a refusal that only\n // shows up as text snapping back is a refusal a screen reader never hears.\n if (next === \"\" && !props.allowEmpty) {\n restored.value = text.value.restored({ value: value.value });\n emit(\"cancel\");\n return;\n }\n\n // Optimistic only while uncontrolled. With a `modelValue` prop the host owns\n // the value, and echoing it here would show a value they may be about to\n // reject — the prop watcher above is what applies the one they accept.\n if (props.modelValue === undefined) value.value = next;\n emit(\"update:modelValue\", next);\n emit(\"submit\", next);\n}\n\n// A read-only preview is not a control, so it is not rendered as one: a\n// `<button>` that refuses to act is worse than plain text. It keeps a\n// `tabindex` of its own instead — a read-only value is one a reader may reach\n// and copy, the same contract TextField's read-only input keeps — while the\n// button state drops Reka's hardcoded `tabindex=\"0\"` entirely, because a\n// `<button>` is focusable without it and a *disabled* one carrying it is\n// focusable when it should not be.\nconst previewAs = computed(() => (field.readonly ? \"span\" : \"button\"));\n\nconst rootProps = computed(() => optional({ name: field.name, maxLength: props.maxLength }));\n\n// `name` is dropped from the bag before it reaches the editor. Reka already\n// renders a hidden input under that name for any Editable inside a `<form>`,\n// and an editor carrying it as well would post the field twice — once with the\n// committed value and once with whatever the box held. Removed from a copy\n// rather than listed positively, so a key added to the resolved bag later\n// reaches this input without anyone remembering to come back here.\nconst editorAttrs = computed(() => {\n const aria: Record<string, unknown> = { ...field.attrs };\n delete aria.name;\n return aria;\n});\n\n// `aria-label` outranks a `<label for>` in the accessible-name order, so a\n// generic fallback would silently replace the name a Field row already gives\n// the editor. It is supplied only where nothing else names it at all — which\n// is also the state Reka would otherwise fill with \"editable input\".\nconst editorLabel = computed<string | undefined>(() => {\n if (props.ariaLabel !== undefined) return props.ariaLabel;\n if (field.id !== undefined) return undefined;\n if (attrs[\"aria-label\"] !== undefined || attrs[\"aria-labelledby\"] !== undefined) return undefined;\n return text.value.input;\n});\n\nconst areaClass = computed(() =>\n cn(\n // One box, two children. The border is present in both states and only\n // changes colour, the padding never changes, and the floor height keeps an\n // empty value from collapsing the row it sits in — between them, nothing\n // below this control moves when it switches.\n \"flex min-h-9 min-w-0 items-center rounded-md border border-transparent px-2 py-1\",\n // A control that sizes to its own text cannot also fill its parent: under\n // `autoResize` Reka makes this box an `inline-grid` measured by the two\n // states stacked inside it, and a width of 100% would measure the row\n // instead.\n props.autoResize ? \"w-auto\" : \"w-full\",\n \"text-inherit transition-[color,background-color,border-color,box-shadow] duration-fast ease-out\",\n // Rim-lit at rest, the weave blooms on focus (Signature law), and it blooms\n // for the preview as much as for the editor: at rest the preview is the\n // focusable node, and a control a reader can tab to has to show it.\n \"focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring\",\n !field.invalid && \"focus-within:shadow-halo\",\n editing.value && \"border-input bg-background\",\n // The affordance for a pointer, since the resting state is deliberately\n // just text: the box lights under the cursor and the caret says the text\n // can be typed into. Never the only signal — the preview announces itself,\n // and carries a glyph.\n !editing.value && !field.disabled && !field.readonly && \"cursor-text hover:bg-subtle\",\n // Lifted rather than dimmed, exactly as a read-only text field is: the\n // value is the whole reason the control is on the page, so it stays at\n // full contrast — 13.45:1 over this fill — whether or not it can be\n // changed. The rim comes up with it, from the resting `transparent` to\n // `input`: at rest this control is deliberately just text, so without a\n // border there is nothing but hue to say the value is on show, and the box\n // was already reserving the width for one.\n field.readonly && \"border-input bg-subtle\",\n // Drained, not faded, and a step further down all three channels: the fill\n // to `muted`, the text to `muted-foreground` (4.67:1 over it) and the rim\n // to the lighter `border`. Half-opacity text on this box measures under\n // 4.5:1, and a value nobody can read is worse than one nobody can edit.\n //\n // Read-only and disabled used to share `bg-muted` and part on the text\n // colour alone — a distinction made in hue and nothing else, which is the\n // one a reader with a colour deficiency does not receive.\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 control disables the preview `<button>`\n // and the `<input>` behind it natively — both are on the list a fieldset\n // reaches — and never touches `field.disabled`, so the rule above cannot\n // fire and the value rendered byte-identical to an editable one.\n //\n // `in-[fieldset:disabled]:` reads the attribute that did the disabling, so\n // the fill and the native inertness cannot disagree. See TextField.vue for\n // why it is preferred to a `has-[:disabled]:` rule reading this box's own\n // 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 rule below is ordered: Tailwind emits the\n // ancestor half of `in-*` inside `:where()`, so this carries no more\n // specificity than `border-destructive` and would win on emission order\n // alone.\n !field.invalid && \"in-[fieldset:disabled]:border-border\",\n // Last of the rules naming a border colour: `cn()` resolves one by\n // whichever class it saw last, so a control both in error and unavailable\n // would lose its destructive rim if this sat above them.\n field.invalid && \"border-destructive focus-within:outline-destructive\",\n ),\n);\n\n// The submit/cancel triggers are glyph-only, so the drained treatment they\n// take is the transparent control's: the neutral well under a glyph that is\n// already `text-muted-foreground`. `opacity-50` used to fade that glyph below\n// contrast — the failure Button records for its own dim — and the native\n// `disabled` attribute these Reka triggers carry already tells assistive tech.\nconst triggerClass = cn(\n buttonVariants({ variant: \"ghost\", size: \"icon-sm\" }),\n \"disabled:cursor-not-allowed disabled:bg-muted disabled:shadow-none\",\n);\n</script>\n\n<template>\n <EditableRoot\n ref=\"rootRef\"\n v-slot=\"{ edit }\"\n v-bind=\"rootProps\"\n :model-value=\"value\"\n :placeholder=\"placeholder ?? ''\"\n activation-mode=\"none\"\n :disabled=\"field.disabled\"\n :readonly=\"field.readonly\"\n :required=\"field.required\"\n :submit-mode=\"submitMode\"\n :auto-resize=\"autoResize\"\n :data-editing=\"editing || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :data-readonly=\"field.readonly || undefined\"\n :data-disabled=\"field.disabled || undefined\"\n :class=\"\n cn(\n 'inline-flex items-center gap-1',\n autoResize ? 'w-auto align-baseline' : 'w-full',\n attrs.class as string,\n )\n \"\n @update:state=\"onState\"\n @submit=\"onSubmit\"\n >\n <EditableArea :class=\"areaClass\">\n <!-- The preview is the control, and Reka's `EditableEditTrigger` is\n deliberately not rendered beside it: a second button doing the same\n job costs a second Tab stop on one value, and its click handler\n fires in every activation mode, which would make `dblclick` and\n `focus` lies. A real `<button>` rather than a `role`, so Enter and\n Space are the browser's job and the affordance survives\n forced-colors mode. -->\n <EditablePreview\n ref=\"previewRef\"\n :as=\"previewAs\"\n :type=\"field.readonly ? undefined : 'button'\"\n :tabindex=\"field.readonly ? 0 : undefined\"\n :disabled=\"!field.readonly && field.disabled ? true : undefined\"\n :aria-describedby=\"field.attrs['aria-describedby']\"\n :aria-invalid=\"field.attrs['aria-invalid']\"\n class=\"flex min-w-0 flex-1 items-center gap-1.5 text-start outline-none\"\n @click=\"(event: MouseEvent) => onPreviewClick(event, edit)\"\n @dblclick=\"() => onPreviewDoubleClick(edit)\"\n @focus=\"() => onPreviewFocus(edit)\"\n @blur=\"onPreviewBlur\"\n >\n <!-- Single-line and truncated, because the editor it swaps with is a\n single-line input: a preview that wrapped would be a taller box\n than the thing replacing it. -->\n <span :class=\"cn('truncate', !value && 'text-muted-foreground')\">\n {{ value || placeholder }}\n </span>\n <template v-if=\"!field.readonly\">\n <!-- The affordance for a sighted reader, and the counterpart to the\n span below it: the resting state is text, so something has to\n say it is more than text. Hidden from assistive tech, which is\n told the same thing in words. -->\n <Pencil class=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <!-- The whole accessibility problem of edit-in-place, in one span.\n The value reads first so it stays the start of the accessible\n name (WCAG 2.5.3, and what a voice-control reader says out\n loud); the verb follows, so the text announces as something\n that can be acted on rather than as prose. -->\n <span class=\"sr-only\">{{ text.edit }}</span>\n </template>\n </EditablePreview>\n\n <EditableInput\n v-bind=\"{ ...inputAttrs, ...editorAttrs }\"\n :aria-label=\"editorLabel\"\n class=\"min-w-0 flex-1 bg-transparent text-inherit outline-none placeholder:text-muted-foreground\"\n />\n </EditableArea>\n\n <!-- Both triggers hide themselves while the preview is showing, so there\n is nothing to guard here. They exist for the reader who has no way to\n know that Enter commits and Escape abandons — an invisible keyboard\n contract is not an affordance. -->\n <EditableSubmitTrigger :aria-label=\"text.submit\" :class=\"triggerClass\">\n <Check class=\"h-4 w-4\" aria-hidden=\"true\" />\n </EditableSubmitTrigger>\n <EditableCancelTrigger :aria-label=\"text.cancel\" :class=\"triggerClass\">\n <X class=\"h-4 w-4\" aria-hidden=\"true\" />\n </EditableCancelTrigger>\n\n <!-- A refused empty submit changes the screen without moving focus or\n opening anything, which a screen reader would otherwise never\n announce. Empty until there is something to say, so it never repeats\n itself on an unrelated re-render. -->\n <span role=\"status\" class=\"sr-only\">{{ restored }}</span>\n </EditableRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,IAAa,kBAAkC;CAC7C,MAAM;CACN,OAAO;CACP,QAAQ;CACR,QAAQ;CACR,WAAW,EAAE,YAAY,0BAA0B,MAAM;AAC3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsGA,MAAM,QAAQ;EAkEd,MAAM,OAAO;EAgBb,MAAM,EAAE,OAAO,MAAM,eAAe,cAAc;EAMlD,MAAM,QAAQ,uBAAuB;GACnC,IAAI,MAAM;GACV,aAAa,MAAM;GACnB,MAAM,MAAM;GACZ,UAAU,MAAM;GAChB,UAAU,MAAM;GAChB,SAAS,MAAM;GACf,UAAU,MAAM;EAClB,EAAE;EAKF,MAAM,OAAO,UAAU,YAAY,uBAAuB,MAAM,MAAM;EAStE,MAAM,QAAQ,IAAI,MAAM,cAAc,EAAE;EACxC,YACQ,MAAM,aACX,SAAS;GAGR,IAAI,SAAS,KAAA,GAAW,MAAM,QAAQ;EACxC,CACF;EAKA,MAAM,UAAU,IAAI,KAAK;EAEzB,MAAM,aAAa,IAAoC,IAAI;EAC3D,MAAM,UAAU,IAAoC,IAAI;EAMxD,SAAS,UAAU,UAA8D;GAC/E,MAAM,KAAK,UAAU;GACrB,OAAO,cAAc,cAAc,KAAK;EAC1C;EAOA,IAAI,0BAA0B;EAE9B,SAAS,SAAS,MAAwB;GACxC,IAAI,MAAM,YAAY,MAAM,YAAY,QAAQ,OAAO;GACvD,KAAK;EACP;EAiBA,SAAS,eAAe,OAAmB,MAAwB;GACjE,IAAI,MAAM,mBAAmB,cAAc,MAAM,WAAW,GAAG;GAC/D,SAAS,IAAI;EACf;EAEA,SAAS,qBAAqB,MAAwB;GACpD,IAAI,MAAM,mBAAmB,YAAY;GACzC,SAAS,IAAI;EACf;EAEA,SAAS,eAAe,MAAwB;GAC9C,IAAI,MAAM,mBAAmB,WAAW,yBAAyB;GACjE,SAAS,IAAI;EACf;EAEA,SAAS,gBAAsB;GAC7B,0BAA0B;EAC5B;EAaA,SAAS,eAAqB;GAC5B,eAAoB;IAClB,MAAM,UAAU,UAAU,WAAW,KAAK;IAC1C,MAAM,OAAO,UAAU,QAAQ,KAAK;IACpC,IAAI,YAAY,MAAM;IAEtB,MAAM,SAAS,SAAS;IAExB,IAAI,EADS,WAAW,QAAQ,WAAW,SAAS,SAAS,MAAM,SAAS,MAAM,KAAK,SAC5E;IAEX,0BAA0B;IAC1B,QAAQ,MAAM;GAChB,CAAC;EACH;EAEA,SAAS,QAAQ,OAA2C;GAC1D,QAAQ,QAAQ,UAAU;GAC1B,IAAI,UAAU,QAAQ;GACtB,IAAI,UAAU,UAAU,KAAK,QAAQ;GACrC,aAAa;EACf;EAMA,MAAM,WAAW,IAAI,EAAE;EACvB,MAAM,UAAU,cAAc;GAC5B,IAAI,WAAW,SAAS,QAAQ;EAClC,CAAC;EAKD,SAAS,SAAS,WAA4C;GAC5D,MAAM,OAAO,aAAa;GAQ1B,IAAI,SAAS,MAAM,CAAC,MAAM,YAAY;IACpC,SAAS,QAAQ,KAAK,MAAM,SAAS,EAAE,OAAO,MAAM,MAAM,CAAC;IAC3D,KAAK,QAAQ;IACb;GACF;GAKA,IAAI,MAAM,eAAe,KAAA,GAAW,MAAM,QAAQ;GAClD,KAAK,qBAAqB,IAAI;GAC9B,KAAK,UAAU,IAAI;EACrB;EASA,MAAM,YAAY,eAAgB,MAAM,WAAW,SAAS,QAAS;EAErE,MAAM,YAAY,eAAe,SAAS;GAAE,MAAM,MAAM;GAAM,WAAW,MAAM;EAAU,CAAC,CAAC;EAQ3F,MAAM,cAAc,eAAe;GACjC,MAAM,OAAgC,EAAE,GAAG,MAAM,MAAM;GACvD,OAAO,KAAK;GACZ,OAAO;EACT,CAAC;EAMD,MAAM,cAAc,eAAmC;GACrD,IAAI,MAAM,cAAc,KAAA,GAAW,OAAO,MAAM;GAChD,IAAI,MAAM,OAAO,KAAA,GAAW,OAAO,KAAA;GACnC,IAAI,MAAM,kBAAkB,KAAA,KAAa,MAAM,uBAAuB,KAAA,GAAW,OAAO,KAAA;GACxF,OAAO,KAAK,MAAM;EACpB,CAAC;EAED,MAAM,YAAY,eAChB,GAKE,oFAKA,MAAM,aAAa,WAAW,UAC9B,mGAIA,kFACA,CAAC,MAAM,WAAW,4BAClB,QAAQ,SAAS,8BAKjB,CAAC,QAAQ,SAAS,CAAC,MAAM,YAAY,CAAC,MAAM,YAAY,+BAQxD,MAAM,YAAY,0BASlB,MAAM,YAAY,mEAWlB,0HAKA,CAAC,MAAM,WAAW,wCAIlB,MAAM,WAAW,qDACnB,CACF;EAOA,MAAM,eAAe,GACnB,eAAe;GAAE,SAAS;GAAS,MAAM;EAAU,CAAC,GACpD,oEACF;;GAIE,OAAA,UAAA,GAAA,YA4Fe,MAAA,YAAA,GA5Ff,WA4Fe;IA3FT,SAAA;IAAJ,KAAI;GAEI,GAAA,UAAA,OAAS;IAChB,eAAa,MAAA;IACb,aAAa,QAAA,eAAW;IACzB,mBAAgB;IACf,UAAU,MAAA,KAAA,CAAK,CAAC;IAChB,UAAU,MAAA,KAAA,CAAK,CAAC;IAChB,UAAU,MAAA,KAAA,CAAK,CAAC;IAChB,eAAa,QAAA;IACb,eAAa,QAAA;IACb,gBAAc,QAAA,SAAW,KAAA;IACzB,gBAAc,MAAA,KAAA,CAAK,CAAC,WAAW,KAAA;IAC/B,iBAAe,MAAA,KAAA,CAAK,CAAC,YAAY,KAAA;IACjC,iBAAe,MAAA,KAAA,CAAK,CAAC,YAAY,KAAA;IACjC,OAAc,MAAA,EAAA,CAAE,CAAA,kCAAoD,QAAA,aAAU,0BAAA,UAA+C,MAAA,KAAA,CAAK,CAAC,KAAA;IAOnI,kBAAc;IACN;;IAET,SAAA,SAgDe,EAxEL,WAAI;KAwBd,YAgDe,MAAA,YAAA,GAAA,EAhDA,OAAK,eAAE,UAAA,KAAS,EAAA,GAAA;MAQ7B,SAAA,cAiCkB,CAjClB,YAiCkB,MAAA,eAAA,GAAA;OAhCZ,SAAA;OAAJ,KAAI;OACH,IAAI,UAAA;OACJ,MAAM,MAAA,KAAA,CAAK,CAAC,WAAW,KAAA,IAAS;OAChC,UAAU,MAAA,KAAA,CAAK,CAAC,WAAQ,IAAO,KAAA;OAC/B,UAAQ,CAAG,MAAA,KAAA,CAAK,CAAC,YAAY,MAAA,KAAA,CAAK,CAAC,WAAQ,OAAU,KAAA;OACrD,oBAAkB,MAAA,KAAA,CAAK,CAAC,MAAK;OAC7B,gBAAc,MAAA,KAAA,CAAK,CAAC,MAAK;OAC1B,OAAM;OACL,UAAQ,UAAsB,eAAe,OAAO,IAAI;OACxD,kBAAgB,qBAAqB,IAAI;OACzC,eAAa,eAAe,IAAI;OAChC,QAAM;;OAKP,SAAA,cAEO,CAFP,mBAEO,QAAA,EAFA,OAAK,eAAE,MAAA,EAAA,CAAE,CAAA,YAAA,CAAc,MAAA,SAAK,uBAAA,CAAA,EAC9B,GAAA,gBAAA,MAAA,SAAS,QAAA,WAAW,GAAA,CAAA,GAER,CAAA,MAAA,KAAA,CAAK,CAAC,YAAvB,UAAA,GAAA,mBAYW,UAAA,EAAA,KAAA,EAAA,GAAA,CAPT,YAAgF,MAAA,MAAA,GAAA;QAAxE,OAAM;QAA6C,eAAY;OAMvE,CAAA,GAAA,mBAA4C,QAA5C,YAA4C,gBAAnB,MAAA,IAAA,CAAI,CAAC,IAAI,GAAA,CAAA,CAAA,GAAA,EAAA,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA;;;;;;;;;;;;MAItC,CAAA,GAAA,YAIE,MAAA,aAAA,GAJF,WAIE;OAAA,GAHa,MAAA,UAAA;OAAU,GAAK,YAAA;MAAW,GAAA;OACtC,cAAY,YAAA;OACb,OAAM;;;;KAQV,YAEwB,MAAA,qBAAA,GAAA;MAFA,cAAY,MAAA,IAAA,CAAI,CAAC;MAAS,OAAK,eAAE,MAAA,YAAA,CAAY;;MACnE,SAAA,cAA4C,CAA5C,YAA4C,MAAA,KAAA,GAAA;OAArC,OAAM;OAAU,eAAY;;;;KAErC,YAEwB,MAAA,qBAAA,GAAA;MAFA,cAAY,MAAA,IAAA,CAAI,CAAC;MAAS,OAAK,eAAE,MAAA,YAAA,CAAY;;MACnE,SAAA,cAAwC,CAAxC,YAAwC,MAAA,CAAA,GAAA;OAArC,OAAM;OAAU,eAAY;;;;KAOjC,mBAAyD,QAAzD,YAAyD,gBAAlB,SAAA,KAAQ,GAAA,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Field.js","names":[],"sources":["../../../../../packages/primitives/field/src/Field.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/* eslint vuejs-accessibility/label-has-for: [\"error\", { \"required\": \"id\" }] */\n/*\n * The workspace default for this rule requires BOTH a `for`/id pairing AND\n * the control physically nested inside the `<label>` (`required: {every:\n * [\"nesting\",\"id\"]}`). Field labels a control passed through the default\n * slot — never nested inside the `<label>` — so \"nesting\" can never be\n * satisfied by any slot-based composition, regardless of how the label is\n * written. The `for`/id pairing below is itself a fully valid, standard\n * accessible-name association (WCAG 1.3.1 / 4.1.2); this override scopes the\n * rule to that single valid strategy for this file only.\n */\nimport { computed, useId, useSlots } from \"vue\";\nimport InlineError from \"@ecoma-io/loom-inline-error\";\nimport { provideFieldContext, useOuterFieldContext } from \"@ecoma-io/loom-labels\";\n\n/**\n * Field — the form-row wrapper: label + control + one hint-or-error line, so\n * a consumer stops hand-assembling that layout at every call site. Pure\n * composition, not a Reka component — the default slot is the control\n * (TextField, Textarea, a select, …). Setting `error` swaps InlineError in\n * for `hint`, because a row shows one message at a time, never both stacked.\n *\n * **A Loom control in the slot wires itself.** Field publishes the row's id,\n * the id of whichever message is showing, and `required` / `invalid` /\n * `disabled` / `readonly` / `name`; every Loom form control picks those up\n * through `useFieldControl()`. So the three attributes this component used to\n * ask a caller to copy by hand — `id`, `aria-describedby`, `invalid` — are now\n * the default, and forgetting one is no longer a silent defect:\n *\n * ```vue\n * <Field label=\"Email\" error=\"Invalid address\" required>\n * <TextField />\n * </Field>\n * ```\n *\n * A prop set on the control always wins, in both directions: `undefined` is\n * the only value that yields, `false` is a decision. One control inside a row\n * that is showing an error can still declare itself individually fine.\n *\n * **`for` is not a legacy path.** `provide`/`inject` only reaches a component\n * that injects, so a bare `<input>`, a product's own control or a third-party\n * widget in the slot cannot be wired this way — and that is the case `for` has\n * always answered. Pass it and the label points at your id, the message line\n * publishes `${for}-description` for your own `aria-describedby`, and a Loom\n * control adopts that id rather than a generated one, so an existing call site\n * keeps every id it published.\n */\nconst props = withDefaults(\n defineProps<{\n /** The visible label text. Renders as a real `<label>` once there is a control for it to name. */\n label?: string;\n /** Supporting text shown below the control. Hidden while `error` is set. */\n hint?: string;\n /** The error message. Renders through InlineError, replaces `hint`, and marks a Loom control inside invalid. */\n error?: string;\n /** Marks the row mandatory: a destructive asterisk on the label, and `aria-required` on a Loom control inside. */\n required?: boolean;\n /** Disables a Loom control inside. Leave unset to let the control decide for itself. */\n disabled?: boolean | undefined;\n /** Renders a Loom control inside read-only: still focusable, still submitted, not editable. */\n readonly?: boolean | undefined;\n /** The name a Loom control inside submits under, for a native form post or `FormData`. */\n name?: string;\n /** The id of the control in the default slot. Omit it and Field generates one for a Loom control. */\n for?: string;\n }>(),\n {\n // `disabled` and `readonly` carry an explicit `undefined` because absent\n // has to stay tellable from `false` all the way down: a Field saying\n // nothing must not overrule a control that disabled itself, and Vue casts\n // an absent Boolean prop with no declared default to `false`. `required`\n // stays a plain boolean — Field is the only thing that claims a row is\n // mandatory, so there is no lower opinion for a `false` to beat.\n required: false,\n disabled: undefined,\n readonly: undefined,\n },\n);\n\n// Called unconditionally, even when `for` makes it unused: `useId()` draws\n// from a per-app counter walked in setup order, and a conditional call makes\n// that sequence depend on props — every id after it shifts, and the server's\n// walk stops matching the client's.\nconst generatedId = useId();\n\n// Whether the call site wrote children at all is a fact about the template,\n// not about state, so it is read once rather than computed — `slots` is not a\n// reactive source and a `computed` over it would cache and go stale. It also\n// has to be answerable during *this* component's render: the server renders a\n// component's own output before any of its slot children, so anything Field\n// learned from the mounted controls would arrive after the label and the hint\n// were already written on the server and before them on the client, which is a\n// hydration mismatch by construction.\nconst hasControl = useSlots().default !== undefined;\n\n// The row's control id is what you passed, or a generated one when there is a\n// control in the slot to give it to. Nothing in the slot means nothing to name\n// and nothing to describe — a `<label for>` pointing at no control names\n// nobody, and an id nothing references is a landmark for no one.\nconst controlId = computed(() => props.for ?? (hasControl ? generatedId : undefined));\n\n// The label's own id, for group controls that name themselves with\n// `aria-labelledby` rather than by `label for`. Follows the same `-label`\n// convention as the description line's `-description`, and it exists for the\n// same reason: a group element inside the slot cannot be pointed at by `<label\n// for>` (that element is not a labelable element), so it needs a second way to\n// learn the label's id.\nconst labelId = computed(() => (controlId.value ? `${controlId.value}-label` : undefined));\n\n// The hint and the error are mutually exclusive, so one id covers whichever is\n// showing.\nconst descriptionId = computed(() =>\n controlId.value ? `${controlId.value}-description` : undefined,\n);\n\n// A Fieldset above answers exactly one key this Field also answers, and its\n// `readonly` is a claim about the whole group that a row does not get to\n// forget. Everything else a Fieldset knows either stops there deliberately\n// (`required`, `invalid`, the group's own description) or travels natively\n// (`disabled`, through the real `<fieldset>`) — see Fieldset.vue. Merging it\n// here rather than inside the context keeps the one overlapping key visible.\nconst group = useOuterFieldContext();\n\nprovideFieldContext({\n controlId: () => controlId.value,\n // Group controls name themselves with `aria-labelledby`, not `label for`, so\n // they need the label's own id. Only when the label is actually rendered: an\n // IDREF that resolves to nothing is worse than no attribute at all.\n labelledBy: () => (props.label ? labelId.value : undefined),\n // Only while a message is actually rendered. An IDREF resolving to nothing\n // is a worse answer than no attribute — the same reasoning Fieldset already\n // carries for its own `aria-describedby`.\n describedBy: () => ((props.error ?? props.hint) ? descriptionId.value : undefined),\n name: () => props.name,\n required: () => props.required || undefined,\n // The row's message and the control's `aria-invalid` are two halves of one\n // state; two independent switches for it is how they come to disagree.\n invalid: () => (props.error ? true : undefined),\n disabled: () => props.disabled,\n readonly: () => props.readonly ?? group?.readonly.value,\n});\n</script>\n\n<template>\n <div class=\"flex flex-col gap-1.5\">\n <label\n v-if=\"label && controlId\"\n :id=\"labelId\"\n :for=\"controlId\"\n class=\"text-sm font-medium text-foreground\"\n >\n {{ label }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </label>\n <span v-else-if=\"label\" class=\"text-sm font-medium text-foreground\">\n {{ label }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </span>\n <slot />\n <p v-if=\"hint && !error\" :id=\"descriptionId\" class=\"text-xs text-muted-foreground\">\n {{ hint }}\n </p>\n <InlineError v-if=\"error\" :id=\"descriptionId\" :message=\"error\" />\n </div>\n</template>\n"],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Field.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../../packages/primitives/field/src/Field.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/* eslint vuejs-accessibility/label-has-for: [\"error\", { \"required\": \"id\" }] */\n/*\n * The workspace default for this rule requires BOTH a `for`/id pairing AND\n * the control physically nested inside the `<label>` (`required: {every:\n * [\"nesting\",\"id\"]}`). Field labels a control passed through the default\n * slot — never nested inside the `<label>` — so \"nesting\" can never be\n * satisfied by any slot-based composition, regardless of how the label is\n * written. The `for`/id pairing below is itself a fully valid, standard\n * accessible-name association (WCAG 1.3.1 / 4.1.2); this override scopes the\n * rule to that single valid strategy for this file only.\n */\nimport { computed, useId, useSlots } from \"vue\";\nimport InlineError from \"@ecoma-io/loom-inline-error\";\nimport { provideFieldContext, useOuterFieldContext } from \"@ecoma-io/loom-labels\";\n\n/**\n * Field — the form-row wrapper: label + control + one hint-or-error line, so\n * a consumer stops hand-assembling that layout at every call site. Pure\n * composition, not a Reka component — the default slot is the control\n * (TextField, Textarea, a select, …). Setting `error` swaps InlineError in\n * for `hint`, because a row shows one message at a time, never both stacked.\n *\n * **A Loom control in the slot wires itself.** Field publishes the row's id,\n * the id of whichever message is showing, and `required` / `invalid` /\n * `disabled` / `readonly` / `name`; every Loom form control picks those up\n * through `useFieldControl()`. So the three attributes this component used to\n * ask a caller to copy by hand — `id`, `aria-describedby`, `invalid` — are now\n * the default, and forgetting one is no longer a silent defect:\n *\n * ```vue\n * <Field label=\"Email\" error=\"Invalid address\" required>\n * <TextField />\n * </Field>\n * ```\n *\n * A prop set on the control always wins, in both directions: `undefined` is\n * the only value that yields, `false` is a decision. One control inside a row\n * that is showing an error can still declare itself individually fine.\n *\n * **`for` is not a legacy path.** `provide`/`inject` only reaches a component\n * that injects, so a bare `<input>`, a product's own control or a third-party\n * widget in the slot cannot be wired this way — and that is the case `for` has\n * always answered. Pass it and the label points at your id, the message line\n * publishes `${for}-description` for your own `aria-describedby`, and a Loom\n * control adopts that id rather than a generated one, so an existing call site\n * keeps every id it published.\n */\nconst props = withDefaults(\n defineProps<{\n /** The visible label text. Renders as a real `<label>` once there is a control for it to name. */\n label?: string;\n /** Supporting text shown below the control. Hidden while `error` is set. */\n hint?: string;\n /** The error message. Renders through InlineError, replaces `hint`, and marks a Loom control inside invalid. */\n error?: string;\n /** Marks the row mandatory: a destructive asterisk on the label, and `aria-required` on a Loom control inside. */\n required?: boolean;\n /** Disables a Loom control inside. Leave unset to let the control decide for itself. */\n disabled?: boolean | undefined;\n /** Renders a Loom control inside read-only: still focusable, still submitted, not editable. */\n readonly?: boolean | undefined;\n /** The name a Loom control inside submits under, for a native form post or `FormData`. */\n name?: string;\n /** The id of the control in the default slot. Omit it and Field generates one for a Loom control. */\n for?: string;\n }>(),\n {\n // `disabled` and `readonly` carry an explicit `undefined` because absent\n // has to stay tellable from `false` all the way down: a Field saying\n // nothing must not overrule a control that disabled itself, and Vue casts\n // an absent Boolean prop with no declared default to `false`. `required`\n // stays a plain boolean — Field is the only thing that claims a row is\n // mandatory, so there is no lower opinion for a `false` to beat.\n required: false,\n disabled: undefined,\n readonly: undefined,\n },\n);\n\n// Called unconditionally, even when `for` makes it unused: `useId()` draws\n// from a per-app counter walked in setup order, and a conditional call makes\n// that sequence depend on props — every id after it shifts, and the server's\n// walk stops matching the client's.\nconst generatedId = useId();\n\n// Whether the call site wrote children at all is a fact about the template,\n// not about state, so it is read once rather than computed — `slots` is not a\n// reactive source and a `computed` over it would cache and go stale. It also\n// has to be answerable during *this* component's render: the server renders a\n// component's own output before any of its slot children, so anything Field\n// learned from the mounted controls would arrive after the label and the hint\n// were already written on the server and before them on the client, which is a\n// hydration mismatch by construction.\nconst hasControl = useSlots().default !== undefined;\n\n// The row's control id is what you passed, or a generated one when there is a\n// control in the slot to give it to. Nothing in the slot means nothing to name\n// and nothing to describe — a `<label for>` pointing at no control names\n// nobody, and an id nothing references is a landmark for no one.\nconst controlId = computed(() => props.for ?? (hasControl ? generatedId : undefined));\n\n// The label's own id, for group controls that name themselves with\n// `aria-labelledby` rather than by `label for`. Follows the same `-label`\n// convention as the description line's `-description`, and it exists for the\n// same reason: a group element inside the slot cannot be pointed at by `<label\n// for>` (that element is not a labelable element), so it needs a second way to\n// learn the label's id.\nconst labelId = computed(() => (controlId.value ? `${controlId.value}-label` : undefined));\n\n// The hint and the error are mutually exclusive, so one id covers whichever is\n// showing.\nconst descriptionId = computed(() =>\n controlId.value ? `${controlId.value}-description` : undefined,\n);\n\n// A Fieldset above answers exactly one key this Field also answers, and its\n// `readonly` is a claim about the whole group that a row does not get to\n// forget. Everything else a Fieldset knows either stops there deliberately\n// (`required`, `invalid`, the group's own description) or travels natively\n// (`disabled`, through the real `<fieldset>`) — see Fieldset.vue. Merging it\n// here rather than inside the context keeps the one overlapping key visible.\nconst group = useOuterFieldContext();\n\nprovideFieldContext({\n controlId: () => controlId.value,\n // Group controls name themselves with `aria-labelledby`, not `label for`, so\n // they need the label's own id. Only when the label is actually rendered: an\n // IDREF that resolves to nothing is worse than no attribute at all.\n labelledBy: () => (props.label ? labelId.value : undefined),\n // Only while a message is actually rendered. An IDREF resolving to nothing\n // is a worse answer than no attribute — the same reasoning Fieldset already\n // carries for its own `aria-describedby`.\n describedBy: () => ((props.error ?? props.hint) ? descriptionId.value : undefined),\n name: () => props.name,\n required: () => props.required || undefined,\n // The row's message and the control's `aria-invalid` are two halves of one\n // state; two independent switches for it is how they come to disagree.\n invalid: () => (props.error ? true : undefined),\n disabled: () => props.disabled,\n readonly: () => props.readonly ?? group?.readonly.value,\n});\n</script>\n\n<template>\n <div class=\"flex flex-col gap-1.5\">\n <label\n v-if=\"label && controlId\"\n :id=\"labelId\"\n :for=\"controlId\"\n class=\"text-sm font-medium text-foreground\"\n >\n {{ label }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </label>\n <span v-else-if=\"label\" class=\"text-sm font-medium text-foreground\">\n {{ label }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </span>\n <slot />\n <p v-if=\"hint && !error\" :id=\"descriptionId\" class=\"text-xs text-muted-foreground\">\n {{ hint }}\n </p>\n <InlineError v-if=\"error\" :id=\"descriptionId\" :message=\"error\" />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgDA,MAAM,QAAQ;EAoCd,MAAM,cAAc,MAAM;EAU1B,MAAM,aAAa,SAAS,CAAC,CAAC,YAAY,KAAA;EAM1C,MAAM,YAAY,eAAe,MAAM,QAAQ,aAAa,cAAc,KAAA,EAAU;EAQpF,MAAM,UAAU,eAAgB,UAAU,QAAQ,GAAG,UAAU,MAAM,UAAU,KAAA,CAAU;EAIzF,MAAM,gBAAgB,eACpB,UAAU,QAAQ,GAAG,UAAU,MAAM,gBAAgB,KAAA,CACvD;EAQA,MAAM,QAAQ,qBAAqB;EAEnC,oBAAoB;GAClB,iBAAiB,UAAU;GAI3B,kBAAmB,MAAM,QAAQ,QAAQ,QAAQ,KAAA;GAIjD,mBAAqB,MAAM,SAAS,MAAM,OAAQ,cAAc,QAAQ,KAAA;GACxE,YAAY,MAAM;GAClB,gBAAgB,MAAM,YAAY,KAAA;GAGlC,eAAgB,MAAM,QAAQ,OAAO,KAAA;GACrC,gBAAgB,MAAM;GACtB,gBAAgB,MAAM,YAAY,OAAO,SAAS;EACpD,CAAC;;GAIC,OAAA,UAAA,GAAA,mBAiBM,OAjBN,YAiBM;IAfI,QAAA,SAAS,UAAA,SADjB,UAAA,GAAA,mBAOQ,SAAA;;KALL,IAAI,QAAA;KACJ,KAAK,UAAA;KACN,OAAM;IAEH,GAAA,CAAA,gBAAA,gBAAA,QAAA,KAAK,IAAG,KAAC,CAAA,GAAY,QAAA,YAAZ,UAAA,GAAA,mBAA4D,QAA5D,YAAoD,GAAC,KAAA,mBAAA,IAAA,IAAA,CAAA,GAAA,GAAA,UAAA,KAElD,QAAA,SAAjB,UAAA,GAAA,mBAEO,QAFP,YAEO,CADF,gBAAA,gBAAA,QAAA,KAAK,IAAG,KAAC,CAAA,GAAY,QAAA,YAAZ,UAAA,GAAA,mBAA4D,QAA5D,YAAoD,GAAC,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;IAEnE,WAAQ,KAAA,QAAA,SAAA;IACC,QAAA,QAAI,CAAK,QAAA,SAAlB,UAAA,GAAA,mBAEI,KAAA;;KAFsB,IAAI,cAAA;KAAe,OAAM;IAC9C,GAAA,gBAAA,QAAA,IAAI,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA;IAEU,QAAA,SAAnB,UAAA,GAAA,YAAiE,MAAA,mBAAA,GAAA;;KAAtC,IAAI,cAAA;KAAgB,SAAS,QAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Fieldset.js","names":[],"sources":["../../../../../packages/primitives/fieldset/src/Fieldset.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport InlineError from \"@ecoma-io/loom-inline-error\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { provideFieldContext } from \"@ecoma-io/loom-labels\";\n\n/**\n * Fieldset — several related controls under one name and one shared\n * hint-or-error line: an address block, a set of notification switches, a\n * date range. Where Field is a single row (label, control, message), Fieldset\n * is the group those rows sit in, and the two nest — a Fieldset of Fields is\n * the shape it was drawn for. A lone control does not need a group; that is a\n * Field.\n *\n * It renders a real `<fieldset>` and `<legend>`, and that choice is most of\n * the component. A `<div role=\"group\" aria-labelledby>` names the group just\n * as well and gives up `<fieldset disabled>`, which disables every form\n * control inside it natively — including controls that arrived through the\n * default slot and that Fieldset holds no reference to. Nothing adds that\n * back from a `div`: a wrapper cannot pass a `disabled` prop to a control it\n * never rendered.\n *\n * The hint-or-error line answers exactly as Field's does, for the reason\n * Field.vue sets out — a wrapper cannot reach into a slotted control to set\n * `aria-describedby`, so it publishes a predictable `${id}-description` and\n * leaves that one attribute to the caller. One half differs: Fieldset owns a\n * real element, so it points the group's own `aria-describedby` at that id\n * itself. Wire a control inside to the same id only when you want the message\n * announced a second time on that control.\n *\n * ```vue\n * <Fieldset legend=\"Shipping address\" id=\"shipping\" hint=\"Where the order goes\" required>\n * <Field label=\"Street\"><TextField /></Field>\n * <Field label=\"City\"><TextField /></Field>\n * </Fieldset>\n * ```\n *\n * **The group hands down exactly one thing: `readonly`.** Everything else it\n * knows either travels natively or is a claim about the group that is not\n * automatically a claim about each control in it, and the reasoning is worth\n * stating because the next person will ask:\n *\n * - `disabled` travels through the real `<fieldset>`, and a second mechanism\n * alongside it would be actively harmful rather than merely redundant. One\n * fact carried two ways lets the two disagree: a control written\n * `:disabled=\"false\"` beats a context by the precedence rule, while the\n * native attribute disables it anyway — leaving a control that renders\n * enabled and silently refuses input. The element also reaches strictly\n * further, which is the argument for rendering a `<fieldset>` at all.\n * - `required` and `invalid` stop here. \"This group is mandatory\" is not\n * \"every control in it is mandatory\" — an address block needs a street and\n * not an apartment number — and a group-level error does not make each\n * control in it individually wrong. `aria-required` or `aria-invalid` on a\n * control that is fine is a false statement to the only audience that hears\n * it.\n * - The description stops here too, because unlike Field this component owns a\n * real element and already points its own `aria-describedby` at the message.\n * - `controlId` would collide with the id on the `<fieldset>` itself, and one\n * shared `name` is right for a set of radios and wrong for everything else.\n *\n * `readonly` is left because nothing else can carry it: there is no native\n * `<fieldset readonly>`, and a group shown in view mode is a real state.\n */\nconst props = withDefaults(\n defineProps<{\n /** The group's name, rendered as a real `<legend>` — the accessible name of the group. */\n legend?: string;\n /** Supporting text shown below the group. Hidden while `error` is set. */\n hint?: string;\n /** The group's error message. Renders through InlineError and replaces `hint`. */\n error?: string;\n /** Marks the group mandatory and appends a destructive asterisk to the legend. */\n required?: boolean;\n /** Disables every control inside, slotted ones included, and dims the group. */\n disabled?: boolean;\n /** Renders every Loom control inside read-only: still focusable, still submitted, not editable. */\n readonly?: boolean | undefined;\n /** Set on the `<fieldset>`, and what the hint/error id is derived from (`${id}-description`). */\n id?: string;\n }>(),\n {\n required: false,\n disabled: false,\n // Explicitly `undefined`, not `false`: a Fieldset that says nothing about\n // `readonly` must not overrule a Field or a control that set it, and Vue\n // casts an absent Boolean prop with no declared default to `false`.\n readonly: undefined,\n },\n);\n\nprovideFieldContext({\n controlId: () => undefined,\n describedBy: () => undefined,\n name: () => undefined,\n required: () => undefined,\n invalid: () => undefined,\n disabled: () => undefined,\n readonly: () => props.readonly,\n});\n\n// The hint and the error are mutually exclusive, so one id covers whichever\n// is showing. Undefined without `id`, exactly as in Field: an id nothing can\n// be pointed at is a landmark for no one. Undefined with no message either —\n// unlike Field, this id is also spent on the group's own `aria-describedby`,\n// and an IDREF resolving to nothing is a worse answer than no attribute.\nconst descriptionId = computed(() =>\n props.id && (props.hint ?? props.error) ? `${props.id}-description` : undefined,\n);\n\n// One rendered node, so this split is only about `class`. Vue's own\n// fallthrough merge concatenates the two lists rather than resolving them, so\n// a caller's `min-w-full` would beat — or lose to — the `min-w-0` below on\n// Tailwind's emission order instead of on being the later declaration. That\n// one utility is load-bearing (see the root class), so the merge has to be\n// Tailwind-aware.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: fieldsetAttrs } = useSplitAttrs();\n</script>\n\n<template>\n <fieldset\n v-bind=\"fieldsetAttrs\"\n :id=\"id\"\n :disabled=\"disabled\"\n :aria-describedby=\"descriptionId\"\n :class=\"\n cn(\n 'flex flex-col gap-4',\n // Not defensive. Every UA stylesheet gives `<fieldset>` a\n // `min-inline-size: min-content` that no `width` can beat, so a group\n // holding a text input refuses to shrink below that input's intrinsic\n // width and blows out the column of any consumer who drops one into a\n // form grid. Overriding the minimum itself is the only fix.\n 'min-w-0',\n // `group`, and no `opacity`. Dimming the group was the worst instance\n // of that mistake in the library, because opacity *composites* and\n // therefore multiplies: this element's 50% ran over a Switch's or a\n // Select's own 50%, so a control inside a disabled group rendered at\n // 25% effective alpha and its label measured 1.65:1 — and the group's\n // own hint, one dim rather than two, still came out at 2.05:1. Neither\n // was reachable by fixing the controls, because neither was the\n // controls' doing.\n //\n // Removing it here is what un-multiplies them: a nested control now\n // computes only its own drained treatment (Select and OtpInput land\n // their labels on 4.67:1 that way), and nothing this element does\n // reduces it further. The group still reads as unavailable — the\n // legend below mutes, and every control in it wears its own disabled\n // state — and the native `disabled` attribute carries the fact to\n // assistive tech, so none of it rests on colour alone.\n //\n // And no fill either, which is the other half of the same answer. Every\n // control in the library drains to `bg-muted` when it is unavailable,\n // so a `bg-muted` on the group would be that exact colour running\n // edge-to-edge behind them: the fills would meet at 1:1 and a row of\n // disabled controls would read as one grey slab with no controls in it.\n // The group is a grouping, not a surface — it has no fill available and\n // no `readonly` appearance either, because a read-only group is a group\n // of read-only controls, each of which now says so on its own.\n 'disabled:cursor-not-allowed',\n 'group',\n attrs.class as string,\n )\n \"\n >\n <!-- Deliberately borderless, like Field: with no border to interrupt, the\n legend's notch rendering never arises and the group is spaced rather\n than boxed. The margin is not a stand-in for the container's `gap`\n either — a rendered legend sits outside the anonymous box that holds\n a fieldset's content, so it is never a flex item and no `gap` reaches\n it. -->\n <!-- The legend is where \"this whole group is unavailable\" is now painted:\n it is the group's accessible name and the only text the group owns\n rather than borrows. `group-disabled:` reads the real `:disabled` on\n the `<fieldset>` above, so there is no second copy of the state to fall\n out of step with the attribute. 14.09:1 available, 5.25:1 not — a drop\n a reader can see, at a colour they can still read. -->\n <legend\n v-if=\"legend\"\n class=\"mb-2 text-sm font-medium text-foreground group-disabled:text-muted-foreground\"\n >\n {{ legend }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </legend>\n <!-- @slot The controls in the group — Fields, most often. -->\n <slot />\n <p v-if=\"hint && !error\" :id=\"descriptionId\" class=\"text-xs text-muted-foreground\">\n {{ hint }}\n </p>\n <InlineError v-if=\"error\" :id=\"descriptionId\" :message=\"error\" />\n </fieldset>\n</template>\n"],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Fieldset.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../../packages/primitives/fieldset/src/Fieldset.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport InlineError from \"@ecoma-io/loom-inline-error\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { provideFieldContext } from \"@ecoma-io/loom-labels\";\n\n/**\n * Fieldset — several related controls under one name and one shared\n * hint-or-error line: an address block, a set of notification switches, a\n * date range. Where Field is a single row (label, control, message), Fieldset\n * is the group those rows sit in, and the two nest — a Fieldset of Fields is\n * the shape it was drawn for. A lone control does not need a group; that is a\n * Field.\n *\n * It renders a real `<fieldset>` and `<legend>`, and that choice is most of\n * the component. A `<div role=\"group\" aria-labelledby>` names the group just\n * as well and gives up `<fieldset disabled>`, which disables every form\n * control inside it natively — including controls that arrived through the\n * default slot and that Fieldset holds no reference to. Nothing adds that\n * back from a `div`: a wrapper cannot pass a `disabled` prop to a control it\n * never rendered.\n *\n * The hint-or-error line answers exactly as Field's does, for the reason\n * Field.vue sets out — a wrapper cannot reach into a slotted control to set\n * `aria-describedby`, so it publishes a predictable `${id}-description` and\n * leaves that one attribute to the caller. One half differs: Fieldset owns a\n * real element, so it points the group's own `aria-describedby` at that id\n * itself. Wire a control inside to the same id only when you want the message\n * announced a second time on that control.\n *\n * ```vue\n * <Fieldset legend=\"Shipping address\" id=\"shipping\" hint=\"Where the order goes\" required>\n * <Field label=\"Street\"><TextField /></Field>\n * <Field label=\"City\"><TextField /></Field>\n * </Fieldset>\n * ```\n *\n * **The group hands down exactly one thing: `readonly`.** Everything else it\n * knows either travels natively or is a claim about the group that is not\n * automatically a claim about each control in it, and the reasoning is worth\n * stating because the next person will ask:\n *\n * - `disabled` travels through the real `<fieldset>`, and a second mechanism\n * alongside it would be actively harmful rather than merely redundant. One\n * fact carried two ways lets the two disagree: a control written\n * `:disabled=\"false\"` beats a context by the precedence rule, while the\n * native attribute disables it anyway — leaving a control that renders\n * enabled and silently refuses input. The element also reaches strictly\n * further, which is the argument for rendering a `<fieldset>` at all.\n * - `required` and `invalid` stop here. \"This group is mandatory\" is not\n * \"every control in it is mandatory\" — an address block needs a street and\n * not an apartment number — and a group-level error does not make each\n * control in it individually wrong. `aria-required` or `aria-invalid` on a\n * control that is fine is a false statement to the only audience that hears\n * it.\n * - The description stops here too, because unlike Field this component owns a\n * real element and already points its own `aria-describedby` at the message.\n * - `controlId` would collide with the id on the `<fieldset>` itself, and one\n * shared `name` is right for a set of radios and wrong for everything else.\n *\n * `readonly` is left because nothing else can carry it: there is no native\n * `<fieldset readonly>`, and a group shown in view mode is a real state.\n */\nconst props = withDefaults(\n defineProps<{\n /** The group's name, rendered as a real `<legend>` — the accessible name of the group. */\n legend?: string;\n /** Supporting text shown below the group. Hidden while `error` is set. */\n hint?: string;\n /** The group's error message. Renders through InlineError and replaces `hint`. */\n error?: string;\n /** Marks the group mandatory and appends a destructive asterisk to the legend. */\n required?: boolean;\n /** Disables every control inside, slotted ones included, and dims the group. */\n disabled?: boolean;\n /** Renders every Loom control inside read-only: still focusable, still submitted, not editable. */\n readonly?: boolean | undefined;\n /** Set on the `<fieldset>`, and what the hint/error id is derived from (`${id}-description`). */\n id?: string;\n }>(),\n {\n required: false,\n disabled: false,\n // Explicitly `undefined`, not `false`: a Fieldset that says nothing about\n // `readonly` must not overrule a Field or a control that set it, and Vue\n // casts an absent Boolean prop with no declared default to `false`.\n readonly: undefined,\n },\n);\n\nprovideFieldContext({\n controlId: () => undefined,\n describedBy: () => undefined,\n name: () => undefined,\n required: () => undefined,\n invalid: () => undefined,\n disabled: () => undefined,\n readonly: () => props.readonly,\n});\n\n// The hint and the error are mutually exclusive, so one id covers whichever\n// is showing. Undefined without `id`, exactly as in Field: an id nothing can\n// be pointed at is a landmark for no one. Undefined with no message either —\n// unlike Field, this id is also spent on the group's own `aria-describedby`,\n// and an IDREF resolving to nothing is a worse answer than no attribute.\nconst descriptionId = computed(() =>\n props.id && (props.hint ?? props.error) ? `${props.id}-description` : undefined,\n);\n\n// One rendered node, so this split is only about `class`. Vue's own\n// fallthrough merge concatenates the two lists rather than resolving them, so\n// a caller's `min-w-full` would beat — or lose to — the `min-w-0` below on\n// Tailwind's emission order instead of on being the later declaration. That\n// one utility is load-bearing (see the root class), so the merge has to be\n// Tailwind-aware.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: fieldsetAttrs } = useSplitAttrs();\n</script>\n\n<template>\n <fieldset\n v-bind=\"fieldsetAttrs\"\n :id=\"id\"\n :disabled=\"disabled\"\n :aria-describedby=\"descriptionId\"\n :class=\"\n cn(\n 'flex flex-col gap-4',\n // Not defensive. Every UA stylesheet gives `<fieldset>` a\n // `min-inline-size: min-content` that no `width` can beat, so a group\n // holding a text input refuses to shrink below that input's intrinsic\n // width and blows out the column of any consumer who drops one into a\n // form grid. Overriding the minimum itself is the only fix.\n 'min-w-0',\n // `group`, and no `opacity`. Dimming the group was the worst instance\n // of that mistake in the library, because opacity *composites* and\n // therefore multiplies: this element's 50% ran over a Switch's or a\n // Select's own 50%, so a control inside a disabled group rendered at\n // 25% effective alpha and its label measured 1.65:1 — and the group's\n // own hint, one dim rather than two, still came out at 2.05:1. Neither\n // was reachable by fixing the controls, because neither was the\n // controls' doing.\n //\n // Removing it here is what un-multiplies them: a nested control now\n // computes only its own drained treatment (Select and OtpInput land\n // their labels on 4.67:1 that way), and nothing this element does\n // reduces it further. The group still reads as unavailable — the\n // legend below mutes, and every control in it wears its own disabled\n // state — and the native `disabled` attribute carries the fact to\n // assistive tech, so none of it rests on colour alone.\n //\n // And no fill either, which is the other half of the same answer. Every\n // control in the library drains to `bg-muted` when it is unavailable,\n // so a `bg-muted` on the group would be that exact colour running\n // edge-to-edge behind them: the fills would meet at 1:1 and a row of\n // disabled controls would read as one grey slab with no controls in it.\n // The group is a grouping, not a surface — it has no fill available and\n // no `readonly` appearance either, because a read-only group is a group\n // of read-only controls, each of which now says so on its own.\n 'disabled:cursor-not-allowed',\n 'group',\n attrs.class as string,\n )\n \"\n >\n <!-- Deliberately borderless, like Field: with no border to interrupt, the\n legend's notch rendering never arises and the group is spaced rather\n than boxed. The margin is not a stand-in for the container's `gap`\n either — a rendered legend sits outside the anonymous box that holds\n a fieldset's content, so it is never a flex item and no `gap` reaches\n it. -->\n <!-- The legend is where \"this whole group is unavailable\" is now painted:\n it is the group's accessible name and the only text the group owns\n rather than borrows. `group-disabled:` reads the real `:disabled` on\n the `<fieldset>` above, so there is no second copy of the state to fall\n out of step with the attribute. 14.09:1 available, 5.25:1 not — a drop\n a reader can see, at a colour they can still read. -->\n <legend\n v-if=\"legend\"\n class=\"mb-2 text-sm font-medium text-foreground group-disabled:text-muted-foreground\"\n >\n {{ legend }} <span v-if=\"required\" class=\"text-destructive-text\">*</span>\n </legend>\n <!-- @slot The controls in the group — Fields, most often. -->\n <slot />\n <p v-if=\"hint && !error\" :id=\"descriptionId\" class=\"text-xs text-muted-foreground\">\n {{ hint }}\n </p>\n <InlineError v-if=\"error\" :id=\"descriptionId\" :message=\"error\" />\n </fieldset>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgEA,MAAM,QAAQ;EA2Bd,oBAAoB;GAClB,iBAAiB,KAAA;GACjB,mBAAmB,KAAA;GACnB,YAAY,KAAA;GACZ,gBAAgB,KAAA;GAChB,eAAe,KAAA;GACf,gBAAgB,KAAA;GAChB,gBAAgB,MAAM;EACxB,CAAC;EAOD,MAAM,gBAAgB,eACpB,MAAM,OAAO,MAAM,QAAQ,MAAM,SAAS,GAAG,MAAM,GAAG,gBAAgB,KAAA,CACxE;EASA,MAAM,EAAE,OAAO,MAAM,kBAAkB,cAAc;;GAInD,OAAA,UAAA,GAAA,mBAqEW,YArEX,WACU,MAoEC,aAAA,GApEY;IACpB,IAAI,QAAA;IACJ,UAAU,QAAA;IACV,oBAAkB,cAAA;IAClB,OAAc,MAAA,EAAA,CAAE,CAAA,uBAAA,WAAA,+BAAA,SAAqrE,MAAA,KAAA,CAAK,CAAC,KAAA;;IAqDpsE,QAAA,UADR,UAAA,GAAA,mBAKS,UALT,YAKS,CADJ,gBAAA,gBAAA,QAAA,MAAM,IAAG,KAAC,CAAA,GAAY,QAAA,YAAZ,UAAA,GAAA,mBAA4D,QAA5D,YAAoD,GAAC,KAAA,mBAAA,IAAA,IAAA,CAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;IAGpE,WAAQ,KAAA,QAAA,SAAA;IACC,QAAA,QAAI,CAAK,QAAA,SAAlB,UAAA,GAAA,mBAEI,KAAA;;KAFsB,IAAI,cAAA;KAAe,OAAM;IAC9C,GAAA,gBAAA,QAAA,IAAI,GAAA,GAAA,UAAA,KAAA,mBAAA,IAAA,IAAA;IAEU,QAAA,SAAnB,UAAA,GAAA,YAAiE,MAAA,mBAAA,GAAA;;KAAtC,IAAI,cAAA;KAAgB,SAAS,QAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"FileUpload.js","names":[],"sources":["../../../../../packages/primitives/file-upload/src/FileUpload.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { FileUploadLabels, FileUploadRejection } from \"@ecoma-io/loom-labels\";\n\nconst BYTE_UNITS = [\"B\", \"KB\", \"MB\", \"GB\"] as const;\n\n/**\n * A byte count as a person reads it.\n *\n * Binary steps with the short decimal names, which is what every operating\n * system file dialog beside this control shows — a reader comparing \"1.4 MB\"\n * here against \"1.4 MB\" in their own file browser should see the same number,\n * and the pedantically-correct \"1.5 MB\" (or \"1.4 MiB\") only reads as a bug.\n * One decimal below ten and none above it, so the size column stays the same\n * width down the list.\n *\n * Deliberately not exported: it is a formatter this control needs, not a\n * public utility, and the moment a host imports it from here the wording of a\n * file size becomes part of this component's API.\n */\nfunction formatBytes(bytes: number): string {\n let value = Math.max(bytes, 0);\n let step = 0;\n while (value >= 1024 && step < BYTE_UNITS.length - 1) {\n value /= 1024;\n step += 1;\n }\n const rounded = step > 0 && value < 10 ? Math.round(value * 10) / 10 : Math.round(value);\n return `${String(rounded)} ${BYTE_UNITS[step] ?? \"B\"}`;\n}\n\n/**\n * Every refusal names the file, because the reader is looking at a list of\n * several and \"that file is too large\" identifies none of them.\n */\nfunction describeRejection(rejection: FileUploadRejection, limit: string): string {\n const name = rejection.file.name;\n switch (rejection.reason) {\n case \"too-large\":\n return `${name} is larger than ${limit}.`;\n case \"type\":\n return `${name} is not an accepted file type.`;\n case \"duplicate\":\n return `${name} has already been chosen.`;\n case \"too-many\":\n return `${name} was not added — only one file can be chosen.`;\n }\n}\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it, and\n * exported so a host can build a partial vocabulary against the real thing.\n */\nexport const FILE_UPLOAD_LABELS: FileUploadLabels = {\n zone: ({ multiple }) =>\n multiple ? \"Choose files or drag them here\" : \"Choose a file or drag it here\",\n hint: ({ maxSize }) => `Up to ${formatBytes(maxSize)}`,\n size: ({ bytes }) => formatBytes(bytes),\n remove: ({ file }) => `Remove ${file.name}`,\n rejected: ({ rejections, maxSize }) => {\n const limit = maxSize === undefined ? \"the size limit\" : formatBytes(maxSize);\n return rejections.map((rejection) => describeRejection(rejection, limit)).join(\" \");\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useId, useTemplateRef } from \"vue\";\nimport { CloudUpload, File as FileIcon, TriangleAlert, X } from \"@lucide/vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { listStaggerDelay } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { useAncestorDisabled } from \"@ecoma-io/loom-labels\";\nimport { useFieldControl } from \"@ecoma-io/loom-labels\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\n/**\n * FileUpload — choosing files, and nothing else. A drop zone that is also a\n * real file dialog, plus the list of what has been chosen so far, with each\n * row removable.\n *\n * **It chooses; it does not upload.** There is no progress bar here and no\n * request: the host reads `modelValue`, sends it wherever it goes, and renders\n * `Progress` (or `Spinner`, when there is no percentage) for that half. Two\n * controls rather than one, because the upload's states — retrying, partial,\n * failed on the server — belong to whatever is doing the uploading, and a\n * control that owned both would have to guess at all of them.\n *\n * **Drag and drop is a shortcut, never the path.** The zone is a `<label>`\n * wrapped around a real `<input type=\"file\">`, visually hidden by the clip\n * technique rather than by `display: none` or `hidden` — both of which take\n * the input out of the tab order and leave a control only a pointer can reach.\n * Tab lands on the input, Space or Enter opens the system file dialog, and the\n * zone draws the focus ring on its behalf because a 1px input cannot show one.\n * A `div` with a click handler in place of that input is the standard defect\n * in this control, and it is invisible to everyone testing with a mouse.\n *\n * Files arriving while `multiple` is set are appended to the list rather than\n * replacing it: a reader who drops two files and then a third means three, and\n * the native input's replace-everything behaviour is the surprise. Without\n * `multiple` the newest choice replaces the old one, exactly as the input does.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself through\n * `useFieldControl()`: the row's id lands on the input (and on the `<label>`'s\n * `for`, so the zone keeps activating it), and the row's `name`, `required`,\n * `invalid` and the id of its hint or error line arrive with it. The row's\n * description is **merged** with this control's own refusal message rather than\n * replacing it — a file turned away for being too large has to keep saying so.\n *\n * There is no `readonly`, and a row's is ignored rather than approximated.\n * `readonly` is inert on `<input type=\"file\">` in every browser, for the reason\n * it is inert on a checkbox: there is no text to protect, only a dialog to\n * open. A zone that may be read but not added to is a disabled zone above a\n * list — and the list, which is where the value actually is, stays readable\n * either way.\n */\nconst props = withDefaults(\n defineProps<{\n /** The chosen files. Leave it unbound to let the control keep its own list. */\n modelValue?: File[] | undefined;\n /** What the file dialog offers and what a drop is checked against — the native `accept` syntax: `.csv`, `image/png`, `image/*`, comma-separated. */\n accept?: string;\n /** Allows more than one file, and appends each new choice to the list instead of replacing it. */\n multiple?: boolean;\n /** Largest file accepted, in bytes. A file over it is refused and named in the message. */\n maxSize?: number;\n /** Unavailable: dims the zone, refuses the dialog, the drop and every remove button. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Error state: paints the destructive border and ring, and sets `aria-invalid` on the input. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** The zone's own line of copy, which is also the input's accessible name. Defaults to `labels.zone`, whose wording matches `multiple`. */\n label?: string;\n /** The smaller line under it. Defaults to `labels.hint` against the `maxSize` limit, when there is one. */\n hint?: string;\n /**\n * Everything this control says that is not a file name, as any subset of\n * `FileUploadLabels` — 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. `label` and `hint` are the shorter way to reach the two\n * keys of the same name for one zone; this is what reaches the refusal\n * message, the remove buttons and the size column.\n */\n labels?: LabelOverrides<FileUploadLabels>;\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 then watch every\n // file it chose vanish on the next render. `undefined` is what leaves the\n // control managing its own, the same distinction `optional()` exists to\n // preserve for the Reka-backed primitives.\n modelValue: undefined,\n multiple: false,\n // Not `false`, for either. `false` is a caller saying \"this zone is fine /\n // enabled even though its row is not\"; absent is a caller saying nothing,\n // and only `undefined` survives to mean that past Vue's\n // absent-Boolean-casts-to-false rule — see TextField.vue, which carries the\n // full reasoning.\n disabled: undefined,\n invalid: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** The full list after the change — files added, or one removed. Never a partial list. */\n \"update:modelValue\": [files: File[]];\n /** Every file refused by this one interaction, each with the rule that refused it. Fires once per interaction, not once per file. */\n reject: [rejections: FileUploadRejection[]];\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(\"fileUpload\", FILE_UPLOAD_LABELS, () => props.labels);\n\n// `class` sizes the whole control, so it lands on the root; everything else a\n// caller passes — `name`, `id`, `data-testid`, `aria-describedby` — describes\n// the real `<input type=\"file\">` and lands there. Splitting them is the only\n// way to route both correctly: the root is not a form control and the input is\n// not the box a caller lays out.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\n\n// The label's `for` needs the input's id, and a caller passing their own id —\n// or a Field row publishing one — must not end up with a label pointing at\n// nothing. `inputId` is resolved from `field` at the foot of this block.\nconst generatedId = useId();\nconst messageId = useId();\n\nconst ownFiles = ref<File[]>([]);\nconst files = computed(() => props.modelValue ?? ownFiles.value);\n\nconst rejections = ref<FileUploadRejection[]>([]);\n\n/**\n * A stable key per file, held against the File object itself.\n *\n * Keying the rows by index instead re-keys every row after the one removed, so\n * removing the first of five replays the entrance animation on the other four\n * — the list appears to reload because one row left it. A WeakMap keys by\n * identity, holds nothing alive, and survives the list being reordered.\n */\nconst rowIds = new WeakMap<File, number>();\nlet nextRowId = 0;\nfunction rowId(file: File): number {\n let id = rowIds.get(file);\n if (id === undefined) {\n id = nextRowId++;\n rowIds.set(file, id);\n }\n return id;\n}\n\n/** Name, size and mtime — what the file system itself calls the same file. */\nfunction signature(file: File): string {\n return `${file.name}:${String(file.size)}:${String(file.lastModified)}`;\n}\n\n/**\n * The same test the native input applies to `accept`, applied again to a drop\n * — the browser enforces it in the file dialog and not at all on a drag, so a\n * zone that only sets the attribute accepts anything dropped on it.\n *\n * `file.type` is the browser's guess from the extension and it is empty for\n * anything it does not recognise, which is why an `accept` written as MIME\n * types alone turns away files it meant to take. Naming both — `.csv,text/csv`\n * — is the form that works, and it is what the documentation shows.\n */\nfunction accepts(file: File): boolean {\n const accept = props.accept?.trim();\n if (accept === undefined || accept.length === 0) return true;\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n return accept.split(\",\").some((raw) => {\n const pattern = raw.trim().toLowerCase();\n if (pattern.length === 0) return false;\n if (pattern.startsWith(\".\")) return name.endsWith(pattern);\n if (pattern.endsWith(\"/*\")) return type.startsWith(pattern.slice(0, -1));\n return type === pattern;\n });\n}\n\nfunction commit(next: File[]): void {\n if (props.modelValue === undefined) ownFiles.value = next;\n emit(\"update:modelValue\", next);\n}\n\n/** Runs the offered files past every rule, keeping what passes and reporting the rest. */\nfunction add(incoming: File[]): void {\n if (field.disabled) return;\n\n const current = files.value;\n const kept = props.multiple ? [...current] : [];\n const seen = new Set(kept.map(signature));\n const refused: FileUploadRejection[] = [];\n const limit = props.maxSize;\n\n for (const file of incoming) {\n if (!props.multiple && kept.length > 0) {\n refused.push({ file, reason: \"too-many\" });\n } else if (limit !== undefined && file.size > limit) {\n refused.push({ file, reason: \"too-large\" });\n } else if (!accepts(file)) {\n refused.push({ file, reason: \"type\" });\n } else if (seen.has(signature(file))) {\n refused.push({ file, reason: \"duplicate\" });\n } else {\n seen.add(signature(file));\n kept.push(file);\n }\n }\n\n rejections.value = refused;\n if (refused.length > 0) emit(\"reject\", refused);\n\n const unchanged = kept.length === current.length && kept.every((file, i) => file === current[i]);\n if (!unchanged) commit(kept);\n}\n\nfunction remove(index: number): void {\n if (field.disabled) return;\n // The message named files from the last selection. Once the reader edits the\n // list themselves it no longer describes anything on screen, and an error\n // sitting under a list somebody is actively fixing reads as an error about\n // that list.\n rejections.value = [];\n commit(files.value.filter((_, i) => i !== index));\n}\n\nfunction onSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n add(Array.from(input.files ?? []));\n // Cleared so choosing the same file a second time still fires `change`. The\n // input compares the new selection against its own value and stays silent\n // when they match — which, after a file has been removed from the list, is a\n // control that refuses to take back the file the reader just took out.\n input.value = \"\";\n}\n\n/**\n * Enters minus leaves, rather than a boolean.\n *\n * `dragleave` fires on the zone every time the pointer crosses onto one of its\n * own children, so an enter/leave pair drops the highlight and picks it up\n * again as the reader drags across the icon and the copy — the zone flickers\n * under the cursor at the exact moment it is meant to be saying \"let go here\".\n * A child's `dragenter` always lands before the parent's `dragleave`, so the\n * count never reaches zero until the pointer has genuinely left. `relatedTarget`\n * answers the same question in one line, but it is not reliably populated for a\n * drag that began outside the document — which is every drag this zone sees.\n */\nconst dragDepth = ref(0);\nconst dragging = computed(() => dragDepth.value > 0 && !field.disabled);\n\nfunction onDragEnter(): void {\n dragDepth.value += 1;\n}\n\nfunction onDragLeave(): void {\n dragDepth.value = Math.max(dragDepth.value - 1, 0);\n}\n\nfunction onDragOver(event: DragEvent): void {\n // Without this the browser keeps its default handling, which for a file is\n // \"navigate to it\" — the drop never reaches the zone and the page is gone.\n // Setting dropEffect is what makes the cursor say copy rather than move.\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = field.disabled ? \"none\" : \"copy\";\n}\n\nfunction onDrop(event: DragEvent): void {\n event.preventDefault();\n // Reset rather than decrement: the drop consumes the drag, and no matching\n // `dragleave` follows it.\n dragDepth.value = 0;\n add(Array.from(event.dataTransfer?.files ?? []));\n}\n\n// Nothing here listens on `window` or `document`. A page-wide drag handler\n// would be the usual way to stop a file dropped *beside* the zone from\n// navigating the browser away, but a library primitive that installs one\n// silently governs every other drop target on the host's page. That decision\n// is the host's, so the listeners a component cannot tear down are the ones it\n// never registers.\n\n// The two content props sit *above* the resolved label rather than replacing\n// it: `label` is the wording for one zone — \"Drop last month's export here\" —\n// and the label is what every other zone says. Read through `text.` here and\n// not resolved above, so a language switch after mount repaints the copy.\nconst zoneLabel = computed(() => props.label ?? text.value.zone({ multiple: props.multiple }));\n\nconst zoneHint = computed(() => {\n if (props.hint !== undefined) return props.hint;\n // The limit is handed over as a byte count, never as `formatBytes` output: a\n // host that writes `1,5 Mo` or Eastern Arabic digits cannot get there from a\n // string this component already decided the shape of.\n return props.maxSize === undefined ? undefined : text.value.hint({ maxSize: props.maxSize });\n});\n\n// One call over the whole list rather than one per refusal joined with a\n// space. The joiner was the fragment: which character separates two sentences\n// is a property of the script, and a language that would rather count the\n// refused files than list them has no way to say so from a per-file message.\nconst message = computed(() =>\n rejections.value.length === 0\n ? \"\"\n : text.value.rejected({ rejections: rejections.value, maxSize: props.maxSize }),\n);\n\n/**\n * The drop is the reason this control cannot be left to the platform.\n *\n * `<fieldset disabled>` makes the nested `<input type=\"file\">` inert, which\n * closes the click and the keyboard, and it makes each file's remove button\n * inert too. It does nothing at all to the `drop` handler, because that sits on\n * a `<label>` — not a form control, and never disabled by a fieldset. `add()`\n * bails on `field.disabled`, which is exactly the value a disabled fieldset\n * does not reach, so a zone inside a disabled group accepted a dragged file\n * while refusing every other way in.\n *\n * Read off the DOM rather than taken from the Field context, which publishes no\n * `disabled` on purpose — see `../../lib/ancestor-disabled.ts`.\n */\nconst root = useTemplateRef<HTMLElement>(\"root\");\nconst groupDisabled = useAncestorDisabled(() => root.value);\n\n// The Field wiring sits here, below `message`, because it reads it: this is the\n// one control in the family that already had something of its own to say about\n// itself, so its `describedBy` is a *merge* and not a hand-over. Its refusal\n// message reads first — a file turned away for being too large is the most\n// specific thing there is to say — then whatever the caller pointed at, then\n// the row's hint or error, which `useFieldControl` appends. Replacing rather\n// than merging at either end is how a rejection stops being announced.\n//\n// The condition is `message` itself, not `rejections`, so the id can never\n// point at a `<p>` the template has not rendered.\n//\n// `name` and `required` are absent from the object because this component has\n// no prop for either: the row's answer stands unopposed, and its `name` reaches\n// the real `<input type=\"file\">`, which is what a `<form>` posts. `readonly` is\n// absent for the reason the docblock gives.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [message.value.length > 0 ? messageId : undefined, attrs[\"aria-describedby\"]]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n // The fieldset beats the prop in both directions, exactly as it does for the\n // `<input type=\"file\">` inside this very control.\n disabled: groupDisabled.value ? true : props.disabled,\n invalid: props.invalid,\n}));\n\n// `field.id` is the caller's own id, then the row's; the generated one is the\n// floor beneath both, because the `<label for>` and the input have to agree on\n// an id whether or not anybody supplied one.\nconst inputId = computed(() => field.id ?? generatedId);\n</script>\n\n<template>\n <div ref=\"root\" :class=\"cn('flex w-full flex-col', attrs.class as string)\">\n <!-- The drag handlers sit on a <label>, which the rule reads as a static\n element — and it is usually right to: a box with a drop handler and\n nothing else is a control no keyboard can reach. Here the keyboard\n path is the real <input type=\"file\"> nested inside, which the label\n both names and activates, so the drop adds a pointer shortcut to a\n control that already works without one. -->\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <label\n :for=\"inputId\"\n :data-dragging=\"dragging || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :data-disabled=\"field.disabled || undefined\"\n :class=\"\n cn(\n // `group` so the two lines of copy below can name their own disabled\n // colour off this element's state. A colour set here would only be\n // *inherited* by them, and both declare a colour of their own — an\n // inherited value loses to any declaration, however weak.\n 'group flex flex-col items-center justify-center gap-2 rounded-md border border-dashed border-input bg-background px-6 py-8 text-center',\n // Border and fill are the drag feedback, so they carry the transition\n // — fast, because a zone that lights up after the pointer has already\n // crossed it is answering a question the reader stopped asking.\n 'transition-[color,background-color,border-color,box-shadow] duration-fast ease-out',\n // Focus lives on the clipped input, which is 1px and can show a reader\n // nothing. The zone wears the ring on its behalf, the same\n // focus-within arrangement TextField uses for its own inner input.\n 'focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring',\n !field.invalid && 'focus-within:shadow-halo',\n // The dash going solid is what keeps the drag state off colour alone.\n 'data-[dragging]:border-solid data-[dragging]:border-primary data-[dragging]:bg-primary-muted',\n // Drained, not dimmed. The zone is a large blank region whose whole\n // purpose is the two lines of text in the middle of it, and\n // `opacity-50` took the headline to 3.06:1 and the hint below it to\n // 2.05:1 — the reader least able to guess what a drop zone wants is\n // the one it stopped telling. The fill falls to the neutral well\n // instead, which is where every other unavailable surface in the\n // library goes, and both lines land at 4.67:1 over it. The dash stays,\n // because it is what marks this out as a drop target even while\n // nothing may be dropped on it; only its colour slackens, from\n // `input` to the lighter `border`, so the state is told in a weight\n // as well as in two fills rather than in hue alone.\n field.disabled\n ? 'cursor-not-allowed border-border bg-muted'\n : 'cursor-pointer hover:bg-subtle',\n // Last of the rules naming a border colour, and the order is\n // load-bearing: `cn()` resolves one by whichever class it saw last,\n // so a zone both refusing a file and unavailable would lose its\n // destructive rim to the disabled one if this sat above it.\n field.invalid && 'border-destructive focus-within:outline-destructive',\n )\n \"\n @dragenter=\"onDragEnter\"\n @dragleave=\"onDragLeave\"\n @dragover=\"onDragOver\"\n @drop=\"onDrop\"\n >\n <!-- `field.attrs` spreads **after** the fallthrough attrs, and that\n position is the contract (see TextField.vue): the bag has already\n resolved the caller's own id and merged their description with this\n zone's refusal message and the row's hint, and it drops every key\n that resolved to nothing, so it can only add. The `:aria-invalid` and\n `:aria-describedby` bindings that used to sit here went with it — an\n individual attribute written after a `v-bind` wins, so either one\n kept would overwrite the resolved value with the raw prop.\n\n `:id` is the deliberate exception, and not that failure: `inputId` is\n the bag's own id with the generated one beneath it, so it can only\n ever restate what the bag holds or supply the id the `<label for>`\n needs when the bag holds none. -->\n <input\n v-bind=\"{ ...inputAttrs, ...field.attrs }\"\n :id=\"inputId\"\n type=\"file\"\n :accept=\"accept\"\n :multiple=\"multiple\"\n :disabled=\"field.disabled\"\n class=\"sr-only\"\n @change=\"onSelect\"\n />\n <!-- The medallion, as EmptyState draws it: a 20px glyph alone in a large\n blank region has nothing holding it and reads as a stray mark. -->\n <span\n aria-hidden=\"true\"\n class=\"grid h-10 w-10 place-items-center rounded-full border border-border bg-subtle text-muted-foreground\"\n >\n <CloudUpload class=\"h-5 w-5\" />\n </span>\n <!-- The disabled colour is declared here rather than inherited from the\n zone, for the reason the `group` on it records: this span sets\n `text-foreground` itself, and an inherited value never beats a\n declared one. The hint below needs no such rule — it is already on\n the muted colour, which holds 4.67:1 over the drained fill. -->\n <span class=\"text-sm text-foreground group-data-[disabled]:text-muted-foreground\">{{\n zoneLabel\n }}</span>\n <span v-if=\"zoneHint\" class=\"text-small text-muted-foreground\">{{ zoneHint }}</span>\n </label>\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 —\n is 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-2 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\n <ul v-if=\"files.length > 0\" class=\"mt-3 flex flex-col gap-1.5\">\n <li\n v-for=\"(file, index) in files\"\n :key=\"rowId(file)\"\n class=\"flex animate-fade-rise items-center gap-2 rounded-md border border-border bg-card px-3 py-2\"\n :style=\"{ animationDelay: listStaggerDelay(index) }\"\n >\n <FileIcon class=\"h-4 w-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <span class=\"min-w-0 flex-1 truncate text-sm text-foreground\">{{ file.name }}</span>\n <span class=\"shrink-0 tabular text-small text-muted-foreground\">\n {{ text.size({ bytes: file.size }) }}\n </span>\n <!-- Named with the file it removes. Seven buttons all called \"Remove\"\n are seven identical announcements and one guess about which row a\n reader is on. -->\n <!-- Drained, not dimmed: `opacity-50` faded the glyph inside its own\n row card, compositing it below contrast — the failure Button\n records for its dim. The glyph-only control takes the neutral\n well, and the native attribute carries unavailability to AT. -->\n <button\n type=\"button\"\n :aria-label=\"text.remove({ file })\"\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 disabled:bg-muted disabled:shadow-none\"\n @click=\"remove(index)\"\n >\n <X class=\"h-4 w-4\" />\n </button>\n </li>\n </ul>\n </div>\n</template>\n"],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"FileUpload.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../../packages/primitives/file-upload/src/FileUpload.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { FileUploadLabels, FileUploadRejection } from \"@ecoma-io/loom-labels\";\n\nconst BYTE_UNITS = [\"B\", \"KB\", \"MB\", \"GB\"] as const;\n\n/**\n * A byte count as a person reads it.\n *\n * Binary steps with the short decimal names, which is what every operating\n * system file dialog beside this control shows — a reader comparing \"1.4 MB\"\n * here against \"1.4 MB\" in their own file browser should see the same number,\n * and the pedantically-correct \"1.5 MB\" (or \"1.4 MiB\") only reads as a bug.\n * One decimal below ten and none above it, so the size column stays the same\n * width down the list.\n *\n * Deliberately not exported: it is a formatter this control needs, not a\n * public utility, and the moment a host imports it from here the wording of a\n * file size becomes part of this component's API.\n */\nfunction formatBytes(bytes: number): string {\n let value = Math.max(bytes, 0);\n let step = 0;\n while (value >= 1024 && step < BYTE_UNITS.length - 1) {\n value /= 1024;\n step += 1;\n }\n const rounded = step > 0 && value < 10 ? Math.round(value * 10) / 10 : Math.round(value);\n return `${String(rounded)} ${BYTE_UNITS[step] ?? \"B\"}`;\n}\n\n/**\n * Every refusal names the file, because the reader is looking at a list of\n * several and \"that file is too large\" identifies none of them.\n */\nfunction describeRejection(rejection: FileUploadRejection, limit: string): string {\n const name = rejection.file.name;\n switch (rejection.reason) {\n case \"too-large\":\n return `${name} is larger than ${limit}.`;\n case \"type\":\n return `${name} is not an accepted file type.`;\n case \"duplicate\":\n return `${name} has already been chosen.`;\n case \"too-many\":\n return `${name} was not added — only one file can be chosen.`;\n }\n}\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it, and\n * exported so a host can build a partial vocabulary against the real thing.\n */\nexport const FILE_UPLOAD_LABELS: FileUploadLabels = {\n zone: ({ multiple }) =>\n multiple ? \"Choose files or drag them here\" : \"Choose a file or drag it here\",\n hint: ({ maxSize }) => `Up to ${formatBytes(maxSize)}`,\n size: ({ bytes }) => formatBytes(bytes),\n remove: ({ file }) => `Remove ${file.name}`,\n rejected: ({ rejections, maxSize }) => {\n const limit = maxSize === undefined ? \"the size limit\" : formatBytes(maxSize);\n return rejections.map((rejection) => describeRejection(rejection, limit)).join(\" \");\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useId, useTemplateRef } from \"vue\";\nimport { CloudUpload, File as FileIcon, TriangleAlert, X } from \"@lucide/vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { listStaggerDelay } from \"@ecoma-io/loom-core\";\nimport { useSplitAttrs } from \"@ecoma-io/loom-core\";\nimport { useAncestorDisabled } from \"@ecoma-io/loom-labels\";\nimport { useFieldControl } from \"@ecoma-io/loom-labels\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\n/**\n * FileUpload — choosing files, and nothing else. A drop zone that is also a\n * real file dialog, plus the list of what has been chosen so far, with each\n * row removable.\n *\n * **It chooses; it does not upload.** There is no progress bar here and no\n * request: the host reads `modelValue`, sends it wherever it goes, and renders\n * `Progress` (or `Spinner`, when there is no percentage) for that half. Two\n * controls rather than one, because the upload's states — retrying, partial,\n * failed on the server — belong to whatever is doing the uploading, and a\n * control that owned both would have to guess at all of them.\n *\n * **Drag and drop is a shortcut, never the path.** The zone is a `<label>`\n * wrapped around a real `<input type=\"file\">`, visually hidden by the clip\n * technique rather than by `display: none` or `hidden` — both of which take\n * the input out of the tab order and leave a control only a pointer can reach.\n * Tab lands on the input, Space or Enter opens the system file dialog, and the\n * zone draws the focus ring on its behalf because a 1px input cannot show one.\n * A `div` with a click handler in place of that input is the standard defect\n * in this control, and it is invisible to everyone testing with a mouse.\n *\n * Files arriving while `multiple` is set are appended to the list rather than\n * replacing it: a reader who drops two files and then a third means three, and\n * the native input's replace-everything behaviour is the surprise. Without\n * `multiple` the newest choice replaces the old one, exactly as the input does.\n *\n * Inside a [Field](../Field/Field.vue) it wires itself through\n * `useFieldControl()`: the row's id lands on the input (and on the `<label>`'s\n * `for`, so the zone keeps activating it), and the row's `name`, `required`,\n * `invalid` and the id of its hint or error line arrive with it. The row's\n * description is **merged** with this control's own refusal message rather than\n * replacing it — a file turned away for being too large has to keep saying so.\n *\n * There is no `readonly`, and a row's is ignored rather than approximated.\n * `readonly` is inert on `<input type=\"file\">` in every browser, for the reason\n * it is inert on a checkbox: there is no text to protect, only a dialog to\n * open. A zone that may be read but not added to is a disabled zone above a\n * list — and the list, which is where the value actually is, stays readable\n * either way.\n */\nconst props = withDefaults(\n defineProps<{\n /** The chosen files. Leave it unbound to let the control keep its own list. */\n modelValue?: File[] | undefined;\n /** What the file dialog offers and what a drop is checked against — the native `accept` syntax: `.csv`, `image/png`, `image/*`, comma-separated. */\n accept?: string;\n /** Allows more than one file, and appends each new choice to the list instead of replacing it. */\n multiple?: boolean;\n /** Largest file accepted, in bytes. A file over it is refused and named in the message. */\n maxSize?: number;\n /** Unavailable: dims the zone, refuses the dialog, the drop and every remove button. Unset defers to a wrapping Field. */\n disabled?: boolean | undefined;\n /** Error state: paints the destructive border and ring, and sets `aria-invalid` on the input. Unset defers to a wrapping Field's `error`. */\n invalid?: boolean | undefined;\n /** The zone's own line of copy, which is also the input's accessible name. Defaults to `labels.zone`, whose wording matches `multiple`. */\n label?: string;\n /** The smaller line under it. Defaults to `labels.hint` against the `maxSize` limit, when there is one. */\n hint?: string;\n /**\n * Everything this control says that is not a file name, as any subset of\n * `FileUploadLabels` — 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. `label` and `hint` are the shorter way to reach the two\n * keys of the same name for one zone; this is what reaches the refusal\n * message, the remove buttons and the size column.\n */\n labels?: LabelOverrides<FileUploadLabels>;\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 then watch every\n // file it chose vanish on the next render. `undefined` is what leaves the\n // control managing its own, the same distinction `optional()` exists to\n // preserve for the Reka-backed primitives.\n modelValue: undefined,\n multiple: false,\n // Not `false`, for either. `false` is a caller saying \"this zone is fine /\n // enabled even though its row is not\"; absent is a caller saying nothing,\n // and only `undefined` survives to mean that past Vue's\n // absent-Boolean-casts-to-false rule — see TextField.vue, which carries the\n // full reasoning.\n disabled: undefined,\n invalid: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** The full list after the change — files added, or one removed. Never a partial list. */\n \"update:modelValue\": [files: File[]];\n /** Every file refused by this one interaction, each with the rule that refused it. Fires once per interaction, not once per file. */\n reject: [rejections: FileUploadRejection[]];\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(\"fileUpload\", FILE_UPLOAD_LABELS, () => props.labels);\n\n// `class` sizes the whole control, so it lands on the root; everything else a\n// caller passes — `name`, `id`, `data-testid`, `aria-describedby` — describes\n// the real `<input type=\"file\">` and lands there. Splitting them is the only\n// way to route both correctly: the root is not a form control and the input is\n// not the box a caller lays out.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: inputAttrs } = useSplitAttrs();\n\n// The label's `for` needs the input's id, and a caller passing their own id —\n// or a Field row publishing one — must not end up with a label pointing at\n// nothing. `inputId` is resolved from `field` at the foot of this block.\nconst generatedId = useId();\nconst messageId = useId();\n\nconst ownFiles = ref<File[]>([]);\nconst files = computed(() => props.modelValue ?? ownFiles.value);\n\nconst rejections = ref<FileUploadRejection[]>([]);\n\n/**\n * A stable key per file, held against the File object itself.\n *\n * Keying the rows by index instead re-keys every row after the one removed, so\n * removing the first of five replays the entrance animation on the other four\n * — the list appears to reload because one row left it. A WeakMap keys by\n * identity, holds nothing alive, and survives the list being reordered.\n */\nconst rowIds = new WeakMap<File, number>();\nlet nextRowId = 0;\nfunction rowId(file: File): number {\n let id = rowIds.get(file);\n if (id === undefined) {\n id = nextRowId++;\n rowIds.set(file, id);\n }\n return id;\n}\n\n/** Name, size and mtime — what the file system itself calls the same file. */\nfunction signature(file: File): string {\n return `${file.name}:${String(file.size)}:${String(file.lastModified)}`;\n}\n\n/**\n * The same test the native input applies to `accept`, applied again to a drop\n * — the browser enforces it in the file dialog and not at all on a drag, so a\n * zone that only sets the attribute accepts anything dropped on it.\n *\n * `file.type` is the browser's guess from the extension and it is empty for\n * anything it does not recognise, which is why an `accept` written as MIME\n * types alone turns away files it meant to take. Naming both — `.csv,text/csv`\n * — is the form that works, and it is what the documentation shows.\n */\nfunction accepts(file: File): boolean {\n const accept = props.accept?.trim();\n if (accept === undefined || accept.length === 0) return true;\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n return accept.split(\",\").some((raw) => {\n const pattern = raw.trim().toLowerCase();\n if (pattern.length === 0) return false;\n if (pattern.startsWith(\".\")) return name.endsWith(pattern);\n if (pattern.endsWith(\"/*\")) return type.startsWith(pattern.slice(0, -1));\n return type === pattern;\n });\n}\n\nfunction commit(next: File[]): void {\n if (props.modelValue === undefined) ownFiles.value = next;\n emit(\"update:modelValue\", next);\n}\n\n/** Runs the offered files past every rule, keeping what passes and reporting the rest. */\nfunction add(incoming: File[]): void {\n if (field.disabled) return;\n\n const current = files.value;\n const kept = props.multiple ? [...current] : [];\n const seen = new Set(kept.map(signature));\n const refused: FileUploadRejection[] = [];\n const limit = props.maxSize;\n\n for (const file of incoming) {\n if (!props.multiple && kept.length > 0) {\n refused.push({ file, reason: \"too-many\" });\n } else if (limit !== undefined && file.size > limit) {\n refused.push({ file, reason: \"too-large\" });\n } else if (!accepts(file)) {\n refused.push({ file, reason: \"type\" });\n } else if (seen.has(signature(file))) {\n refused.push({ file, reason: \"duplicate\" });\n } else {\n seen.add(signature(file));\n kept.push(file);\n }\n }\n\n rejections.value = refused;\n if (refused.length > 0) emit(\"reject\", refused);\n\n const unchanged = kept.length === current.length && kept.every((file, i) => file === current[i]);\n if (!unchanged) commit(kept);\n}\n\nfunction remove(index: number): void {\n if (field.disabled) return;\n // The message named files from the last selection. Once the reader edits the\n // list themselves it no longer describes anything on screen, and an error\n // sitting under a list somebody is actively fixing reads as an error about\n // that list.\n rejections.value = [];\n commit(files.value.filter((_, i) => i !== index));\n}\n\nfunction onSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n add(Array.from(input.files ?? []));\n // Cleared so choosing the same file a second time still fires `change`. The\n // input compares the new selection against its own value and stays silent\n // when they match — which, after a file has been removed from the list, is a\n // control that refuses to take back the file the reader just took out.\n input.value = \"\";\n}\n\n/**\n * Enters minus leaves, rather than a boolean.\n *\n * `dragleave` fires on the zone every time the pointer crosses onto one of its\n * own children, so an enter/leave pair drops the highlight and picks it up\n * again as the reader drags across the icon and the copy — the zone flickers\n * under the cursor at the exact moment it is meant to be saying \"let go here\".\n * A child's `dragenter` always lands before the parent's `dragleave`, so the\n * count never reaches zero until the pointer has genuinely left. `relatedTarget`\n * answers the same question in one line, but it is not reliably populated for a\n * drag that began outside the document — which is every drag this zone sees.\n */\nconst dragDepth = ref(0);\nconst dragging = computed(() => dragDepth.value > 0 && !field.disabled);\n\nfunction onDragEnter(): void {\n dragDepth.value += 1;\n}\n\nfunction onDragLeave(): void {\n dragDepth.value = Math.max(dragDepth.value - 1, 0);\n}\n\nfunction onDragOver(event: DragEvent): void {\n // Without this the browser keeps its default handling, which for a file is\n // \"navigate to it\" — the drop never reaches the zone and the page is gone.\n // Setting dropEffect is what makes the cursor say copy rather than move.\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = field.disabled ? \"none\" : \"copy\";\n}\n\nfunction onDrop(event: DragEvent): void {\n event.preventDefault();\n // Reset rather than decrement: the drop consumes the drag, and no matching\n // `dragleave` follows it.\n dragDepth.value = 0;\n add(Array.from(event.dataTransfer?.files ?? []));\n}\n\n// Nothing here listens on `window` or `document`. A page-wide drag handler\n// would be the usual way to stop a file dropped *beside* the zone from\n// navigating the browser away, but a library primitive that installs one\n// silently governs every other drop target on the host's page. That decision\n// is the host's, so the listeners a component cannot tear down are the ones it\n// never registers.\n\n// The two content props sit *above* the resolved label rather than replacing\n// it: `label` is the wording for one zone — \"Drop last month's export here\" —\n// and the label is what every other zone says. Read through `text.` here and\n// not resolved above, so a language switch after mount repaints the copy.\nconst zoneLabel = computed(() => props.label ?? text.value.zone({ multiple: props.multiple }));\n\nconst zoneHint = computed(() => {\n if (props.hint !== undefined) return props.hint;\n // The limit is handed over as a byte count, never as `formatBytes` output: a\n // host that writes `1,5 Mo` or Eastern Arabic digits cannot get there from a\n // string this component already decided the shape of.\n return props.maxSize === undefined ? undefined : text.value.hint({ maxSize: props.maxSize });\n});\n\n// One call over the whole list rather than one per refusal joined with a\n// space. The joiner was the fragment: which character separates two sentences\n// is a property of the script, and a language that would rather count the\n// refused files than list them has no way to say so from a per-file message.\nconst message = computed(() =>\n rejections.value.length === 0\n ? \"\"\n : text.value.rejected({ rejections: rejections.value, maxSize: props.maxSize }),\n);\n\n/**\n * The drop is the reason this control cannot be left to the platform.\n *\n * `<fieldset disabled>` makes the nested `<input type=\"file\">` inert, which\n * closes the click and the keyboard, and it makes each file's remove button\n * inert too. It does nothing at all to the `drop` handler, because that sits on\n * a `<label>` — not a form control, and never disabled by a fieldset. `add()`\n * bails on `field.disabled`, which is exactly the value a disabled fieldset\n * does not reach, so a zone inside a disabled group accepted a dragged file\n * while refusing every other way in.\n *\n * Read off the DOM rather than taken from the Field context, which publishes no\n * `disabled` on purpose — see `../../lib/ancestor-disabled.ts`.\n */\nconst root = useTemplateRef<HTMLElement>(\"root\");\nconst groupDisabled = useAncestorDisabled(() => root.value);\n\n// The Field wiring sits here, below `message`, because it reads it: this is the\n// one control in the family that already had something of its own to say about\n// itself, so its `describedBy` is a *merge* and not a hand-over. Its refusal\n// message reads first — a file turned away for being too large is the most\n// specific thing there is to say — then whatever the caller pointed at, then\n// the row's hint or error, which `useFieldControl` appends. Replacing rather\n// than merging at either end is how a rejection stops being announced.\n//\n// The condition is `message` itself, not `rejections`, so the id can never\n// point at a `<p>` the template has not rendered.\n//\n// `name` and `required` are absent from the object because this component has\n// no prop for either: the row's answer stands unopposed, and its `name` reaches\n// the real `<input type=\"file\">`, which is what a `<form>` posts. `readonly` is\n// absent for the reason the docblock gives.\nconst field = useFieldControl(() => ({\n id: attrs.id as string | undefined,\n describedBy: [message.value.length > 0 ? messageId : undefined, attrs[\"aria-describedby\"]]\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .join(\" \"),\n // The fieldset beats the prop in both directions, exactly as it does for the\n // `<input type=\"file\">` inside this very control.\n disabled: groupDisabled.value ? true : props.disabled,\n invalid: props.invalid,\n}));\n\n// `field.id` is the caller's own id, then the row's; the generated one is the\n// floor beneath both, because the `<label for>` and the input have to agree on\n// an id whether or not anybody supplied one.\nconst inputId = computed(() => field.id ?? generatedId);\n</script>\n\n<template>\n <div ref=\"root\" :class=\"cn('flex w-full flex-col', attrs.class as string)\">\n <!-- The drag handlers sit on a <label>, which the rule reads as a static\n element — and it is usually right to: a box with a drop handler and\n nothing else is a control no keyboard can reach. Here the keyboard\n path is the real <input type=\"file\"> nested inside, which the label\n both names and activates, so the drop adds a pointer shortcut to a\n control that already works without one. -->\n <!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->\n <label\n :for=\"inputId\"\n :data-dragging=\"dragging || undefined\"\n :data-invalid=\"field.invalid || undefined\"\n :data-disabled=\"field.disabled || undefined\"\n :class=\"\n cn(\n // `group` so the two lines of copy below can name their own disabled\n // colour off this element's state. A colour set here would only be\n // *inherited* by them, and both declare a colour of their own — an\n // inherited value loses to any declaration, however weak.\n 'group flex flex-col items-center justify-center gap-2 rounded-md border border-dashed border-input bg-background px-6 py-8 text-center',\n // Border and fill are the drag feedback, so they carry the transition\n // — fast, because a zone that lights up after the pointer has already\n // crossed it is answering a question the reader stopped asking.\n 'transition-[color,background-color,border-color,box-shadow] duration-fast ease-out',\n // Focus lives on the clipped input, which is 1px and can show a reader\n // nothing. The zone wears the ring on its behalf, the same\n // focus-within arrangement TextField uses for its own inner input.\n 'focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-ring',\n !field.invalid && 'focus-within:shadow-halo',\n // The dash going solid is what keeps the drag state off colour alone.\n 'data-[dragging]:border-solid data-[dragging]:border-primary data-[dragging]:bg-primary-muted',\n // Drained, not dimmed. The zone is a large blank region whose whole\n // purpose is the two lines of text in the middle of it, and\n // `opacity-50` took the headline to 3.06:1 and the hint below it to\n // 2.05:1 — the reader least able to guess what a drop zone wants is\n // the one it stopped telling. The fill falls to the neutral well\n // instead, which is where every other unavailable surface in the\n // library goes, and both lines land at 4.67:1 over it. The dash stays,\n // because it is what marks this out as a drop target even while\n // nothing may be dropped on it; only its colour slackens, from\n // `input` to the lighter `border`, so the state is told in a weight\n // as well as in two fills rather than in hue alone.\n field.disabled\n ? 'cursor-not-allowed border-border bg-muted'\n : 'cursor-pointer hover:bg-subtle',\n // Last of the rules naming a border colour, and the order is\n // load-bearing: `cn()` resolves one by whichever class it saw last,\n // so a zone both refusing a file and unavailable would lose its\n // destructive rim to the disabled one if this sat above it.\n field.invalid && 'border-destructive focus-within:outline-destructive',\n )\n \"\n @dragenter=\"onDragEnter\"\n @dragleave=\"onDragLeave\"\n @dragover=\"onDragOver\"\n @drop=\"onDrop\"\n >\n <!-- `field.attrs` spreads **after** the fallthrough attrs, and that\n position is the contract (see TextField.vue): the bag has already\n resolved the caller's own id and merged their description with this\n zone's refusal message and the row's hint, and it drops every key\n that resolved to nothing, so it can only add. The `:aria-invalid` and\n `:aria-describedby` bindings that used to sit here went with it — an\n individual attribute written after a `v-bind` wins, so either one\n kept would overwrite the resolved value with the raw prop.\n\n `:id` is the deliberate exception, and not that failure: `inputId` is\n the bag's own id with the generated one beneath it, so it can only\n ever restate what the bag holds or supply the id the `<label for>`\n needs when the bag holds none. -->\n <input\n v-bind=\"{ ...inputAttrs, ...field.attrs }\"\n :id=\"inputId\"\n type=\"file\"\n :accept=\"accept\"\n :multiple=\"multiple\"\n :disabled=\"field.disabled\"\n class=\"sr-only\"\n @change=\"onSelect\"\n />\n <!-- The medallion, as EmptyState draws it: a 20px glyph alone in a large\n blank region has nothing holding it and reads as a stray mark. -->\n <span\n aria-hidden=\"true\"\n class=\"grid h-10 w-10 place-items-center rounded-full border border-border bg-subtle text-muted-foreground\"\n >\n <CloudUpload class=\"h-5 w-5\" />\n </span>\n <!-- The disabled colour is declared here rather than inherited from the\n zone, for the reason the `group` on it records: this span sets\n `text-foreground` itself, and an inherited value never beats a\n declared one. The hint below needs no such rule — it is already on\n the muted colour, which holds 4.67:1 over the drained fill. -->\n <span class=\"text-sm text-foreground group-data-[disabled]:text-muted-foreground\">{{\n zoneLabel\n }}</span>\n <span v-if=\"zoneHint\" class=\"text-small text-muted-foreground\">{{ zoneHint }}</span>\n </label>\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 —\n is 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-2 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\n <ul v-if=\"files.length > 0\" class=\"mt-3 flex flex-col gap-1.5\">\n <li\n v-for=\"(file, index) in files\"\n :key=\"rowId(file)\"\n class=\"flex animate-fade-rise items-center gap-2 rounded-md border border-border bg-card px-3 py-2\"\n :style=\"{ animationDelay: listStaggerDelay(index) }\"\n >\n <FileIcon class=\"h-4 w-4 shrink-0 text-muted-foreground\" aria-hidden=\"true\" />\n <span class=\"min-w-0 flex-1 truncate text-sm text-foreground\">{{ file.name }}</span>\n <span class=\"shrink-0 tabular text-small text-muted-foreground\">\n {{ text.size({ bytes: file.size }) }}\n </span>\n <!-- Named with the file it removes. Seven buttons all called \"Remove\"\n are seven identical announcements and one guess about which row a\n reader is on. -->\n <!-- Drained, not dimmed: `opacity-50` faded the glyph inside its own\n row card, compositing it below contrast — the failure Button\n records for its dim. The glyph-only control takes the neutral\n well, and the native attribute carries unavailability to AT. -->\n <button\n type=\"button\"\n :aria-label=\"text.remove({ file })\"\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 disabled:bg-muted disabled:shadow-none\"\n @click=\"remove(index)\"\n >\n <X class=\"h-4 w-4\" />\n </button>\n </li>\n </ul>\n </div>\n</template>\n"],"mappings":"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"}