@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
@@ -28,6 +28,8 @@ export { default as Separator } from "../../primitives/separator/src/index";
28
28
  export type { SeparatorOrientation } from "../../primitives/separator/src/index";
29
29
  export { default as Skeleton, skeletonVariants } from "../../primitives/skeleton/src/index";
30
30
  export type { SkeletonVariant } from "../../primitives/skeleton/src/index";
31
+ export { default as SkipLink, SKIP_LINK_LABELS } from "../../primitives/skip-link/src/index";
32
+ export type { SkipLinkLabels } from "../../primitives/skip-link/src/index";
31
33
  export { default as Spinner, spinnerVariants } from "../../primitives/spinner/src/index";
32
34
  export type { SpinnerSize } from "../../primitives/spinner/src/index";
33
35
  export { default as Surface, surfaceVariants } from "../../primitives/surface/src/index";
@@ -42,8 +44,14 @@ export { default as Breadcrumb, BREADCRUMB_LABELS } from "../../primitives/bread
42
44
  export type { BreadcrumbItem, BreadcrumbSeparator, BreadcrumbLabels, } from "../../primitives/breadcrumb/src/index";
43
45
  export { default as Button, buttonVariants } from "../../primitives/button/src/index";
44
46
  export type { ButtonSize, ButtonVariant } from "../../primitives/button/src/index";
47
+ export { default as CopyButton } from "../../primitives/copy-button/src/index";
48
+ export type { CopyButtonLabels, CopyButtonSize, CopyButtonVariant, } from "../../primitives/copy-button/src/index";
49
+ export { default as Calendar, CALENDAR_LABELS } from "../../primitives/calendar/src/index";
50
+ export type { CalendarLabels } from "../../primitives/calendar/src/index";
45
51
  export { default as Carousel, CAROUSEL_LABELS } from "../../primitives/carousel/src/index";
46
52
  export type { CarouselLabels } from "../../primitives/carousel/src/index";
53
+ export { default as Meter, meterVariants, METER_LABELS } from "../../primitives/meter/src/index";
54
+ export type { MeterLabels, MeterSize } from "../../primitives/meter/src/index";
47
55
  export { default as Card } from "../../primitives/card/src/index";
48
56
  export type { CardPad } from "../../primitives/card/src/index";
49
57
  export { default as Chip, chipVariants } from "../../primitives/chip/src/index";
@@ -58,12 +66,16 @@ export type { IconButtonSize, IconButtonVariant } from "../../primitives/icon-bu
58
66
  export { default as InlineError } from "../../primitives/inline-error/src/index";
59
67
  export { default as Kbd, kbdVariants } from "../../primitives/kbd/src/index";
60
68
  export type { KbdSize } from "../../primitives/kbd/src/index";
69
+ export { default as LiveRegion, useAnnounce } from "../../primitives/live-region/src/index";
70
+ export type { Announce, LiveRegionContext, LiveRegionPoliteness } from "../../primitives/live-region/src/index";
61
71
  export { default as Link, linkVariants } from "../../primitives/link/src/index";
62
72
  export type { LinkVariant } from "../../primitives/link/src/index";
63
73
  export { List, ListItem } from "../../primitives/list/src/index";
64
74
  export type { ListItemShape } from "../../primitives/list/src/index";
65
75
  export { default as Menubar } from "../../primitives/menubar/src/index";
66
76
  export type { MenubarItem, MenubarMenu } from "../../primitives/menubar/src/index";
77
+ export { default as NavigationMenu } from "../../primitives/navigation-menu/src/index";
78
+ export type { NavigationMenuItem, NavigationMenuLink } from "../../primitives/navigation-menu/src/index";
67
79
  export { default as Popover } from "../../primitives/popover/src/index";
68
80
  export type { PopoverAlign, PopoverSide } from "../../primitives/popover/src/index";
69
81
  export { default as SpeedDial } from "../../primitives/speed-dial/src/index";
@@ -86,8 +98,12 @@ export type { AvatarGroupItem, AvatarGroupLabels, AvatarGroupSurface, } from "..
86
98
  export { default as Checkbox } from "../../primitives/checkbox/src/index";
87
99
  export { default as ColorPicker, COLOR_PICKER_LABELS } from "../../primitives/color-picker/src/index";
88
100
  export type { ColorPickerLabels } from "../../primitives/color-picker/src/index";
101
+ export { default as Command, COMMAND_LABELS } from "../../primitives/command/src/index";
102
+ export type { CommandItem, CommandGroup, CommandLabels } from "../../primitives/command/src/index";
89
103
  export { default as Combobox, comboboxVariants, COMBOBOX_LABELS } from "../../primitives/combobox/src/index";
90
104
  export type { ComboboxLabels, ComboboxOption, ComboboxSize } from "../../primitives/combobox/src/index";
105
+ export { default as DataGrid, DATA_GRID_LABELS } from "../../primitives/data-grid/src/index";
106
+ export type { DataGridLabels, DataGridColumn, DataGridSort, DataGridSortState, } from "../../primitives/data-grid/src/index";
91
107
  export { default as DatePicker } from "../../primitives/date-picker/src/index";
92
108
  export type { DatePickerLabels } from "../../primitives/date-picker/src/index";
93
109
  export { default as DateRangePicker, DATE_RANGE_LABELS } from "../../primitives/date-range-picker/src/index";
@@ -134,8 +150,16 @@ export { default as TextField, TEXT_FIELD_LABELS } from "../../primitives/text-f
134
150
  export type { TextFieldLabels, TextFieldSize, TextFieldType } from "../../primitives/text-field/src/index";
135
151
  export { default as TimePicker } from "../../primitives/time-picker/src/index";
136
152
  export type { TimePickerLabels } from "../../primitives/time-picker/src/index";
153
+ export { default as ToggleGroup } from "../../primitives/toggle-group/src/index";
154
+ export type { ToggleGroupItem } from "../../primitives/toggle-group/src/index";
155
+ export { default as Toolbar, ToolbarSeparator } from "../../primitives/toolbar/src/index";
156
+ export type { ToolbarContext, ToolbarOrientation } from "../../primitives/toolbar/src/index";
137
157
  export { Toast, ToastItem, TOAST_LABELS } from "../../primitives/toast/src/index";
138
158
  export type { ToastVariant, ToastLabels } from "../../primitives/toast/src/index";
159
+ export { default as TreeView, TREE_VIEW_LABELS } from "../../primitives/tree-view/src/index";
160
+ export type { TreeNode, TreeViewLabels, TreeViewSelectionMode } from "../../primitives/tree-view/src/index";
161
+ export { default as VisuallyHidden } from "../../primitives/visually-hidden/src/index";
162
+ export type { VisuallyHiddenElement } from "../../primitives/visually-hidden/src/index";
139
163
  export { default as WindowControls, WINDOW_CONTROLS_LABELS } from "../../primitives/window-controls/src/index";
140
164
  export type { WindowPlatform, WindowControlsLabels } from "../../primitives/window-controls/src/index";
141
165
  export { default as Center } from "../../composition/center/src/index";
@@ -169,12 +193,14 @@ export type { ReadingGutter } from "../../layouts/reading/src/index";
169
193
  export { default as Settings } from "../../layouts/settings/src/index";
170
194
  export type { SettingsNavWidth } from "../../layouts/settings/src/index";
171
195
  export { default as SplitLayout } from "../../layouts/split-layout/src/index";
172
- export type { SplitLayoutCollapseAt, SplitLayoutGap } from "../../layouts/split-layout/src/index";
196
+ export type { SplitLayoutGap } from "../../layouts/split-layout/src/index";
173
197
  export { default as AppHeader } from "../../blocks/app-header/src/index";
174
198
  export { default as DashboardGrid } from "../../blocks/dashboard-grid/src/index";
175
199
  export { default as DesktopAppShell } from "../../blocks/desktop-app-shell/src/index";
176
200
  export { default as EmptyState } from "../../blocks/empty-state/src/index";
177
201
  export { default as ErrorState } from "../../blocks/error-state/src/index";
202
+ export { default as ErrorSummary, ERROR_SUMMARY_LABELS } from "../../blocks/error-summary/src/index";
203
+ export type { ErrorSummaryEntry, ErrorSummaryLabels } from "../../blocks/error-summary/src/index";
178
204
  export { default as FormActions } from "../../blocks/form-actions/src/index";
179
205
  export type { FormActionsAlign } from "../../blocks/form-actions/src/index";
180
206
  export { default as FormSection } from "../../blocks/form-section/src/index";
