@ecoma-io/loom 0.4.0 → 0.5.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 (251) hide show
  1. package/README.md +11 -9
  2. package/dist/a11y.js +2 -2
  3. package/dist/index.js +36 -1
  4. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/CalendarDate.js +1 -1
  5. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/CalendarDate.js.map +1 -1
  6. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/calendars/GregorianCalendar.js +1 -1
  7. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/calendars/GregorianCalendar.js.map +1 -1
  8. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/conversion.js +1 -1
  9. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/conversion.js.map +1 -1
  10. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/manipulation.js +1 -1
  11. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/manipulation.js.map +1 -1
  12. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/queries.js +1 -1
  13. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/queries.js.map +1 -1
  14. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/string.js +1 -1
  15. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/string.js.map +1 -1
  16. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/utils.js +1 -1
  17. package/dist/node_modules/.pnpm/{@internationalized_date@3.12.3 → @internationalized_date@3.12.4}/node_modules/@internationalized/date/dist/private/utils.js.map +1 -1
  18. package/dist/packages/blocks/empty-state/src/EmptyState.js.map +1 -1
  19. package/dist/packages/blocks/empty-state/src/EmptyState.vue.d.ts.map +1 -1
  20. package/dist/packages/blocks/empty-state/src/EmptyState.vue_vue_type_script_setup_true_lang.js +5 -6
  21. package/dist/packages/blocks/empty-state/src/EmptyState.vue_vue_type_script_setup_true_lang.js.map +1 -1
  22. package/dist/packages/blocks/error-summary/src/ErrorSummary.js +7 -0
  23. package/dist/packages/blocks/error-summary/src/ErrorSummary.js.map +1 -0
  24. package/dist/packages/blocks/error-summary/src/ErrorSummary.vue.d.ts +31 -0
  25. package/dist/packages/blocks/error-summary/src/ErrorSummary.vue_vue_type_script_setup_true_lang.js +90 -0
  26. package/dist/packages/blocks/error-summary/src/ErrorSummary.vue_vue_type_script_setup_true_lang.js.map +1 -0
  27. package/dist/packages/blocks/error-summary/src/index.d.ts +4 -0
  28. package/dist/packages/blocks/error-summary/src/index.js +3 -0
  29. package/dist/packages/composition/scroll-reel/src/ScrollReel.js.map +1 -1
  30. package/dist/packages/composition/scroll-reel/src/ScrollReel.vue_vue_type_script_setup_true_lang.js +1 -0
  31. package/dist/packages/composition/scroll-reel/src/ScrollReel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  32. package/dist/packages/composition/sidebar/src/Sidebar.js.map +1 -1
  33. package/dist/packages/composition/sidebar/src/Sidebar.vue.d.ts +4 -0
  34. package/dist/packages/composition/sidebar/src/Sidebar.vue.d.ts.map +1 -1
  35. package/dist/packages/composition/sidebar/src/Sidebar.vue_vue_type_script_setup_true_lang.js +13 -4
  36. package/dist/packages/composition/sidebar/src/Sidebar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  37. package/dist/packages/composition/split/src/Split.js.map +1 -1
  38. package/dist/packages/composition/split/src/Split.vue.d.ts +11 -12
  39. package/dist/packages/composition/split/src/Split.vue.d.ts.map +1 -1
  40. package/dist/packages/composition/split/src/Split.vue_vue_type_script_setup_true_lang.js +15 -5
  41. package/dist/packages/composition/split/src/Split.vue_vue_type_script_setup_true_lang.js.map +1 -1
  42. package/dist/packages/core/src/a11y-scope.d.ts +71 -5
  43. package/dist/packages/core/src/a11y-scope.d.ts.map +1 -1
  44. package/dist/packages/core/src/a11y-scope.js +126 -6
  45. package/dist/packages/core/src/a11y-scope.js.map +1 -1
  46. package/dist/packages/core/src/index.d.ts +1 -1
  47. package/dist/packages/core/src/index.d.ts.map +1 -1
  48. package/dist/packages/core/src/index.js +2 -2
  49. package/dist/packages/labels/src/component-shapes.d.ts +163 -1
  50. package/dist/packages/labels/src/component-shapes.d.ts.map +1 -1
  51. package/dist/packages/labels/src/date-labels.d.ts +82 -5
  52. package/dist/packages/labels/src/date-labels.d.ts.map +1 -1
  53. package/dist/packages/labels/src/date-labels.js +54 -7
  54. package/dist/packages/labels/src/date-labels.js.map +1 -1
  55. package/dist/packages/labels/src/field-context.d.ts +2 -2
  56. package/dist/packages/labels/src/field-context.js.map +1 -1
  57. package/dist/packages/labels/src/index.d.ts +3 -3
  58. package/dist/packages/labels/src/index.d.ts.map +1 -1
  59. package/dist/packages/labels/src/index.js +2 -2
  60. package/dist/packages/labels/src/label-registry.d.ts +9 -1
  61. package/dist/packages/labels/src/label-registry.d.ts.map +1 -1
  62. package/dist/packages/layouts/dashboard/src/Dashboard.js.map +1 -1
  63. package/dist/packages/layouts/dashboard/src/Dashboard.vue.d.ts +4 -4
  64. package/dist/packages/layouts/dashboard/src/Dashboard.vue.d.ts.map +1 -1
  65. package/dist/packages/layouts/dashboard/src/Dashboard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  66. package/dist/packages/layouts/settings/src/Settings.js.map +1 -1
  67. package/dist/packages/layouts/settings/src/Settings.vue.d.ts +3 -3
  68. package/dist/packages/layouts/settings/src/Settings.vue.d.ts.map +1 -1
  69. package/dist/packages/layouts/settings/src/Settings.vue_vue_type_script_setup_true_lang.js.map +1 -1
  70. package/dist/packages/layouts/split-layout/src/SplitLayout.js.map +1 -1
  71. package/dist/packages/layouts/split-layout/src/SplitLayout.vue.d.ts +4 -6
  72. package/dist/packages/layouts/split-layout/src/SplitLayout.vue.d.ts.map +1 -1
  73. package/dist/packages/layouts/split-layout/src/SplitLayout.vue_vue_type_script_setup_true_lang.js +20 -5
  74. package/dist/packages/layouts/split-layout/src/SplitLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  75. package/dist/packages/layouts/split-layout/src/index.d.ts +1 -1
  76. package/dist/packages/layouts/split-layout/src/index.d.ts.map +1 -1
  77. package/dist/packages/loom/src/a11y.d.ts +1 -1
  78. package/dist/packages/loom/src/index.d.ts +27 -1
  79. package/dist/packages/primitives/alert/src/Alert.js.map +1 -1
  80. package/dist/packages/primitives/alert/src/Alert.vue.d.ts +18 -0
  81. package/dist/packages/primitives/alert/src/Alert.vue_vue_type_script_setup_true_lang.js +10 -7
  82. package/dist/packages/primitives/alert/src/Alert.vue_vue_type_script_setup_true_lang.js.map +1 -1
  83. package/dist/packages/primitives/avatar/src/Avatar.js.map +1 -1
  84. package/dist/packages/primitives/avatar/src/Avatar.vue.d.ts +2 -2
  85. package/dist/packages/primitives/avatar/src/Avatar.vue.d.ts.map +1 -1
  86. package/dist/packages/primitives/avatar/src/Avatar.vue_vue_type_script_setup_true_lang.js +1 -1
  87. package/dist/packages/primitives/avatar/src/Avatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  88. package/dist/packages/primitives/calendar/src/Calendar.js +7 -0
  89. package/dist/packages/primitives/calendar/src/Calendar.js.map +1 -0
  90. package/dist/packages/primitives/calendar/src/Calendar.vue.d.ts +95 -0
  91. package/dist/packages/primitives/calendar/src/Calendar.vue_vue_type_script_setup_true_lang.js +204 -0
  92. package/dist/packages/primitives/calendar/src/Calendar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  93. package/dist/packages/primitives/calendar/src/index.d.ts +3 -0
  94. package/dist/packages/primitives/calendar/src/index.js +3 -0
  95. package/dist/packages/primitives/combobox/src/Combobox.vue.d.ts +1 -1
  96. package/dist/packages/primitives/command/src/Command.js +7 -0
  97. package/dist/packages/primitives/command/src/Command.js.map +1 -0
  98. package/dist/packages/primitives/command/src/Command.vue.d.ts +77 -0
  99. package/dist/packages/primitives/command/src/Command.vue_vue_type_script_setup_true_lang.js +333 -0
  100. package/dist/packages/primitives/command/src/Command.vue_vue_type_script_setup_true_lang.js.map +1 -0
  101. package/dist/packages/primitives/command/src/index.d.ts +4 -0
  102. package/dist/packages/primitives/command/src/index.js +3 -0
  103. package/dist/packages/primitives/copy-button/src/CopyButton.js +7 -0
  104. package/dist/packages/primitives/copy-button/src/CopyButton.js.map +1 -0
  105. package/dist/packages/primitives/copy-button/src/CopyButton.vue.d.ts +64 -0
  106. package/dist/packages/primitives/copy-button/src/CopyButton.vue_vue_type_script_setup_true_lang.js +113 -0
  107. package/dist/packages/primitives/copy-button/src/CopyButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
  108. package/dist/packages/primitives/copy-button/src/index.d.ts +4 -0
  109. package/dist/packages/primitives/copy-button/src/index.js +3 -0
  110. package/dist/packages/primitives/data-grid/src/DataGrid.js +7 -0
  111. package/dist/packages/primitives/data-grid/src/DataGrid.js.map +1 -0
  112. package/dist/packages/primitives/data-grid/src/DataGrid.vue.d.ts +128 -0
  113. package/dist/packages/primitives/data-grid/src/DataGrid.vue_vue_type_script_setup_true_lang.js +347 -0
  114. package/dist/packages/primitives/data-grid/src/DataGrid.vue_vue_type_script_setup_true_lang.js.map +1 -0
  115. package/dist/packages/primitives/data-grid/src/index.d.ts +4 -0
  116. package/dist/packages/primitives/data-grid/src/index.js +3 -0
  117. package/dist/packages/primitives/date-picker/src/DatePicker.js.map +1 -1
  118. package/dist/packages/primitives/date-picker/src/DatePicker.vue_vue_type_script_setup_true_lang.js +13 -13
  119. package/dist/packages/primitives/date-picker/src/DatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  120. package/dist/packages/primitives/date-range-picker/src/DateRangePicker.js.map +1 -1
  121. package/dist/packages/primitives/date-range-picker/src/DateRangePicker.vue_vue_type_script_setup_true_lang.js +21 -18
  122. package/dist/packages/primitives/date-range-picker/src/DateRangePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  123. package/dist/packages/primitives/date-time-picker/src/DateTimePicker.js.map +1 -1
  124. package/dist/packages/primitives/date-time-picker/src/DateTimePicker.vue_vue_type_script_setup_true_lang.js +17 -16
  125. package/dist/packages/primitives/date-time-picker/src/DateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  126. package/dist/packages/primitives/date-time-range-picker/src/DateTimeRangePicker.js.map +1 -1
  127. package/dist/packages/primitives/date-time-range-picker/src/DateTimeRangePicker.vue_vue_type_script_setup_true_lang.js +17 -16
  128. package/dist/packages/primitives/date-time-range-picker/src/DateTimeRangePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  129. package/dist/packages/primitives/dialog/src/Dialog.js.map +1 -1
  130. package/dist/packages/primitives/dialog/src/Dialog.vue.d.ts +15 -7
  131. package/dist/packages/primitives/dialog/src/Dialog.vue_vue_type_script_setup_true_lang.js +5 -3
  132. package/dist/packages/primitives/dialog/src/Dialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  133. package/dist/packages/primitives/drawer/src/Drawer.js.map +1 -1
  134. package/dist/packages/primitives/drawer/src/Drawer.vue.d.ts +10 -2
  135. package/dist/packages/primitives/drawer/src/Drawer.vue_vue_type_script_setup_true_lang.js +11 -3
  136. package/dist/packages/primitives/drawer/src/Drawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  137. package/dist/packages/primitives/hover-card/src/index.d.ts.map +1 -1
  138. package/dist/packages/primitives/live-region/src/LiveRegion.js +7 -0
  139. package/dist/packages/primitives/live-region/src/LiveRegion.js.map +1 -0
  140. package/dist/packages/primitives/live-region/src/LiveRegion.vue.d.ts +36 -0
  141. package/dist/packages/primitives/live-region/src/LiveRegion.vue.d.ts.map +1 -0
  142. package/dist/packages/primitives/live-region/src/LiveRegion.vue_vue_type_script_setup_true_lang.js +59 -0
  143. package/dist/packages/primitives/live-region/src/LiveRegion.vue_vue_type_script_setup_true_lang.js.map +1 -0
  144. package/dist/packages/primitives/live-region/src/context.d.ts +40 -0
  145. package/dist/packages/primitives/live-region/src/context.d.ts.map +1 -0
  146. package/dist/packages/primitives/live-region/src/context.js +85 -0
  147. package/dist/packages/primitives/live-region/src/context.js.map +1 -0
  148. package/dist/packages/primitives/live-region/src/index.d.ts +4 -0
  149. package/dist/packages/primitives/live-region/src/index.d.ts.map +1 -0
  150. package/dist/packages/primitives/live-region/src/index.js +3 -0
  151. package/dist/packages/primitives/live-region/src/useAnnounce.d.ts +17 -0
  152. package/dist/packages/primitives/live-region/src/useAnnounce.d.ts.map +1 -0
  153. package/dist/packages/primitives/live-region/src/useAnnounce.js +25 -0
  154. package/dist/packages/primitives/live-region/src/useAnnounce.js.map +1 -0
  155. package/dist/packages/primitives/menubar/src/Menubar.js.map +1 -1
  156. package/dist/packages/primitives/menubar/src/Menubar.vue.d.ts.map +1 -1
  157. package/dist/packages/primitives/menubar/src/Menubar.vue_vue_type_script_setup_true_lang.js +33 -0
  158. package/dist/packages/primitives/menubar/src/Menubar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  159. package/dist/packages/primitives/meter/src/Meter.js +7 -0
  160. package/dist/packages/primitives/meter/src/Meter.js.map +1 -0
  161. package/dist/packages/primitives/meter/src/Meter.vue.d.ts +87 -0
  162. package/dist/packages/primitives/meter/src/Meter.vue_vue_type_script_setup_true_lang.js +236 -0
  163. package/dist/packages/primitives/meter/src/Meter.vue_vue_type_script_setup_true_lang.js.map +1 -0
  164. package/dist/packages/primitives/meter/src/index.d.ts +4 -0
  165. package/dist/packages/primitives/meter/src/index.js +3 -0
  166. package/dist/packages/primitives/navigation-menu/src/NavigationMenu.js +7 -0
  167. package/dist/packages/primitives/navigation-menu/src/NavigationMenu.js.map +1 -0
  168. package/dist/packages/primitives/navigation-menu/src/NavigationMenu.vue.d.ts +69 -0
  169. package/dist/packages/primitives/navigation-menu/src/NavigationMenu.vue.d.ts.map +1 -0
  170. package/dist/packages/primitives/navigation-menu/src/NavigationMenu.vue_vue_type_script_setup_true_lang.js +118 -0
  171. package/dist/packages/primitives/navigation-menu/src/NavigationMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  172. package/dist/packages/primitives/navigation-menu/src/index.d.ts +3 -0
  173. package/dist/packages/primitives/navigation-menu/src/index.d.ts.map +1 -0
  174. package/dist/packages/primitives/navigation-menu/src/index.js +2 -0
  175. package/dist/packages/primitives/segmented-control/src/SegmentedControl.js.map +1 -1
  176. package/dist/packages/primitives/segmented-control/src/SegmentedControl.vue.d.ts.map +1 -1
  177. package/dist/packages/primitives/segmented-control/src/SegmentedControl.vue_vue_type_script_setup_true_lang.js +1 -1
  178. package/dist/packages/primitives/segmented-control/src/SegmentedControl.vue_vue_type_script_setup_true_lang.js.map +1 -1
  179. package/dist/packages/primitives/skip-link/src/SkipLink.js +7 -0
  180. package/dist/packages/primitives/skip-link/src/SkipLink.js.map +1 -0
  181. package/dist/packages/primitives/skip-link/src/SkipLink.vue.d.ts +62 -0
  182. package/dist/packages/primitives/skip-link/src/SkipLink.vue_vue_type_script_setup_true_lang.js +64 -0
  183. package/dist/packages/primitives/skip-link/src/SkipLink.vue_vue_type_script_setup_true_lang.js.map +1 -0
  184. package/dist/packages/primitives/skip-link/src/index.d.ts +3 -0
  185. package/dist/packages/primitives/skip-link/src/index.js +3 -0
  186. package/dist/packages/primitives/stepper/src/Stepper.js.map +1 -1
  187. package/dist/packages/primitives/stepper/src/Stepper.vue_vue_type_script_setup_true_lang.js +7 -5
  188. package/dist/packages/primitives/stepper/src/Stepper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  189. package/dist/packages/primitives/switch/src/Switch.js.map +1 -1
  190. package/dist/packages/primitives/switch/src/Switch.vue.d.ts.map +1 -1
  191. package/dist/packages/primitives/switch/src/Switch.vue_vue_type_script_setup_true_lang.js +1 -1
  192. package/dist/packages/primitives/switch/src/Switch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  193. package/dist/packages/primitives/table/src/index.d.ts +1 -1
  194. package/dist/packages/primitives/table/src/index.js +2 -2
  195. package/dist/packages/primitives/time-picker/src/TimePicker.js.map +1 -1
  196. package/dist/packages/primitives/time-picker/src/TimePicker.vue_vue_type_script_setup_true_lang.js +10 -8
  197. package/dist/packages/primitives/time-picker/src/TimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  198. package/dist/packages/primitives/toast/src/ToastItem.js.map +1 -1
  199. package/dist/packages/primitives/toast/src/ToastItem.vue_vue_type_script_setup_true_lang.js +3 -1
  200. package/dist/packages/primitives/toast/src/ToastItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  201. package/dist/packages/primitives/toggle-group/src/ToggleGroup.js +7 -0
  202. package/dist/packages/primitives/toggle-group/src/ToggleGroup.js.map +1 -0
  203. package/dist/packages/primitives/toggle-group/src/ToggleGroup.vue.d.ts +53 -0
  204. package/dist/packages/primitives/toggle-group/src/ToggleGroup.vue.d.ts.map +1 -0
  205. package/dist/packages/primitives/toggle-group/src/ToggleGroup.vue_vue_type_script_setup_true_lang.js +111 -0
  206. package/dist/packages/primitives/toggle-group/src/ToggleGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
  207. package/dist/packages/primitives/toggle-group/src/index.d.ts +3 -0
  208. package/dist/packages/primitives/toggle-group/src/index.d.ts.map +1 -0
  209. package/dist/packages/primitives/toggle-group/src/index.js +2 -0
  210. package/dist/packages/primitives/toolbar/src/Toolbar.js +7 -0
  211. package/dist/packages/primitives/toolbar/src/Toolbar.js.map +1 -0
  212. package/dist/packages/primitives/toolbar/src/Toolbar.vue.d.ts +31 -0
  213. package/dist/packages/primitives/toolbar/src/Toolbar.vue.d.ts.map +1 -0
  214. package/dist/packages/primitives/toolbar/src/Toolbar.vue_vue_type_script_setup_true_lang.js +149 -0
  215. package/dist/packages/primitives/toolbar/src/Toolbar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  216. package/dist/packages/primitives/toolbar/src/ToolbarSeparator.js +7 -0
  217. package/dist/packages/primitives/toolbar/src/ToolbarSeparator.js.map +1 -0
  218. package/dist/packages/primitives/toolbar/src/ToolbarSeparator.vue.d.ts +24 -0
  219. package/dist/packages/primitives/toolbar/src/ToolbarSeparator.vue.d.ts.map +1 -0
  220. package/dist/packages/primitives/toolbar/src/ToolbarSeparator.vue_vue_type_script_setup_true_lang.js +40 -0
  221. package/dist/packages/primitives/toolbar/src/ToolbarSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -0
  222. package/dist/packages/primitives/toolbar/src/index.d.ts +4 -0
  223. package/dist/packages/primitives/toolbar/src/index.d.ts.map +1 -0
  224. package/dist/packages/primitives/toolbar/src/index.js +3 -0
  225. package/dist/packages/primitives/tree-view/src/TreeView.js +7 -0
  226. package/dist/packages/primitives/tree-view/src/TreeView.js.map +1 -0
  227. package/dist/packages/primitives/tree-view/src/TreeView.vue.d.ts +99 -0
  228. package/dist/packages/primitives/tree-view/src/TreeView.vue_vue_type_script_setup_true_lang.js +310 -0
  229. package/dist/packages/primitives/tree-view/src/TreeView.vue_vue_type_script_setup_true_lang.js.map +1 -0
  230. package/dist/packages/primitives/tree-view/src/TreeViewNode.js +7 -0
  231. package/dist/packages/primitives/tree-view/src/TreeViewNode.js.map +1 -0
  232. package/dist/packages/primitives/tree-view/src/TreeViewNode.vue.d.ts +15 -0
  233. package/dist/packages/primitives/tree-view/src/TreeViewNode.vue.d.ts.map +1 -0
  234. package/dist/packages/primitives/tree-view/src/TreeViewNode.vue_vue_type_script_setup_true_lang.js +103 -0
  235. package/dist/packages/primitives/tree-view/src/TreeViewNode.vue_vue_type_script_setup_true_lang.js.map +1 -0
  236. package/dist/packages/primitives/tree-view/src/context.d.ts +39 -0
  237. package/dist/packages/primitives/tree-view/src/context.d.ts.map +1 -0
  238. package/dist/packages/primitives/tree-view/src/context.js +6 -0
  239. package/dist/packages/primitives/tree-view/src/context.js.map +1 -0
  240. package/dist/packages/primitives/tree-view/src/index.d.ts +4 -0
  241. package/dist/packages/primitives/tree-view/src/index.js +3 -0
  242. package/dist/packages/primitives/visually-hidden/src/VisuallyHidden.js +7 -0
  243. package/dist/packages/primitives/visually-hidden/src/VisuallyHidden.js.map +1 -0
  244. package/dist/packages/primitives/visually-hidden/src/VisuallyHidden.vue.d.ts +21 -0
  245. package/dist/packages/primitives/visually-hidden/src/VisuallyHidden.vue.d.ts.map +1 -0
  246. package/dist/packages/primitives/visually-hidden/src/VisuallyHidden.vue_vue_type_script_setup_true_lang.js +27 -0
  247. package/dist/packages/primitives/visually-hidden/src/VisuallyHidden.vue_vue_type_script_setup_true_lang.js.map +1 -0
  248. package/dist/packages/primitives/visually-hidden/src/index.d.ts +3 -0
  249. package/dist/packages/primitives/visually-hidden/src/index.d.ts.map +1 -0
  250. package/dist/packages/primitives/visually-hidden/src/index.js +2 -0
  251. package/package.json +29 -28