@@ -1 +1 @@
1
- {"version":3,"file":"Alert.js","names":[],"sources":["../../../../../packages/primitives/alert/src/Alert.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { AlertLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n * The feedback tones, matching Toast and Badge so one functional hue means\n * one thing everywhere. `neutral` is the default because an alert's first\n * job is to be seen at all, not to alarm.\n */\nexport type AlertVariant = \"neutral\" | \"info\" | \"success\" | \"warning\" | \"destructive\";\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it,\n * and exported so a host can build a partial vocabulary against the real\n * thing rather than a transcription of it.\n */\nexport const ALERT_LABELS: AlertLabels = {\n dismiss: \"Dismiss\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from \"vue\";\nimport { Info, CircleCheck, TriangleAlert, CircleX, X } from \"@lucide/vue\";\nimport IconButton from \"@ecoma-io/loom-icon-button\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\nimport { cn } from \"@ecoma-io/loom-core\";\n\nconst props = withDefaults(\n defineProps<{\n /** Selects the tinted wash and the default icon. */\n variant?: AlertVariant;\n /** The headline. Optional — a one-line alert can speak through its body alone. */\n title?: string;\n /** The detail line below the title. Longer content belongs in the default slot. */\n description?: string;\n /** Shows the dismiss control and lets the alert leave; pair with `v-model:open`. */\n dismissible?: boolean;\n /**\n * Controls visibility. Omit it and the alert owns its own state until\n * dismissed; pass bindings through `v-model:open` to own it yourself.\n * Pick one mode per instance and stay there: while the prop is bound the\n * internal state never moves, so removing the binding later brings back\n * whatever the host last left visible.\n */\n open?: boolean | undefined;\n /** Names for what the alert says on its own account, as any subset of `AlertLabels`. */\n labels?: LabelOverrides<AlertLabels>;\n }>(),\n {\n // `undefined` is the uncontrolled state, and only an explicit default\n // keeps it reachable past Vue's Boolean casting.\n open: undefined,\n variant: \"neutral\",\n dismissible: false,\n },\n);\n\nconst emit = defineEmits<{ \"update:open\": [value: boolean] }>();\n\n// `<Transition>` cannot pass fallthrough attributes through to its child —\n// a `class` or `@click` on the caller's `<Alert>` would land on the\n// Transition node and vanish. Opting out and forwarding by hand is what\n// keeps this component ordinary from the outside.\ndefineOptions({ inheritAttrs: false });\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(\"alert\", ALERT_LABELS, () => props.labels);\n\n/**\n * Per-tone accent icon and measured wash. The tinted pairs are the same ones\n * Badge paints (`bg-*-muted text-*-text`) because those are the tokens mixed\n * to hold their contrast in both themes; `-text`, never the bare `warning`,\n * for the failure Badge records. `neutral` carries no icon of its own — an\n * unremarkable note does not need one, and the slot remains available.\n */\nconst TONE_ACCENTS = {\n // Badge's own neutral pair: the recessed well, not a borrowed status hue.\n neutral: { icon: undefined, wash: \"bg-subtle text-subtle-foreground\" },\n info: { icon: Info, wash: \"bg-info-muted text-info-text\" },\n success: { icon: CircleCheck, wash: \"bg-success-muted text-success-text\" },\n warning: { icon: TriangleAlert, wash: \"bg-warning-muted text-warning-text\" },\n destructive: { icon: CircleX, wash: \"bg-destructive-muted text-destructive-text\" },\n} satisfies Record<AlertVariant, { icon: typeof Info | undefined; wash: string }>;\n\n// Controlled/uncontrolled split by hand — there is no Reka root to lean on,\n// and `optional()` exists for exactly the prop-forwarding case this is not.\nconst innerOpen = ref(true);\nconst isOpen = computed(() => props.open ?? innerOpen.value);\n\nfunction dismiss(): void {\n if (props.open === undefined) innerOpen.value = false;\n emit(\"update:open\", false);\n}\n\nconst accent = computed(() => TONE_ACCENTS[props.variant]);\n</script>\n\n<template>\n <!-- Enter rises like every revealed surface; exit falls back down it. Vue\n holds the leaving element itself, so no Presence machinery is needed\n the way it is under Reka, and the global reduced-motion collapse still\n ends both phases instantly — dismissal stays immediate for readers who\n asked for less motion. -->\n <Transition enter-active-class=\"animate-fade-rise\" leave-active-class=\"animate-fade-fall\">\n <div\n v-if=\"isOpen\"\n v-bind=\"$attrs\"\n role=\"alert\"\n :class=\"cn('flex items-start gap-3 rounded-md border border-transparent p-3', accent?.wash)\"\n >\n <slot name=\"icon\">\n <component\n :is=\"accent.icon\"\n v-if=\"accent?.icon\"\n class=\"mt-0.5 h-4 w-4 shrink-0\"\n aria-hidden=\"true\"\n />\n </slot>\n\n <div class=\"min-w-0 flex-1 break-words\">\n <p v-if=\"title\" class=\"text-sm font-medium\">{{ title }}</p>\n <p v-if=\"description\" :class=\"cn('text-small', title && 'mt-0.5')\">\n {{ description }}\n </p>\n <!-- @slot Anything beyond a title and one line of detail — a list of\n what failed, a link out. Rendered after the description, inside\n the tone's measured text colour. -->\n <div v-if=\"$slots.default\" :class=\"cn((title || description) && 'mt-1')\">\n <slot />\n </div>\n </div>\n\n <!-- In the flow, not overlaid: an absolutely-positioned close control\n collides with long titles at narrow widths, which is exactly where\n alerts wrap. -->\n <IconButton\n v-if=\"dismissible\"\n variant=\"ghost\"\n size=\"sm\"\n :label=\"text.dismiss\"\n class=\"-mr-1 -mt-1 shrink-0\"\n @click=\"dismiss()\"\n >\n <X class=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n </div>\n </Transition>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"Alert.js","names":[],"sources":["../../../../../packages/primitives/alert/src/Alert.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { AlertLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n * The feedback tones, matching Toast and Badge so one functional hue means\n * one thing everywhere. `neutral` is the default because an alert's first\n * job is to be seen at all, not to alarm.\n */\nexport type AlertVariant = \"neutral\" | \"info\" | \"success\" | \"warning\" | \"destructive\";\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it,\n * and exported so a host can build a partial vocabulary against the real\n * thing rather than a transcription of it.\n */\nexport const ALERT_LABELS: AlertLabels = {\n dismiss: \"Dismiss\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from \"vue\";\nimport { Info, CircleCheck, TriangleAlert, CircleX, X } from \"@lucide/vue\";\nimport IconButton from \"@ecoma-io/loom-icon-button\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\nimport { cn } from \"@ecoma-io/loom-core\";\n\nconst props = withDefaults(\n defineProps<{\n /** Selects the tinted wash and the default icon. */\n variant?: AlertVariant;\n /** The headline. Optional — a one-line alert can speak through its body alone. */\n title?: string;\n /** The detail line below the title. Longer content belongs in the default slot. */\n description?: string;\n /** Shows the dismiss control and lets the alert leave; pair with `v-model:open`. */\n dismissible?: boolean;\n /**\n * Controls visibility. Omit it and the alert owns its own state until\n * dismissed; pass bindings through `v-model:open` to own it yourself.\n * Pick one mode per instance and stay there: while the prop is bound the\n * internal state never moves, so removing the binding later brings back\n * whatever the host last left visible.\n */\n open?: boolean | undefined;\n /** Names for what the alert says on its own account, as any subset of `AlertLabels`. */\n labels?: LabelOverrides<AlertLabels>;\n /**\n * How assertively the alert announces itself, overriding the per-tone\n * default. Destructive and warning news are assertive `role=\"alert\"`\n * interruptions; neutral, info and success are polite `role=\"status\"` —\n * a \"Saved\" note should not cut off what is being read. `\"off\"` removes\n * the live semantics for surfaces that are not interruptions at all,\n * such as a static wall of notices.\n */\n live?: \"assertive\" | \"polite\" | \"off\";\n }>(),\n {\n // `undefined` is the uncontrolled state, and only an explicit default\n // keeps it reachable past Vue's Boolean casting.\n open: undefined,\n variant: \"neutral\",\n dismissible: false,\n },\n);\n\nconst emit = defineEmits<{ \"update:open\": [value: boolean] }>();\n\n// `<Transition>` cannot pass fallthrough attributes through to its child —\n// a `class` or `@click` on the caller's `<Alert>` would land on the\n// Transition node and vanish. Opting out and forwarding by hand is what\n// keeps this component ordinary from the outside.\ndefineOptions({ inheritAttrs: false });\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(\"alert\", ALERT_LABELS, () => props.labels);\n\n/**\n * Per-tone accent icon and measured wash. The tinted pairs are the same ones\n * Badge paints (`bg-*-muted text-*-text`) because those are the tokens mixed\n * to hold their contrast in both themes; `-text`, never the bare `warning`,\n * for the failure Badge records. `neutral` carries no icon of its own — an\n * unremarkable note does not need one, and the slot remains available.\n */\nconst TONE_ACCENTS = {\n // Badge's own neutral pair: the recessed well, not a borrowed status hue.\n neutral: { icon: undefined, wash: \"bg-subtle text-subtle-foreground\" },\n info: { icon: Info, wash: \"bg-info-muted text-info-text\" },\n success: { icon: CircleCheck, wash: \"bg-success-muted text-success-text\" },\n warning: { icon: TriangleAlert, wash: \"bg-warning-muted text-warning-text\" },\n destructive: { icon: CircleX, wash: \"bg-destructive-muted text-destructive-text\" },\n} satisfies Record<AlertVariant, { icon: typeof Info | undefined; wash: string }>;\n\n// Controlled/uncontrolled split by hand — there is no Reka root to lean on,\n// and `optional()` exists for exactly the prop-forwarding case this is not.\nconst innerOpen = ref(true);\nconst isOpen = computed(() => props.open ?? innerOpen.value);\n\nfunction dismiss(): void {\n if (props.open === undefined) innerOpen.value = false;\n emit(\"update:open\", false);\n}\n\nconst accent = computed(() => TONE_ACCENTS[props.variant]);\n\n// The interruption an alert makes follows its stakes: failure and warning\n// news is the assertive role, the rest polite. A live region that says\n// \"Saved\" on every save should not be cutting off whatever is being read.\nconst live = computed<\"assertive\" | \"polite\" | \"off\">(\n () =>\n props.live ??\n (props.variant === \"destructive\" || props.variant === \"warning\" ? \"assertive\" : \"polite\"),\n);\n</script>\n\n<template>\n <!-- Enter rises like every revealed surface; exit falls back down it. Vue\n holds the leaving element itself, so no Presence machinery is needed\n the way it is under Reka, and the global reduced-motion collapse still\n ends both phases instantly — dismissal stays immediate for readers who\n asked for less motion. -->\n <Transition enter-active-class=\"animate-fade-rise\" leave-active-class=\"animate-fade-fall\">\n <div\n v-if=\"isOpen\"\n v-bind=\"$attrs\"\n :role=\"live === 'off' ? undefined : live === 'assertive' ? 'alert' : 'status'\"\n :class=\"cn('flex items-start gap-3 rounded-md border border-transparent p-3', accent?.wash)\"\n >\n <slot name=\"icon\">\n <component\n :is=\"accent.icon\"\n v-if=\"accent?.icon\"\n class=\"mt-0.5 h-4 w-4 shrink-0\"\n aria-hidden=\"true\"\n />\n </slot>\n\n <div class=\"min-w-0 flex-1 break-words\">\n <p v-if=\"title\" class=\"text-sm font-medium\">{{ title }}</p>\n <p v-if=\"description\" :class=\"cn('text-small', title && 'mt-0.5')\">\n {{ description }}\n </p>\n <!-- @slot Anything beyond a title and one line of detail — a list of\n what failed, a link out. Rendered after the description, inside\n the tone's measured text colour. -->\n <div v-if=\"$slots.default\" :class=\"cn((title || description) && 'mt-1')\">\n <slot />\n </div>\n </div>\n\n <!-- In the flow, not overlaid: an absolutely-positioned close control\n collides with long titles at narrow widths, which is exactly where\n alerts wrap. -->\n <IconButton\n v-if=\"dismissible\"\n variant=\"ghost\"\n size=\"sm\"\n :label=\"text.dismiss\"\n class=\"-mr-1 -mt-1 shrink-0\"\n @click=\"dismiss()\"\n >\n <X class=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n </div>\n </Transition>\n</template>\n"],"mappings":""}
@@ -33,6 +33,15 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
33
33
  open?: boolean | undefined;
34
34
  /** Names for what the alert says on its own account, as any subset of `AlertLabels`. */
35
35
  labels?: LabelOverrides<AlertLabels>;
36
+ /**
37
+ * How assertively the alert announces itself, overriding the per-tone
38
+ * default. Destructive and warning news are assertive `role="alert"`
39
+ * interruptions; neutral, info and success are polite `role="status"` —
40
+ * a "Saved" note should not cut off what is being read. `"off"` removes
41
+ * the live semantics for surfaces that are not interruptions at all,
42
+ * such as a static wall of notices.
43
+ */
44
+ live?: "assertive" | "polite" | "off";
36
45
  }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
37
46
  "update:open": (value: boolean) => any;
38
47
  }, string, import("vue").PublicProps, Readonly<{
@@ -54,6 +63,15 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
54
63
  open?: boolean | undefined;
55
64
  /** Names for what the alert says on its own account, as any subset of `AlertLabels`. */
56
65
  labels?: LabelOverrides<AlertLabels>;
66
+ /**
67
+ * How assertively the alert announces itself, overriding the per-tone
68
+ * default. Destructive and warning news are assertive `role="alert"`
69
+ * interruptions; neutral, info and success are polite `role="status"` —
70
+ * a "Saved" note should not cut off what is being read. `"off"` removes
71
+ * the live semantics for surfaces that are not interruptions at all,
72
+ * such as a static wall of notices.
73
+ */
74
+ live?: "assertive" | "polite" | "off";
57
75
  }> & Readonly<{
58
76
  "onUpdate:open"?: (value: boolean) => any;
59
77
  }>, {
@@ -7,8 +7,9 @@ import "../../icon-button/src/index.js";
7
7
  import { Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeProps, normalizeClass, openBlock, ref, renderSlot, resolveDynamicComponent, toDisplayString, unref, withCtx } from "vue";
8
8
  import { CircleCheck, CircleX, Info, TriangleAlert, X } from "@lucide/vue";
9
9
  //#region packages/primitives/alert/src/Alert.vue?vue&type=script&setup=true&lang.ts
10
- var _hoisted_1 = { class: "min-w-0 flex-1 break-words" };
11
- var _hoisted_2 = {
10
+ var _hoisted_1 = ["role"];
11
+ var _hoisted_2 = { class: "min-w-0 flex-1 break-words" };
12
+ var _hoisted_3 = {
12
13
  key: 0,
13
14
  class: "text-sm font-medium"
14
15
  };
@@ -33,7 +34,8 @@ var Alert_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
33
34
  type: Boolean,
34
35
  default: void 0
35
36
  },
36
- labels: {}
37
+ labels: {},
38
+ live: {}
37
39
  },
38
40
  emits: ["update:open"],
39
41
  setup(__props, { emit: __emit }) {
@@ -76,13 +78,14 @@ var Alert_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
76
78
  emit("update:open", false);
77
79
  }
78
80
  const accent = computed(() => TONE_ACCENTS[props.variant]);
81
+ const live = computed(() => props.live ?? (props.variant === "destructive" || props.variant === "warning" ? "assertive" : "polite"));
79
82
  return (_ctx, _cache) => {
80
83
  return openBlock(), createBlock(Transition, {
81
84
  "enter-active-class": "animate-fade-rise",
82
85
  "leave-active-class": "animate-fade-fall"
83
86
  }, {
84
87
  default: withCtx(() => [isOpen.value ? (openBlock(), createElementBlock("div", mergeProps({ key: 0 }, _ctx.$attrs, {
85
- role: "alert",
88
+ role: live.value === "off" ? void 0 : live.value === "assertive" ? "alert" : "status",
86
89
  class: unref(cn)("flex items-start gap-3 rounded-md border border-transparent p-3", accent.value?.wash)
87
90
  }), [
88
91
  renderSlot(_ctx.$slots, "icon", {}, () => [accent.value?.icon ? (openBlock(), createBlock(resolveDynamicComponent(accent.value.icon), {
@@ -90,8 +93,8 @@ var Alert_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
90
93
  class: "mt-0.5 h-4 w-4 shrink-0",
91
94
  "aria-hidden": "true"
92
95
  })) : createCommentVNode("", true)]),
93
- createElementVNode("div", _hoisted_1, [
94
- __props.title ? (openBlock(), createElementBlock("p", _hoisted_2, toDisplayString(__props.title), 1)) : createCommentVNode("", true),
96
+ createElementVNode("div", _hoisted_2, [
97
+ __props.title ? (openBlock(), createElementBlock("p", _hoisted_3, toDisplayString(__props.title), 1)) : createCommentVNode("", true),
95
98
  __props.description ? (openBlock(), createElementBlock("p", {
96
99
  key: 1,
97
100
  class: normalizeClass(unref(cn)("text-small", __props.title && "mt-0.5"))
@@ -115,7 +118,7 @@ var Alert_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
115
118
  })]),
116
119
  _: 1
117
120
  }, 8, ["label"])) : createCommentVNode("", true)
118
- ], 16)) : createCommentVNode("", true)]),
121
+ ], 16, _hoisted_1)) : createCommentVNode("", true)]),
119
122
  _: 3
120
123
  });
121
124
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Alert.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots"],"sources":["../../../../../packages/primitives/alert/src/Alert.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { AlertLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n * The feedback tones, matching Toast and Badge so one functional hue means\n * one thing everywhere. `neutral` is the default because an alert's first\n * job is to be seen at all, not to alarm.\n */\nexport type AlertVariant = \"neutral\" | \"info\" | \"success\" | \"warning\" | \"destructive\";\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it,\n * and exported so a host can build a partial vocabulary against the real\n * thing rather than a transcription of it.\n */\nexport const ALERT_LABELS: AlertLabels = {\n dismiss: \"Dismiss\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from \"vue\";\nimport { Info, CircleCheck, TriangleAlert, CircleX, X } from \"@lucide/vue\";\nimport IconButton from \"@ecoma-io/loom-icon-button\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\nimport { cn } from \"@ecoma-io/loom-core\";\n\nconst props = withDefaults(\n defineProps<{\n /** Selects the tinted wash and the default icon. */\n variant?: AlertVariant;\n /** The headline. Optional — a one-line alert can speak through its body alone. */\n title?: string;\n /** The detail line below the title. Longer content belongs in the default slot. */\n description?: string;\n /** Shows the dismiss control and lets the alert leave; pair with `v-model:open`. */\n dismissible?: boolean;\n /**\n * Controls visibility. Omit it and the alert owns its own state until\n * dismissed; pass bindings through `v-model:open` to own it yourself.\n * Pick one mode per instance and stay there: while the prop is bound the\n * internal state never moves, so removing the binding later brings back\n * whatever the host last left visible.\n */\n open?: boolean | undefined;\n /** Names for what the alert says on its own account, as any subset of `AlertLabels`. */\n labels?: LabelOverrides<AlertLabels>;\n }>(),\n {\n // `undefined` is the uncontrolled state, and only an explicit default\n // keeps it reachable past Vue's Boolean casting.\n open: undefined,\n variant: \"neutral\",\n dismissible: false,\n },\n);\n\nconst emit = defineEmits<{ \"update:open\": [value: boolean] }>();\n\n// `<Transition>` cannot pass fallthrough attributes through to its child —\n// a `class` or `@click` on the caller's `<Alert>` would land on the\n// Transition node and vanish. Opting out and forwarding by hand is what\n// keeps this component ordinary from the outside.\ndefineOptions({ inheritAttrs: false });\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(\"alert\", ALERT_LABELS, () => props.labels);\n\n/**\n * Per-tone accent icon and measured wash. The tinted pairs are the same ones\n * Badge paints (`bg-*-muted text-*-text`) because those are the tokens mixed\n * to hold their contrast in both themes; `-text`, never the bare `warning`,\n * for the failure Badge records. `neutral` carries no icon of its own — an\n * unremarkable note does not need one, and the slot remains available.\n */\nconst TONE_ACCENTS = {\n // Badge's own neutral pair: the recessed well, not a borrowed status hue.\n neutral: { icon: undefined, wash: \"bg-subtle text-subtle-foreground\" },\n info: { icon: Info, wash: \"bg-info-muted text-info-text\" },\n success: { icon: CircleCheck, wash: \"bg-success-muted text-success-text\" },\n warning: { icon: TriangleAlert, wash: \"bg-warning-muted text-warning-text\" },\n destructive: { icon: CircleX, wash: \"bg-destructive-muted text-destructive-text\" },\n} satisfies Record<AlertVariant, { icon: typeof Info | undefined; wash: string }>;\n\n// Controlled/uncontrolled split by hand — there is no Reka root to lean on,\n// and `optional()` exists for exactly the prop-forwarding case this is not.\nconst innerOpen = ref(true);\nconst isOpen = computed(() => props.open ?? innerOpen.value);\n\nfunction dismiss(): void {\n if (props.open === undefined) innerOpen.value = false;\n emit(\"update:open\", false);\n}\n\nconst accent = computed(() => TONE_ACCENTS[props.variant]);\n</script>\n\n<template>\n <!-- Enter rises like every revealed surface; exit falls back down it. Vue\n holds the leaving element itself, so no Presence machinery is needed\n the way it is under Reka, and the global reduced-motion collapse still\n ends both phases instantly — dismissal stays immediate for readers who\n asked for less motion. -->\n <Transition enter-active-class=\"animate-fade-rise\" leave-active-class=\"animate-fade-fall\">\n <div\n v-if=\"isOpen\"\n v-bind=\"$attrs\"\n role=\"alert\"\n :class=\"cn('flex items-start gap-3 rounded-md border border-transparent p-3', accent?.wash)\"\n >\n <slot name=\"icon\">\n <component\n :is=\"accent.icon\"\n v-if=\"accent?.icon\"\n class=\"mt-0.5 h-4 w-4 shrink-0\"\n aria-hidden=\"true\"\n />\n </slot>\n\n <div class=\"min-w-0 flex-1 break-words\">\n <p v-if=\"title\" class=\"text-sm font-medium\">{{ title }}</p>\n <p v-if=\"description\" :class=\"cn('text-small', title && 'mt-0.5')\">\n {{ description }}\n </p>\n <!-- @slot Anything beyond a title and one line of detail — a list of\n what failed, a link out. Rendered after the description, inside\n the tone's measured text colour. -->\n <div v-if=\"$slots.default\" :class=\"cn((title || description) && 'mt-1')\">\n <slot />\n </div>\n </div>\n\n <!-- In the flow, not overlaid: an absolutely-positioned close control\n collides with long titles at narrow widths, which is exactly where\n alerts wrap. -->\n <IconButton\n v-if=\"dismissible\"\n variant=\"ghost\"\n size=\"sm\"\n :label=\"text.dismiss\"\n class=\"-mr-1 -mt-1 shrink-0\"\n @click=\"dismiss()\"\n >\n <X class=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n </div>\n </Transition>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAeA,IAAa,eAA4B,EACvC,SAAS,UACX;;;;;;;;;;;;;;;;;;;;EAUA,MAAM,QAAQ;EA8Bd,MAAM,OAAO;EAWb,MAAM,OAAO,UAAU,SAAS,oBAAoB,MAAM,MAAM;;;;;;;;EAShE,MAAM,eAAe;GAEnB,SAAS;IAAE,MAAM,KAAA;IAAW,MAAM;GAAmC;GACrE,MAAM;IAAE,MAAM;IAAM,MAAM;GAA+B;GACzD,SAAS;IAAE,MAAM;IAAa,MAAM;GAAqC;GACzE,SAAS;IAAE,MAAM;IAAe,MAAM;GAAqC;GAC3E,aAAa;IAAE,MAAM;IAAS,MAAM;GAA6C;EACnF;EAIA,MAAM,YAAY,IAAI,IAAI;EAC1B,MAAM,SAAS,eAAe,MAAM,QAAQ,UAAU,KAAK;EAE3D,SAAS,UAAgB;GACvB,IAAI,MAAM,SAAS,KAAA,GAAW,UAAU,QAAQ;GAChD,KAAK,eAAe,KAAK;EAC3B;EAEA,MAAM,SAAS,eAAe,aAAa,MAAM,QAAQ;;GASvD,OAAA,UAAA,GAAA,YA2Ca,YAAA;IA3CD,sBAAmB;IAAoB,sBAAmB;;IACpE,SAAA,cAyCM,CAxCE,OAAA,SADR,UAAA,GAAA,mBAyCM,OAzCN,WAyCM,EAAA,KAAA,EAAA,GAvCIA,KAAAA,QAAM;KACd,MAAK;KACJ,OAAO,MAAA,EAAA,CAAE,CAAA,mEAAoE,OAAA,OAAQ,IAAI;;KAE1F,WAOO,KAAA,QAAA,QAAA,CAAA,SAAA,CAJG,OAAA,OAAQ,QAFhB,UAAA,GAAA,YAKE,wBAJK,OAAA,MAAO,IAAI,GAAA;;MAEhB,OAAM;MACN,eAAY;;KAIhB,mBAWM,OAXN,YAWM;MAVK,QAAA,SAAT,UAAA,GAAA,mBAA2D,KAA3D,YAA2D,gBAAZ,QAAA,KAAK,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;MAC3C,QAAA,eAAT,UAAA,GAAA,mBAEI,KAAA;;OAFmB,OAAK,eAAE,MAAA,EAAA,CAAE,CAAA,cAAe,QAAA,SAAK,QAAA,CAAA;MAC/C,GAAA,gBAAA,QAAA,WAAW,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;MAKLC,KAAAA,OAAO,WAAlB,UAAA,GAAA,mBAEM,OAAA;;OAFsB,OAAK,eAAE,MAAA,EAAA,CAAE,EAAE,QAAA,SAAS,QAAA,gBAAW,MAAA,CAAA;MACzD,GAAA,CAAA,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;;KAQJ,QAAA,eADR,UAAA,GAAA,YASa,MAAA,kBAAA,GAAA;;MAPX,SAAQ;MACR,MAAK;MACJ,OAAO,MAAA,IAAA,CAAI,CAAC;MACb,OAAM;MACL,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,QAAO;;MAEf,SAAA,cAAwC,CAAxC,YAAwC,MAAA,CAAA,GAAA;OAArC,OAAM;OAAU,eAAY"}
1
+ {"version":3,"file":"Alert.vue_vue_type_script_setup_true_lang.js","names":["$attrs","$slots"],"sources":["../../../../../packages/primitives/alert/src/Alert.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { AlertLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n * The feedback tones, matching Toast and Badge so one functional hue means\n * one thing everywhere. `neutral` is the default because an alert's first\n * job is to be seen at all, not to alarm.\n */\nexport type AlertVariant = \"neutral\" | \"info\" | \"success\" | \"warning\" | \"destructive\";\n\n/**\n * Loom's English, co-located with the component so it tree-shakes with it,\n * and exported so a host can build a partial vocabulary against the real\n * thing rather than a transcription of it.\n */\nexport const ALERT_LABELS: AlertLabels = {\n dismiss: \"Dismiss\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from \"vue\";\nimport { Info, CircleCheck, TriangleAlert, CircleX, X } from \"@lucide/vue\";\nimport IconButton from \"@ecoma-io/loom-icon-button\";\nimport { useLabels, type LabelOverrides } from \"@ecoma-io/loom-labels\";\nimport { cn } from \"@ecoma-io/loom-core\";\n\nconst props = withDefaults(\n defineProps<{\n /** Selects the tinted wash and the default icon. */\n variant?: AlertVariant;\n /** The headline. Optional — a one-line alert can speak through its body alone. */\n title?: string;\n /** The detail line below the title. Longer content belongs in the default slot. */\n description?: string;\n /** Shows the dismiss control and lets the alert leave; pair with `v-model:open`. */\n dismissible?: boolean;\n /**\n * Controls visibility. Omit it and the alert owns its own state until\n * dismissed; pass bindings through `v-model:open` to own it yourself.\n * Pick one mode per instance and stay there: while the prop is bound the\n * internal state never moves, so removing the binding later brings back\n * whatever the host last left visible.\n */\n open?: boolean | undefined;\n /** Names for what the alert says on its own account, as any subset of `AlertLabels`. */\n labels?: LabelOverrides<AlertLabels>;\n /**\n * How assertively the alert announces itself, overriding the per-tone\n * default. Destructive and warning news are assertive `role=\"alert\"`\n * interruptions; neutral, info and success are polite `role=\"status\"` —\n * a \"Saved\" note should not cut off what is being read. `\"off\"` removes\n * the live semantics for surfaces that are not interruptions at all,\n * such as a static wall of notices.\n */\n live?: \"assertive\" | \"polite\" | \"off\";\n }>(),\n {\n // `undefined` is the uncontrolled state, and only an explicit default\n // keeps it reachable past Vue's Boolean casting.\n open: undefined,\n variant: \"neutral\",\n dismissible: false,\n },\n);\n\nconst emit = defineEmits<{ \"update:open\": [value: boolean] }>();\n\n// `<Transition>` cannot pass fallthrough attributes through to its child —\n// a `class` or `@click` on the caller's `<Alert>` would land on the\n// Transition node and vanish. Opting out and forwarding by hand is what\n// keeps this component ordinary from the outside.\ndefineOptions({ inheritAttrs: false });\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(\"alert\", ALERT_LABELS, () => props.labels);\n\n/**\n * Per-tone accent icon and measured wash. The tinted pairs are the same ones\n * Badge paints (`bg-*-muted text-*-text`) because those are the tokens mixed\n * to hold their contrast in both themes; `-text`, never the bare `warning`,\n * for the failure Badge records. `neutral` carries no icon of its own — an\n * unremarkable note does not need one, and the slot remains available.\n */\nconst TONE_ACCENTS = {\n // Badge's own neutral pair: the recessed well, not a borrowed status hue.\n neutral: { icon: undefined, wash: \"bg-subtle text-subtle-foreground\" },\n info: { icon: Info, wash: \"bg-info-muted text-info-text\" },\n success: { icon: CircleCheck, wash: \"bg-success-muted text-success-text\" },\n warning: { icon: TriangleAlert, wash: \"bg-warning-muted text-warning-text\" },\n destructive: { icon: CircleX, wash: \"bg-destructive-muted text-destructive-text\" },\n} satisfies Record<AlertVariant, { icon: typeof Info | undefined; wash: string }>;\n\n// Controlled/uncontrolled split by hand — there is no Reka root to lean on,\n// and `optional()` exists for exactly the prop-forwarding case this is not.\nconst innerOpen = ref(true);\nconst isOpen = computed(() => props.open ?? innerOpen.value);\n\nfunction dismiss(): void {\n if (props.open === undefined) innerOpen.value = false;\n emit(\"update:open\", false);\n}\n\nconst accent = computed(() => TONE_ACCENTS[props.variant]);\n\n// The interruption an alert makes follows its stakes: failure and warning\n// news is the assertive role, the rest polite. A live region that says\n// \"Saved\" on every save should not be cutting off whatever is being read.\nconst live = computed<\"assertive\" | \"polite\" | \"off\">(\n () =>\n props.live ??\n (props.variant === \"destructive\" || props.variant === \"warning\" ? \"assertive\" : \"polite\"),\n);\n</script>\n\n<template>\n <!-- Enter rises like every revealed surface; exit falls back down it. Vue\n holds the leaving element itself, so no Presence machinery is needed\n the way it is under Reka, and the global reduced-motion collapse still\n ends both phases instantly — dismissal stays immediate for readers who\n asked for less motion. -->\n <Transition enter-active-class=\"animate-fade-rise\" leave-active-class=\"animate-fade-fall\">\n <div\n v-if=\"isOpen\"\n v-bind=\"$attrs\"\n :role=\"live === 'off' ? undefined : live === 'assertive' ? 'alert' : 'status'\"\n :class=\"cn('flex items-start gap-3 rounded-md border border-transparent p-3', accent?.wash)\"\n >\n <slot name=\"icon\">\n <component\n :is=\"accent.icon\"\n v-if=\"accent?.icon\"\n class=\"mt-0.5 h-4 w-4 shrink-0\"\n aria-hidden=\"true\"\n />\n </slot>\n\n <div class=\"min-w-0 flex-1 break-words\">\n <p v-if=\"title\" class=\"text-sm font-medium\">{{ title }}</p>\n <p v-if=\"description\" :class=\"cn('text-small', title && 'mt-0.5')\">\n {{ description }}\n </p>\n <!-- @slot Anything beyond a title and one line of detail — a list of\n what failed, a link out. Rendered after the description, inside\n the tone's measured text colour. -->\n <div v-if=\"$slots.default\" :class=\"cn((title || description) && 'mt-1')\">\n <slot />\n </div>\n </div>\n\n <!-- In the flow, not overlaid: an absolutely-positioned close control\n collides with long titles at narrow widths, which is exactly where\n alerts wrap. -->\n <IconButton\n v-if=\"dismissible\"\n variant=\"ghost\"\n size=\"sm\"\n :label=\"text.dismiss\"\n class=\"-mr-1 -mt-1 shrink-0\"\n @click=\"dismiss()\"\n >\n <X class=\"h-4 w-4\" aria-hidden=\"true\" />\n </IconButton>\n </div>\n </Transition>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAeA,IAAa,eAA4B,EACvC,SAAS,UACX;;;;;;;;;;;;;;;;;;;;;EAUA,MAAM,QAAQ;EAuCd,MAAM,OAAO;EAWb,MAAM,OAAO,UAAU,SAAS,oBAAoB,MAAM,MAAM;;;;;;;;EAShE,MAAM,eAAe;GAEnB,SAAS;IAAE,MAAM,KAAA;IAAW,MAAM;GAAmC;GACrE,MAAM;IAAE,MAAM;IAAM,MAAM;GAA+B;GACzD,SAAS;IAAE,MAAM;IAAa,MAAM;GAAqC;GACzE,SAAS;IAAE,MAAM;IAAe,MAAM;GAAqC;GAC3E,aAAa;IAAE,MAAM;IAAS,MAAM;GAA6C;EACnF;EAIA,MAAM,YAAY,IAAI,IAAI;EAC1B,MAAM,SAAS,eAAe,MAAM,QAAQ,UAAU,KAAK;EAE3D,SAAS,UAAgB;GACvB,IAAI,MAAM,SAAS,KAAA,GAAW,UAAU,QAAQ;GAChD,KAAK,eAAe,KAAK;EAC3B;EAEA,MAAM,SAAS,eAAe,aAAa,MAAM,QAAQ;EAKzD,MAAM,OAAO,eAET,MAAM,SACL,MAAM,YAAY,iBAAiB,MAAM,YAAY,YAAY,cAAc,SACpF;;GASE,OAAA,UAAA,GAAA,YA2Ca,YAAA;IA3CD,sBAAmB;IAAoB,sBAAmB;;IACpE,SAAA,cAyCM,CAxCE,OAAA,SADR,UAAA,GAAA,mBAyCM,OAzCN,WAyCM,EAAA,KAAA,EAAA,GAvCIA,KAAAA,QAAM;KACb,MAAM,KAAA,UAAI,QAAa,KAAA,IAAY,KAAA,UAAI,cAAA,UAAA;KACvC,OAAO,MAAA,EAAA,CAAE,CAAA,mEAAoE,OAAA,OAAQ,IAAI;;KAE1F,WAOO,KAAA,QAAA,QAAA,CAAA,SAAA,CAJG,OAAA,OAAQ,QAFhB,UAAA,GAAA,YAKE,wBAJK,OAAA,MAAO,IAAI,GAAA;;MAEhB,OAAM;MACN,eAAY;;KAIhB,mBAWM,OAXN,YAWM;MAVK,QAAA,SAAT,UAAA,GAAA,mBAA2D,KAA3D,YAA2D,gBAAZ,QAAA,KAAK,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;MAC3C,QAAA,eAAT,UAAA,GAAA,mBAEI,KAAA;;OAFmB,OAAK,eAAE,MAAA,EAAA,CAAE,CAAA,cAAe,QAAA,SAAK,QAAA,CAAA;MAC/C,GAAA,gBAAA,QAAA,WAAW,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;MAKLC,KAAAA,OAAO,WAAlB,UAAA,GAAA,mBAEM,OAAA;;OAFsB,OAAK,eAAE,MAAA,EAAA,CAAE,EAAE,QAAA,SAAS,QAAA,gBAAW,MAAA,CAAA;MACzD,GAAA,CAAA,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA;;KAQJ,QAAA,eADR,UAAA,GAAA,YASa,MAAA,kBAAA,GAAA;;MAPX,SAAQ;MACR,MAAK;MACJ,OAAO,MAAA,IAAA,CAAI,CAAC;MACb,OAAM;MACL,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,QAAO;;MAEf,SAAA,cAAwC,CAAxC,YAAwC,MAAA,CAAA,GAAA;OAArC,OAAM;OAAU,eAAY"}
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.js","names":[],"sources":["../../../../../packages/primitives/avatar/src/Avatar.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/** Control height, and the text size the initials fallback prints at. */\nexport type AvatarSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\n/** A circle, or a rounded square tile. */\nexport type AvatarShape = \"circle\" | \"square\";\n\n/**\n * Which visual treatment the avatar receives. `accent` applies the accent\n * colour as a rim, signalling a second semantic category distinct from the\n * default — a different role, origin, or mode.\n */\nexport type AvatarVariant = \"default\" | \"accent\";\n\nexport const avatarVariants = cva(\n \"relative inline-flex shrink-0 items-center justify-center overflow-hidden select-none\",\n {\n // `satisfies` keeps the two halves honest: the unions above are the names a\n // consumer imports and the documentation prints, the maps below are the\n // classes. Adding a member to one and not the other stops compiling — which\n // is what the three inline `size === '…' &&` conditionals this replaced\n // could not do, and the reason five sizes could not stay written that way.\n variants: {\n size: {\n // `text-xs` twice, deliberately. It is the smallest step Tailwind's own\n // scale has, and the step below it — Loom's `text-micro` — is a name\n // tailwind-merge classifies as a text *colour* rather than a size, so\n // `cn()` drops it the moment the force map adds `text-muted-foreground`\n // after it. Two initials at 12px still fit inside 24px.\n xs: \"h-6 w-6 text-xs\",\n sm: \"h-8 w-8 text-xs\",\n md: \"h-10 w-10 text-sm\",\n lg: \"h-12 w-12 text-base\",\n xl: \"h-16 w-16 text-lg\",\n } satisfies Record<AvatarSize, string>,\n force: {\n default: \"bg-muted text-muted-foreground\",\n // The accent rim. Two signals, not one: the rim's *presence* is what a\n // reader who cannot resolve the hue still sees — a default avatar has no\n // edge at all — and the hidden `accentLabel` is what a reader who sees\n // no avatar hears. The corner is left alone on purpose, because the\n // corner is Indicator's: a presence dot pinned there would land on top\n // of anything this component drew.\n accent: \"border-2 border-accent bg-accent-muted text-accent-text\",\n } satisfies Record<AvatarVariant, string>,\n },\n defaultVariants: { size: \"md\", force: \"default\" },\n },\n);\n\n/**\n * A square avatar's corner radius, one value per size rather than the control\n * radius throughout. `rounded-md` is calibrated against a ~36px control; on a\n * 24px tile it is a third of the side, where a milled fillet stops reading as\n * a corner and starts reading as a blob, and on a 64px one it has almost\n * disappeared. Stepping it holds the corner between a sixth and a quarter of\n * the side at every size — the band the control radius already sits in — which\n * is the nesting law applied to a tile whose \"padding\" is its own edge.\n */\nconst SQUARE_RADIUS = {\n xs: \"rounded-sm\",\n sm: \"rounded-md\",\n md: \"rounded-md\",\n lg: \"rounded-lg\",\n xl: \"rounded-xl\",\n} satisfies Record<AvatarSize, string>;\n\n/**\n * The rounding for one size and shape. A circle is one value at every size; a\n * square is not, which is why the radius cannot live in the `cva` map beside\n * the heights. Kept off the public surface deliberately: a consumer wanting an\n * avatar-shaped tile should render an `Avatar`, not reassemble one.\n */\nfunction avatarRadius(size: AvatarSize, shape: AvatarShape): string {\n return shape === \"circle\" ? \"rounded-full\" : SQUARE_RADIUS[size];\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { AvatarRoot, AvatarImage, AvatarFallback } from \"reka-ui\";\nimport { cn, useSplitAttrs } from \"@ecoma-io/loom-core\";\n\n/**\n * Avatar — a user's picture, with a graceful initials fallback for\n * no `src`, a broken URL, or a still-loading image. Built on Reka UI's\n * Avatar: the image only paints once it has actually finished loading, so\n * the fallback stays visible the whole time until then — first paint is\n * either the real photo or the initials, never a broken-image icon.\n *\n * Two neighbours are worth naming. Several faces standing for one thing — the\n * people on a task, the agents on a run — are an `AvatarGroup`, which owns the\n * overlap, the stacking order and the \"+3\" so a row of them is one object to a\n * screen reader rather than N unrelated images. Anything pinned onto the\n * avatar's corner — a presence dot, an unread count — is an `Indicator`\n * wrapped around it; this component deliberately draws nothing there.\n */\nconst props = withDefaults(\n defineProps<{\n /** Image URL. Omit it to render the fallback outright. */\n src?: string;\n /** Accessible name for the photo — required on `AvatarImage` so a screen reader announces who it is, not just that an image loaded. */\n alt?: string;\n /** Initials to show while there is no image, or once one has failed — computed by the caller, never derived from `alt` here. */\n fallback?: string;\n /** Control height. */\n size?: AvatarSize;\n /** A circle, or a rounded square tile. Square suits a subject a circle would misdescribe — an organisation, a project, a repository — and takes a radius that steps with the size rather than one fixed value. */\n shape?: AvatarShape;\n /** Which visual treatment the avatar receives. `accent` applies the accent rim and `accentLabel` for a screen reader, so the distinction never rests on the hue alone. */\n variant?: AvatarVariant;\n /** What a screen reader announces after the name of an `accent` avatar. Localise it. Set it empty when something outside already says so — `AvatarGroup` does, because each row item composes its own name — and nothing is added for a `default` avatar either way. */\n accentLabel?: string;\n }>(),\n {\n alt: \"\",\n size: \"md\",\n shape: \"circle\",\n variant: \"default\",\n accentLabel: \"\",\n },\n);\n\n// One rendered node, and it is the right home for every fallthrough attribute\n// — but `class` still goes the long way round, through `cn()`. Vue's own merge\n// only concatenates, so the `bg-subtle` an AvatarGroup paints its overflow tile\n// with would win or lose against this root's `bg-muted` depending on the order\n// Tailwind happened to emit the two rules in, rather than on intent.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest } = useSplitAttrs();\n\nconst radius = computed(() => avatarRadius(props.size, props.shape));\n</script>\n\n<template>\n <AvatarRoot\n v-bind=\"rest\"\n :data-variant=\"variant\"\n :class=\"cn(avatarVariants({ size, force: variant }), radius, attrs.class as string)\"\n >\n <!-- Reka paints AvatarImage only once the photo has loaded, so scale-in\n plays exactly on that swap-in — a gentle settle over the fallback. -->\n <AvatarImage\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt\"\n class=\"h-full w-full animate-scale-in object-cover\"\n />\n <AvatarFallback class=\"font-medium\">{{ fallback }}</AvatarFallback>\n <!-- The half of the accent signal a rim cannot carry. It sits after the\n image so it is announced as a qualifier on the name rather than in\n place of it, and it is dropped entirely for an empty `accentLabel`: a\n wrapper that has already worked the qualifier into its own name would\n otherwise leave a second copy of it in the tree. -->\n <span v-if=\"variant === 'accent' && accentLabel\" class=\"sr-only\">{{ accentLabel }}</span>\n </AvatarRoot>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"Avatar.js","names":[],"sources":["../../../../../packages/primitives/avatar/src/Avatar.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/** Control height, and the text size the initials fallback prints at. */\nexport type AvatarSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\n/** A circle, or a rounded square tile. */\nexport type AvatarShape = \"circle\" | \"square\";\n\n/**\n * Which visual treatment the avatar receives. `accent` applies the accent\n * colour as a rim, signalling a second semantic category distinct from the\n * default — a different role, origin, or mode.\n */\nexport type AvatarVariant = \"default\" | \"accent\";\n\nexport const avatarVariants = cva(\n \"relative inline-flex shrink-0 items-center justify-center overflow-hidden select-none\",\n {\n // `satisfies` keeps the two halves honest: the unions above are the names a\n // consumer imports and the documentation prints, the maps below are the\n // classes. Adding a member to one and not the other stops compiling — which\n // is what the three inline `size === '…' &&` conditionals this replaced\n // could not do, and the reason five sizes could not stay written that way.\n variants: {\n size: {\n // `text-xs` twice, deliberately. It is the smallest step Tailwind's own\n // scale has, and the step below it — Loom's `text-micro` — is a name\n // tailwind-merge classifies as a text *colour* rather than a size, so\n // `cn()` drops it the moment the force map adds `text-muted-foreground`\n // after it. Two initials at 12px still fit inside 24px.\n xs: \"h-6 w-6 text-xs\",\n sm: \"h-8 w-8 text-xs\",\n md: \"h-10 w-10 text-sm\",\n lg: \"h-12 w-12 text-base\",\n xl: \"h-16 w-16 text-lg\",\n } satisfies Record<AvatarSize, string>,\n force: {\n default: \"bg-muted text-muted-foreground\",\n // The accent rim. Two signals, not one: the rim's *presence* is what a\n // reader who cannot resolve the hue still sees — a default avatar has no\n // edge at all — and the hidden `accentLabel` is what a reader who sees\n // no avatar hears. The corner is left alone on purpose, because the\n // corner is Indicator's: a presence dot pinned there would land on top\n // of anything this component drew.\n accent: \"border-2 border-accent bg-accent-muted text-accent-text\",\n } satisfies Record<AvatarVariant, string>,\n },\n defaultVariants: { size: \"md\", force: \"default\" },\n },\n);\n\n/**\n * A square avatar's corner radius, one value per size rather than the control\n * radius throughout. `rounded-md` is calibrated against a ~36px control; on a\n * 24px tile it is a third of the side, where a milled fillet stops reading as\n * a corner and starts reading as a blob, and on a 64px one it has almost\n * disappeared. Stepping it holds the corner between a sixth and a quarter of\n * the side at every size — the band the control radius already sits in — which\n * is the nesting law applied to a tile whose \"padding\" is its own edge.\n */\nconst SQUARE_RADIUS = {\n xs: \"rounded-sm\",\n sm: \"rounded-md\",\n md: \"rounded-md\",\n lg: \"rounded-lg\",\n xl: \"rounded-xl\",\n} satisfies Record<AvatarSize, string>;\n\n/**\n * The rounding for one size and shape. A circle is one value at every size; a\n * square is not, which is why the radius cannot live in the `cva` map beside\n * the heights. Kept off the public surface deliberately: a consumer wanting an\n * avatar-shaped tile should render an `Avatar`, not reassemble one.\n */\nfunction avatarRadius(size: AvatarSize, shape: AvatarShape): string {\n return shape === \"circle\" ? \"rounded-full\" : SQUARE_RADIUS[size];\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { AvatarRoot, AvatarImage, AvatarFallback } from \"reka-ui\";\nimport { cn, useSplitAttrs } from \"@ecoma-io/loom-core\";\n\n/**\n * Avatar — a user's picture, with a graceful initials fallback for\n * no `src`, a broken URL, or a still-loading image. Built on Reka UI's\n * Avatar: the image only paints once it has actually finished loading, so\n * the fallback stays visible the whole time until then — first paint is\n * either the real photo or the initials, never a broken-image icon.\n *\n * Two neighbours are worth naming. Several faces standing for one thing — the\n * people on a task, the agents on a run — are an `AvatarGroup`, which owns the\n * overlap, the stacking order and the \"+3\" so a row of them is one object to a\n * screen reader rather than N unrelated images. Anything pinned onto the\n * avatar's corner — a presence dot, an unread count — is an `Indicator`\n * wrapped around it; this component deliberately draws nothing there.\n */\nconst props = withDefaults(\n defineProps<{\n /** Image URL. Omit it to render the fallback outright. */\n src?: string;\n /** Accessible name for the photo — required on `AvatarImage` so a screen reader announces who it is, not just that an image loaded. */\n alt?: string;\n /** Initials to show while there is no image, or once one has failed — computed by the caller, never derived from `alt` here. */\n fallback?: string;\n /** Control height. */\n size?: AvatarSize;\n /** A circle, or a rounded square tile. Square suits a subject a circle would misdescribe — an organisation, a project, a repository — and takes a radius that steps with the size rather than one fixed value. */\n shape?: AvatarShape;\n /** Which visual treatment the avatar receives. `accent` applies the accent rim and `accentLabel` for a screen reader, so the distinction never rests on the hue alone. */\n variant?: AvatarVariant;\n /** What a screen reader announces after the name of an `accent` avatar — \"Accent\" by default, so the accent never rests on the hue alone. Localise it. Set it empty when something outside already says so — `AvatarGroup` does, because each row item composes its own name — and nothing is added for a `default` avatar either way. */\n accentLabel?: string;\n }>(),\n {\n alt: \"\",\n size: \"md\",\n shape: \"circle\",\n variant: \"default\",\n accentLabel: \"Accent\",\n },\n);\n\n// One rendered node, and it is the right home for every fallthrough attribute\n// — but `class` still goes the long way round, through `cn()`. Vue's own merge\n// only concatenates, so the `bg-subtle` an AvatarGroup paints its overflow tile\n// with would win or lose against this root's `bg-muted` depending on the order\n// Tailwind happened to emit the two rules in, rather than on intent.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest } = useSplitAttrs();\n\nconst radius = computed(() => avatarRadius(props.size, props.shape));\n</script>\n\n<template>\n <AvatarRoot\n v-bind=\"rest\"\n :data-variant=\"variant\"\n :class=\"cn(avatarVariants({ size, force: variant }), radius, attrs.class as string)\"\n >\n <!-- Reka paints AvatarImage only once the photo has loaded, so scale-in\n plays exactly on that swap-in — a gentle settle over the fallback. -->\n <AvatarImage\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt\"\n class=\"h-full w-full animate-scale-in object-cover\"\n />\n <AvatarFallback class=\"font-medium\">{{ fallback }}</AvatarFallback>\n <!-- The half of the accent signal a rim cannot carry. It sits after the\n image so it is announced as a qualifier on the name rather than in\n place of it, and it is dropped entirely for an empty `accentLabel`: a\n wrapper that has already worked the qualifier into its own name would\n otherwise leave a second copy of it in the tree. -->\n <span v-if=\"variant === 'accent' && accentLabel\" class=\"sr-only\">{{ accentLabel }}</span>\n </AvatarRoot>\n</template>\n"],"mappings":""}
@@ -27,7 +27,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
27
27
  shape?: AvatarShape;