@@ -0,0 +1,333 @@
1
+ import { cn } from "../../../core/src/cn.js";
2
+ import "../../../core/src/index.js";
3
+ import { useLabels } from "../../../labels/src/labels.js";
4
+ import "../../../labels/src/index.js";
5
+ import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, nextTick, normalizeClass, openBlock, ref, renderList, toDisplayString, unref, useId, watch } from "vue";
6
+ //#region packages/primitives/command/src/Command.vue?vue&type=script&setup=true&lang.ts
7
+ var _hoisted_1 = ["data-state"];
8
+ var _hoisted_2 = { class: "flex items-center border-b border-border" };
9
+ var _hoisted_3 = [
10
+ "id",
11
+ "aria-controls",
12
+ "aria-activedescendant",
13
+ "aria-labelledby",
14
+ "aria-label",
15
+ "placeholder",
16
+ "value"
17
+ ];
18
+ var _hoisted_4 = ["id", "aria-labelledby"];
19
+ var _hoisted_5 = ["id"];
20
+ var _hoisted_6 = [
21
+ "id",
22
+ "aria-selected",
23
+ "aria-disabled",
24
+ "data-active",
25
+ "onMouseenter",
26
+ "onClick"
27
+ ];
28
+ var _hoisted_7 = {
29
+ key: 0,
30
+ class: "text-xs text-muted-foreground"
31
+ };
32
+ var _hoisted_8 = {
33
+ key: 0,
34
+ role: "option",
35
+ "aria-selected": "false",
36
+ "aria-disabled": "true",
37
+ class: "px-2 py-6 text-center text-sm text-muted-foreground"
38
+ };
39
+ var _hoisted_9 = ["id"];
40
+ /**
41
+ * Loom's English, co-located with the component so it tree-shakes with it.
42
+ * Every string a Command actually says is the chrome around the host's items,
43
+ * so the whole slot is here and none of it hides in the template.
44
+ */
45
+ var COMMAND_LABELS = {
46
+ placeholder: "Type to search…",
47
+ emptyMessage: "No results found.",
48
+ searchLabel: "Search",
49
+ resultSingular: "{count} result available",
50
+ resultPlural: "{count} results available"
51
+ };
52
+ var Command_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
53
+ __name: "Command",
54
+ props: {
55
+ items: {},
56
+ groups: {},
57
+ query: { default: void 0 },
58
+ open: {
59
+ type: Boolean,
60
+ default: void 0
61
+ },
62
+ labels: { default: void 0 },
63
+ ariaLabelledby: {}
64
+ },
65
+ emits: [
66
+ "select",
67
+ "update:query",
68
+ "update:open"
69
+ ],
70
+ setup(__props, { emit: __emit }) {
71
+ const props = __props;
72
+ const emit = __emit;
73
+ const resolvedLabels = useLabels("command", COMMAND_LABELS, () => props.labels);
74
+ const inputId = useId();
75
+ const listboxId = useId();
76
+ const liveRegionId = useId();
77
+ /**
78
+ * The controlled/uncontrolled query. When `query` is bound from outside, the
79
+ * prop wins; otherwise the component owns its own state.
80
+ */
81
+ const internalQuery = ref("");
82
+ const queryValue = computed(() => props.query ?? internalQuery.value);
83
+ function setQuery(value) {
84
+ internalQuery.value = value;
85
+ emit("update:query", value);
86
+ }
87
+ /**
88
+ * The controlled/uncontrolled open state. `true` when the listbox is visible.
89
+ */
90
+ const internalOpen = ref(true);
91
+ const isOpen = computed(() => props.open ?? internalOpen.value);
92
+ function setOpen(value) {
93
+ if (props.open !== void 0) emit("update:open", value);
94
+ else internalOpen.value = value;
95
+ }
96
+ /**
97
+ * Bring the listbox back after Escape closed it. Focus never leaves the
98
+ * search input, so without this a closed Command is a dead end — the only
99
+ * escape, before this fix, was unmounting the component. Controlled mode is
100
+ * untouched: the emit the host chose stays with the host, and this rewrites
101
+ * only the fallback state a host never bound.
102
+ */
103
+ function restoreOpen() {
104
+ if (props.open === void 0) internalOpen.value = true;
105
+ }
106
+ /**
107
+ * The index of the highlighted item within the filtered list. Reset to `0`
108
+ * whenever the query changes so the first match is always ready to select.
109
+ */
110
+ const highlightedIndex = ref(0);
111
+ const listboxRef = ref(null);
112
+ watch([highlightedIndex, isOpen], async () => {
113
+ if (!isOpen.value) return;
114
+ await nextTick();
115
+ listboxRef.value?.querySelector("[data-active]")?.scrollIntoView?.({ block: "nearest" });
116
+ });
117
+ /**
118
+ * Items filtered by the current query. Case-insensitive substring match
119
+ * across `label`, `description` and `value`.
120
+ */
121
+ const filteredItems = computed(() => {
122
+ const needle = queryValue.value.trim().toLowerCase();
123
+ if (!needle) return props.items;
124
+ return props.items.filter((item) => {
125
+ return [
126
+ item.label,
127
+ item.description ?? "",
128
+ item.value
129
+ ].join(" ").toLowerCase().includes(needle);
130
+ });
131
+ });
132
+ /**
133
+ * Items grouped for rendering. Each entry is either a group heading or a flat
134
+ * item. Groups with no matching items are omitted entirely.
135
+ */
136
+ const renderEntries = computed(() => {
137
+ if (filteredItems.value.length === 0) return [];
138
+ const groupDefs = props.groups;
139
+ if (!groupDefs || groupDefs.length === 0) return filteredItems.value.map((item, i) => ({
140
+ kind: "item",
141
+ item,
142
+ globalIndex: i
143
+ }));
144
+ const ungrouped = [];
145
+ const grouped = /* @__PURE__ */ new Map();
146
+ for (const item of filteredItems.value) if (item.group) {
147
+ const list = grouped.get(item.group) ?? [];
148
+ list.push(item);
149
+ grouped.set(item.group, list);
150
+ } else ungrouped.push(item);
151
+ const entries = [];
152
+ let globalIndex = 0;
153
+ for (const def of groupDefs) {
154
+ const items = grouped.get(def.heading);
155
+ if (!items || items.length === 0) continue;
156
+ entries.push({
157
+ kind: "heading",
158
+ heading: def.heading,
159
+ groupId: `${inputId}-group-${def.heading}`
160
+ });
161
+ for (const item of items) {
162
+ entries.push({
163
+ kind: "item",
164
+ item,
165
+ globalIndex
166
+ });
167
+ globalIndex++;
168
+ }
169
+ }
170
+ for (const item of ungrouped) {
171
+ entries.push({
172
+ kind: "item",
173
+ item,
174
+ globalIndex
175
+ });
176
+ globalIndex++;
177
+ }
178
+ return entries;
179
+ });
180
+ /**
181
+ * The item list for the non-grouped case, used by keyboard navigation. Derived
182
+ * from `renderEntries` so the two are always in sync.
183
+ */
184
+ const flatItems = computed(() => renderEntries.value.filter((e) => e.kind === "item"));
185
+ /**
186
+ * Keep the highlight within bounds. A filter that removes items can strand the
187
+ * index past the end.
188
+ */
189
+ watch(flatItems, (items) => {
190
+ if (highlightedIndex.value >= items.length) highlightedIndex.value = Math.max(0, items.length - 1);
191
+ });
192
+ /**
193
+ * The documented reset: the highlight returns to the first match whenever the
194
+ * query changes — whether the query came from typing or from a parent updating
195
+ * the controlled `query` prop. Typing reaches this watcher through `setQuery`,
196
+ * which is why onInput no longer resets the highlight itself.
197
+ */
198
+ watch(queryValue, () => {
199
+ highlightedIndex.value = 0;
200
+ });
201
+ /**
202
+ * The total number of results, announced to assistive technology through a live
203
+ * region. Changes only when the filtered set changes, not on every keystroke.
204
+ */
205
+ const resultCount = computed(() => filteredItems.value.length);
206
+ const announcement = ref("");
207
+ watch(resultCount, (count) => {
208
+ const template = count === 1 ? resolvedLabels.value.resultSingular : resolvedLabels.value.resultPlural;
209
+ announcement.value = template.replace("{count}", String(count));
210
+ });
211
+ /**
212
+ * The currently highlighted item, or `undefined` when the list is empty.
213
+ */
214
+ const highlightedItem = computed(() => flatItems.value[highlightedIndex.value]?.item);
215
+ function highlightUp() {
216
+ if (flatItems.value.length === 0) return;
217
+ highlightedIndex.value = highlightedIndex.value <= 0 ? flatItems.value.length - 1 : highlightedIndex.value - 1;
218
+ }
219
+ function highlightDown() {
220
+ if (flatItems.value.length === 0) return;
221
+ highlightedIndex.value = highlightedIndex.value >= flatItems.value.length - 1 ? 0 : highlightedIndex.value + 1;
222
+ }
223
+ function selectHighlighted() {
224
+ const item = highlightedItem.value;
225
+ if (!item || item.disabled) return;
226
+ emit("select", item.value);
227
+ }
228
+ function onKeydown(event) {
229
+ if (!isOpen.value && event.key !== "Escape" && event.key !== "Tab") restoreOpen();
230
+ switch (event.key) {
231
+ case "ArrowDown":
232
+ event.preventDefault();
233
+ highlightDown();
234
+ break;
235
+ case "ArrowUp":
236
+ event.preventDefault();
237
+ highlightUp();
238
+ break;
239
+ case "Enter":
240
+ event.preventDefault();
241
+ selectHighlighted();
242
+ break;
243
+ case "Escape":
244
+ event.preventDefault();
245
+ if (queryValue.value.length > 0) setQuery("");
246
+ else setOpen(false);
247
+ break;
248
+ case "Home":
249
+ event.preventDefault();
250
+ if (flatItems.value.length > 0) highlightedIndex.value = 0;
251
+ break;
252
+ case "End":
253
+ event.preventDefault();
254
+ if (flatItems.value.length > 0) highlightedIndex.value = flatItems.value.length - 1;
255
+ }
256
+ }
257
+ function onInput(event) {
258
+ const value = event.target.value;
259
+ setQuery(value);
260
+ }
261
+ function selectItem(item) {
262
+ if (item.disabled) return;
263
+ emit("select", item.value);
264
+ }
265
+ function itemId(index) {
266
+ return `${inputId}-option-${String(index)}`;
267
+ }
268
+ return (_ctx, _cache) => {
269
+ return openBlock(), createElementBlock("div", {
270
+ "data-state": isOpen.value ? "open" : "closed",
271
+ class: normalizeClass(unref(cn)("rounded-md border border-border bg-popover text-popover-foreground shadow-md overflow-hidden", "outline-none"))
272
+ }, [
273
+ createElementVNode("div", _hoisted_2, [createElementVNode("input", {
274
+ id: unref(inputId),
275
+ type: "text",
276
+ role: "searchbox",
277
+ autocomplete: "off",
278
+ autocorrect: "off",
279
+ spellcheck: "false",
280
+ "aria-autocomplete": "list",
281
+ "aria-controls": unref(listboxId),
282
+ "aria-activedescendant": highlightedItem.value ? itemId(highlightedIndex.value) : void 0,
283
+ "aria-labelledby": __props.ariaLabelledby,
284
+ "aria-label": __props.ariaLabelledby ? void 0 : unref(resolvedLabels).searchLabel,
285
+ placeholder: unref(resolvedLabels).placeholder,
286
+ value: queryValue.value,
287
+ class: "w-full px-3 py-2 text-sm bg-transparent text-foreground border-none outline-none placeholder:text-muted-foreground",
288
+ onInput,
289
+ onKeydown,
290
+ onFocus: restoreOpen,
291
+ onClick: restoreOpen
292
+ }, null, 40, _hoisted_3)]),
293
+ isOpen.value ? (openBlock(), createElementBlock("div", {
294
+ key: 0,
295
+ id: unref(listboxId),
296
+ ref_key: "listboxRef",
297
+ ref: listboxRef,
298
+ role: "listbox",
299
+ tabindex: "0",
300
+ "aria-labelledby": unref(inputId),
301
+ class: "max-h-[300px] overflow-y-auto p-1"
302
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(renderEntries.value, (entry) => {
303
+ return openBlock(), createElementBlock(Fragment, { key: entry.kind === "heading" ? entry.groupId : entry.item.value }, [entry.kind === "heading" ? (openBlock(), createElementBlock("div", {
304
+ key: 0,
305
+ id: entry.groupId,
306
+ role: "presentation",
307
+ class: "px-2 py-1.5 text-micro font-medium uppercase tracking-wide text-muted-foreground"
308
+ }, toDisplayString(entry.heading), 9, _hoisted_5)) : (openBlock(), createElementBlock("div", {
309
+ key: 1,
310
+ id: itemId(entry.globalIndex),
311
+ role: "option",
312
+ "aria-selected": highlightedIndex.value === entry.globalIndex,
313
+ "aria-disabled": entry.item.disabled || void 0,
314
+ "data-active": highlightedIndex.value === entry.globalIndex || void 0,
315
+ class: "flex flex-col gap-0.5 rounded-sm px-2 py-1.5 text-sm cursor-pointer outline-none transition-colors duration-fast ease-out data-[active]:bg-primary-muted data-[active]:text-primary-text",
316
+ onMouseenter: ($event) => highlightedIndex.value = entry.globalIndex,
317
+ onClick: ($event) => selectItem(entry.item)
318
+ }, [createElementVNode("span", null, toDisplayString(entry.item.label), 1), entry.item.description ? (openBlock(), createElementBlock("span", _hoisted_7, toDisplayString(entry.item.description), 1)) : createCommentVNode("", true)], 40, _hoisted_6))], 64);
319
+ }), 128)), filteredItems.value.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_8, toDisplayString(unref(resolvedLabels).emptyMessage), 1)) : createCommentVNode("", true)], 8, _hoisted_4)) : createCommentVNode("", true),
320
+ createElementVNode("span", {
321
+ id: unref(liveRegionId),
322
+ role: "status",
323
+ "aria-live": "polite",
324
+ class: "sr-only"
325
+ }, toDisplayString(announcement.value), 9, _hoisted_9)
326
+ ], 10, _hoisted_1);
327
+ };
328
+ }
329
+ });
330
+ //#endregion
331
+ export { COMMAND_LABELS, Command_vue_vue_type_script_setup_true_lang_default as default };
332
+
333
+ //# sourceMappingURL=Command.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Command.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../../packages/primitives/command/src/Command.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { CommandLabels, LabelOverrides } from \"@ecoma-io/loom-labels\";\n/**\n * One searchable item in the command list. `value` is what the host receives on\n * select; `label` is what the reader sees and what the filter matches against.\n *\n * Deliberately not `ComboboxOption` or `DropdownMenuEntry`: those shapes carry\n * `modelValue` and `separator` fields respectively, and either would be\n * dead weight here — a command is an action, not a value or a menu row.\n */\nexport interface CommandItem {\n /** Unique key. */\n value: string;\n /** Visible label. */\n label: string;\n /** Optional description shown below the label. */\n description?: string;\n /** Group heading this item belongs to. */\n group?: string;\n /** Disabled state. */\n disabled?: boolean;\n}\n\n/**\n * A named section heading above a run of items. Only rendered when the group\n * contains at least one item that survived the current filter.\n */\nexport interface CommandGroup {\n /** Group heading text. */\n heading: string;\n}\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it.\n * Every string a Command actually says is the chrome around the host's items,\n * so the whole slot is here and none of it hides in the template.\n */\nexport const COMMAND_LABELS: CommandLabels = {\n placeholder: \"Type to search…\",\n emptyMessage: \"No results found.\",\n searchLabel: \"Search\",\n resultSingular: \"{count} result available\",\n resultPlural: \"{count} results available\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useId, watch } from \"vue\";\nimport { cn } from \"@ecoma-io/loom-core\";\nimport { useLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n * Command — a keyboard-driven command search, the universal \"Cmd+K\" pattern.\n *\n * A text input that narrows a grouped list as you type, for executing actions\n * rather than selecting values. Its neighbour is `Combobox`, which selects a\n * value for a form field; this control runs an action and has no `modelValue`.\n *\n * The two are one family in the same way a Combobox and a Select are: the same\n * surface vocabulary, the same tokens, the same keyboard model. What differs is\n * intent — \"open settings\" is not a value you could submit in a form — and that\n * intent shapes the API: `onSelect` rather than `v-model`.\n *\n * Built from native ARIA roles rather than Reka UI, because Reka ships no\n * Command primitive. The semantics follow the WAI-ARIA combobox pattern with\n * `aria-activedescendant` navigation: focus stays in the input while the\n * highlighted item moves, which is the only model that keeps typing fluid.\n *\n * `aria-expanded` is deliberately absent. The input is a fixed searchbox, not\n * a popover trigger, so it has no collapsed state to announce: the listbox is\n * visible on mount and returns on any interaction after Escape closes it.\n */\nconst props = withDefaults(\n defineProps<{\n /** The items to search through. */\n items: CommandItem[];\n /** Optional group definitions for section headers. */\n groups?: CommandGroup[];\n /** Controlled search query. */\n query?: string | undefined;\n /** Whether the command menu is open. */\n open?: boolean | undefined;\n /** Names for the strings this control supplies itself. */\n labels?: LabelOverrides<CommandLabels> | undefined;\n /** Accessible label by reference for the search input. */\n ariaLabelledby?: string;\n }>(),\n {\n query: undefined,\n open: undefined,\n labels: undefined,\n },\n);\n\nconst emit = defineEmits<{\n /** Fired when an item is selected. */\n select: [value: string];\n /** Fired when the query changes. */\n \"update:query\": [value: string];\n /** Fired when open state changes. */\n \"update:open\": [value: boolean];\n}>();\n\nconst resolvedLabels = useLabels(\"command\", COMMAND_LABELS, () => props.labels);\n\nconst inputId = useId();\nconst listboxId = useId();\nconst liveRegionId = useId();\n\n/**\n * The controlled/uncontrolled query. When `query` is bound from outside, the\n * prop wins; otherwise the component owns its own state.\n */\nconst internalQuery = ref(\"\");\nconst queryValue = computed(() => props.query ?? internalQuery.value);\n\nfunction setQuery(value: string): void {\n internalQuery.value = value;\n emit(\"update:query\", value);\n}\n\n/**\n * The controlled/uncontrolled open state. `true` when the listbox is visible.\n */\nconst internalOpen = ref(true);\nconst isOpen = computed(() => props.open ?? internalOpen.value);\n\nfunction setOpen(value: boolean): void {\n if (props.open !== undefined) {\n emit(\"update:open\", value);\n } else {\n internalOpen.value = value;\n }\n}\n\n/**\n * Bring the listbox back after Escape closed it. Focus never leaves the\n * search input, so without this a closed Command is a dead end — the only\n * escape, before this fix, was unmounting the component. Controlled mode is\n * untouched: the emit the host chose stays with the host, and this rewrites\n * only the fallback state a host never bound.\n */\nfunction restoreOpen(): void {\n if (props.open === undefined) internalOpen.value = true;\n}\n\n/**\n * The index of the highlighted item within the filtered list. Reset to `0`\n * whenever the query changes so the first match is always ready to select.\n */\nconst highlightedIndex = ref(0);\n\nconst listboxRef = ref<HTMLElement | null>(null);\n\n// Arrow-key focus never leaves the input (aria-activedescendant), so the\n// scrollable listbox must be tab-reachable itself — an overflow container no\n// keyboard can reach is the scrollable-region-focusable violation the harness\n// axe gate exists to catch. Scrolling the highlighted option into view is the\n// other half: an active item moved off-screen is navigation the user cannot\n// see. jsdom has no scrollIntoView, hence the optional call.\nwatch([highlightedIndex, isOpen], async () => {\n if (!isOpen.value) return;\n await nextTick();\n listboxRef.value?.querySelector(\"[data-active]\")?.scrollIntoView?.({ block: \"nearest\" });\n});\n\n/**\n * Items filtered by the current query. Case-insensitive substring match\n * across `label`, `description` and `value`.\n */\nconst filteredItems = computed(() => {\n const needle = queryValue.value.trim().toLowerCase();\n if (!needle) return props.items;\n return props.items.filter((item) => {\n const haystack = [item.label, item.description ?? \"\", item.value].join(\" \").toLowerCase();\n return haystack.includes(needle);\n });\n});\n\n/**\n * Items grouped for rendering. Each entry is either a group heading or a flat\n * item. Groups with no matching items are omitted entirely.\n */\ninterface GroupedEntry {\n kind: \"heading\";\n heading: string;\n groupId: string;\n}\n\ninterface GroupedItem {\n kind: \"item\";\n item: CommandItem;\n globalIndex: number;\n}\n\ntype RenderEntry = GroupedEntry | GroupedItem;\n\nconst renderEntries = computed<RenderEntry[]>(() => {\n if (filteredItems.value.length === 0) return [];\n\n const groupDefs = props.groups;\n if (!groupDefs || groupDefs.length === 0) {\n return filteredItems.value.map((item, i) => ({ kind: \"item\", item, globalIndex: i }));\n }\n\n const ungrouped: CommandItem[] = [];\n const grouped = new Map<string, CommandItem[]>();\n\n for (const item of filteredItems.value) {\n if (item.group) {\n const list = grouped.get(item.group) ?? [];\n list.push(item);\n grouped.set(item.group, list);\n } else {\n ungrouped.push(item);\n }\n }\n\n const entries: RenderEntry[] = [];\n let globalIndex = 0;\n\n for (const def of groupDefs) {\n const items = grouped.get(def.heading);\n if (!items || items.length === 0) continue;\n entries.push({\n kind: \"heading\",\n heading: def.heading,\n groupId: `${inputId}-group-${def.heading}`,\n });\n for (const item of items) {\n entries.push({ kind: \"item\", item, globalIndex });\n globalIndex++;\n }\n }\n\n for (const item of ungrouped) {\n entries.push({ kind: \"item\", item, globalIndex });\n globalIndex++;\n }\n\n return entries;\n});\n\n/**\n * The item list for the non-grouped case, used by keyboard navigation. Derived\n * from `renderEntries` so the two are always in sync.\n */\nconst flatItems = computed(() =>\n renderEntries.value.filter((e): e is GroupedItem => e.kind === \"item\"),\n);\n\n/**\n * Keep the highlight within bounds. A filter that removes items can strand the\n * index past the end.\n */\nwatch(flatItems, (items) => {\n if (highlightedIndex.value >= items.length) {\n highlightedIndex.value = Math.max(0, items.length - 1);\n }\n});\n\n/**\n * The documented reset: the highlight returns to the first match whenever the\n * query changes — whether the query came from typing or from a parent updating\n * the controlled `query` prop. Typing reaches this watcher through `setQuery`,\n * which is why onInput no longer resets the highlight itself.\n */\nwatch(queryValue, () => {\n highlightedIndex.value = 0;\n});\n\n/**\n * The total number of results, announced to assistive technology through a live\n * region. Changes only when the filtered set changes, not on every keystroke.\n */\nconst resultCount = computed(() => filteredItems.value.length);\nconst announcement = ref(\"\");\nwatch(resultCount, (count) => {\n const template =\n count === 1 ? resolvedLabels.value.resultSingular : resolvedLabels.value.resultPlural;\n announcement.value = template.replace(\"{count}\", String(count));\n});\n\n/**\n * The currently highlighted item, or `undefined` when the list is empty.\n */\nconst highlightedItem = computed(() => flatItems.value[highlightedIndex.value]?.item);\n\nfunction highlightUp(): void {\n if (flatItems.value.length === 0) return;\n highlightedIndex.value =\n highlightedIndex.value <= 0 ? flatItems.value.length - 1 : highlightedIndex.value - 1;\n}\n\nfunction highlightDown(): void {\n if (flatItems.value.length === 0) return;\n highlightedIndex.value =\n highlightedIndex.value >= flatItems.value.length - 1 ? 0 : highlightedIndex.value + 1;\n}\n\nfunction selectHighlighted(): void {\n const item = highlightedItem.value;\n if (!item || item.disabled) return;\n emit(\"select\", item.value);\n}\n\nfunction onKeydown(event: KeyboardEvent): void {\n // A closed Command returns on any interaction except the two that leave it —\n // Escape (the key that closed it, still under the same finger) and Tab\n // (which moves focus elsewhere). Keydown fires before the input event, so\n // typing also lands on an open list.\n if (!isOpen.value && event.key !== \"Escape\" && event.key !== \"Tab\") restoreOpen();\n switch (event.key) {\n case \"ArrowDown\": {\n event.preventDefault();\n highlightDown();\n break;\n }\n case \"ArrowUp\": {\n event.preventDefault();\n highlightUp();\n break;\n }\n case \"Enter\": {\n event.preventDefault();\n selectHighlighted();\n break;\n }\n case \"Escape\": {\n event.preventDefault();\n if (queryValue.value.length > 0) {\n setQuery(\"\");\n } else {\n setOpen(false);\n }\n break;\n }\n case \"Home\": {\n event.preventDefault();\n if (flatItems.value.length > 0) highlightedIndex.value = 0;\n break;\n }\n case \"End\": {\n event.preventDefault();\n if (flatItems.value.length > 0) highlightedIndex.value = flatItems.value.length - 1;\n break;\n }\n }\n}\n\nfunction onInput(event: Event): void {\n const value = (event.target as HTMLInputElement).value;\n setQuery(value);\n}\n\nfunction selectItem(item: CommandItem): void {\n if (item.disabled) return;\n emit(\"select\", item.value);\n}\n\nfunction itemId(index: number): string {\n return `${inputId}-option-${String(index)}`;\n}\n</script>\n\n<template>\n <div\n :data-state=\"isOpen ? 'open' : 'closed'\"\n :class=\"\n cn(\n 'rounded-md border border-border bg-popover text-popover-foreground shadow-md overflow-hidden',\n 'outline-none',\n )\n \"\n >\n <div class=\"flex items-center border-b border-border\">\n <input\n :id=\"inputId\"\n type=\"text\"\n role=\"searchbox\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n spellcheck=\"false\"\n aria-autocomplete=\"list\"\n :aria-controls=\"listboxId\"\n :aria-activedescendant=\"highlightedItem ? itemId(highlightedIndex) : undefined\"\n :aria-labelledby=\"ariaLabelledby\"\n :aria-label=\"ariaLabelledby ? undefined : resolvedLabels.searchLabel\"\n :placeholder=\"resolvedLabels.placeholder\"\n :value=\"queryValue\"\n class=\"w-full px-3 py-2 text-sm bg-transparent text-foreground border-none outline-none placeholder:text-muted-foreground\"\n @input=\"onInput\"\n @keydown=\"onKeydown\"\n @focus=\"restoreOpen\"\n @click=\"restoreOpen\"\n />\n </div>\n <div\n v-if=\"isOpen\"\n :id=\"listboxId\"\n ref=\"listboxRef\"\n role=\"listbox\"\n tabindex=\"0\"\n :aria-labelledby=\"inputId\"\n class=\"max-h-[300px] overflow-y-auto p-1\"\n >\n <template\n v-for=\"entry in renderEntries\"\n :key=\"entry.kind === 'heading' ? entry.groupId : entry.item.value\"\n >\n <div\n v-if=\"entry.kind === 'heading'\"\n :id=\"entry.groupId\"\n role=\"presentation\"\n class=\"px-2 py-1.5 text-micro font-medium uppercase tracking-wide text-muted-foreground\"\n >\n {{ entry.heading }}\n </div>\n <!-- eslint-disable vuejs-accessibility/click-events-have-key-events, vuejs-accessibility/interactive-supports-focus, vuejs-accessibility/mouse-events-have-key-events -->\n <div\n v-else\n :id=\"itemId(entry.globalIndex)\"\n role=\"option\"\n :aria-selected=\"highlightedIndex === entry.globalIndex\"\n :aria-disabled=\"entry.item.disabled || undefined\"\n :data-active=\"highlightedIndex === entry.globalIndex || undefined\"\n class=\"flex flex-col gap-0.5 rounded-sm px-2 py-1.5 text-sm cursor-pointer outline-none transition-colors duration-fast ease-out data-[active]:bg-primary-muted data-[active]:text-primary-text\"\n @mouseenter=\"highlightedIndex = entry.globalIndex\"\n @click=\"selectItem(entry.item)\"\n >\n <span>{{ entry.item.label }}</span>\n <span v-if=\"entry.item.description\" class=\"text-xs text-muted-foreground\">\n {{ entry.item.description }}\n </span>\n </div>\n </template>\n\n <div\n v-if=\"filteredItems.length === 0\"\n role=\"option\"\n aria-selected=\"false\"\n aria-disabled=\"true\"\n class=\"px-2 py-6 text-center text-sm text-muted-foreground\"\n >\n {{ resolvedLabels.emptyMessage }}\n </div>\n </div>\n\n <span :id=\"liveRegionId\" role=\"status\" aria-live=\"polite\" class=\"sr-only\">\n {{ announcement }}\n </span>\n </div>\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { default, COMMAND_LABELS } from "./Command.vue";
2
+ export type { CommandItem, CommandGroup } from "./Command.vue";
3
+ export type { CommandLabels } from "../../../labels/src/index";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { COMMAND_LABELS } from "./Command.vue_vue_type_script_setup_true_lang.js";
2
+ import Command_default from "./Command.js";
3
+ export { COMMAND_LABELS, Command_default as default };
@@ -0,0 +1,7 @@
1
+ import CopyButton_vue_vue_type_script_setup_true_lang_default, { COPY_BUTTON_LABELS, COPY_REVERT_MS } from "./CopyButton.vue_vue_type_script_setup_true_lang.js";
2
+ //#region packages/primitives/copy-button/src/CopyButton.vue
3
+ var CopyButton_default = CopyButton_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { COPY_BUTTON_LABELS, COPY_REVERT_MS, CopyButton_default as default };
6
+
7
+ //# sourceMappingURL=CopyButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CopyButton.js","names":[],"sources":["../../../../../packages/primitives/copy-button/src/CopyButton.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { CopyButtonLabels } from \"@ecoma-io/loom-labels\";\nimport type { IconButtonSize, IconButtonVariant } from \"@ecoma-io/loom-icon-button\";\n\n/**\n * The visual weights and hit areas are IconButton's, verbatim — a copy button\n * is an icon button that happens to own a clipboard contract, and there is no\n * second press language to maintain.\n */\nexport type CopyButtonVariant = IconButtonVariant;\nexport type CopyButtonSize = IconButtonSize;\n\nexport const COPY_BUTTON_LABELS: CopyButtonLabels = {\n copy: \"Copy to clipboard\",\n copied: \"Copied to clipboard\",\n failed: \"Could not copy to clipboard\",\n};\n\n/** How long the copied/failed feedback holds before the button returns to its resting glyph. */\nexport const COPY_REVERT_MS = 2000;\n</script>\n\n<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref } from \"vue\";\nimport { Check, Copy, X } from \"@lucide/vue\";\nimport IconButton from \"@ecoma-io/loom-icon-button\";\nimport { useAnnounce } from \"@ecoma-io/loom-live-region\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\nconst props = withDefaults(\n defineProps<{\n /** The text to copy. Provide `value` or `getText` — a `CopyButton` with neither has nothing to do. */\n value?: string;\n /** Resolved at click time instead of a static `value` — for text the host computes on demand, possibly asynchronously. */\n getText?: () => string | Promise<string>;\n /**\n * Names for what the button says, as any subset of `CopyButtonLabels` —\n * the per-instance correction over `COPY_BUTTON_LABELS`, in the same\n * shape every component's `labels` prop takes. `copy` is the button's\n * accessible name and never changes with the state; `copied` and\n * `failed` are what assistive technology hears.\n */\n labels?: LabelOverrides<CopyButtonLabels>;\n /** Visual weight, shared with IconButton. */\n variant?: CopyButtonVariant;\n /** Square hit area, shared with IconButton. */\n size?: CopyButtonSize;\n /** Unavailable rather than dimmed — drains to the neutral well and blocks pointer events. */\n disabled?: boolean;\n /** The native button type. Defaults to `button`, never an accidental submit. */\n type?: \"button\" | \"submit\" | \"reset\";\n }>(),\n { variant: \"default\", size: \"md\", disabled: false, type: \"button\" },\n);\n\n/**\n * The outcome is announced through the shared LiveRegion seam, not a\n * region of this component's own: a region must pre-exist the messages it\n * announces, and the seam's standalone pair on `document.body` guarantees\n * that without every copy button mounting its own.\n */\nconst announce = useAnnounce();\n\n// `text`, not `labels`: the prop of that name is one of the three sources\n// this resolves (own prop, then the host vocabulary from\n// `provideLoomLabels`, then these English defaults), and a template reading\n// the raw prop would be reading the overrides rather than the answer.\nconst text = useLabels(\"copyButton\", COPY_BUTTON_LABELS, () => props.labels);\n\n/**\n * idle → copied | failed → idle, on a two-second revert timer. The guard\n * covers only the await window: a click during the feedback window is a\n * legitimate \"copy again\", not a duplicate — the announcement seam re-adds\n * the message, so a repeat is heard.\n */\ntype CopyState = \"idle\" | \"copied\" | \"failed\";\nconst state = ref<CopyState>(\"idle\");\nlet pending = false;\nlet revertTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction scheduleRevert(): void {\n if (revertTimer !== null) clearTimeout(revertTimer);\n revertTimer = setTimeout(() => {\n state.value = \"idle\";\n revertTimer = null;\n }, COPY_REVERT_MS);\n}\n\nonBeforeUnmount(() => {\n // The timer holds the only writer into `state`; firing after unmount\n // would write into a dead component. Cleared, not waited out.\n if (revertTimer !== null) clearTimeout(revertTimer);\n revertTimer = null;\n});\n\nasync function copy(): Promise<void> {\n if (props.disabled || pending) return;\n pending = true;\n try {\n // A throwing `getText` and a refusing clipboard take the same road:\n // the failed state is announced, the glyph says so, and the button\n // stays operable so the very next click retries the whole attempt.\n const value = props.getText ? await props.getText() : (props.value ?? \"\");\n await navigator.clipboard.writeText(value);\n state.value = \"copied\";\n announce(text.value.copied);\n } catch {\n state.value = \"failed\";\n announce(text.value.failed);\n } finally {\n pending = false;\n scheduleRevert();\n }\n}\n</script>\n\n<template>\n <IconButton\n :label=\"text.copy\"\n :variant=\"variant\"\n :size=\"size\"\n :disabled=\"disabled\"\n :type=\"type\"\n @click=\"copy\"\n >\n <!-- The glyph swap is the feedback's visual half only — never its only\n carrier. The announcement carries the state to assistive technology,\n and the accessible name stays `copy` throughout: a button whose name\n changes under a screen reader's cursor is its own confusion. -->\n <Check v-if=\"state === 'copied'\" class=\"h-4 w-4\" aria-hidden=\"true\" />\n <X v-else-if=\"state === 'failed'\" class=\"h-4 w-4\" aria-hidden=\"true\" />\n <Copy v-else class=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n</template>\n"],"mappings":""}
@@ -0,0 +1,64 @@
1
+ import { type LabelOverrides } from "../../../labels/src/index";
2
+ import type { CopyButtonLabels } from "../../../labels/src/index";
3
+ import type { IconButtonSize, IconButtonVariant } from "../../icon-button/src/index";
4
+ /**
5
+ * The visual weights and hit areas are IconButton's, verbatim — a copy button
6
+ * is an icon button that happens to own a clipboard contract, and there is no
7
+ * second press language to maintain.
8
+ */
9
+ export type CopyButtonVariant = IconButtonVariant;
10
+ export type CopyButtonSize = IconButtonSize;
11
+ export declare const COPY_BUTTON_LABELS: CopyButtonLabels;
12
+ /** How long the copied/failed feedback holds before the button returns to its resting glyph. */
13
+ export declare const COPY_REVERT_MS = 2000;
14
+ declare const _default: typeof __VLS_export;
15
+ export default _default;
16
+ declare const __VLS_export: import("vue").DefineComponent<{
17
+ /** The text to copy. Provide `value` or `getText` — a `CopyButton` with neither has nothing to do. */
18
+ value?: string;
19
+ /** Resolved at click time instead of a static `value` — for text the host computes on demand, possibly asynchronously. */
20
+ getText?: () => string | Promise<string>;
21
+ /**
22
+ * Names for what the button says, as any subset of `CopyButtonLabels` —
23
+ * the per-instance correction over `COPY_BUTTON_LABELS`, in the same
24
+ * shape every component's `labels` prop takes. `copy` is the button's
25
+ * accessible name and never changes with the state; `copied` and
26
+ * `failed` are what assistive technology hears.
27
+ */
28
+ labels?: LabelOverrides<CopyButtonLabels>;
29
+ /** Visual weight, shared with IconButton. */
30
+ variant?: CopyButtonVariant;
31
+ /** Square hit area, shared with IconButton. */
32
+ size?: CopyButtonSize;
33
+ /** Unavailable rather than dimmed — drains to the neutral well and blocks pointer events. */
34
+ disabled?: boolean;
35
+ /** The native button type. Defaults to `button`, never an accidental submit. */
36
+ type?: "button" | "submit" | "reset";
37
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
38
+ /** The text to copy. Provide `value` or `getText` — a `CopyButton` with neither has nothing to do. */
39
+ value?: string;
40
+ /** Resolved at click time instead of a static `value` — for text the host computes on demand, possibly asynchronously. */
41
+ getText?: () => string | Promise<string>;
42
+ /**
43
+ * Names for what the button says, as any subset of `CopyButtonLabels` —
44
+ * the per-instance correction over `COPY_BUTTON_LABELS`, in the same
45
+ * shape every component's `labels` prop takes. `copy` is the button's
46
+ * accessible name and never changes with the state; `copied` and
47
+ * `failed` are what assistive technology hears.
48
+ */
49
+ labels?: LabelOverrides<CopyButtonLabels>;
50
+ /** Visual weight, shared with IconButton. */
51
+ variant?: CopyButtonVariant;
52
+ /** Square hit area, shared with IconButton. */
53
+ size?: CopyButtonSize;
54
+ /** Unavailable rather than dimmed — drains to the neutral well and blocks pointer events. */
55
+ disabled?: boolean;
56
+ /** The native button type. Defaults to `button`, never an accidental submit. */
57
+ type?: "button" | "submit" | "reset";
58
+ }> & Readonly<{}>, {
59
+ size: CopyButtonSize;
60
+ type: "button" | "submit" | "reset";
61
+ disabled: boolean;
62
+ variant: CopyButtonVariant;
63
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
64
+ //# sourceMappingURL=CopyButton.vue.d.ts.map
@@ -0,0 +1,113 @@
1
+ import { useLabels } from "../../../labels/src/labels.js";
2
+ import "../../../labels/src/index.js";
3
+ import IconButton_default from "../../icon-button/src/IconButton.js";
4
+ import "../../icon-button/src/index.js";
5
+ import { useAnnounce } from "../../live-region/src/useAnnounce.js";
6
+ import "../../live-region/src/index.js";
7
+ import { createBlock, defineComponent, onBeforeUnmount, openBlock, ref, unref, withCtx } from "vue";
8
+ import { Check, Copy, X } from "@lucide/vue";
9
+ //#region packages/primitives/copy-button/src/CopyButton.vue?vue&type=script&setup=true&lang.ts
10
+ var COPY_BUTTON_LABELS = {
11
+ copy: "Copy to clipboard",
12
+ copied: "Copied to clipboard",
13
+ failed: "Could not copy to clipboard"
14
+ };
15
+ /** How long the copied/failed feedback holds before the button returns to its resting glyph. */
16
+ var COPY_REVERT_MS = 2e3;
17
+ var CopyButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
18
+ __name: "CopyButton",
19
+ props: {
20
+ value: {},
21
+ getText: {},
22
+ labels: {},
23
+ variant: { default: "default" },
24
+ size: { default: "md" },
25
+ disabled: {
26
+ type: Boolean,
27
+ default: false
28
+ },
29
+ type: { default: "button" }
30
+ },
31
+ setup(__props) {
32
+ const props = __props;
33
+ /**
34
+ * The outcome is announced through the shared LiveRegion seam, not a
35
+ * region of this component's own: a region must pre-exist the messages it
36
+ * announces, and the seam's standalone pair on `document.body` guarantees
37
+ * that without every copy button mounting its own.
38
+ */
39
+ const announce = useAnnounce();
40
+ const text = useLabels("copyButton", COPY_BUTTON_LABELS, () => props.labels);
41
+ /**
42
+ * idle → copied | failed → idle, on a two-second revert timer. The guard
43
+ * covers only the await window: a click during the feedback window is a
44
+ * legitimate "copy again", not a duplicate — the announcement seam re-adds
45
+ * the message, so a repeat is heard.
46
+ */
47
+ const state = ref("idle");
48
+ let pending = false;
49
+ let revertTimer = null;
50
+ function scheduleRevert() {
51
+ if (revertTimer !== null) clearTimeout(revertTimer);
52
+ revertTimer = setTimeout(() => {
53
+ state.value = "idle";
54
+ revertTimer = null;
55
+ }, COPY_REVERT_MS);
56
+ }
57
+ onBeforeUnmount(() => {
58
+ if (revertTimer !== null) clearTimeout(revertTimer);
59
+ revertTimer = null;
60
+ });
61
+ async function copy() {
62
+ if (props.disabled || pending) return;
63
+ pending = true;
64
+ try {
65
+ const value = props.getText ? await props.getText() : props.value ?? "";
66
+ await navigator.clipboard.writeText(value);
67
+ state.value = "copied";
68
+ announce(text.value.copied);
69
+ } catch {
70
+ state.value = "failed";
71
+ announce(text.value.failed);
72
+ } finally {
73
+ pending = false;
74
+ scheduleRevert();
75
+ }
76
+ }
77
+ return (_ctx, _cache) => {
78
+ return openBlock(), createBlock(unref(IconButton_default), {
79
+ label: unref(text).copy,
80
+ variant: __props.variant,
81
+ size: __props.size,
82
+ disabled: __props.disabled,
83
+ type: __props.type,
84
+ onClick: copy
85
+ }, {
86
+ default: withCtx(() => [state.value === "copied" ? (openBlock(), createBlock(unref(Check), {
87
+ key: 0,
88
+ class: "h-4 w-4",
89
+ "aria-hidden": "true"
90
+ })) : state.value === "failed" ? (openBlock(), createBlock(unref(X), {
91
+ key: 1,
92
+ class: "h-4 w-4",
93
+ "aria-hidden": "true"
94
+ })) : (openBlock(), createBlock(unref(Copy), {
95
+ key: 2,
96
+ class: "h-4 w-4",
97
+ "aria-hidden": "true"
98
+ }))]),
99
+ _: 1
100
+ }, 8, [
101
+ "label",
102
+ "variant",
103
+ "size",
104
+ "disabled",
105
+ "type"
106
+ ]);
107
+ };
108
+ }
109
+ });
110
+ //#endregion
111
+ export { COPY_BUTTON_LABELS, COPY_REVERT_MS, CopyButton_vue_vue_type_script_setup_true_lang_default as default };
112
+
113
+ //# sourceMappingURL=CopyButton.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CopyButton.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../../packages/primitives/copy-button/src/CopyButton.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { CopyButtonLabels } from \"@ecoma-io/loom-labels\";\nimport type { IconButtonSize, IconButtonVariant } from \"@ecoma-io/loom-icon-button\";\n\n/**\n * The visual weights and hit areas are IconButton's, verbatim — a copy button\n * is an icon button that happens to own a clipboard contract, and there is no\n * second press language to maintain.\n */\nexport type CopyButtonVariant = IconButtonVariant;\nexport type CopyButtonSize = IconButtonSize;\n\nexport const COPY_BUTTON_LABELS: CopyButtonLabels = {\n copy: \"Copy to clipboard\",\n copied: \"Copied to clipboard\",\n failed: \"Could not copy to clipboard\",\n};\n\n/** How long the copied/failed feedback holds before the button returns to its resting glyph. */\nexport const COPY_REVERT_MS = 2000;\n</script>\n\n<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref } from \"vue\";\nimport { Check, Copy, X } from \"@lucide/vue\";\nimport IconButton from \"@ecoma-io/loom-icon-button\";\nimport { useAnnounce } from \"@ecoma-io/loom-live-region\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\n\nconst props = withDefaults(\n defineProps<{\n /** The text to copy. Provide `value` or `getText` — a `CopyButton` with neither has nothing to do. */\n value?: string;\n /** Resolved at click time instead of a static `value` — for text the host computes on demand, possibly asynchronously. */\n getText?: () => string | Promise<string>;\n /**\n * Names for what the button says, as any subset of `CopyButtonLabels` —\n * the per-instance correction over `COPY_BUTTON_LABELS`, in the same\n * shape every component's `labels` prop takes. `copy` is the button's\n * accessible name and never changes with the state; `copied` and\n * `failed` are what assistive technology hears.\n */\n labels?: LabelOverrides<CopyButtonLabels>;\n /** Visual weight, shared with IconButton. */\n variant?: CopyButtonVariant;\n /** Square hit area, shared with IconButton. */\n size?: CopyButtonSize;\n /** Unavailable rather than dimmed — drains to the neutral well and blocks pointer events. */\n disabled?: boolean;\n /** The native button type. Defaults to `button`, never an accidental submit. */\n type?: \"button\" | \"submit\" | \"reset\";\n }>(),\n { variant: \"default\", size: \"md\", disabled: false, type: \"button\" },\n);\n\n/**\n * The outcome is announced through the shared LiveRegion seam, not a\n * region of this component's own: a region must pre-exist the messages it\n * announces, and the seam's standalone pair on `document.body` guarantees\n * that without every copy button mounting its own.\n */\nconst announce = useAnnounce();\n\n// `text`, not `labels`: the prop of that name is one of the three sources\n// this resolves (own prop, then the host vocabulary from\n// `provideLoomLabels`, then these English defaults), and a template reading\n// the raw prop would be reading the overrides rather than the answer.\nconst text = useLabels(\"copyButton\", COPY_BUTTON_LABELS, () => props.labels);\n\n/**\n * idle → copied | failed → idle, on a two-second revert timer. The guard\n * covers only the await window: a click during the feedback window is a\n * legitimate \"copy again\", not a duplicate — the announcement seam re-adds\n * the message, so a repeat is heard.\n */\ntype CopyState = \"idle\" | \"copied\" | \"failed\";\nconst state = ref<CopyState>(\"idle\");\nlet pending = false;\nlet revertTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction scheduleRevert(): void {\n if (revertTimer !== null) clearTimeout(revertTimer);\n revertTimer = setTimeout(() => {\n state.value = \"idle\";\n revertTimer = null;\n }, COPY_REVERT_MS);\n}\n\nonBeforeUnmount(() => {\n // The timer holds the only writer into `state`; firing after unmount\n // would write into a dead component. Cleared, not waited out.\n if (revertTimer !== null) clearTimeout(revertTimer);\n revertTimer = null;\n});\n\nasync function copy(): Promise<void> {\n if (props.disabled || pending) return;\n pending = true;\n try {\n // A throwing `getText` and a refusing clipboard take the same road:\n // the failed state is announced, the glyph says so, and the button\n // stays operable so the very next click retries the whole attempt.\n const value = props.getText ? await props.getText() : (props.value ?? \"\");\n await navigator.clipboard.writeText(value);\n state.value = \"copied\";\n announce(text.value.copied);\n } catch {\n state.value = \"failed\";\n announce(text.value.failed);\n } finally {\n pending = false;\n scheduleRevert();\n }\n}\n</script>\n\n<template>\n <IconButton\n :label=\"text.copy\"\n :variant=\"variant\"\n :size=\"size\"\n :disabled=\"disabled\"\n :type=\"type\"\n @click=\"copy\"\n >\n <!-- The glyph swap is the feedback's visual half only — never its only\n carrier. The announcement carries the state to assistive technology,\n and the accessible name stays `copy` throughout: a button whose name\n changes under a screen reader's cursor is its own confusion. -->\n <Check v-if=\"state === 'copied'\" class=\"h-4 w-4\" aria-hidden=\"true\" />\n <X v-else-if=\"state === 'failed'\" class=\"h-4 w-4\" aria-hidden=\"true\" />\n <Copy v-else class=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n</template>\n"],"mappings":";;;;;;;;;AAYA,IAAa,qBAAuC;CAClD,MAAM;CACN,QAAQ;CACR,QAAQ;AACV;;AAGA,IAAa,iBAAiB;;;;;;;;;;;;;;;;EAU9B,MAAM,QAAQ;;;;;;;EAgCd,MAAM,WAAW,YAAY;EAM7B,MAAM,OAAO,UAAU,cAAc,0BAA0B,MAAM,MAAM;;;;;;;EAS3E,MAAM,QAAQ,IAAe,MAAM;EACnC,IAAI,UAAU;EACd,IAAI,cAAoD;EAExD,SAAS,iBAAuB;GAC9B,IAAI,gBAAgB,MAAM,aAAa,WAAW;GAClD,cAAc,iBAAiB;IAC7B,MAAM,QAAQ;IACd,cAAc;GAChB,GAAG,cAAc;EACnB;EAEA,sBAAsB;GAGpB,IAAI,gBAAgB,MAAM,aAAa,WAAW;GAClD,cAAc;EAChB,CAAC;EAED,eAAe,OAAsB;GACnC,IAAI,MAAM,YAAY,SAAS;GAC/B,UAAU;GACV,IAAI;IAIF,MAAM,QAAQ,MAAM,UAAU,MAAM,MAAM,QAAQ,IAAK,MAAM,SAAS;IACtE,MAAM,UAAU,UAAU,UAAU,KAAK;IACzC,MAAM,QAAQ;IACd,SAAS,KAAK,MAAM,MAAM;GAC5B,QAAQ;IACN,MAAM,QAAQ;IACd,SAAS,KAAK,MAAM,MAAM;GAC5B,UAAU;IACR,UAAU;IACV,eAAe;GACjB;EACF;;GAIE,OAAA,UAAA,GAAA,YAea,MAAA,kBAAA,GAAA;IAdV,OAAO,MAAA,IAAA,CAAI,CAAC;IACZ,SAAS,QAAA;IACT,MAAM,QAAA;IACN,UAAU,QAAA;IACV,MAAM,QAAA;IACN,SAAO;;IAMK,SAAA,cAAA,CAAA,MAAA,UAAK,YAAlB,UAAA,GAAA,YAAsE,MAAA,KAAA,GAAA;;KAArC,OAAM;KAAU,eAAY;IAC/C,CAAA,KAAA,MAAA,UAAK,YAAnB,UAAA,GAAA,YAAuE,MAAA,CAAA,GAAA;;KAArC,OAAM;KAAU,eAAY;IAC9D,CAAA,MAAA,UAAA,GAAA,YAAkD,MAAA,IAAA,GAAA;;KAArC,OAAM;KAAU,eAAY"}
@@ -0,0 +1,4 @@
1
+ export { COPY_BUTTON_LABELS, COPY_REVERT_MS, default } from "./CopyButton.vue";
2
+ export type { CopyButtonSize, CopyButtonVariant } from "./CopyButton.vue";
3
+ export type { CopyButtonLabels } from "../../../labels/src/index";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,3 @@
1
+ import "./CopyButton.vue_vue_type_script_setup_true_lang.js";
2
+ import CopyButton_default from "./CopyButton.js";
3
+ export { CopyButton_default as default };
@@ -0,0 +1,7 @@
1
+ import DataGrid_vue_vue_type_script_setup_true_lang_default, { DATA_GRID_LABELS } from "./DataGrid.vue_vue_type_script_setup_true_lang.js";
2
+ //#region packages/primitives/data-grid/src/DataGrid.vue
3
+ var DataGrid_default = DataGrid_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { DATA_GRID_LABELS, DataGrid_default as default };
6
+
7
+ //# sourceMappingURL=DataGrid.js.map