28
28
  /** Which visual treatment the avatar receives. `accent` applies the accent rim and `accentLabel` for a screen reader, so the distinction never rests on the hue alone. */
29
29
  variant?: AvatarVariant;
30
- /** What a screen reader announces after the name of an `accent` avatar. Localise it. Set it empty when something outside already says so — `AvatarGroup` does, because each row item composes its own name — and nothing is added for a `default` avatar either way. */
30
+ /** What a screen reader announces after the name of an `accent` avatar — "Accent" by default, so the accent never rests on the hue alone. Localise it. Set it empty when something outside already says so — `AvatarGroup` does, because each row item composes its own name — and nothing is added for a `default` avatar either way. */
31
31
  accentLabel?: string;
32
32
  }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
33
33
  /** Image URL. Omit it to render the fallback outright. */
@@ -42,7 +42,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
42
42
  shape?: AvatarShape;
43
43
  /** Which visual treatment the avatar receives. `accent` applies the accent rim and `accentLabel` for a screen reader, so the distinction never rests on the hue alone. */
44
44
  variant?: AvatarVariant;
45
- /** What a screen reader announces after the name of an `accent` avatar. Localise it. Set it empty when something outside already says so — `AvatarGroup` does, because each row item composes its own name — and nothing is added for a `default` avatar either way. */
45
+ /** What a screen reader announces after the name of an `accent` avatar — "Accent" by default, so the accent never rests on the hue alone. Localise it. Set it empty when something outside already says so — `AvatarGroup` does, because each row item composes its own name — and nothing is added for a `default` avatar either way. */
46
46
  accentLabel?: string;
47
47
  }> & Readonly<{}>, {
48
48
  size: AvatarSize;
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.vue.d.ts","sourceRoot":"","sources":["../../../../../packages/primitives/avatar/src/Avatar.vue"],"names":[],"mappings":"AAyKA,yEAAyE;AACzE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE1D,0CAA0C;AAC1C,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE9C;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEjD,eAAO,MAAM,cAAc;;;8EAkC1B,CAAC;wBA4BmB,OAAO,YAAY;AAAxC,wBAAyC;AACzC,QAAA,MAAM,YAAY;IAgBd,0DAA0D;UACpD,MAAM;IACZ,uIAAuI;UACjI,MAAM;IACZ,gIAAgI;eACrH,MAAM;IACjB,sBAAsB;WACf,UAAU;IACjB,kNAAkN;YAC1M,WAAW;IACnB,0KAA0K;cAChK,aAAa;IACvB,wQAAwQ;kBAC1P,MAAM;;IAbpB,0DAA0D;UACpD,MAAM;IACZ,uIAAuI;UACjI,MAAM;IACZ,gIAAgI;eACrH,MAAM;IACjB,sBAAsB;WACf,UAAU;IACjB,kNAAkN;YAC1M,WAAW;IACnB,0KAA0K;cAChK,aAAa;IACvB,wQAAwQ;kBAC1P,MAAM;;UANb,UAAU;aAIP,aAAa;SARjB,MAAM;WAMJ,WAAW;iBAIL,MAAM;6EA4HpB,CAAC"}
1
+ {"version":3,"file":"Avatar.vue.d.ts","sourceRoot":"","sources":["../../../../../packages/primitives/avatar/src/Avatar.vue"],"names":[],"mappings":"AAyKA,yEAAyE;AACzE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE1D,0CAA0C;AAC1C,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE9C;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEjD,eAAO,MAAM,cAAc;;;8EAkC1B,CAAC;wBA4BmB,OAAO,YAAY;AAAxC,wBAAyC;AACzC,QAAA,MAAM,YAAY;IAgBd,0DAA0D;UACpD,MAAM;IACZ,uIAAuI;UACjI,MAAM;IACZ,gIAAgI;eACrH,MAAM;IACjB,sBAAsB;WACf,UAAU;IACjB,kNAAkN;YAC1M,WAAW;IACnB,0KAA0K;cAChK,aAAa;IACvB,0UAA0U;kBAC5T,MAAM;;IAbpB,0DAA0D;UACpD,MAAM;IACZ,uIAAuI;UACjI,MAAM;IACZ,gIAAgI;eACrH,MAAM;IACjB,sBAAsB;WACf,UAAU;IACjB,kNAAkN;YAC1M,WAAW;IACnB,0KAA0K;cAChK,aAAa;IACvB,0UAA0U;kBAC5T,MAAM;;UANb,UAAU;aAIP,aAAa;SARjB,MAAM;WAMJ,WAAW;iBAIL,MAAM;6EA4HpB,CAAC"}
@@ -77,7 +77,7 @@ var Avatar_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCom
77
77
  size: { default: "md" },
78
78
  shape: { default: "circle" },
79
79
  variant: { default: "default" },
80
- accentLabel: { default: "" }
80
+ accentLabel: { default: "Accent" }
81
81
  },
82
82
  setup(__props) {
83
83
  const props = __props;
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../../packages/primitives/avatar/src/Avatar.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/** Control height, and the text size the initials fallback prints at. */\nexport type AvatarSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\n/** A circle, or a rounded square tile. */\nexport type AvatarShape = \"circle\" | \"square\";\n\n/**\n * Which visual treatment the avatar receives. `accent` applies the accent\n * colour as a rim, signalling a second semantic category distinct from the\n * default — a different role, origin, or mode.\n */\nexport type AvatarVariant = \"default\" | \"accent\";\n\nexport const avatarVariants = cva(\n \"relative inline-flex shrink-0 items-center justify-center overflow-hidden select-none\",\n {\n // `satisfies` keeps the two halves honest: the unions above are the names a\n // consumer imports and the documentation prints, the maps below are the\n // classes. Adding a member to one and not the other stops compiling — which\n // is what the three inline `size === '…' &&` conditionals this replaced\n // could not do, and the reason five sizes could not stay written that way.\n variants: {\n size: {\n // `text-xs` twice, deliberately. It is the smallest step Tailwind's own\n // scale has, and the step below it — Loom's `text-micro` — is a name\n // tailwind-merge classifies as a text *colour* rather than a size, so\n // `cn()` drops it the moment the force map adds `text-muted-foreground`\n // after it. Two initials at 12px still fit inside 24px.\n xs: \"h-6 w-6 text-xs\",\n sm: \"h-8 w-8 text-xs\",\n md: \"h-10 w-10 text-sm\",\n lg: \"h-12 w-12 text-base\",\n xl: \"h-16 w-16 text-lg\",\n } satisfies Record<AvatarSize, string>,\n force: {\n default: \"bg-muted text-muted-foreground\",\n // The accent rim. Two signals, not one: the rim's *presence* is what a\n // reader who cannot resolve the hue still sees — a default avatar has no\n // edge at all — and the hidden `accentLabel` is what a reader who sees\n // no avatar hears. The corner is left alone on purpose, because the\n // corner is Indicator's: a presence dot pinned there would land on top\n // of anything this component drew.\n accent: \"border-2 border-accent bg-accent-muted text-accent-text\",\n } satisfies Record<AvatarVariant, string>,\n },\n defaultVariants: { size: \"md\", force: \"default\" },\n },\n);\n\n/**\n * A square avatar's corner radius, one value per size rather than the control\n * radius throughout. `rounded-md` is calibrated against a ~36px control; on a\n * 24px tile it is a third of the side, where a milled fillet stops reading as\n * a corner and starts reading as a blob, and on a 64px one it has almost\n * disappeared. Stepping it holds the corner between a sixth and a quarter of\n * the side at every size — the band the control radius already sits in — which\n * is the nesting law applied to a tile whose \"padding\" is its own edge.\n */\nconst SQUARE_RADIUS = {\n xs: \"rounded-sm\",\n sm: \"rounded-md\",\n md: \"rounded-md\",\n lg: \"rounded-lg\",\n xl: \"rounded-xl\",\n} satisfies Record<AvatarSize, string>;\n\n/**\n * The rounding for one size and shape. A circle is one value at every size; a\n * square is not, which is why the radius cannot live in the `cva` map beside\n * the heights. Kept off the public surface deliberately: a consumer wanting an\n * avatar-shaped tile should render an `Avatar`, not reassemble one.\n */\nfunction avatarRadius(size: AvatarSize, shape: AvatarShape): string {\n return shape === \"circle\" ? \"rounded-full\" : SQUARE_RADIUS[size];\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { AvatarRoot, AvatarImage, AvatarFallback } from \"reka-ui\";\nimport { cn, useSplitAttrs } from \"@ecoma-io/loom-core\";\n\n/**\n * Avatar — a user's picture, with a graceful initials fallback for\n * no `src`, a broken URL, or a still-loading image. Built on Reka UI's\n * Avatar: the image only paints once it has actually finished loading, so\n * the fallback stays visible the whole time until then — first paint is\n * either the real photo or the initials, never a broken-image icon.\n *\n * Two neighbours are worth naming. Several faces standing for one thing — the\n * people on a task, the agents on a run — are an `AvatarGroup`, which owns the\n * overlap, the stacking order and the \"+3\" so a row of them is one object to a\n * screen reader rather than N unrelated images. Anything pinned onto the\n * avatar's corner — a presence dot, an unread count — is an `Indicator`\n * wrapped around it; this component deliberately draws nothing there.\n */\nconst props = withDefaults(\n defineProps<{\n /** Image URL. Omit it to render the fallback outright. */\n src?: string;\n /** Accessible name for the photo — required on `AvatarImage` so a screen reader announces who it is, not just that an image loaded. */\n alt?: string;\n /** Initials to show while there is no image, or once one has failed — computed by the caller, never derived from `alt` here. */\n fallback?: string;\n /** Control height. */\n size?: AvatarSize;\n /** A circle, or a rounded square tile. Square suits a subject a circle would misdescribe — an organisation, a project, a repository — and takes a radius that steps with the size rather than one fixed value. */\n shape?: AvatarShape;\n /** Which visual treatment the avatar receives. `accent` applies the accent rim and `accentLabel` for a screen reader, so the distinction never rests on the hue alone. */\n variant?: AvatarVariant;\n /** What a screen reader announces after the name of an `accent` avatar. Localise it. Set it empty when something outside already says so — `AvatarGroup` does, because each row item composes its own name — and nothing is added for a `default` avatar either way. */\n accentLabel?: string;\n }>(),\n {\n alt: \"\",\n size: \"md\",\n shape: \"circle\",\n variant: \"default\",\n accentLabel: \"\",\n },\n);\n\n// One rendered node, and it is the right home for every fallthrough attribute\n// — but `class` still goes the long way round, through `cn()`. Vue's own merge\n// only concatenates, so the `bg-subtle` an AvatarGroup paints its overflow tile\n// with would win or lose against this root's `bg-muted` depending on the order\n// Tailwind happened to emit the two rules in, rather than on intent.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest } = useSplitAttrs();\n\nconst radius = computed(() => avatarRadius(props.size, props.shape));\n</script>\n\n<template>\n <AvatarRoot\n v-bind=\"rest\"\n :data-variant=\"variant\"\n :class=\"cn(avatarVariants({ size, force: variant }), radius, attrs.class as string)\"\n >\n <!-- Reka paints AvatarImage only once the photo has loaded, so scale-in\n plays exactly on that swap-in — a gentle settle over the fallback. -->\n <AvatarImage\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt\"\n class=\"h-full w-full animate-scale-in object-cover\"\n />\n <AvatarFallback class=\"font-medium\">{{ fallback }}</AvatarFallback>\n <!-- The half of the accent signal a rim cannot carry. It sits after the\n image so it is announced as a qualifier on the name rather than in\n place of it, and it is dropped entirely for an empty `accentLabel`: a\n wrapper that has already worked the qualifier into its own name would\n otherwise leave a second copy of it in the tree. -->\n <span v-if=\"variant === 'accent' && accentLabel\" class=\"sr-only\">{{ accentLabel }}</span>\n </AvatarRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,IAAa,iBAAiB,IAC5B,yFACA;CAME,UAAU;EACR,MAAM;GAMJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,OAAO;GACL,SAAS;GAOT,QAAQ;EACV;CACF;CACA,iBAAiB;EAAE,MAAM;EAAM,OAAO;CAAU;AAClD,CACF;;;;;;;;;;AAWA,IAAM,gBAAgB;CACpB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;;;;AAQA,SAAS,aAAa,MAAkB,OAA4B;CAClE,OAAO,UAAU,WAAW,iBAAiB,cAAc;AAC7D;;;;;;;;;;;;;;EAsBA,MAAM,QAAQ;EAgCd,MAAM,EAAE,OAAO,SAAS,cAAc;EAEtC,MAAM,SAAS,eAAe,aAAa,MAAM,MAAM,MAAM,KAAK,CAAC;;GAIjE,OAAA,UAAA,GAAA,YAoBa,MAAA,UAAA,GApBb,WACU,MAmBG,IAAA,GAnBC;IACX,gBAAc,QAAA;IACd,OAAO,MAAA,EAAA,CAAE,CAAC,MAAA,cAAA,CAAc,CAAA;KAAA,MAAG,QAAA;KAAI,OAAS,QAAA;IAAO,CAAA,GAAK,OAAA,OAAQ,MAAA,KAAA,CAAK,CAAC,KAAK;;IAIxE,SAAA,cAKE;KAJM,QAAA,OADR,UAAA,GAAA,YAKE,MAAA,WAAA,GAAA;;MAHC,KAAK,QAAA;MACL,KAAK,QAAA;MACN,OAAM;;KAER,YAAmE,MAAA,cAAA,GAAA,EAAnD,OAAM,cAAa,GAAA;MAAC,SAAA,cAAc,CAAX,gBAAA,gBAAA,QAAA,QAAQ,GAAA,CAAA,CAAA,CAAA;;;KAMnC,QAAA,YAAO,YAAiB,QAAA,eAApC,UAAA,GAAA,mBAAyF,QAAzF,YAAyF,gBAArB,QAAA,WAAW,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA"}
1
+ {"version":3,"file":"Avatar.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../../../packages/primitives/avatar/src/Avatar.vue"],"sourcesContent":["<script lang=\"ts\">\nimport { cva } from \"class-variance-authority\";\n\n/** Control height, and the text size the initials fallback prints at. */\nexport type AvatarSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\n/** A circle, or a rounded square tile. */\nexport type AvatarShape = \"circle\" | \"square\";\n\n/**\n * Which visual treatment the avatar receives. `accent` applies the accent\n * colour as a rim, signalling a second semantic category distinct from the\n * default — a different role, origin, or mode.\n */\nexport type AvatarVariant = \"default\" | \"accent\";\n\nexport const avatarVariants = cva(\n \"relative inline-flex shrink-0 items-center justify-center overflow-hidden select-none\",\n {\n // `satisfies` keeps the two halves honest: the unions above are the names a\n // consumer imports and the documentation prints, the maps below are the\n // classes. Adding a member to one and not the other stops compiling — which\n // is what the three inline `size === '…' &&` conditionals this replaced\n // could not do, and the reason five sizes could not stay written that way.\n variants: {\n size: {\n // `text-xs` twice, deliberately. It is the smallest step Tailwind's own\n // scale has, and the step below it — Loom's `text-micro` — is a name\n // tailwind-merge classifies as a text *colour* rather than a size, so\n // `cn()` drops it the moment the force map adds `text-muted-foreground`\n // after it. Two initials at 12px still fit inside 24px.\n xs: \"h-6 w-6 text-xs\",\n sm: \"h-8 w-8 text-xs\",\n md: \"h-10 w-10 text-sm\",\n lg: \"h-12 w-12 text-base\",\n xl: \"h-16 w-16 text-lg\",\n } satisfies Record<AvatarSize, string>,\n force: {\n default: \"bg-muted text-muted-foreground\",\n // The accent rim. Two signals, not one: the rim's *presence* is what a\n // reader who cannot resolve the hue still sees — a default avatar has no\n // edge at all — and the hidden `accentLabel` is what a reader who sees\n // no avatar hears. The corner is left alone on purpose, because the\n // corner is Indicator's: a presence dot pinned there would land on top\n // of anything this component drew.\n accent: \"border-2 border-accent bg-accent-muted text-accent-text\",\n } satisfies Record<AvatarVariant, string>,\n },\n defaultVariants: { size: \"md\", force: \"default\" },\n },\n);\n\n/**\n * A square avatar's corner radius, one value per size rather than the control\n * radius throughout. `rounded-md` is calibrated against a ~36px control; on a\n * 24px tile it is a third of the side, where a milled fillet stops reading as\n * a corner and starts reading as a blob, and on a 64px one it has almost\n * disappeared. Stepping it holds the corner between a sixth and a quarter of\n * the side at every size — the band the control radius already sits in — which\n * is the nesting law applied to a tile whose \"padding\" is its own edge.\n */\nconst SQUARE_RADIUS = {\n xs: \"rounded-sm\",\n sm: \"rounded-md\",\n md: \"rounded-md\",\n lg: \"rounded-lg\",\n xl: \"rounded-xl\",\n} satisfies Record<AvatarSize, string>;\n\n/**\n * The rounding for one size and shape. A circle is one value at every size; a\n * square is not, which is why the radius cannot live in the `cva` map beside\n * the heights. Kept off the public surface deliberately: a consumer wanting an\n * avatar-shaped tile should render an `Avatar`, not reassemble one.\n */\nfunction avatarRadius(size: AvatarSize, shape: AvatarShape): string {\n return shape === \"circle\" ? \"rounded-full\" : SQUARE_RADIUS[size];\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { AvatarRoot, AvatarImage, AvatarFallback } from \"reka-ui\";\nimport { cn, useSplitAttrs } from \"@ecoma-io/loom-core\";\n\n/**\n * Avatar — a user's picture, with a graceful initials fallback for\n * no `src`, a broken URL, or a still-loading image. Built on Reka UI's\n * Avatar: the image only paints once it has actually finished loading, so\n * the fallback stays visible the whole time until then — first paint is\n * either the real photo or the initials, never a broken-image icon.\n *\n * Two neighbours are worth naming. Several faces standing for one thing — the\n * people on a task, the agents on a run — are an `AvatarGroup`, which owns the\n * overlap, the stacking order and the \"+3\" so a row of them is one object to a\n * screen reader rather than N unrelated images. Anything pinned onto the\n * avatar's corner — a presence dot, an unread count — is an `Indicator`\n * wrapped around it; this component deliberately draws nothing there.\n */\nconst props = withDefaults(\n defineProps<{\n /** Image URL. Omit it to render the fallback outright. */\n src?: string;\n /** Accessible name for the photo — required on `AvatarImage` so a screen reader announces who it is, not just that an image loaded. */\n alt?: string;\n /** Initials to show while there is no image, or once one has failed — computed by the caller, never derived from `alt` here. */\n fallback?: string;\n /** Control height. */\n size?: AvatarSize;\n /** A circle, or a rounded square tile. Square suits a subject a circle would misdescribe — an organisation, a project, a repository — and takes a radius that steps with the size rather than one fixed value. */\n shape?: AvatarShape;\n /** Which visual treatment the avatar receives. `accent` applies the accent rim and `accentLabel` for a screen reader, so the distinction never rests on the hue alone. */\n variant?: AvatarVariant;\n /** What a screen reader announces after the name of an `accent` avatar — \"Accent\" by default, so the accent never rests on the hue alone. Localise it. Set it empty when something outside already says so — `AvatarGroup` does, because each row item composes its own name — and nothing is added for a `default` avatar either way. */\n accentLabel?: string;\n }>(),\n {\n alt: \"\",\n size: \"md\",\n shape: \"circle\",\n variant: \"default\",\n accentLabel: \"Accent\",\n },\n);\n\n// One rendered node, and it is the right home for every fallthrough attribute\n// — but `class` still goes the long way round, through `cn()`. Vue's own merge\n// only concatenates, so the `bg-subtle` an AvatarGroup paints its overflow tile\n// with would win or lose against this root's `bg-muted` depending on the order\n// Tailwind happened to emit the two rules in, rather than on intent.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest } = useSplitAttrs();\n\nconst radius = computed(() => avatarRadius(props.size, props.shape));\n</script>\n\n<template>\n <AvatarRoot\n v-bind=\"rest\"\n :data-variant=\"variant\"\n :class=\"cn(avatarVariants({ size, force: variant }), radius, attrs.class as string)\"\n >\n <!-- Reka paints AvatarImage only once the photo has loaded, so scale-in\n plays exactly on that swap-in — a gentle settle over the fallback. -->\n <AvatarImage\n v-if=\"src\"\n :src=\"src\"\n :alt=\"alt\"\n class=\"h-full w-full animate-scale-in object-cover\"\n />\n <AvatarFallback class=\"font-medium\">{{ fallback }}</AvatarFallback>\n <!-- The half of the accent signal a rim cannot carry. It sits after the\n image so it is announced as a qualifier on the name rather than in\n place of it, and it is dropped entirely for an empty `accentLabel`: a\n wrapper that has already worked the qualifier into its own name would\n otherwise leave a second copy of it in the tree. -->\n <span v-if=\"variant === 'accent' && accentLabel\" class=\"sr-only\">{{ accentLabel }}</span>\n </AvatarRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,IAAa,iBAAiB,IAC5B,yFACA;CAME,UAAU;EACR,MAAM;GAMJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EACA,OAAO;GACL,SAAS;GAOT,QAAQ;EACV;CACF;CACA,iBAAiB;EAAE,MAAM;EAAM,OAAO;CAAU;AAClD,CACF;;;;;;;;;;AAWA,IAAM,gBAAgB;CACpB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;;;;AAQA,SAAS,aAAa,MAAkB,OAA4B;CAClE,OAAO,UAAU,WAAW,iBAAiB,cAAc;AAC7D;;;;;;;;;;;;;;EAsBA,MAAM,QAAQ;EAgCd,MAAM,EAAE,OAAO,SAAS,cAAc;EAEtC,MAAM,SAAS,eAAe,aAAa,MAAM,MAAM,MAAM,KAAK,CAAC;;GAIjE,OAAA,UAAA,GAAA,YAoBa,MAAA,UAAA,GApBb,WACU,MAmBG,IAAA,GAnBC;IACX,gBAAc,QAAA;IACd,OAAO,MAAA,EAAA,CAAE,CAAC,MAAA,cAAA,CAAc,CAAA;KAAA,MAAG,QAAA;KAAI,OAAS,QAAA;IAAO,CAAA,GAAK,OAAA,OAAQ,MAAA,KAAA,CAAK,CAAC,KAAK;;IAIxE,SAAA,cAKE;KAJM,QAAA,OADR,UAAA,GAAA,YAKE,MAAA,WAAA,GAAA;;MAHC,KAAK,QAAA;MACL,KAAK,QAAA;MACN,OAAM;;KAER,YAAmE,MAAA,cAAA,GAAA,EAAnD,OAAM,cAAa,GAAA;MAAC,SAAA,cAAc,CAAX,gBAAA,gBAAA,QAAA,QAAQ,GAAA,CAAA,CAAA,CAAA;;;KAMnC,QAAA,YAAO,YAAiB,QAAA,eAApC,UAAA,GAAA,mBAAyF,QAAzF,YAAyF,gBAArB,QAAA,WAAW,GAAA,CAAA,KAAA,mBAAA,IAAA,IAAA"}
@@ -0,0 +1,7 @@
1
+ import Calendar_vue_vue_type_script_setup_true_lang_default, { CALENDAR_LABELS } from "./Calendar.vue_vue_type_script_setup_true_lang.js";
2
+ //#region packages/primitives/calendar/src/Calendar.vue
3
+ var Calendar_default = Calendar_vue_vue_type_script_setup_true_lang_default;
4
+ //#endregion
5
+ export { CALENDAR_LABELS, Calendar_default as default };
6
+
7
+ //# sourceMappingURL=Calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Calendar.js","names":[],"sources":["../../../../../packages/primitives/calendar/src/Calendar.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { CalendarLabels } from \"@ecoma-io/loom-labels\";\n\n/**\n * Loom's English for what this surface speaks of its own account — the two\n * pager names and the selection line — co-located so it tree-shakes with the\n * component that renders it, and exported so a host can build a partial\n * vocabulary against the real thing.\n */\nexport const CALENDAR_LABELS: CalendarLabels = {\n previousMonth: \"Previous month\",\n nextMonth: \"Next month\",\n chosen: ({ date }) => `${date} chosen.`,\n cleared: \"No date chosen.\",\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, ref, useId } from \"vue\";\nimport {\n CalendarRoot,\n CalendarHeader,\n CalendarHeading,\n CalendarPrev,\n CalendarNext,\n CalendarGrid,\n CalendarGridHead,\n CalendarGridRow,\n CalendarHeadCell,\n CalendarGridBody,\n CalendarCell,\n CalendarCellTrigger,\n} from \"reka-ui\";\nimport { ChevronLeft, ChevronRight } from \"@lucide/vue\";\nimport {\n getLocalTimeZone,\n isToday,\n parseDate,\n toCalendarDate,\n type DateValue,\n} from \"@internationalized/date\";\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\";\nimport { CALENDAR_PANEL_LABELS } from \"@ecoma-io/loom-labels\";\nimport { formatFullDay } from \"@ecoma-io/loom-labels\";\n\n/**\n * Calendar — a month on a page: a heading naming it, a row of weekday names,\n * and a grid of days a reader browses and picks from directly.\n *\n * **This is not a date picker, and the difference is the whole point.**\n * DatePicker is a field first — a segmented input a reader types into, with a\n * popover calendar as its second path. This is the calendar alone: no field,\n * no trigger, no open state, nothing to close, and no value echoed anywhere.\n * Reach for it wherever the temporal surface *is* the interface — a booking\n * board's availability grid, a dashboard filter showing the month at all\n * times, a scheduling view a host embeds beside other content.\n *\n * The engine underneath is the same one the four pickers wrap — Reka UI's\n * standalone `CalendarRoot` family — so the month arithmetic, the locale\n * handling and the roving-focus keyboard model are Reka's, not hand-written\n * here. What Loom adds is the value boundary, the label seam and the\n * accessibility decisions documented below.\n *\n * **The model value is a plain ISO date string, `\"YYYY-MM-DD\"`** — parsed on\n * the way in, re-serialised on the way out, exactly as DatePicker draws the\n * same boundary. A value that does not parse is read as *no date chosen*\n * rather than thrown on; a component library cannot decide that a host's bad\n * data is fatal.\n *\n * Three states live on this surface and each has exactly one owner:\n *\n * - **Selected** — the host's, through `modelValue`. Clicking (or pressing\n * Enter on) an already-chosen day clears it; there is no field here whose\n * clearing could be a surprise, and a browsing surface that cannot be\n * un-picked is worse than one that can.\n * - **Focused** — Reka's, through a roving tabindex across the cell triggers.\n * It is not a prop: the whole grid is exactly one Tab stop, and the arrow\n * keys walk it.\n * - **Visible month** — internal, deliberately uncontrolled in this release.\n * Paging buttons move it; selecting a day does not navigate anything, close\n * anything or move focus. A host that needs to drive the view gets a\n * placeholder prop when a use case asks for one, not before.\n *\n * **Timezone assumptions:** everything here operates on bare calendar dates.\n * There are no instants and no conversions — \"today\" resolves against the\n * host's local timezone via `getLocalTimeZone()`, which is the only timezone\n * reading this component ever makes.\n *\n * **Range selection is out of scope here by design.** A future\n * `RangeCalendar` lands as its own sibling primitive — the house precedent is\n * DatePicker and DateRangePicker, separate components sharing an engine,\n * because a span has a different model from a point and pretending otherwise\n * produces a control wrong at both ends.\n */\nconst props = withDefaults(\n defineProps<{\n /**\n * The chosen date as ISO `YYYY-MM-DD`. Unset, empty or unparseable means\n * no date is chosen. The explicit `| undefined` is what lets `v-model`\n * bind a ref that clears — clicking the chosen day again emits\n * `undefined`, and a plain optional prop refuses to take it back.\n */\n modelValue?: string | undefined;\n /** The earliest choosable date, same ISO format. Days before it are announced disabled and skipped by the keyboard. */\n min?: string;\n /** The latest choosable date, same ISO format. Days after it are announced disabled and skipped by the keyboard. */\n max?: string;\n /** BCP 47 tag driving the month and weekday names, each cell's full-date name, and which day a week starts on. */\n locale?: string;\n /**\n * Writing direction of the whole surface: mirrors the pager chevrons and\n * flips which arrow key moves backwards.\n *\n * Absent, it is seeded from the document's own direction — because Reka\n * never reads the document itself. Left to its own devices it resolves\n * `dir` through its ConfigProvider context, defaulting `\"ltr\"`, so under\n * `<html dir=\"rtl\">` with nothing forwarded the `rtl:` chevron classes\n * still fire off the CSS cascade while the arrow-key sign stays LTR:\n * visuals and semantics disagreeing on one surface. An explicit prop\n * wins over the seed, and a host driving direction through Reka's own\n * ConfigProvider keeps that where the document declares nothing.\n */\n dir?: \"ltr\" | \"rtl\";\n /**\n * Names for everything this control says out loud, as any subset of\n * `CalendarLabels` — 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: both keys name controls every calendar in the library\n * pages with, and a language is set once with `provideLoomLabels`.\n */\n labels?: LabelOverrides<CalendarLabels>;\n }>(),\n { locale: \"en\" },\n);\n\nconst emit = defineEmits<{\n /** The chosen date as ISO `YYYY-MM-DD`, or `undefined` once the choice has been cleared. */\n \"update:modelValue\": [value: string | undefined];\n}>();\n\n// Two slots resolved, one of them behind the prop. `text` is this control's\n// own pager vocabulary; the panel slice answers only for the surface's own\n// name (`calendar`), which Reka publishes twice — as the container's\n// `aria-label` and inside a visually-hidden live region a fallthrough\n// attribute could not reach — and which defaults to `\"Event Date\"`, a name\n// for somebody else's application. The per-instance `labels` prop stays\n// exactly `CalendarLabels`: a standalone surface renders no open button, so\n// the rest of that shared slice would be keys nothing on it could say.\nconst text = useLabels(\"calendar\", CALENDAR_LABELS, () => props.labels);\nconst chromeText = useLabels(\"calendarPanel\", CALENDAR_PANEL_LABELS);\n\n// The root is the whole surface, so every fallthrough attribute belongs on it\n// — there is no second node they could sensibly describe. `class` is pulled\n// out of that spread and merged through `cn()` instead: spreading it alongside\n// the root's own `:class` only concatenates the two lists, so a caller's\n// `w-full` would win or lose depending on which utility Tailwind emitted last.\ndefineOptions({ inheritAttrs: false });\nconst { attrs, rest: rootAttrs } = useSplitAttrs();\n\nfunction fromIso(value: string | undefined): DateValue | undefined {\n if (!value) return undefined;\n try {\n return parseDate(value);\n } catch {\n return undefined;\n }\n}\n\n// `toString()` already normalises to the Gregorian ISO form whatever calendar\n// the value carries — a locale such as `th-TH` gives Reka a Buddhist\n// placeholder whose year reads 2569, and it still prints `2026-08-11`. What\n// `toCalendarDate` adds is dropping a time component if one ever arrives.\nfunction toIso(date: DateValue): string {\n return toCalendarDate(date).toString();\n}\n\n// Reka resolves direction through its ConfigProvider context and defaults\n// `\"ltr\"` — it never reads the document (its `useDirection` is literally\n// `dir || context.dir || \"ltr\"`). Seeding the forwarded direction from the\n// document closes the half-behaviour that leaves behind: chevrons mirrored by\n// CSS, arrows still LTR. Only `\"rtl\"` is ever injected rather than a resolved\n// `\"ltr\"` too — forwarding `\"ltr\"` unconditionally would clobber a\n// ConfigProvider context the host set on purpose, and absence lets Reka's own\n// chain answer. `typeof document` guards the server-side pass that builds the\n// documentation site, where there is no document to read.\nconst resolvedDir = computed(() => {\n if (props.dir) return props.dir;\n if (typeof document === \"undefined\") return undefined;\n return document.documentElement.dir === \"rtl\" ? \"rtl\" : undefined;\n});\n\n// `optional()` rather than four separate bindings: an absent bound forwarded\n// as an explicit `undefined` is still a key Reka sees, and an absent\n// `modelValue` forwarded that way is what turns an uncontrolled surface into\n// a permanently empty one. Dropping the key says what is true — including\n// for `dir`, whose absence defers to Reka's own resolution wherever neither\n// the prop nor the document speaks.\nconst rootValue = computed(() =>\n optional({\n modelValue: fromIso(props.modelValue),\n minValue: fromIso(props.min),\n maxValue: fromIso(props.max),\n dir: resolvedDir.value,\n }),\n);\n\n// The status line below announces by changing, but a live region also\n// announces its content the moment it enters the document — so a calendar\n// mounted with a preselected value would read the chosen date out as if the\n// user had just picked it. `announced` stays false until the first real\n// selection event, and the line is aria-hidden meanwhile: hidden, it says\n// nothing at mount; revealed on the first change, it announces exactly that\n// change. Programmatic `modelValue` sets never fire this handler (a host\n// prop write is not an interaction), so before the first user action they\n// stay silent too — after it, the region is an ordinary live region and\n// speaks real changes from either side, which is correct.\nconst announced = ref(false);\n\nfunction onDateChange(date: DateValue | undefined) {\n announced.value = true;\n emit(\"update:modelValue\", date ? toIso(date) : undefined);\n}\n\n// Today is a state, and it may not be carried by the marker dot alone — a\n// reader who cannot see the dot gets `aria-current=\"date\"`, which is the one\n// attribute screen readers already announce for \"this is the current one\".\n// Reka publishes today only as a `data-` attribute and a slot prop, neither of\n// which can reach an attribute binding on the cell itself.\nfunction isDateToday(date: DateValue): boolean {\n return isToday(date, getLocalTimeZone());\n}\n\n// The month-and-year heading names the grid, so the two are wired together\n// rather than the grid being an unnamed table of numbers.\nconst headingId = useId();\n\n// Each cell's accessible name is formatted here rather than read off Reka,\n// replacing Reka's own — the same mechanism DateRangePicker's cells rely on:\n// the binding reaches the node as a fallthrough attribute, which Vue merges\n// last, so it replaces rather than competes. A standalone calendar has no\n// input echoing the chosen value back, so the full date is the only thing a\n// screen reader ever says for a day, and it comes from the shared cached\n// formatter rather than a second `Intl` path built for this one component.\nfunction dayLabel(day: DateValue): string {\n return formatFullDay(props.locale, day);\n}\n\n// A choice announces itself through no attribute of this engine: Reka\n// publishes a selection only as `aria-selected` flipping on a cell under an\n// unmoved focus point, and a flipped attribute announces nothing — there is\n// no field here whose value change would speak instead. DateRangePicker met\n// the identical fieldless-announcement problem with a `role=\"status\"` line,\n// and this mirrors that precedent. It changes exactly when the selection\n// changes, which is what makes it announceable rather than noise.\n//\n// It reads the selection off Reka's own slot rather than off `modelValue`:\n// the two agree once a host binds one, but this surface is usable unbound,\n// and a line wired to the prop would stay silent about exactly the clicks it\n// exists to announce.\nfunction selectionStatus(selected: DateValue | DateValue[] | undefined): string {\n const value = Array.isArray(selected) ? undefined : selected;\n return value ? text.value.chosen({ date: dayLabel(value) }) : text.value.cleared;\n}\n</script>\n\n<template>\n <CalendarRoot\n v-slot=\"{ grid, weekDays, modelValue: selected }\"\n v-bind=\"{ ...rootAttrs, ...rootValue }\"\n :locale=\"locale\"\n :calendar-label=\"chromeText.calendar\"\n :class=\"\n cn(\n 'flex w-fit flex-col gap-3 rounded-md border border-border bg-popover p-3 text-popover-foreground',\n attrs.class as string,\n )\n \"\n @update:model-value=\"onDateChange\"\n >\n <CalendarHeader class=\"flex items-center justify-between gap-2\">\n <!-- The two pagers keep `data-[disabled]:opacity-50` where the cells\n gave it up, and the difference is what is inside them: a chevron and\n nothing else. Fading a glyph costs a reader nothing, and the buttons\n carry their name in `aria-label` rather than in dimmed text. -->\n <CalendarPrev\n :aria-label=\"text.previousMonth\"\n class=\"inline-flex h-7 w-7 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 data-[disabled]:pointer-events-none data-[disabled]:opacity-50\"\n >\n <ChevronLeft class=\"h-4 w-4 rtl:-scale-x-100\" aria-hidden=\"true\" />\n </CalendarPrev>\n\n <!-- Paging the calendar changes nothing a reader is looking at except\n this line, and nothing moves focus — so without the live region the\n month silently becomes a different month. -->\n <CalendarHeading\n :id=\"headingId\"\n aria-live=\"polite\"\n class=\"text-sm font-medium text-foreground\"\n />\n\n <CalendarNext\n :aria-label=\"text.nextMonth\"\n class=\"inline-flex h-7 w-7 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 data-[disabled]:pointer-events-none data-[disabled]:opacity-50\"\n >\n <ChevronRight class=\"h-4 w-4 rtl:-scale-x-100\" aria-hidden=\"true\" />\n </CalendarNext>\n </CalendarHeader>\n\n <!-- Visually subordinate on purpose — the grid is the interface, and this\n is its spoken half: what a picker's field would have echoed. -->\n <p\n role=\"status\"\n :aria-hidden=\"announced ? undefined : 'true'\"\n class=\"text-xs text-muted-foreground\"\n >\n {{ selectionStatus(selected) }}\n </p>\n\n <CalendarGrid\n v-for=\"month in grid\"\n :key=\"month.value.toString()\"\n role=\"grid\"\n :aria-labelledby=\"headingId\"\n class=\"border-collapse select-none\"\n >\n <!-- Reka renders `role=\"application\"` here, which hands every key\n straight to the page and takes the table's own semantics away\n with it. A calendar is a grid: `role=\"grid\"` is what makes the\n cells rows and columns to a screen reader rather than 42\n unrelated buttons, and the arrow-key handling Reka installs on\n the cells is what a grid promises anyway.\n\n The rows and cells below are laid out by the table itself\n rather than by flex, and that is load-bearing: `display: flex`\n on a `tr` drops its implicit `row` mapping in Chromium and\n WebKit, which leaves `role=\"gridcell\"` inside a grid with no\n row between them — a broken grid that looks identical. -->\n <CalendarGridHead>\n <CalendarGridRow>\n <CalendarHeadCell\n v-for=\"(day, index) in weekDays\"\n :key=\"index\"\n class=\"w-9 text-xs font-normal text-muted-foreground\"\n >\n {{ day }}\n </CalendarHeadCell>\n </CalendarGridRow>\n </CalendarGridHead>\n\n <CalendarGridBody>\n <CalendarGridRow v-for=\"(week, weekIndex) in month.rows\" :key=\"weekIndex\">\n <CalendarCell\n v-for=\"day in week\"\n :key=\"day.toString()\"\n :date=\"day\"\n class=\"p-0 text-center\"\n >\n <!-- The `:aria-label` below replaces one Reka writes inside its\n own render function, reaching the DOM node as a fallthrough\n attribute that Vue merges last. Removing it falls back not\n to English but to the engine's own locale-formatted cell\n names. -->\n <CalendarCellTrigger\n v-slot=\"{ dayValue, today }\"\n :day=\"day\"\n :month=\"month.value\"\n :aria-label=\"dayLabel(day)\"\n :aria-current=\"isDateToday(day) ? 'date' : undefined\"\n class=\"group relative inline-flex h-9 w-9 items-center justify-center rounded-sm text-sm text-foreground transition-colors duration-fast ease-out hover:bg-subtle focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:shadow-halo data-[outside-view]:text-muted-foreground data-[selected]:bg-primary data-[selected]:text-primary-foreground data-[disabled]:pointer-events-none data-[disabled]:line-through [&[data-disabled]:not([data-selected])]:text-muted-foreground\"\n >\n {{ dayValue }}\n <!-- Today's second cue. The dot is decoration to a screen\n reader — `aria-current` on the cell is what it reads — but\n it is the whole cue for a reader who is looking at the\n grid, and it is a shape rather than a hue so it survives a\n colour deficiency and forced-colors both. -->\n <span\n v-if=\"today\"\n aria-hidden=\"true\"\n class=\"absolute bottom-1 h-1 w-1 rounded-full bg-primary group-data-[selected]:bg-primary-foreground\"\n />\n </CalendarCellTrigger>\n </CalendarCell>\n </CalendarGridRow>\n </CalendarGridBody>\n </CalendarGrid>\n </CalendarRoot>\n</template>\n"],"mappings":""}
@@ -0,0 +1,95 @@
1
+ import { type LabelOverrides } from "../../../labels/src/index";
2
+ import type { CalendarLabels } from "../../../labels/src/index";
3
+ /**
4
+ * Loom's English for what this surface speaks of its own account — the two
5
+ * pager names and the selection line — co-located so it tree-shakes with the
6
+ * component that renders it, and exported so a host can build a partial
7
+ * vocabulary against the real thing.
8
+ */
9
+ export declare const CALENDAR_LABELS: CalendarLabels;
10
+ declare const _default: typeof __VLS_export;
11
+ export default _default;
12
+ declare const __VLS_export: import("vue").DefineComponent<{
13
+ /**
14
+ * The chosen date as ISO `YYYY-MM-DD`. Unset, empty or unparseable means
15
+ * no date is chosen. The explicit `| undefined` is what lets `v-model`
16
+ * bind a ref that clears — clicking the chosen day again emits
17
+ * `undefined`, and a plain optional prop refuses to take it back.
18
+ */
19
+ modelValue?: string | undefined;
20
+ /** The earliest choosable date, same ISO format. Days before it are announced disabled and skipped by the keyboard. */
21
+ min?: string;
22
+ /** The latest choosable date, same ISO format. Days after it are announced disabled and skipped by the keyboard. */
23
+ max?: string;
24
+ /** BCP 47 tag driving the month and weekday names, each cell's full-date name, and which day a week starts on. */
25
+ locale?: string;
26
+ /**
27
+ * Writing direction of the whole surface: mirrors the pager chevrons and
28
+ * flips which arrow key moves backwards.
29
+ *
30
+ * Absent, it is seeded from the document's own direction — because Reka
31
+ * never reads the document itself. Left to its own devices it resolves
32
+ * `dir` through its ConfigProvider context, defaulting `"ltr"`, so under
33
+ * `<html dir="rtl">` with nothing forwarded the `rtl:` chevron classes
34
+ * still fire off the CSS cascade while the arrow-key sign stays LTR:
35
+ * visuals and semantics disagreeing on one surface. An explicit prop
36
+ * wins over the seed, and a host driving direction through Reka's own
37
+ * ConfigProvider keeps that where the document declares nothing.
38
+ */
39
+ dir?: "ltr" | "rtl";
40
+ /**
41
+ * Names for everything this control says out loud, as any subset of
42
+ * `CalendarLabels` — the rest stay as the host's `provideLoomLabels`
43
+ * vocabulary left them, and then as Loom's English.
44
+ *
45
+ * This is the per-instance correction, not the place to localise an
46
+ * application: both keys name controls every calendar in the library
47
+ * pages with, and a language is set once with `provideLoomLabels`.
48
+ */
49
+ labels?: LabelOverrides<CalendarLabels>;
50
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
51
+ "update:modelValue": (value: string | undefined) => any;
52
+ }, string, import("vue").PublicProps, Readonly<{
53
+ /**
54
+ * The chosen date as ISO `YYYY-MM-DD`. Unset, empty or unparseable means
55
+ * no date is chosen. The explicit `| undefined` is what lets `v-model`
56
+ * bind a ref that clears — clicking the chosen day again emits
57
+ * `undefined`, and a plain optional prop refuses to take it back.
58
+ */
59
+ modelValue?: string | undefined;
60
+ /** The earliest choosable date, same ISO format. Days before it are announced disabled and skipped by the keyboard. */
61
+ min?: string;
62
+ /** The latest choosable date, same ISO format. Days after it are announced disabled and skipped by the keyboard. */
63
+ max?: string;
64
+ /** BCP 47 tag driving the month and weekday names, each cell's full-date name, and which day a week starts on. */
65
+ locale?: string;
66
+ /**
67
+ * Writing direction of the whole surface: mirrors the pager chevrons and
68
+ * flips which arrow key moves backwards.
69
+ *
70
+ * Absent, it is seeded from the document's own direction — because Reka
71
+ * never reads the document itself. Left to its own devices it resolves
72
+ * `dir` through its ConfigProvider context, defaulting `"ltr"`, so under
73
+ * `<html dir="rtl">` with nothing forwarded the `rtl:` chevron classes
74
+ * still fire off the CSS cascade while the arrow-key sign stays LTR:
75
+ * visuals and semantics disagreeing on one surface. An explicit prop
76
+ * wins over the seed, and a host driving direction through Reka's own
77
+ * ConfigProvider keeps that where the document declares nothing.
78
+ */
79
+ dir?: "ltr" | "rtl";
80
+ /**
81
+ * Names for everything this control says out loud, as any subset of
82
+ * `CalendarLabels` — the rest stay as the host's `provideLoomLabels`
83
+ * vocabulary left them, and then as Loom's English.
84
+ *
85
+ * This is the per-instance correction, not the place to localise an
86
+ * application: both keys name controls every calendar in the library
87
+ * pages with, and a language is set once with `provideLoomLabels`.
88
+ */
89
+ labels?: LabelOverrides<CalendarLabels>;
90
+ }> & Readonly<{
91
+ "onUpdate:modelValue"?: (value: string | undefined) => any;
92
+ }>, {
93
+ locale: string;
94
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
95
+ //# sourceMappingURL=Calendar.vue.d.ts.map