vectis-ui 0.10.0 → 0.10.2

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 (334) hide show
  1. package/dist/components/VAccordion/VAccordion.js.map +1 -1
  2. package/dist/components/VAccordion/VAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  3. package/dist/components/VAccordion/VAccordionItem.d.ts +6 -21
  4. package/dist/components/VAccordion/VAccordionItem.js.map +1 -1
  5. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/VAccordion/context.js.map +1 -1
  7. package/dist/components/VAvatar/VAvatar.d.ts +2 -12
  8. package/dist/components/VAvatar/VAvatar.js.map +1 -1
  9. package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  10. package/dist/components/VAvatar/VAvatarGroup.d.ts +2 -2
  11. package/dist/components/VAvatar/VAvatarGroup.js.map +1 -1
  12. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js +6 -6
  13. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  14. package/dist/components/VAvatar/context.d.ts +1 -5
  15. package/dist/components/VAvatar/context.js.map +1 -1
  16. package/dist/components/VBadge/VBadge.d.ts +13 -27
  17. package/dist/components/VBadge/VBadge.js.map +1 -1
  18. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/VBreadcrumb/VBreadcrumb.d.ts +3 -9
  20. package/dist/components/VBreadcrumb/VBreadcrumb.js.map +1 -1
  21. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -1
  22. package/dist/components/VButton/VButton.d.ts +10 -17
  23. package/dist/components/VButton/VButton.js.map +1 -1
  24. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/VButton/VButtonGroup.d.ts +6 -15
  26. package/dist/components/VButton/VButtonGroup.js.map +1 -1
  27. package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/components/VButton/context.d.ts +1 -9
  29. package/dist/components/VButton/context.js.map +1 -1
  30. package/dist/components/VCalendar/VCalendar.d.ts +9 -24
  31. package/dist/components/VCalendar/VCalendar.js.map +1 -1
  32. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/VCalendar/VCalendarEvent.d.ts +4 -13
  34. package/dist/components/VCalendar/VCalendarEvent.js.map +1 -1
  35. package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  36. package/dist/components/VCalendar/VCalendarMonth.js.map +1 -1
  37. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -1
  38. package/dist/components/VCalendar/VCalendarTimeGrid.d.ts +1 -5
  39. package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -1
  40. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/VCalendar/VCalendarYear.js.map +1 -1
  42. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  43. package/dist/components/VCalendar/color.d.ts +1 -7
  44. package/dist/components/VCalendar/color.js.map +1 -1
  45. package/dist/components/VCalendar/edgeStep.d.ts +5 -15
  46. package/dist/components/VCalendar/edgeStep.js.map +1 -1
  47. package/dist/components/VCalendar/gesture.d.ts +12 -36
  48. package/dist/components/VCalendar/gesture.js.map +1 -1
  49. package/dist/components/VCalendar/keyboard.d.ts +5 -42
  50. package/dist/components/VCalendar/keyboard.js.map +1 -1
  51. package/dist/components/VCalendar/layout.d.ts +38 -199
  52. package/dist/components/VCalendar/layout.js.map +1 -1
  53. package/dist/components/VCalendar/timeGrid.d.ts +3 -25
  54. package/dist/components/VCalendar/timeGrid.js.map +1 -1
  55. package/dist/components/VCalendar/types.d.ts +6 -23
  56. package/dist/components/VCarousel/VCarousel.d.ts +25 -96
  57. package/dist/components/VCarousel/VCarousel.js.map +1 -1
  58. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js +6 -6
  59. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  60. package/dist/components/VCarousel/VCarouselItem.d.ts +1 -6
  61. package/dist/components/VCarousel/VCarouselItem.js.map +1 -1
  62. package/dist/components/VCarousel/VCarouselItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/VCarousel/context.js.map +1 -1
  64. package/dist/components/VCheckbox/VCheckbox.d.ts +1 -5
  65. package/dist/components/VCheckbox/VCheckbox.js.map +1 -1
  66. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  67. package/dist/components/VChip/VChip.d.ts +2 -8
  68. package/dist/components/VChip/VChip.js.map +1 -1
  69. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  70. package/dist/components/VCombobox/VCombobox.d.ts +21 -59
  71. package/dist/components/VCombobox/VCombobox.js.map +1 -1
  72. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +117 -119
  73. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/VCombobox/VComboboxGroup.js.map +1 -1
  75. package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  76. package/dist/components/VCombobox/VComboboxOption.js.map +1 -1
  77. package/dist/components/VCombobox/VComboboxOption.vue_vue_type_script_setup_true_lang.js.map +1 -1
  78. package/dist/components/VCombobox/VComboboxSeparator.js.map +1 -1
  79. package/dist/components/VCombobox/VComboboxSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  80. package/dist/components/VCombobox/infiniteScroll.d.ts +4 -10
  81. package/dist/components/VCombobox/infiniteScroll.js.map +1 -1
  82. package/dist/components/VDataTable/VDataTable.d.ts +11 -36
  83. package/dist/components/VDataTable/VDataTable.js.map +1 -1
  84. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +23 -20
  85. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  86. package/dist/components/VDateInput/VDateInput.d.ts +12 -21
  87. package/dist/components/VDateInput/VDateInput.js.map +1 -1
  88. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  89. package/dist/components/VDateInput/mask.d.ts +14 -59
  90. package/dist/components/VDateInput/mask.js.map +1 -1
  91. package/dist/components/VDatePicker/VDatePicker.d.ts +6 -12
  92. package/dist/components/VDatePicker/VDatePicker.js.map +1 -1
  93. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  94. package/dist/components/VDatePicker/keyboard.d.ts +10 -42
  95. package/dist/components/VDatePicker/keyboard.js.map +1 -1
  96. package/dist/components/VDatePicker/names.d.ts +8 -22
  97. package/dist/components/VDatePicker/names.js.map +1 -1
  98. package/dist/components/VDialog/VDialog.d.ts +5 -10
  99. package/dist/components/VDialog/VDialog.js.map +1 -1
  100. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js +51 -53
  101. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  102. package/dist/components/VDialog/VDialogAlert.d.ts +2 -3
  103. package/dist/components/VDialog/VDialogAlert.js.map +1 -1
  104. package/dist/components/VDialog/VDialogAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
  105. package/dist/components/VFileInput/VFileInput.d.ts +11 -37
  106. package/dist/components/VFileInput/VFileInput.js.map +1 -1
  107. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  108. package/dist/components/VFileInput/truncate.d.ts +3 -23
  109. package/dist/components/VFileInput/truncate.js.map +1 -1
  110. package/dist/components/VFilePicker/VFilePicker.d.ts +15 -65
  111. package/dist/components/VFilePicker/VFilePicker.js.map +1 -1
  112. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  113. package/dist/components/VFilePicker/fileKind.js.map +1 -1
  114. package/dist/components/VHotkeys/VHotkeys.d.ts +6 -15
  115. package/dist/components/VHotkeys/VHotkeys.js.map +1 -1
  116. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
  117. package/dist/components/VHotkeys/platform.d.ts +10 -49
  118. package/dist/components/VHotkeys/platform.js.map +1 -1
  119. package/dist/components/VIcon/VIcon.d.ts +7 -19
  120. package/dist/components/VIcon/VIcon.js.map +1 -1
  121. package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  122. package/dist/components/VIcon/iconProps.d.ts +5 -19
  123. package/dist/components/VIcon/iconProps.js.map +1 -1
  124. package/dist/components/VIcon/resolver.d.ts +15 -43
  125. package/dist/components/VIcon/resolver.js.map +1 -1
  126. package/dist/components/VIcon/types.d.ts +7 -34
  127. package/dist/components/VIconButton/VIconButton.d.ts +2 -3
  128. package/dist/components/VIconButton/VIconButton.js.map +1 -1
  129. package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  130. package/dist/components/VInput/VInput.d.ts +14 -29
  131. package/dist/components/VInput/VInput.js.map +1 -1
  132. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  133. package/dist/components/VInput/VInputGroup.js.map +1 -1
  134. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js +34 -50
  135. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  136. package/dist/components/VInput/context.js.map +1 -1
  137. package/dist/components/VInputOTP/VInputOTP.d.ts +8 -16
  138. package/dist/components/VInputOTP/VInputOTP.js.map +1 -1
  139. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +55 -63
  140. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -1
  141. package/dist/components/VMenu/VMenu.js.map +1 -1
  142. package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  143. package/dist/components/VMenu/VMenuGroup.d.ts +1 -6
  144. package/dist/components/VMenu/VMenuGroup.js.map +1 -1
  145. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  146. package/dist/components/VMenu/VMenuItem.d.ts +0 -5
  147. package/dist/components/VMenu/VMenuItem.js.map +1 -1
  148. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  149. package/dist/components/VMenu/VMenuPanel.d.ts +1 -6
  150. package/dist/components/VMenu/VMenuPanel.js.map +1 -1
  151. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +2 -2
  152. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  153. package/dist/components/VMenu/VMenuSeparator.js.map +1 -1
  154. package/dist/components/VMenu/VMenuSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  155. package/dist/components/VMenu/context.d.ts +3 -11
  156. package/dist/components/VMenu/context.js.map +1 -1
  157. package/dist/components/VPagination/VPagination.d.ts +9 -20
  158. package/dist/components/VPagination/VPagination.js.map +1 -1
  159. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  160. package/dist/components/VPopover/VPopover.d.ts +7 -18
  161. package/dist/components/VPopover/VPopover.js.map +1 -1
  162. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js +23 -27
  163. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
  164. package/dist/components/VProgressCircular/VProgressCircular.d.ts +2 -6
  165. package/dist/components/VProgressCircular/VProgressCircular.js.map +1 -1
  166. package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js.map +1 -1
  167. package/dist/components/VProgressLinear/VProgressLinear.d.ts +4 -15
  168. package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -1
  169. package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  170. package/dist/components/VRadio/VRadio.d.ts +1 -5
  171. package/dist/components/VRadio/VRadio.js.map +1 -1
  172. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  173. package/dist/components/VSeparator/VSeparator.d.ts +2 -15
  174. package/dist/components/VSeparator/VSeparator.js.map +1 -1
  175. package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  176. package/dist/components/VSideNavigation/VSideNavigation.d.ts +1 -1
  177. package/dist/components/VSideNavigation/VSideNavigation.js.map +1 -1
  178. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js.map +1 -1
  179. package/dist/components/VSideNavigation/VSideNavigationGroup.d.ts +1 -5
  180. package/dist/components/VSideNavigation/VSideNavigationGroup.js.map +1 -1
  181. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  182. package/dist/components/VSideNavigation/VSideNavigationItem.d.ts +1 -5
  183. package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -1
  184. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +80 -75
  185. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  186. package/dist/components/VSideNavigation/VSideNavigationSeparator.js.map +1 -1
  187. package/dist/components/VSideNavigation/context.js.map +1 -1
  188. package/dist/components/VSkeletonLoader/VSkeletonLoader.d.ts +6 -19
  189. package/dist/components/VSkeletonLoader/VSkeletonLoader.js.map +1 -1
  190. package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  191. package/dist/components/VSlider/VSlider.d.ts +5 -13
  192. package/dist/components/VSlider/VSlider.js.map +1 -1
  193. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  194. package/dist/components/VSnackbar/VSnackbar.js.map +1 -1
  195. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  196. package/dist/components/VSnackbar/state.d.ts +4 -17
  197. package/dist/components/VSnackbar/state.js.map +1 -1
  198. package/dist/components/VSpinner/VSpinner.d.ts +3 -5
  199. package/dist/components/VSpinner/VSpinner.js.map +1 -1
  200. package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  201. package/dist/components/VSwitch/VSwitch.js.map +1 -1
  202. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  203. package/dist/components/VTabs/VTab.d.ts +1 -5
  204. package/dist/components/VTabs/VTab.js.map +1 -1
  205. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
  206. package/dist/components/VTabs/VTabPanel.js.map +1 -1
  207. package/dist/components/VTabs/VTabPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  208. package/dist/components/VTabs/VTabs.d.ts +5 -17
  209. package/dist/components/VTabs/VTabs.js.map +1 -1
  210. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  211. package/dist/components/VTabs/context.js.map +1 -1
  212. package/dist/components/VTextarea/VTextarea.d.ts +13 -20
  213. package/dist/components/VTextarea/VTextarea.js.map +1 -1
  214. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  215. package/dist/components/VTimeInput/VTimeInput.d.ts +8 -21
  216. package/dist/components/VTimeInput/VTimeInput.js.map +1 -1
  217. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  218. package/dist/components/VTimeInput/search.d.ts +3 -34
  219. package/dist/components/VTimeInput/search.js.map +1 -1
  220. package/dist/components/VTimePicker/VTimePicker.d.ts +9 -31
  221. package/dist/components/VTimePicker/VTimePicker.js.map +1 -1
  222. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  223. package/dist/components/VTimePicker/limits.d.ts +18 -45
  224. package/dist/components/VTimePicker/limits.js.map +1 -1
  225. package/dist/components/VToast/VToast.js.map +1 -1
  226. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js.map +1 -1
  227. package/dist/components/VToast/VToaster.js.map +1 -1
  228. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
  229. package/dist/components/VToast/state.d.ts +2 -7
  230. package/dist/components/VToast/state.js.map +1 -1
  231. package/dist/components/VToggle/VToggle.d.ts +5 -9
  232. package/dist/components/VToggle/VToggle.js.map +1 -1
  233. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js.map +1 -1
  234. package/dist/components/VToggle/VToggleItem.d.ts +1 -9
  235. package/dist/components/VToggle/VToggleItem.js.map +1 -1
  236. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  237. package/dist/components/VToggle/context.js.map +1 -1
  238. package/dist/components/VTooltip/VTooltip.d.ts +3 -16
  239. package/dist/components/VTooltip/VTooltip.js.map +1 -1
  240. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js +2 -2
  241. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  242. package/dist/components/VTypography/VTypography.d.ts +4 -8
  243. package/dist/components/VTypography/VTypography.js.map +1 -1
  244. package/dist/components/VTypography/VTypography.vue_vue_type_script_setup_true_lang.js.map +1 -1
  245. package/dist/composables/useAriaLabel.js.map +1 -1
  246. package/dist/composables/useClearable.d.ts +2 -8
  247. package/dist/composables/useClearable.js.map +1 -1
  248. package/dist/composables/useControlShape.js.map +1 -1
  249. package/dist/composables/useDetailsOpen.d.ts +2 -10
  250. package/dist/composables/useDetailsOpen.js.map +1 -1
  251. package/dist/composables/useFieldIds.js.map +1 -1
  252. package/dist/composables/useFieldPanel.d.ts +4 -17
  253. package/dist/composables/useFieldPanel.js.map +1 -1
  254. package/dist/composables/useFileDrop.js.map +1 -1
  255. package/dist/composables/useFileField.d.ts +1 -5
  256. package/dist/composables/useFileField.js.map +1 -1
  257. package/dist/composables/useFocusoutDismiss.js.map +1 -1
  258. package/dist/composables/useIconClickHandlers.d.ts +4 -19
  259. package/dist/composables/useIconClickHandlers.js.map +1 -1
  260. package/dist/composables/useInertLink.d.ts +1 -1
  261. package/dist/composables/useInertLink.js.map +1 -1
  262. package/dist/composables/useLiveAnnouncer.js.map +1 -1
  263. package/dist/composables/useMaskedField.d.ts +12 -27
  264. package/dist/composables/useMaskedField.js.map +1 -1
  265. package/dist/composables/usePopover.d.ts +3 -11
  266. package/dist/composables/usePopover.js.map +1 -1
  267. package/dist/composables/useProgressValue.js.map +1 -1
  268. package/dist/composables/useRootAttrs.d.ts +0 -9
  269. package/dist/composables/useRootAttrs.js +11 -4
  270. package/dist/composables/useRootAttrs.js.map +1 -1
  271. package/dist/composables/useSlotNodes.d.ts +3 -14
  272. package/dist/composables/useSlotNodes.js.map +1 -1
  273. package/dist/composables/useTextLimit.d.ts +4 -16
  274. package/dist/composables/useTextLimit.js.map +1 -1
  275. package/dist/composables/useTimer.d.ts +2 -15
  276. package/dist/composables/useTimer.js.map +1 -1
  277. package/dist/i18n/en.js.map +1 -1
  278. package/dist/i18n/fr.js.map +1 -1
  279. package/dist/i18n/state.d.ts +9 -38
  280. package/dist/i18n/state.js.map +1 -1
  281. package/dist/i18n/types.d.ts +19 -81
  282. package/dist/icons.d.ts +2 -12
  283. package/dist/styles.css +1 -1
  284. package/dist/tokens/css.d.ts +3 -16
  285. package/dist/tokens/css.js.map +1 -1
  286. package/dist/tokens/index.d.ts +5 -0
  287. package/dist/tokens/index.js.map +1 -1
  288. package/dist/tokens/primitives.js.map +1 -1
  289. package/dist/tokens/semantic.d.ts +6 -23
  290. package/dist/tokens/semantic.js +5 -0
  291. package/dist/tokens/semantic.js.map +1 -1
  292. package/dist/tokens/themes/dark.js.map +1 -1
  293. package/dist/tokens/types.d.ts +2 -12
  294. package/dist/tokens/types.js.map +1 -1
  295. package/dist/tokens.json +14 -0
  296. package/dist/types.d.ts +3 -21
  297. package/dist/utils/array.d.ts +2 -4
  298. package/dist/utils/array.js.map +1 -1
  299. package/dist/utils/arrowNav.d.ts +2 -26
  300. package/dist/utils/arrowNav.js.map +1 -1
  301. package/dist/utils/chip.d.ts +1 -8
  302. package/dist/utils/chip.js.map +1 -1
  303. package/dist/utils/clock.d.ts +16 -39
  304. package/dist/utils/clock.js.map +1 -1
  305. package/dist/utils/css.d.ts +5 -16
  306. package/dist/utils/css.js.map +1 -1
  307. package/dist/utils/date.d.ts +17 -60
  308. package/dist/utils/date.js.map +1 -1
  309. package/dist/utils/direction.d.ts +2 -9
  310. package/dist/utils/direction.js.map +1 -1
  311. package/dist/utils/env.d.ts +2 -15
  312. package/dist/utils/env.js.map +1 -1
  313. package/dist/utils/file.d.ts +8 -46
  314. package/dist/utils/file.js.map +1 -1
  315. package/dist/utils/focus.d.ts +1 -14
  316. package/dist/utils/focus.js +1 -6
  317. package/dist/utils/focus.js.map +1 -1
  318. package/dist/utils/hostWarns.d.ts +3 -8
  319. package/dist/utils/hostWarns.js.map +1 -1
  320. package/dist/utils/ids.d.ts +2 -7
  321. package/dist/utils/ids.js.map +1 -1
  322. package/dist/utils/matcher.d.ts +1 -8
  323. package/dist/utils/matcher.js.map +1 -1
  324. package/dist/utils/memo.d.ts +1 -11
  325. package/dist/utils/memo.js.map +1 -1
  326. package/dist/utils/number.d.ts +1 -7
  327. package/dist/utils/number.js.map +1 -1
  328. package/dist/utils/text.d.ts +4 -23
  329. package/dist/utils/text.js.map +1 -1
  330. package/dist/utils/time.d.ts +4 -12
  331. package/dist/utils/time.js.map +1 -1
  332. package/dist/utils/vnode.d.ts +0 -10
  333. package/dist/utils/vnode.js.map +1 -1
  334. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useMaskedField.js","names":[],"sources":["../../src/composables/useMaskedField.ts"],"sourcesContent":["// @core — module-wide: mask, caret and commit are the field's own behaviour.\n/**\n * The masked field of VDateInput and VTimeInput: the reader types digits, the separators\n * appear as they go. The FIELD half, `useFieldPanel` being the panel half.\n *\n * Only the mask's vocabulary is injected — how many digits, how they become text, where the\n * caret lands, how the text becomes a value. A date's separator is locale-dependent where a\n * time's is universal, so the two compute the caret differently; nothing here cares beyond\n * telling them whether the edit was an INSERTION.\n */\nimport { computed, ref, watch, type Ref, type WritableComputedRef } from 'vue'\n\nimport { digitsOf } from '../utils/text'\n\nexport interface MaskedFieldOptions<T extends string> {\n /** The real input, which is written to directly: see below. */\n fieldEl: Ref<HTMLInputElement | null>\n /** Whether the field can be typed into at all. Everything here is inert when it cannot. */\n typing: () => boolean\n /** What the field shows when it is NOT being typed into: the value, written out in full. */\n displayText: () => string\n /** The current value, or nothing. */\n readValue: () => T | null\n /** Writes a new value. */\n writeValue: (value: T | null) => void\n /** How many digits the mask holds: eight for a date, four for a time. */\n maxDigits: () => number\n /** Lays a run of digits out as masked text. */\n format: (digits: string) => string\n /**\n * Where the caret goes so as to sit after a given number of digits.\n *\n * The flag says whether something was INSERTED rather than deleted, and it matters: on\n * a deletion the caret must stay IN FRONT of the separator, or the next press of the key\n * would step over it instead of erasing, and the key would appear to do nothing.\n */\n caret: (text: string, digitsBefore: number, inserting: boolean) => number\n /**\n * Reads masked text back into a value, or nothing when it is not one yet.\n *\n * The flag marks the FINAL reading, when the reader leaves the field. A date expands a\n * two-digit year only there: \"26\" must not be committed as 2026 while it may still be on\n * its way to becoming it.\n */\n parse: (text: string, final: boolean) => T | null\n /** Writes a value as masked text, and nothing at all for no value. */\n toMask: (value: T | null) => string\n /**\n * Whether a value the reader has finished typing may be taken: within the bounds, not\n * one of the excluded days. Everything is acceptable by default.\n */\n acceptable?: (value: T) => boolean\n}\n\n/** What a component adds to the mask's own keys. */\nexport interface MaskedKeyHooks {\n /**\n * A key that is not a digit was typed: a separator, most often. Its character never\n * reaches the field; what it MEANS is the component's: a date pads the field being typed\n * and moves on to the next, a time pads the hour.\n */\n onSeparator: (el: HTMLInputElement) => void\n /**\n * The down arrow, which a component with a panel turns into the way into it. It answers\n * whether it handled the press: only then is the default cancelled, and a press left\n * alone travels on to whatever opens the panel.\n */\n onArrowDown?: () => boolean\n /** Runs once Enter has committed or reverted what was typed: closing a panel, say. */\n onEnter?: () => void\n}\n\nexport interface MaskedField<T extends string> {\n /** The text currently in the field while it is being typed into. */\n draft: Ref<string>\n /**\n * TRAP: bind with `v-model` and NEVER `:model-value`. Without an `onUpdate:modelValue`\n * listener, `useModel` keeps an internal copy of the RAW typed text and rewrites it on the\n * next patch, erasing the mask exactly when the masked text did NOT change: a rejected\n * character, or a digit past the last. Both components lock it with a test.\n */\n fieldModel: WritableComputedRef<string | number>\n /**\n * Writes into both the draft and the input. Both are needed: Vue does not patch an element\n * whose value it believes unchanged, and after a reformat it often is.\n */\n writeField: (text: string, caret?: number) => void\n /** Takes the value as soon as what has been typed is complete and acceptable. */\n commitLive: () => void\n /** Called as the reader leaves the field. It is safe to call twice. */\n commitOrRevert: () => void\n /** The handler to bind to the field's input event. */\n onFieldInput: (event: Event) => void\n /** The handler for the field's keydown event, with what the component adds to it. */\n onKeydown: (event: KeyboardEvent, hooks: MaskedKeyHooks) => void\n /**\n * The handler for the field's paste event. `recognize` reads the pasted text as a WHOLE\n * value when it is one (a date in ISO form or a canonical time) and answers nothing\n * otherwise, in which case only the digits of what was pasted are taken.\n */\n onPaste: (event: ClipboardEvent, recognize: (pasted: string) => T | null) => void\n}\n\nexport function useMaskedField<T extends string>(options: MaskedFieldOptions<T>): MaskedField<T> {\n const draft = ref('')\n const acceptable = options.acceptable ?? (() => true)\n\n /*\n * The value as masked text. Being a computed it also tracks what the conversion reads —\n * the locale's mask, the hour cycle — so neither component lists those dependencies.\n */\n const maskedValue = computed(() => options.toMask(options.readValue()))\n\n watch(\n maskedValue,\n (next) => {\n // TRAP — the anti-loop guard. A commit made while typing writes the value, which comes\n // straight back here; without the test, the text being typed and its caret would be\n // overwritten by text identical to what is already there.\n if (next !== draft.value) draft.value = next\n },\n { immediate: true },\n )\n\n const fieldModel = computed<string | number>({\n get: () => (options.typing() ? draft.value : options.displayText()),\n set: (value) => {\n if (options.typing()) draft.value = String(value ?? '')\n },\n })\n\n function writeField(text: string, caret?: number) {\n draft.value = text\n const el = options.fieldEl.value\n if (!el) return\n if (el.value !== text) el.value = text\n if (caret !== undefined) el.setSelectionRange(caret, caret)\n }\n\n function commitLive() {\n const value = options.parse(draft.value, false)\n if (value && acceptable(value) && value !== options.readValue()) options.writeValue(value)\n }\n\n /**\n * Commits what was typed, or SILENTLY reverts to the current value.\n *\n * An entry that is incomplete, impossible (31 February), out of bounds or excluded simply\n * disappears. There is deliberately no error state of our own competing with the `invalid`\n * prop the consumer controls.\n */\n function commitOrRevert() {\n if (!options.typing()) return\n if (!digitsOf(draft.value)) {\n if (options.readValue() !== null) options.writeValue(null)\n writeField('')\n return\n }\n const value = options.parse(draft.value, true)\n if (value && acceptable(value)) {\n if (value !== options.readValue()) options.writeValue(value)\n // Rewritten in full: \"5/6/26\" becomes \"05/06/2026\".\n writeField(options.toMask(value))\n return\n }\n writeField(options.toMask(options.readValue()))\n }\n\n /**\n * Reformats the field on every keystroke.\n *\n * The invariant to keep is that the number of digits to the LEFT of the caret survives\n * the reformatting. Restoring an absolute position instead would misplace the caret on\n * exactly the keystrokes that matter: a position jumps by one the moment a separator\n * appears or disappears.\n */\n function onFieldInput(event: Event) {\n if (!options.typing()) return\n const el = event.target as HTMLInputElement\n const raw = el.value\n const caret = el.selectionStart ?? raw.length\n const before = digitsOf(raw.slice(0, caret)).length\n const digits = digitsOf(raw).slice(0, options.maxDigits())\n const inserting = !String((event as InputEvent).inputType ?? '').startsWith('delete')\n const text = options.format(digits)\n writeField(text, options.caret(text, Math.min(before, digits.length), inserting))\n commitLive()\n }\n\n /*\n * Backspace over a SEPARATOR, which erases the digit in front of it instead.\n *\n * TRAP — a separator is placed by the mask and never typed, so erasing one has to erase\n * the DIGIT before it, which is what the reader believes they are erasing. Left alone, the\n * mask writes the separator straight back and the key looks dead.\n *\n * It answers whether it handled the press: `false` means the caret was not sitting after a\n * separator and the browser's own Backspace should run.\n */\n function backspaceOverSeparator(el: HTMLInputElement) {\n const start = el.selectionStart\n if (\n start === null ||\n start !== el.selectionEnd ||\n start === 0 ||\n /\\d/.test(el.value[start - 1] ?? '')\n ) {\n return false\n }\n const before = digitsOf(el.value.slice(0, start)).length\n const digits = digitsOf(el.value)\n const text = options.format(digits.slice(0, before - 1) + digits.slice(before))\n writeField(text, options.caret(text, before - 1, false))\n commitLive()\n return true\n }\n\n /**\n * Splices a pasted run of digits into the one already in the field, at the selection, and\n * puts the caret after what was inserted.\n */\n function pasteDigits(el: HTMLInputElement, pasted: string) {\n const start = el.selectionStart ?? el.value.length\n const end = el.selectionEnd ?? start\n const digits = digitsOf(el.value)\n const from = digitsOf(el.value.slice(0, start)).length\n const to = digitsOf(el.value.slice(0, end)).length\n const inserted = digitsOf(pasted)\n const next = (digits.slice(0, from) + inserted + digits.slice(to)).slice(0, options.maxDigits())\n const text = options.format(next)\n writeField(text, options.caret(text, Math.min(from + inserted.length, next.length), true))\n commitLive()\n }\n\n // @keyboard\n function onKeydown(event: KeyboardEvent, hooks: MaskedKeyHooks) {\n if (!options.typing()) return\n const el = options.fieldEl.value\n if (!el) return\n\n if (event.key === 'Enter') {\n // Cancelling the default does two things at once: it stops the surrounding form from\n // being submitted, and it stops a panel this keystroke closes from being reopened as\n // the event travels up to the component's root.\n event.preventDefault()\n commitOrRevert()\n hooks.onEnter?.()\n return\n }\n if (event.key === 'ArrowDown') {\n if (hooks.onArrowDown?.()) event.preventDefault()\n return\n }\n if (event.key === 'Backspace') {\n if (backspaceOverSeparator(el)) event.preventDefault()\n return\n }\n if (\n event.key.length === 1 &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.altKey &&\n !/\\d/.test(event.key)\n ) {\n event.preventDefault()\n hooks.onSeparator(el)\n }\n }\n\n /**\n * Pasting. Without the whole-value path, pasting \"2026-06-10\" into a field expecting day,\n * month, year would produce \"20/26/0610\": the digits would be taken in order and the\n * separators ignored.\n *\n * A whole value is written as it stands rather than read back from the mask, which is not\n * a detail on a 12-hour clock: \"19:05\" shows as \"07:05\", and reading that text back would\n * take the half of the day from the AM/PM button instead of from what was pasted.\n */\n function onPaste(event: ClipboardEvent, recognize: (pasted: string) => T | null) {\n if (!options.typing()) return\n const el = options.fieldEl.value\n if (!el) return\n event.preventDefault()\n const pasted = (event.clipboardData?.getData('text') ?? '').trim()\n const whole = recognize(pasted)\n if (whole) {\n const text = options.toMask(whole)\n writeField(text, text.length)\n if (acceptable(whole) && whole !== options.readValue()) options.writeValue(whole)\n return\n }\n pasteDigits(el, pasted)\n }\n\n return {\n draft,\n fieldModel,\n writeField,\n commitLive,\n commitOrRevert,\n onFieldInput,\n onKeydown,\n onPaste,\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useMaskedField.js","names":[],"sources":["../../src/composables/useMaskedField.ts"],"sourcesContent":["// @core\n/**\n * Share digit masking, caret preservation and commit logic between date and time fields; each\n * component supplies its format and parser.\n */\nimport { computed, ref, watch, type Ref, type WritableComputedRef } from 'vue'\n\nimport { digitsOf } from '../utils/text'\n\nexport interface MaskedFieldOptions<T extends string> {\n /** The real input, which is written to directly: see below. */\n fieldEl: Ref<HTMLInputElement | null>\n /** Whether the field can be typed into at all. Everything here is inert when it cannot. */\n typing: () => boolean\n /** What the field shows when it is not being typed into: the value, written out in full. */\n displayText: () => string\n /** The current value, or nothing. */\n readValue: () => T | null\n /** Writes a new value. */\n writeValue: (value: T | null) => void\n /** How many digits the mask holds: eight for a date, four for a time. */\n maxDigits: () => number\n /** Lays a run of digits out as masked text. */\n format: (digits: string) => string\n /**\n * Where the caret goes so as to sit after a given number of digits. The flag says whether\n * something was INSERTED rather than deleted, and it matters: on a deletion the caret must\n * stay in FRONT of the separator, or the next press of the key would step over it instead of\n * erasing, and the key would appear to do nothing.\n */\n caret: (text: string, digitsBefore: number, inserting: boolean) => number\n /** Reads masked text back into a value, or nothing when it is not one yet. */\n parse: (text: string, final: boolean) => T | null\n /** Writes a value as masked text, and nothing at all for no value. */\n toMask: (value: T | null) => string\n /**\n * Whether a value the reader has finished typing may be taken: within the bounds, not\n * one of the excluded days. Everything is acceptable by default.\n */\n acceptable?: (value: T) => boolean\n}\n\n/** What a component adds to the mask's own keys. */\nexport interface MaskedKeyHooks {\n /** A key that is not a digit was typed: a separator, most often. */\n onSeparator: (el: HTMLInputElement) => void\n /**\n * The down arrow, which a component with a panel turns into the way into it. It answers\n * whether it handled the press: only then is the default cancelled, and a press left\n * alone travels on to whatever opens the panel.\n */\n onArrowDown?: () => boolean\n /** Runs once Enter has committed or reverted what was typed: closing a panel, say. */\n onEnter?: () => void\n}\n\nexport interface MaskedField<T extends string> {\n /** The text currently in the field while it is being typed into. */\n draft: Ref<string>\n /**\n * Bind with `v-model` and never `:model-value`. Without an `onUpdate:modelValue` listener,\n * `useModel` keeps an internal copy of the RAW typed text and rewrites it on the next patch,\n * erasing the mask exactly when the masked text did not change: a rejected character, or a\n * digit past the last.\n */\n fieldModel: WritableComputedRef<string | number>\n /**\n * Writes into both the draft and the input. Both are needed: Vue does not patch an element\n * whose value it believes unchanged, and after a reformat it often is.\n */\n writeField: (text: string, caret?: number) => void\n /** Takes the value as soon as what has been typed is complete and acceptable. */\n commitLive: () => void\n /** Called as the reader leaves the field. It is safe to call twice. */\n commitOrRevert: () => void\n /** The handler to bind to the field's input event. */\n onFieldInput: (event: Event) => void\n /** The handler for the field's keydown event, with what the component adds to it. */\n onKeydown: (event: KeyboardEvent, hooks: MaskedKeyHooks) => void\n /** The handler for the field's paste event. */\n onPaste: (event: ClipboardEvent, recognize: (pasted: string) => T | null) => void\n}\n\nexport function useMaskedField<T extends string>(options: MaskedFieldOptions<T>): MaskedField<T> {\n const draft = ref('')\n const acceptable = options.acceptable ?? (() => true)\n\n /*\n * The value as masked text. Being a computed it also tracks what the conversion reads; the\n * locale's mask, the hour cycle; so neither component lists those dependencies.\n */\n const maskedValue = computed(() => options.toMask(options.readValue()))\n\n watch(\n maskedValue,\n (next) => {\n // The anti-loop guard. A commit made while typing writes the value, which comes straight\n // back here; without the test, the text being typed and its caret would be overwritten by\n // text identical to what is already there.\n if (next !== draft.value) draft.value = next\n },\n { immediate: true },\n )\n\n const fieldModel = computed<string | number>({\n get: () => (options.typing() ? draft.value : options.displayText()),\n set: (value) => {\n if (options.typing()) draft.value = String(value ?? '')\n },\n })\n\n function writeField(text: string, caret?: number) {\n draft.value = text\n const el = options.fieldEl.value\n if (!el) return\n if (el.value !== text) el.value = text\n if (caret !== undefined) el.setSelectionRange(caret, caret)\n }\n\n function commitLive() {\n const value = options.parse(draft.value, false)\n if (value && acceptable(value) && value !== options.readValue()) options.writeValue(value)\n }\n\n /** Commits what was typed, or SILENTLY reverts to the current value. */\n function commitOrRevert() {\n if (!options.typing()) return\n if (!digitsOf(draft.value)) {\n if (options.readValue() !== null) options.writeValue(null)\n writeField('')\n return\n }\n const value = options.parse(draft.value, true)\n if (value && acceptable(value)) {\n if (value !== options.readValue()) options.writeValue(value)\n writeField(options.toMask(value))\n return\n }\n writeField(options.toMask(options.readValue()))\n }\n\n /**\n * Reformats the field on every keystroke. Restoring an absolute position instead would\n * misplace the caret on exactly the keystrokes that matter: a position jumps by one the\n * moment a separator appears or disappears.\n */\n function onFieldInput(event: Event) {\n if (!options.typing()) return\n const el = event.target as HTMLInputElement\n const raw = el.value\n const caret = el.selectionStart ?? raw.length\n const before = digitsOf(raw.slice(0, caret)).length\n const digits = digitsOf(raw).slice(0, options.maxDigits())\n const inserting = !String((event as InputEvent).inputType ?? '').startsWith('delete')\n const text = options.format(digits)\n writeField(text, options.caret(text, Math.min(before, digits.length), inserting))\n commitLive()\n }\n\n /*\n * A separator is placed by the mask and never typed, so erasing one has to erase the DIGIT\n * before it, which the reader believes they are erasing. Left alone, the mask writes the\n * separator straight back and the key looks dead.\n */\n function backspaceOverSeparator(el: HTMLInputElement) {\n const start = el.selectionStart\n if (\n start === null ||\n start !== el.selectionEnd ||\n start === 0 ||\n /\\d/.test(el.value[start - 1] ?? '')\n ) {\n return false\n }\n const before = digitsOf(el.value.slice(0, start)).length\n const digits = digitsOf(el.value)\n const text = options.format(digits.slice(0, before - 1) + digits.slice(before))\n writeField(text, options.caret(text, before - 1, false))\n commitLive()\n return true\n }\n\n /**\n * Splices a pasted run of digits into the one already in the field, at the selection, and\n * puts the caret after what was inserted.\n */\n function pasteDigits(el: HTMLInputElement, pasted: string) {\n const start = el.selectionStart ?? el.value.length\n const end = el.selectionEnd ?? start\n const digits = digitsOf(el.value)\n const from = digitsOf(el.value.slice(0, start)).length\n const to = digitsOf(el.value.slice(0, end)).length\n const inserted = digitsOf(pasted)\n const next = (digits.slice(0, from) + inserted + digits.slice(to)).slice(0, options.maxDigits())\n const text = options.format(next)\n writeField(text, options.caret(text, Math.min(from + inserted.length, next.length), true))\n commitLive()\n }\n\n // @keyboard\n function onKeydown(event: KeyboardEvent, hooks: MaskedKeyHooks) {\n if (!options.typing()) return\n const el = options.fieldEl.value\n if (!el) return\n\n if (event.key === 'Enter') {\n // Cancelling the default does two things at once: it stops the surrounding form from\n // being submitted, and it stops a panel this keystroke closes from being reopened as\n // the event travels up to the component's root.\n event.preventDefault()\n commitOrRevert()\n hooks.onEnter?.()\n return\n }\n if (event.key === 'ArrowDown') {\n if (hooks.onArrowDown?.()) event.preventDefault()\n return\n }\n if (event.key === 'Backspace') {\n if (backspaceOverSeparator(el)) event.preventDefault()\n return\n }\n if (\n event.key.length === 1 &&\n !event.ctrlKey &&\n !event.metaKey &&\n !event.altKey &&\n !/\\d/.test(event.key)\n ) {\n event.preventDefault()\n hooks.onSeparator(el)\n }\n }\n\n /**\n * Pasting. Without the whole-value path, pasting \"2026-06-10\" into a field expecting day,\n * month, year would produce \"20/26/0610\": the digits would be taken in order and the\n * separators ignored.\n */\n function onPaste(event: ClipboardEvent, recognize: (pasted: string) => T | null) {\n if (!options.typing()) return\n const el = options.fieldEl.value\n if (!el) return\n event.preventDefault()\n const pasted = (event.clipboardData?.getData('text') ?? '').trim()\n const whole = recognize(pasted)\n if (whole) {\n const text = options.toMask(whole)\n writeField(text, text.length)\n if (acceptable(whole) && whole !== options.readValue()) options.writeValue(whole)\n return\n }\n pasteDigits(el, pasted)\n }\n\n return {\n draft,\n fieldModel,\n writeField,\n commitLive,\n commitOrRevert,\n onFieldInput,\n onKeydown,\n onPaste,\n }\n}\n"],"mappings":";;;AAmFA,SAAgB,EAAiC,GAAgD;CAC/F,IAAM,IAAQ,EAAI,EAAE,GACd,IAAa,EAAQ,qBAAqB;CAQhD,EAFoB,QAAe,EAAQ,OAAO,EAAQ,UAAU,CAAC,CAGnE,IACC,MAAS;EAIR,AAAI,MAAS,EAAM,UAAO,EAAM,QAAQ;CAC1C,GACA,EAAE,WAAW,GAAK,CACpB;CAEA,IAAM,IAAa,EAA0B;EAC3C,WAAY,EAAQ,OAAO,IAAI,EAAM,QAAQ,EAAQ,YAAY;EACjE,MAAM,MAAU;GACd,AAAI,EAAQ,OAAO,MAAG,EAAM,QAAQ,OAAO,KAAS,EAAE;EACxD;CACF,CAAC;CAED,SAAS,EAAW,GAAc,GAAgB;EAChD,EAAM,QAAQ;EACd,IAAM,IAAK,EAAQ,QAAQ;EACtB,MACD,EAAG,UAAU,MAAM,EAAG,QAAQ,IAC9B,MAAU,KAAA,KAAW,EAAG,kBAAkB,GAAO,CAAK;CAC5D;CAEA,SAAS,IAAa;EACpB,IAAM,IAAQ,EAAQ,MAAM,EAAM,OAAO,EAAK;EAC9C,AAAI,KAAS,EAAW,CAAK,KAAK,MAAU,EAAQ,UAAU,KAAG,EAAQ,WAAW,CAAK;CAC3F;CAGA,SAAS,IAAiB;EACxB,IAAI,CAAC,EAAQ,OAAO,GAAG;EACvB,IAAI,CAAC,EAAS,EAAM,KAAK,GAAG;GAE1B,AADI,EAAQ,UAAU,MAAM,QAAM,EAAQ,WAAW,IAAI,GACzD,EAAW,EAAE;GACb;EACF;EACA,IAAM,IAAQ,EAAQ,MAAM,EAAM,OAAO,EAAI;EAC7C,IAAI,KAAS,EAAW,CAAK,GAAG;GAE9B,AADI,MAAU,EAAQ,UAAU,KAAG,EAAQ,WAAW,CAAK,GAC3D,EAAW,EAAQ,OAAO,CAAK,CAAC;GAChC;EACF;EACA,EAAW,EAAQ,OAAO,EAAQ,UAAU,CAAC,CAAC;CAChD;CAOA,SAAS,EAAa,GAAc;EAClC,IAAI,CAAC,EAAQ,OAAO,GAAG;EACvB,IAAM,IAAK,EAAM,QACX,IAAM,EAAG,OACT,IAAQ,EAAG,kBAAkB,EAAI,QACjC,IAAS,EAAS,EAAI,MAAM,GAAG,CAAK,CAAC,CAAC,CAAC,QACvC,IAAS,EAAS,CAAG,CAAC,CAAC,MAAM,GAAG,EAAQ,UAAU,CAAC,GACnD,IAAY,CAAC,OAAQ,EAAqB,aAAa,EAAE,CAAC,CAAC,WAAW,QAAQ,GAC9E,IAAO,EAAQ,OAAO,CAAM;EAElC,AADA,EAAW,GAAM,EAAQ,MAAM,GAAM,KAAK,IAAI,GAAQ,EAAO,MAAM,GAAG,CAAS,CAAC,GAChF,EAAW;CACb;CAOA,SAAS,EAAuB,GAAsB;EACpD,IAAM,IAAQ,EAAG;EACjB,IACE,MAAU,QACV,MAAU,EAAG,gBACb,MAAU,KACV,KAAK,KAAK,EAAG,MAAM,IAAQ,MAAM,EAAE,GAEnC,OAAO;EAET,IAAM,IAAS,EAAS,EAAG,MAAM,MAAM,GAAG,CAAK,CAAC,CAAC,CAAC,QAC5C,IAAS,EAAS,EAAG,KAAK,GAC1B,IAAO,EAAQ,OAAO,EAAO,MAAM,GAAG,IAAS,CAAC,IAAI,EAAO,MAAM,CAAM,CAAC;EAG9E,OAFA,EAAW,GAAM,EAAQ,MAAM,GAAM,IAAS,GAAG,EAAK,CAAC,GACvD,EAAW,GACJ;CACT;CAMA,SAAS,EAAY,GAAsB,GAAgB;EACzD,IAAM,IAAQ,EAAG,kBAAkB,EAAG,MAAM,QACtC,IAAM,EAAG,gBAAgB,GACzB,IAAS,EAAS,EAAG,KAAK,GAC1B,IAAO,EAAS,EAAG,MAAM,MAAM,GAAG,CAAK,CAAC,CAAC,CAAC,QAC1C,IAAK,EAAS,EAAG,MAAM,MAAM,GAAG,CAAG,CAAC,CAAC,CAAC,QACtC,IAAW,EAAS,CAAM,GAC1B,KAAQ,EAAO,MAAM,GAAG,CAAI,IAAI,IAAW,EAAO,MAAM,CAAE,EAAA,CAAG,MAAM,GAAG,EAAQ,UAAU,CAAC,GACzF,IAAO,EAAQ,OAAO,CAAI;EAEhC,AADA,EAAW,GAAM,EAAQ,MAAM,GAAM,KAAK,IAAI,IAAO,EAAS,QAAQ,EAAK,MAAM,GAAG,EAAI,CAAC,GACzF,EAAW;CACb;CAGA,SAAS,EAAU,GAAsB,GAAuB;EAC9D,IAAI,CAAC,EAAQ,OAAO,GAAG;EACvB,IAAM,IAAK,EAAQ,QAAQ;EACtB,OAEL;OAAI,EAAM,QAAQ,SAAS;IAMzB,AAFA,EAAM,eAAe,GACrB,EAAe,GACf,EAAM,UAAU;IAChB;GACF;GACA,IAAI,EAAM,QAAQ,aAAa;IAC7B,AAAI,EAAM,cAAc,KAAG,EAAM,eAAe;IAChD;GACF;GACA,IAAI,EAAM,QAAQ,aAAa;IAC7B,AAAI,EAAuB,CAAE,KAAG,EAAM,eAAe;IACrD;GACF;GACA,AACE,EAAM,IAAI,WAAW,KACrB,CAAC,EAAM,WACP,CAAC,EAAM,WACP,CAAC,EAAM,UACP,CAAC,KAAK,KAAK,EAAM,GAAG,MAEpB,EAAM,eAAe,GACrB,EAAM,YAAY,CAAE;EAjBtB;CAmBF;CAOA,SAAS,EAAQ,GAAuB,GAAyC;EAC/E,IAAI,CAAC,EAAQ,OAAO,GAAG;EACvB,IAAM,IAAK,EAAQ,QAAQ;EAC3B,IAAI,CAAC,GAAI;EACT,EAAM,eAAe;EACrB,IAAM,KAAU,EAAM,eAAe,QAAQ,MAAM,KAAK,GAAA,CAAI,KAAK,GAC3D,IAAQ,EAAU,CAAM;EAC9B,IAAI,GAAO;GACT,IAAM,IAAO,EAAQ,OAAO,CAAK;GAEjC,AADA,EAAW,GAAM,EAAK,MAAM,GACxB,EAAW,CAAK,KAAK,MAAU,EAAQ,UAAU,KAAG,EAAQ,WAAW,CAAK;GAChF;EACF;EACA,EAAY,GAAI,CAAM;CACxB;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF"}
@@ -6,16 +6,8 @@ export declare function usePopover(el: Readonly<Ref<HTMLElement | null>>): {
6
6
  hide: () => void;
7
7
  };
8
8
  /**
9
- * The model half of a popover's `v-model:open`, for a component that publishes its open
10
- * state: a change to the model opens or closes the panel. The other half: writing the
11
- * DOM's state back into the model, stays with the component, in its own toggle handler,
12
- * because that is where it knows the state has settled.
13
- *
14
- * `shown` is a getter so that the state may live in a child: VPopover reads its own
15
- * `usePopover`, VMenu reads the one VMenuPanel exposes.
16
- *
17
- * TRAP: the `value === shown()` guard is what keeps the two directions from chasing each
18
- * other. A panel the browser has just dismissed writes `false` into the model; without the
19
- * guard that write would come back here as a request to close a panel already closed.
9
+ * The `value === shown()` guard is what keeps the two directions from chasing each other. A
10
+ * panel the browser has just dismissed writes `false` into the model; without the guard that
11
+ * write would come back here as a request to close a panel already closed.
20
12
  */
21
13
  export declare function usePopoverModel(open: Ref<boolean>, shown: () => boolean, show: () => void, hide: () => void): void;
@@ -1 +1 @@
1
- {"version":3,"file":"usePopover.js","names":[],"sources":["../../src/composables/usePopover.ts"],"sourcesContent":["// @core\n/**\n * The state plumbing of a `[popover]`: whether it is open, and how to open or close it.\n * The JS half of `styles/floating.css`, which places the panel.\n *\n * The Popover API is imperative where the rest of the library is declarative, and it sets\n * three traps a plain boolean would fall into. Closing an already-closed panel throws, hence\n * the idempotence guards. Opening one while the browser is busy with another popover throws\n * as well, hence the retry on `show`. And an `auto` panel dismisses itself on a click outside\n * or on Escape, so the state is READ from the DOM: wire `syncShown` to both `beforetoggle`\n * and `toggle`, the first being the only one that catches light dismiss in time and the\n * second the only one the jsdom stub emits.\n *\n * TRAP — never assign `shown` by hand. A panel the browser dismissed would then still read\n * as open, and the guard would swallow the next request to close it.\n */\n\nimport { onMounted, ref, watch, type Ref } from 'vue'\n\n// @fallback\n// The option below is newer than the type definitions shipped with TypeScript, so the\n// element is described locally rather than being cast about at each call site.\ntype PopoverWithSource = HTMLElement & { showPopover(options?: { source?: HTMLElement }): void }\n\nexport function usePopover(el: Readonly<Ref<HTMLElement | null>>) {\n const shown = ref(false)\n\n /**\n * Reads the state back off the panel. Bind it to both `@beforetoggle` and `@toggle`, and\n * on the popover element itself: ToggleEvents do not bubble.\n */\n function syncShown(event: Event) {\n shown.value = (event as ToggleEvent).newState === 'open'\n }\n\n /**\n * Opens the panel.\n *\n * TRAP — opening from code rather than from a click must name the invoker as `source`.\n * That is what recreates the relationship a click would have: the implicit anchor and the\n * panel's place in the popover stack. Without it the panel has nothing to position\n * against and lands at the corner of the viewport.\n */\n function show(source?: HTMLElement) {\n attempt(source, true)\n }\n\n /*\n * TRAP — the browser REFUSES to open a popover while it is in the middle of another\n * popover operation, and it throws rather than queueing the request\n * (\"Invalid to show a popover during another show operation\").\n *\n * The case that reaches it is ordinary: closing a popover that holds the focus hands\n * that focus back to its invoker SYNCHRONOUSLY, inside the hide, and a component\n * listening for that focus opens a panel of its own from the handler — a tooltip on the\n * button a menu has just closed. Nothing in the calling code can see it coming.\n *\n * A microtask runs once the stack has unwound, hence after the operation the browser was\n * in, which is all it takes. A second refusal is left alone: the panel stays closed\n * rather than the page taking an uncaught error.\n */\n function attempt(source: HTMLElement | undefined, retry: boolean) {\n const panel = el.value as PopoverWithSource | null\n if (!panel || shown.value) return\n try {\n panel.showPopover(source ? { source } : undefined)\n } catch {\n // TRAP — a close asked for before the microtask runs must win: the retry checks\n // that no `hide` came in between, or it would reopen a panel just closed.\n const asked = generation\n if (retry) queueMicrotask(() => asked === generation && attempt(source, false))\n }\n }\n\n /** Bumped by every close, so a retry queued before it knows it was overtaken. */\n let generation = 0\n\n /** Closes the panel. */\n function hide() {\n generation += 1\n if (shown.value) el.value?.hidePopover()\n }\n\n return { shown, syncShown, show, hide }\n}\n\n// @core\n/**\n * The model half of a popover's `v-model:open`, for a component that publishes its open\n * state: a change to the model opens or closes the panel. The other half: writing the\n * DOM's state back into the model, stays with the component, in its own toggle handler,\n * because that is where it knows the state has settled.\n *\n * `shown` is a getter so that the state may live in a child: VPopover reads its own\n * `usePopover`, VMenu reads the one VMenuPanel exposes.\n *\n * TRAP: the `value === shown()` guard is what keeps the two directions from chasing each\n * other. A panel the browser has just dismissed writes `false` into the model; without the\n * guard that write would come back here as a request to close a panel already closed.\n */\nexport function usePopoverModel(\n open: Ref<boolean>,\n shown: () => boolean,\n show: () => void,\n hide: () => void,\n) {\n watch(open, (value) => {\n if (value === shown()) return\n if (value) show()\n else hide()\n })\n\n // @ssr\n // A watcher does not run during the server render, so a panel asked to be open\n // from the start would never be told to open. Replaying the initial state on mount is\n // what covers that case.\n onMounted(() => {\n if (open.value) show()\n })\n}\n"],"mappings":";;AAwBA,SAAgB,EAAW,GAAuC;CAChE,IAAM,IAAQ,EAAI,EAAK;CAMvB,SAAS,EAAU,GAAc;EAC/B,EAAM,QAAS,EAAsB,aAAa;CACpD;CAUA,SAAS,EAAK,GAAsB;EAClC,EAAQ,GAAQ,EAAI;CACtB;CAgBA,SAAS,EAAQ,GAAiC,GAAgB;EAChE,IAAM,IAAQ,EAAG;EACb,OAAC,KAAS,EAAM,QACpB,IAAI;GACF,EAAM,YAAY,IAAS,EAAE,UAAO,IAAI,KAAA,CAAS;EACnD,QAAQ;GAGN,IAAM,IAAQ;GACd,AAAI,KAAO,qBAAqB,MAAU,KAAc,EAAQ,GAAQ,EAAK,CAAC;EAChF;CACF;CAGA,IAAI,IAAa;CAGjB,SAAS,IAAO;EAEd,AADA,KAAc,GACV,EAAM,SAAO,EAAG,OAAO,YAAY;CACzC;CAEA,OAAO;EAAE;EAAO;EAAW;EAAM;CAAK;AACxC;AAgBA,SAAgB,EACd,GACA,GACA,GACA,GACA;CAWA,AAVA,EAAM,IAAO,MAAU;EACjB,MAAU,EAAM,MAChB,IAAO,EAAK,IACX,EAAK;CACZ,CAAC,GAMD,QAAgB;EACd,AAAI,EAAK,SAAO,EAAK;CACvB,CAAC;AACH"}
1
+ {"version":3,"file":"usePopover.js","names":[],"sources":["../../src/composables/usePopover.ts"],"sourcesContent":["// @core\n/**\n * Read open state from the element and update the model from native toggle events. Assigning a\n * separate shown flag would miss browser dismissal.\n */\n\nimport { onMounted, ref, watch, type Ref } from 'vue'\n\n// @fallback\n// The option below is newer than the type definitions shipped with TypeScript, so the\n// element is described locally rather than being cast about at each call site.\ntype PopoverWithSource = HTMLElement & { showPopover(options?: { source?: HTMLElement }): void }\n\nexport function usePopover(el: Readonly<Ref<HTMLElement | null>>) {\n const shown = ref(false)\n\n /**\n * Reads the state back off the panel. Bind it to both `@beforetoggle` and `@toggle`, and\n * on the popover element itself: ToggleEvents do not bubble.\n */\n function syncShown(event: Event) {\n shown.value = (event as ToggleEvent).newState === 'open'\n }\n\n /**\n * Opening from code rather than from a click must name the invoker as `source`. That is what\n * recreates the relationship a click would have: the implicit anchor and the panel's place in\n * the popover stack.\n */\n function show(source?: HTMLElement) {\n attempt(source, true)\n }\n\n /*\n * Retry after the current popover operation: synchronous focus restoration can request\n * another popover while the browser is still hiding the first.\n */\n function attempt(source: HTMLElement | undefined, retry: boolean) {\n const panel = el.value as PopoverWithSource | null\n if (!panel || shown.value) return\n try {\n panel.showPopover(source ? { source } : undefined)\n } catch {\n // A close asked for before the microtask runs must win: the retry checks that no `hide`\n // came in between, or it would reopen a panel just closed.\n const asked = generation\n if (retry) queueMicrotask(() => asked === generation && attempt(source, false))\n }\n }\n\n /** Bumped by every close, so a retry queued before it knows it was overtaken. */\n let generation = 0\n\n /** Closes the panel. */\n function hide() {\n generation += 1\n if (shown.value) el.value?.hidePopover()\n }\n\n return { shown, syncShown, show, hide }\n}\n\n// @core\n/**\n * The `value === shown()` guard is what keeps the two directions from chasing each other. A\n * panel the browser has just dismissed writes `false` into the model; without the guard that\n * write would come back here as a request to close a panel already closed.\n */\nexport function usePopoverModel(\n open: Ref<boolean>,\n shown: () => boolean,\n show: () => void,\n hide: () => void,\n) {\n watch(open, (value) => {\n if (value === shown()) return\n if (value) show()\n else hide()\n })\n\n // @ssr\n // A watcher does not run during the server render, so a panel asked to be open\n // from the start would never be told to open. Replaying the initial state on mount is\n // what covers that case.\n onMounted(() => {\n if (open.value) show()\n })\n}\n"],"mappings":";;AAaA,SAAgB,EAAW,GAAuC;CAChE,IAAM,IAAQ,EAAI,EAAK;CAMvB,SAAS,EAAU,GAAc;EAC/B,EAAM,QAAS,EAAsB,aAAa;CACpD;CAOA,SAAS,EAAK,GAAsB;EAClC,EAAQ,GAAQ,EAAI;CACtB;CAMA,SAAS,EAAQ,GAAiC,GAAgB;EAChE,IAAM,IAAQ,EAAG;EACb,OAAC,KAAS,EAAM,QACpB,IAAI;GACF,EAAM,YAAY,IAAS,EAAE,UAAO,IAAI,KAAA,CAAS;EACnD,QAAQ;GAGN,IAAM,IAAQ;GACd,AAAI,KAAO,qBAAqB,MAAU,KAAc,EAAQ,GAAQ,EAAK,CAAC;EAChF;CACF;CAGA,IAAI,IAAa;CAGjB,SAAS,IAAO;EAEd,AADA,KAAc,GACV,EAAM,SAAO,EAAG,OAAO,YAAY;CACzC;CAEA,OAAO;EAAE;EAAO;EAAW;EAAM;CAAK;AACxC;AAQA,SAAgB,EACd,GACA,GACA,GACA,GACA;CAWA,AAVA,EAAM,IAAO,MAAU;EACjB,MAAU,EAAM,MAChB,IAAO,EAAK,IACX,EAAK;CACZ,CAAC,GAMD,QAAgB;EACd,AAAI,EAAK,SAAO,EAAK;CACvB,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"useProgressValue.js","names":[],"sources":["../../src/composables/useProgressValue.ts"],"sourcesContent":["// @core\n/**\n * A progress value normalized for VProgressLinear and VProgressCircular: the bound brought\n * back to zero or above, the value clamped into range, and its position in that range as a\n * 0-to-1 fraction and as a percentage. Everything either component draws comes from those —\n * the fill, the arc, the percentage written inside, the ARIA values.\n *\n * The bound is returned rather than left for each component to read off its prop: the value\n * is clamped against the NORMALIZED bound, so announcing the raw one would give assistive\n * technology a `aria-valuenow` above an `aria-valuemax` of -5.\n */\n\nimport { computed, type ComputedRef } from 'vue'\nimport { clamp } from '../utils/number'\n\nexport function useProgressValue(\n value: () => number,\n max: () => number,\n): {\n max: ComputedRef<number>\n clamped: ComputedRef<number>\n fraction: ComputedRef<number>\n /** The fraction as a percentage, unrounded: what the default slot receives. */\n percent: ComputedRef<number>\n /** The percentage rounded to a whole number: what the component writes by default. */\n roundedPercent: ComputedRef<number>\n} {\n /* A value computed by the consumer (`loaded / total * 100` before `total` is known) can\n be NaN, which `clamp` and `Math.max` both hand back unchanged: it would reach\n `aria-valuenow` and the text as the word \"NaN\". A value that is not a number is read as\n no progress, and a bound that is not a finite number as the default of 100. */\n const normalizedMax = computed(() => {\n const bound = max()\n return Number.isFinite(bound) ? Math.max(bound, 0) : 100\n })\n const clamped = computed(() => {\n const current = value()\n return Number.isNaN(current) ? 0 : clamp(current, 0, normalizedMax.value)\n })\n\n // The `|| 1` denominator is what keeps a max of 0 from dividing by nothing.\n const fraction = computed(() => clamped.value / (normalizedMax.value || 1))\n const percent = computed(() => fraction.value * 100)\n /* Rounded to the nearest whole number, except at the two ends: \"100%\" is written only\n once the work is complete and \"0%\" only while nothing has been done, so 99.6 reads 99%\n and 0.4 reads 1%. A plain round would announce a finished task that is still running. */\n const roundedPercent = computed(() => {\n const p = percent.value\n return p <= 0 || p >= 100 ? Math.round(p) : clamp(Math.round(p), 1, 99)\n })\n\n return { max: normalizedMax, clamped, fraction, percent, roundedPercent }\n}\n"],"mappings":";;;AAeA,SAAgB,EACd,GACA,GASA;CAKA,IAAM,IAAgB,QAAe;EACnC,IAAM,IAAQ,EAAI;EAClB,OAAO,OAAO,SAAS,CAAK,IAAI,KAAK,IAAI,GAAO,CAAC,IAAI;CACvD,CAAC,GACK,IAAU,QAAe;EAC7B,IAAM,IAAU,EAAM;EACtB,OAAO,OAAO,MAAM,CAAO,IAAI,IAAI,EAAM,GAAS,GAAG,EAAc,KAAK;CAC1E,CAAC,GAGK,IAAW,QAAe,EAAQ,SAAS,EAAc,SAAS,EAAE,GACpE,IAAU,QAAe,EAAS,QAAQ,GAAG;CASnD,OAAO;EAAE,KAAK;EAAe;EAAS;EAAU;EAAS,gBALlC,QAAe;GACpC,IAAM,IAAI,EAAQ;GAClB,OAAO,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM,CAAC,IAAI,EAAM,KAAK,MAAM,CAAC,GAAG,GAAG,EAAE;EACxE,CAEyD;CAAe;AAC1E"}
1
+ {"version":3,"file":"useProgressValue.js","names":[],"sources":["../../src/composables/useProgressValue.ts"],"sourcesContent":["// @core\n/**\n * Normalize finite bounds and values once so CSS, slot text and progressbar ARIA all describe\n * the same range.\n */\n\nimport { computed, type ComputedRef } from 'vue'\nimport { clamp } from '../utils/number'\n\nexport function useProgressValue(\n value: () => number,\n max: () => number,\n): {\n max: ComputedRef<number>\n clamped: ComputedRef<number>\n fraction: ComputedRef<number>\n /** The fraction as a percentage, unrounded: what the default slot receives. */\n percent: ComputedRef<number>\n /** The percentage rounded to a whole number: what the component writes by default. */\n roundedPercent: ComputedRef<number>\n} {\n /* A value computed by the consumer (`loaded / total * 100` before `total` is known) can\n be NaN, which `clamp` and `Math.max` both hand back unchanged: it would reach\n `aria-valuenow` and the text as the word \"NaN\". A value that is not a number is read as\n no progress, and a bound that is not a finite number as the default of 100. */\n const normalizedMax = computed(() => {\n const bound = max()\n return Number.isFinite(bound) ? Math.max(bound, 0) : 100\n })\n const clamped = computed(() => {\n const current = value()\n return Number.isNaN(current) ? 0 : clamp(current, 0, normalizedMax.value)\n })\n\n const fraction = computed(() => clamped.value / (normalizedMax.value || 1))\n const percent = computed(() => fraction.value * 100)\n /* Rounded to the nearest whole number, except at the two ends: \"100%\" is written only\n once the work is complete and \"0%\" only while nothing has been done, so 99.6 reads 99%\n and 0.4 reads 1%. A plain round would announce a finished task that is still running. */\n const roundedPercent = computed(() => {\n const p = percent.value\n return p <= 0 || p >= 100 ? Math.round(p) : clamp(Math.round(p), 1, 99)\n })\n\n return { max: normalizedMax, clamped, fraction, percent, roundedPercent }\n}\n"],"mappings":";;;AASA,SAAgB,EACd,GACA,GASA;CAKA,IAAM,IAAgB,QAAe;EACnC,IAAM,IAAQ,EAAI;EAClB,OAAO,OAAO,SAAS,CAAK,IAAI,KAAK,IAAI,GAAO,CAAC,IAAI;CACvD,CAAC,GACK,IAAU,QAAe;EAC7B,IAAM,IAAU,EAAM;EACtB,OAAO,OAAO,MAAM,CAAO,IAAI,IAAI,EAAM,GAAS,GAAG,EAAc,KAAK;CAC1E,CAAC,GAEK,IAAW,QAAe,EAAQ,SAAS,EAAc,SAAS,EAAE,GACpE,IAAU,QAAe,EAAS,QAAQ,GAAG;CASnD,OAAO;EAAE,KAAK;EAAe;EAAS;EAAU;EAAS,gBALlC,QAAe;GACpC,IAAM,IAAI,EAAQ;GAClB,OAAO,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM,CAAC,IAAI,EAAM,KAAK,MAAM,CAAC,GAAG,GAAG,EAAE;EACxE,CAEyD;CAAe;AAC1E"}
@@ -8,15 +8,6 @@ type ClassBinding = false | null | undefined | string | Record<string, unknown>
8
8
  * The attribute split of the wrapper-root pattern, for components whose root is only a
9
9
  * container: VInput, VTextarea, VTabs, VCombobox, VDataTable, VDateInput, VTimeInput, VSlider,
10
10
  * and the three choice controls, whose root holds the <label> and its hint.
11
- *
12
- * `class`/`style` stay on the root, which is the box the consumer positions; everything
13
- * else is forwarded to the functional element. Unsplit, `name`, `required` and every
14
- * `aria-*` land on a decorative wrapper, where the form ignores them and assistive
15
- * technology never finds them.
16
- *
17
- * `defineOptions({ inheritAttrs: false })` stays in the SFC: it is a compilation option.
18
- * `attrs` is returned whole for the components that need to read one back: a consumer `id`
19
- * that must beat the generated one, a `describedby` to merge rather than replace.
20
11
  */
21
12
  export declare function useRootAttrs(): {
22
13
  attrs: Record<string, unknown>;
@@ -1,12 +1,19 @@
1
1
  import { computed as e, useAttrs as t } from "vue";
2
2
  //#region src/composables/useRootAttrs.ts
3
3
  function n() {
4
- let n = t();
4
+ let n = t(), r = e(() => {
5
+ let { class: e, style: t, ...r } = n;
6
+ return {
7
+ rootClass: e,
8
+ rootStyle: t,
9
+ forwardedAttrs: r
10
+ };
11
+ });
5
12
  return {
6
13
  attrs: n,
7
- rootClass: e(() => n.class),
8
- rootStyle: e(() => n.style),
9
- forwardedAttrs: e(() => Object.fromEntries(Object.entries(n).filter(([e]) => e !== "class" && e !== "style")))
14
+ rootClass: e(() => r.value.rootClass),
15
+ rootStyle: e(() => r.value.rootStyle),
16
+ forwardedAttrs: e(() => r.value.forwardedAttrs)
10
17
  };
11
18
  }
12
19
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"useRootAttrs.js","names":[],"sources":["../../src/composables/useRootAttrs.ts"],"sourcesContent":["import { computed, useAttrs, type ComputedRef, type StyleValue } from 'vue'\n\n/**\n * Redeclared locally: `@vue/runtime-dom` exports this as `ClassValue` and the `vue` package\n * does not re-export it. Typed `unknown` instead, a template refuses to bind it.\n */\ntype ClassBinding = false | null | undefined | string | Record<string, unknown> | ClassBinding[]\n\n// @a11y\n/**\n * The attribute split of the wrapper-root pattern, for components whose root is only a\n * container: VInput, VTextarea, VTabs, VCombobox, VDataTable, VDateInput, VTimeInput, VSlider,\n * and the three choice controls, whose root holds the <label> and its hint.\n *\n * `class`/`style` stay on the root, which is the box the consumer positions; everything\n * else is forwarded to the functional element. Unsplit, `name`, `required` and every\n * `aria-*` land on a decorative wrapper, where the form ignores them and assistive\n * technology never finds them.\n *\n * `defineOptions({ inheritAttrs: false })` stays in the SFC: it is a compilation option.\n * `attrs` is returned whole for the components that need to read one back: a consumer `id`\n * that must beat the generated one, a `describedby` to merge rather than replace.\n */\nexport function useRootAttrs(): {\n attrs: Record<string, unknown>\n rootClass: ComputedRef<ClassBinding>\n rootStyle: ComputedRef<StyleValue>\n forwardedAttrs: ComputedRef<Record<string, unknown>>\n} {\n const attrs = useAttrs()\n\n return {\n attrs,\n rootClass: computed(() => attrs.class as ClassBinding),\n rootStyle: computed(() => attrs.style as StyleValue),\n forwardedAttrs: computed(() =>\n Object.fromEntries(\n Object.entries(attrs).filter(([key]) => key !== 'class' && key !== 'style'),\n ),\n ),\n }\n}\n"],"mappings":";;AAuBA,SAAgB,IAKd;CACA,IAAM,IAAQ,EAAS;CAEvB,OAAO;EACL;EACA,WAAW,QAAe,EAAM,KAAqB;EACrD,WAAW,QAAe,EAAM,KAAmB;EACnD,gBAAgB,QACd,OAAO,YACL,OAAO,QAAQ,CAAK,CAAC,CAAC,QAAQ,CAAC,OAAS,MAAQ,WAAW,MAAQ,OAAO,CAC5E,CACF;CACF;AACF"}
1
+ {"version":3,"file":"useRootAttrs.js","names":[],"sources":["../../src/composables/useRootAttrs.ts"],"sourcesContent":["import { computed, useAttrs, type ComputedRef, type StyleValue } from 'vue'\n\n/**\n * Redeclared locally: `@vue/runtime-dom` exports this as `ClassValue` and the `vue` package\n * does not re-export it. Typed `unknown` instead, a template refuses to bind it.\n */\ntype ClassBinding = false | null | undefined | string | Record<string, unknown> | ClassBinding[]\n\n// @a11y\n/**\n * The attribute split of the wrapper-root pattern, for components whose root is only a\n * container: VInput, VTextarea, VTabs, VCombobox, VDataTable, VDateInput, VTimeInput, VSlider,\n * and the three choice controls, whose root holds the <label> and its hint.\n */\nexport function useRootAttrs(): {\n attrs: Record<string, unknown>\n rootClass: ComputedRef<ClassBinding>\n rootStyle: ComputedRef<StyleValue>\n forwardedAttrs: ComputedRef<Record<string, unknown>>\n} {\n const attrs = useAttrs()\n // Read the styling keys even when absent: enumerating an empty attrs object tracks no reads.\n const split = computed(() => {\n const { class: rootClass, style: rootStyle, ...forwardedAttrs } = attrs\n return { rootClass, rootStyle, forwardedAttrs }\n })\n\n return {\n attrs,\n rootClass: computed(() => split.value.rootClass as ClassBinding),\n rootStyle: computed(() => split.value.rootStyle as StyleValue),\n forwardedAttrs: computed(() => split.value.forwardedAttrs),\n }\n}\n"],"mappings":";;AAcA,SAAgB,IAKd;CACA,IAAM,IAAQ,EAAS,GAEjB,IAAQ,QAAe;EAC3B,IAAM,EAAE,OAAO,GAAW,OAAO,GAAW,GAAG,MAAmB;EAClE,OAAO;GAAE;GAAW;GAAW;EAAe;CAChD,CAAC;CAED,OAAO;EACL;EACA,WAAW,QAAe,EAAM,MAAM,SAAyB;EAC/D,WAAW,QAAe,EAAM,MAAM,SAAuB;EAC7D,gBAAgB,QAAe,EAAM,MAAM,cAAc;CAC3D;AACF"}
@@ -1,18 +1,7 @@
1
1
  import { ComputedRef, VNode } from 'vue';
2
2
  /**
3
- * The VNodes a slot renders, flattened by `flattenSlot`, for a component that has to KNOW
4
- * its children (how many, which kind) rather than merely render them. Reading the slot
5
- * instead of keeping a registry the children feed at mount is what keeps the server and
6
- * the client in agreement.
7
- *
8
- * TRAP: a bare `computed(() => flattenSlot(slots.default?.()))` goes stale. `slots` is not
9
- * reactive: the computed only tracks what the slot READS while it runs, so a parent handing
10
- * down a NEW slot function leaves it cached. That is the case of a render function whose
11
- * slot captures a local, of a `v-for` whose array is replaced wholesale, and of a `v-if`
12
- * between two slot templates: the old children stay on screen with no warning. The tick
13
- * below is bumped before every re-render of the component, which is exactly when a new slot
14
- * can have arrived, so the read is redone then; computeds derived from it keep their cache
15
- * as long as their own value does not change. Bumping it there schedules nothing: Vue does
16
- * not let an update re-queue itself while it runs.
3
+ * A bare `computed(() => flattenSlot(slots.default?.()))` goes stale. `slots` is not reactive:
4
+ * the computed only tracks what the slot READS while it runs, so a parent handing down a NEW
5
+ * slot function leaves it cached.
17
6
  */
18
7
  export declare function useSlotNodes(name?: string): ComputedRef<VNode[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"useSlotNodes.js","names":[],"sources":["../../src/composables/useSlotNodes.ts"],"sourcesContent":["import { computed, onBeforeUpdate, ref, useSlots, type ComputedRef, type VNode } from 'vue'\n\nimport { flattenSlot } from '../utils/vnode'\n\n// @ssr @core\n/**\n * The VNodes a slot renders, flattened by `flattenSlot`, for a component that has to KNOW\n * its children (how many, which kind) rather than merely render them. Reading the slot\n * instead of keeping a registry the children feed at mount is what keeps the server and\n * the client in agreement.\n *\n * TRAP: a bare `computed(() => flattenSlot(slots.default?.()))` goes stale. `slots` is not\n * reactive: the computed only tracks what the slot READS while it runs, so a parent handing\n * down a NEW slot function leaves it cached. That is the case of a render function whose\n * slot captures a local, of a `v-for` whose array is replaced wholesale, and of a `v-if`\n * between two slot templates: the old children stay on screen with no warning. The tick\n * below is bumped before every re-render of the component, which is exactly when a new slot\n * can have arrived, so the read is redone then; computeds derived from it keep their cache\n * as long as their own value does not change. Bumping it there schedules nothing: Vue does\n * not let an update re-queue itself while it runs.\n */\nexport function useSlotNodes(name = 'default'): ComputedRef<VNode[]> {\n const slots = useSlots()\n const tick = ref(0)\n onBeforeUpdate(() => {\n tick.value++\n })\n return computed(() => {\n void tick.value\n return flattenSlot(slots[name]?.())\n })\n}\n"],"mappings":";;;AAqBA,SAAgB,EAAa,IAAO,WAAiC;CACnE,IAAM,IAAQ,EAAS,GACjB,IAAO,EAAI,CAAC;CAIlB,OAHA,QAAqB;EACnB,EAAK;CACP,CAAC,GACM,SACL,EAAU,OACH,EAAY,EAAM,EAAK,GAAG,CAAC,EACnC;AACH"}
1
+ {"version":3,"file":"useSlotNodes.js","names":[],"sources":["../../src/composables/useSlotNodes.ts"],"sourcesContent":["import { computed, onBeforeUpdate, ref, useSlots, type ComputedRef, type VNode } from 'vue'\n\nimport { flattenSlot } from '../utils/vnode'\n\n// @ssr @core\n/**\n * A bare `computed(() => flattenSlot(slots.default?.()))` goes stale. `slots` is not reactive:\n * the computed only tracks what the slot READS while it runs, so a parent handing down a NEW\n * slot function leaves it cached.\n */\nexport function useSlotNodes(name = 'default'): ComputedRef<VNode[]> {\n const slots = useSlots()\n const tick = ref(0)\n onBeforeUpdate(() => {\n tick.value++\n })\n return computed(() => {\n void tick.value\n return flattenSlot(slots[name]?.())\n })\n}\n"],"mappings":";;;AAUA,SAAgB,EAAa,IAAO,WAAiC;CACnE,IAAM,IAAQ,EAAS,GACjB,IAAO,EAAI,CAAC;CAIlB,OAHA,QAAqB;EACnB,EAAK;CACP,CAAC,GACM,SACL,EAAU,OACH,EAAY,EAAM,EAAK,GAAG,CAAC,EACnC;AACH"}
@@ -1,24 +1,12 @@
1
1
  import { ComputedRef, Ref } from 'vue';
2
- /** The least this needs of the real control — the two kinds of field both offer it. */
2
+ /** The least this needs of the real control; the two kinds of field both offer it. */
3
3
  interface ValidatableControl {
4
4
  setCustomValidity: (message: string) => void;
5
5
  }
6
6
  /**
7
- * How much has been typed against how much is allowed: the "12/80" counter under a
8
- * field, whether the allowance has been passed, and the SOFT limit.
9
- *
10
- * A soft limit lets the reader keep typing past the allowance and puts the field in
11
- * error instead of cutting them off mid-word. That error is declared to the BROWSER
12
- * rather than invented here, and three things follow from it for free: the field only
13
- * turns red once the reader has actually interacted with it, exactly as a native error
14
- * does; the form refuses to submit; and anyone inspecting the field finds the error where
15
- * they would look for any other. The price is that the component then owns that error
16
- * for as long as it is standing, and only then. A message the consumer set (a server
17
- * verdict) is left alone whenever the soft limit has nothing to say.
18
- *
19
- * The effect runs AFTER the render rather than before it, because the reference to the
20
- * real element is not filled in yet at the earlier point. It does nothing at all during a
21
- * server render, where there is no element to speak to.
7
+ * How much has been typed against how much is allowed: the "12/80" counter under a field,
8
+ * whether the allowance has been passed, and the SOFT limit. A soft limit lets the reader keep
9
+ * typing past the allowance and puts the field in error instead of cutting them off mid-word.
22
10
  */
23
11
  export declare function useTextLimit(options: {
24
12
  el: Ref<ValidatableControl | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"useTextLimit.js","names":[],"sources":["../../src/composables/useTextLimit.ts"],"sourcesContent":["import { computed, watchEffect, type ComputedRef, type Ref } from 'vue'\n\nimport { useMessages } from '../i18n/state'\n\n/** The least this needs of the real control — the two kinds of field both offer it. */\ninterface ValidatableControl {\n setCustomValidity: (message: string) => void\n}\n\n// @core\n/**\n * How much has been typed against how much is allowed: the \"12/80\" counter under a\n * field, whether the allowance has been passed, and the SOFT limit.\n *\n * A soft limit lets the reader keep typing past the allowance and puts the field in\n * error instead of cutting them off mid-word. That error is declared to the BROWSER\n * rather than invented here, and three things follow from it for free: the field only\n * turns red once the reader has actually interacted with it, exactly as a native error\n * does; the form refuses to submit; and anyone inspecting the field finds the error where\n * they would look for any other. The price is that the component then owns that error\n * for as long as it is standing, and only then. A message the consumer set (a server\n * verdict) is left alone whenever the soft limit has nothing to say.\n *\n * The effect runs AFTER the render rather than before it, because the reference to the\n * real element is not filled in yet at the earlier point. It does nothing at all during a\n * server render, where there is no element to speak to.\n */\nexport function useTextLimit(options: {\n el: Ref<ValidatableControl | null>\n text: () => string\n maxlength: () => number | undefined\n softLimit: () => boolean\n}): { counterText: ComputedRef<string>; over: ComputedRef<boolean> } {\n const length = computed(() => options.text().length)\n const max = computed(() => options.maxlength())\n const m = useMessages()\n\n // Whether the message on the element is ours. Without it the effect would clear the\n // validity on every re-run, erasing a consumer's own `setCustomValidity` the moment an\n // unrelated prop such as `maxlength` changed, and letting the form submit.\n let owned = false\n\n // The dictionary is read INSIDE the effect, which is what makes the error message\n // rewrite itself when the language is changed after the component is on screen. The\n // branches are spelled out rather than written as a ternary so that TypeScript can\n // narrow the limit to a number.\n watchEffect(\n () => {\n const el = options.el.value\n if (!el) return\n const limit = max.value\n if (options.softLimit() && limit != null && length.value > limit) {\n el.setCustomValidity(m.value.field.limitExceeded(limit))\n owned = true\n } else if (owned) {\n el.setCustomValidity('')\n owned = false\n }\n },\n { flush: 'post' },\n )\n\n return {\n counterText: computed(() =>\n max.value != null ? `${length.value}/${max.value}` : `${length.value}`,\n ),\n over: computed(() => max.value != null && length.value > max.value),\n }\n}\n"],"mappings":";;;AA2BA,SAAgB,EAAa,GAKwC;CACnE,IAAM,IAAS,QAAe,EAAQ,KAAK,CAAC,CAAC,MAAM,GAC7C,IAAM,QAAe,EAAQ,UAAU,CAAC,GACxC,IAAI,EAAY,GAKlB,IAAQ;CAsBZ,OAhBA,QACQ;EACJ,IAAM,IAAK,EAAQ,GAAG;EACtB,IAAI,CAAC,GAAI;EACT,IAAM,IAAQ,EAAI;EAClB,AAAI,EAAQ,UAAU,KAAK,KAAS,QAAQ,EAAO,QAAQ,KACzD,EAAG,kBAAkB,EAAE,MAAM,MAAM,cAAc,CAAK,CAAC,GACvD,IAAQ,MACH,AAEL,OADA,EAAG,kBAAkB,EAAE,GACf;CAEZ,GACA,EAAE,OAAO,OAAO,CAClB,GAEO;EACL,aAAa,QACX,EAAI,SAAS,OAAwC,GAAG,EAAO,UAA3C,GAAG,EAAO,MAAM,GAAG,EAAI,OAC7C;EACA,MAAM,QAAe,EAAI,SAAS,QAAQ,EAAO,QAAQ,EAAI,KAAK;CACpE;AACF"}
1
+ {"version":3,"file":"useTextLimit.js","names":[],"sources":["../../src/composables/useTextLimit.ts"],"sourcesContent":["import { computed, watchEffect, type ComputedRef, type Ref } from 'vue'\n\nimport { useMessages } from '../i18n/state'\n\n/** The least this needs of the real control; the two kinds of field both offer it. */\ninterface ValidatableControl {\n setCustomValidity: (message: string) => void\n}\n\n// @core\n/**\n * How much has been typed against how much is allowed: the \"12/80\" counter under a field,\n * whether the allowance has been passed, and the SOFT limit. A soft limit lets the reader keep\n * typing past the allowance and puts the field in error instead of cutting them off mid-word.\n */\nexport function useTextLimit(options: {\n el: Ref<ValidatableControl | null>\n text: () => string\n maxlength: () => number | undefined\n softLimit: () => boolean\n}): { counterText: ComputedRef<string>; over: ComputedRef<boolean> } {\n const length = computed(() => options.text().length)\n const max = computed(() => options.maxlength())\n const m = useMessages()\n\n // Without it the effect would clear the validity on every re-run, erasing a consumer's own\n // `setCustomValidity` the moment an unrelated prop such as `maxlength` changed, and letting\n // the form submit.\n let owned = false\n\n // The dictionary is read INSIDE the effect, which makes the error message rewrite itself when\n // the language is changed after the component is on screen. The branches are spelled out\n // rather than written as a ternary so that TypeScript can narrow the limit to a number.\n watchEffect(\n () => {\n const el = options.el.value\n if (!el) return\n const limit = max.value\n if (options.softLimit() && limit != null && length.value > limit) {\n el.setCustomValidity(m.value.field.limitExceeded(limit))\n owned = true\n } else if (owned) {\n el.setCustomValidity('')\n owned = false\n }\n },\n { flush: 'post' },\n )\n\n return {\n counterText: computed(() =>\n max.value != null ? `${length.value}/${max.value}` : `${length.value}`,\n ),\n over: computed(() => max.value != null && length.value > max.value),\n }\n}\n"],"mappings":";;;AAeA,SAAgB,EAAa,GAKwC;CACnE,IAAM,IAAS,QAAe,EAAQ,KAAK,CAAC,CAAC,MAAM,GAC7C,IAAM,QAAe,EAAQ,UAAU,CAAC,GACxC,IAAI,EAAY,GAKlB,IAAQ;CAqBZ,OAhBA,QACQ;EACJ,IAAM,IAAK,EAAQ,GAAG;EACtB,IAAI,CAAC,GAAI;EACT,IAAM,IAAQ,EAAI;EAClB,AAAI,EAAQ,UAAU,KAAK,KAAS,QAAQ,EAAO,QAAQ,KACzD,EAAG,kBAAkB,EAAE,MAAM,MAAM,cAAc,CAAK,CAAC,GACvD,IAAQ,MACH,AAEL,OADA,EAAG,kBAAkB,EAAE,GACf;CAEZ,GACA,EAAE,OAAO,OAAO,CAClB,GAEO;EACL,aAAa,QACX,EAAI,SAAS,OAAwC,GAAG,EAAO,UAA3C,GAAG,EAAO,MAAM,GAAG,EAAI,OAC7C;EACA,MAAM,QAAe,EAAI,SAAS,QAAQ,EAAO,QAAQ,EAAI,KAAK;CACpE;AACF"}
@@ -1,19 +1,6 @@
1
1
  /**
2
- * A re-armable delay, cancelled on unmount.
3
- *
4
- * `start` always cancels the pending one, or a tooltip armed twice opens, closes and opens
5
- * again. The handle is a plain variable: nothing renders it, and making it reactive would
6
- * cost renders for nothing.
7
- *
8
- * TRAP — a delay of 0 runs the callback SYNCHRONOUSLY, where `setTimeout(fn, 0)` would not.
9
- * The library's convention is that zero disarms the deferral, which is what makes a debounce
10
- * of 0 immediate. Callers for whom 0 means "never" (VSnackbar's duration, VCarousel's
11
- * autoplay) must guard before calling, or the callback fires in the tick that armed it.
12
- *
13
- * Inside `<KeepAlive>` a component is deactivated rather than unmounted: a pending delay is
14
- * held while it is away and armed again, in full, when it comes back. Cancelled on unmount
15
- * alone, it went on firing off screen, and a carousel kept turning on a page the reader had
16
- * left.
2
+ * One cancellable timeout. Nonpositive delays invoke the callback synchronously, so
3
+ * self-rearming consumers must guard against zero-delay recursion.
17
4
  */
18
5
  export declare function useTimer(): {
19
6
  start: (fn: () => void, delay: number) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"useTimer.js","names":[],"sources":["../../src/composables/useTimer.ts"],"sourcesContent":["// @core\n/**\n * A re-armable delay, cancelled on unmount.\n *\n * `start` always cancels the pending one, or a tooltip armed twice opens, closes and opens\n * again. The handle is a plain variable: nothing renders it, and making it reactive would\n * cost renders for nothing.\n *\n * TRAP — a delay of 0 runs the callback SYNCHRONOUSLY, where `setTimeout(fn, 0)` would not.\n * The library's convention is that zero disarms the deferral, which is what makes a debounce\n * of 0 immediate. Callers for whom 0 means \"never\" (VSnackbar's duration, VCarousel's\n * autoplay) must guard before calling, or the callback fires in the tick that armed it.\n *\n * Inside `<KeepAlive>` a component is deactivated rather than unmounted: a pending delay is\n * held while it is away and armed again, in full, when it comes back. Cancelled on unmount\n * alone, it went on firing off screen, and a carousel kept turning on a page the reader had\n * left.\n */\n\nimport { onActivated, onBeforeUnmount, onDeactivated } from 'vue'\n\nexport function useTimer(): { start: (fn: () => void, delay: number) => void; cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | undefined\n let armed: { fn: () => void; delay: number } | undefined\n let held: typeof armed\n\n function cancel() {\n clearTimeout(timer)\n timer = undefined\n armed = undefined\n held = undefined\n }\n\n function start(fn: () => void, delay: number) {\n cancel()\n if (delay <= 0) return fn()\n armed = { fn, delay }\n timer = setTimeout(() => {\n timer = undefined\n armed = undefined\n fn()\n }, delay)\n }\n\n onBeforeUnmount(cancel)\n onDeactivated(() => {\n const pending = armed\n cancel()\n held = pending\n })\n onActivated(() => {\n if (held) start(held.fn, held.delay)\n })\n\n return { start, cancel }\n}\n"],"mappings":";;AAqBA,SAAgB,IAAmF;CACjG,IAAI,GACA,GACA;CAEJ,SAAS,IAAS;EAIhB,AAHA,aAAa,CAAK,GAClB,IAAQ,KAAA,GACR,IAAQ,KAAA,GACR,IAAO,KAAA;CACT;CAEA,SAAS,EAAM,GAAgB,GAAe;EAE5C,IADA,EAAO,GACH,KAAS,GAAG,OAAO,EAAG;EAE1B,AADA,IAAQ;GAAE;GAAI;EAAM,GACpB,IAAQ,iBAAiB;GAGvB,AAFA,IAAQ,KAAA,GACR,IAAQ,KAAA,GACR,EAAG;EACL,GAAG,CAAK;CACV;CAYA,OAVA,EAAgB,CAAM,GACtB,QAAoB;EAClB,IAAM,IAAU;EAEhB,AADA,EAAO,GACP,IAAO;CACT,CAAC,GACD,QAAkB;EAChB,AAAI,KAAM,EAAM,EAAK,IAAI,EAAK,KAAK;CACrC,CAAC,GAEM;EAAE;EAAO;CAAO;AACzB"}
1
+ {"version":3,"file":"useTimer.js","names":[],"sources":["../../src/composables/useTimer.ts"],"sourcesContent":["// @core\n/**\n * One cancellable timeout. Nonpositive delays invoke the callback synchronously, so\n * self-rearming consumers must guard against zero-delay recursion.\n */\n\nimport { onActivated, onBeforeUnmount, onDeactivated } from 'vue'\n\nexport function useTimer(): { start: (fn: () => void, delay: number) => void; cancel: () => void } {\n let timer: ReturnType<typeof setTimeout> | undefined\n let armed: { fn: () => void; delay: number } | undefined\n let held: typeof armed\n\n function cancel() {\n clearTimeout(timer)\n timer = undefined\n armed = undefined\n held = undefined\n }\n\n function start(fn: () => void, delay: number) {\n cancel()\n if (delay <= 0) return fn()\n armed = { fn, delay }\n timer = setTimeout(() => {\n timer = undefined\n armed = undefined\n fn()\n }, delay)\n }\n\n onBeforeUnmount(cancel)\n onDeactivated(() => {\n const pending = armed\n cancel()\n held = pending\n })\n onActivated(() => {\n if (held) start(held.fn, held.delay)\n })\n\n return { start, cancel }\n}\n"],"mappings":";;AAQA,SAAgB,IAAmF;CACjG,IAAI,GACA,GACA;CAEJ,SAAS,IAAS;EAIhB,AAHA,aAAa,CAAK,GAClB,IAAQ,KAAA,GACR,IAAQ,KAAA,GACR,IAAO,KAAA;CACT;CAEA,SAAS,EAAM,GAAgB,GAAe;EAE5C,IADA,EAAO,GACH,KAAS,GAAG,OAAO,EAAG;EAE1B,AADA,IAAQ;GAAE;GAAI;EAAM,GACpB,IAAQ,iBAAiB;GAGvB,AAFA,IAAQ,KAAA,GACR,IAAQ,KAAA,GACR,EAAG;EACL,GAAG,CAAK;CACV;CAYA,OAVA,EAAgB,CAAM,GACtB,QAAoB;EAClB,IAAM,IAAU;EAEhB,AADA,EAAO,GACP,IAAO;CACT,CAAC,GACD,QAAkB;EAChB,AAAI,KAAM,EAAM,EAAK,IAAI,EAAK,KAAK;CACrC,CAAC,GAEM;EAAE;EAAO;CAAO;AACzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"en.js","names":[],"sources":["../../src/i18n/en.ts"],"sourcesContent":["/**\n * English, the dictionary always bundled. Any language without one of its own falls back\n * here entry by entry, so nothing is ever left unsaid.\n *\n * TRAP — these strings are asserted letter for letter by the unit tests, and the play\n * functions query controls BY them (they run with the default globals, so the locale there\n * is deterministically `en-US`). Changing a word means changing what expects it.\n */\n\nimport type { Messages } from './types'\n\nexport const en: Messages = {\n common: {\n loading: 'Loading…',\n clear: 'Clear',\n close: 'Close',\n dismiss: 'Remove',\n remove: (name) => `Remove ${name}`,\n cancel: 'Cancel',\n confirm: 'OK',\n },\n pagination: {\n label: 'Pagination',\n previous: 'Previous page',\n next: 'Next page',\n page: (page) => `Page ${page}`,\n },\n tabs: {\n label: 'Tabs',\n previous: 'Previous tabs',\n next: 'Next tabs',\n },\n breadcrumb: {\n label: 'Breadcrumb',\n ellipsis: 'Show intermediate pages',\n },\n sideNavigation: { label: 'Navigation' },\n combobox: {\n empty: 'No results',\n clear: 'Clear selection',\n },\n dataTable: {\n empty: 'No data',\n loading: 'Loading data…',\n searchLabel: 'Search the table',\n searchPlaceholder: 'Search…',\n perPage: 'Rows per page',\n perPageValue: (label, value) => `${label}: ${value}`,\n selectAll: 'Select all',\n selectRow: (index) => `Select row ${index}`,\n // The plural is chosen right here, in the message itself. That one line is the whole\n // of the design system's handling of plurals, and it is meant to be.\n selection: (count) => `${count} item${count === 1 ? '' : 's'} selected`,\n range: ({ start, end, total }) => `${start}–${end} of ${total}`,\n pagination: 'Table pagination',\n },\n toaster: { label: 'Notifications' },\n snackbar: { label: 'Confirmation', action: 'Undo' },\n inputOTP: {\n label: 'Verification code',\n slot: (index, total) => `Character ${index} of ${total}`,\n },\n slider: {\n value: 'Value',\n start: 'Start',\n end: 'End',\n rangeStart: (label) => `${label} (start)`,\n rangeEnd: (label) => `${label} (end)`,\n },\n field: {\n limitExceeded: (max) => `Exceeds the limit of ${max} characters`,\n },\n progress: { percent: (percent) => `${percent}%`, label: 'Progress' },\n hotkeys: {\n command: 'Command',\n ctrl: 'Ctrl',\n alt: 'Alt',\n shift: 'Shift',\n windows: 'Win',\n super: 'Super',\n enter: 'Enter',\n escape: 'Esc',\n space: 'Space',\n backspace: 'Backspace',\n delete: 'Del',\n tab: 'Tab',\n up: 'Up arrow',\n down: 'Down arrow',\n left: 'Left arrow',\n right: 'Right arrow',\n label: (keys) => `Keyboard shortcut: ${keys}`,\n },\n datePicker: {\n label: 'Date picker',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n previousYear: 'Previous year',\n nextYear: 'Next year',\n monthPicker: 'Choose month',\n yearPicker: 'Choose year',\n },\n dateInput: {\n clear: 'Clear date',\n openPicker: 'Open calendar',\n pickerLabel: 'Choose a date',\n },\n timePicker: {\n label: 'Time picker',\n meridiem: 'AM or PM',\n am: 'AM',\n pm: 'PM',\n selectHour: 'Select hour',\n selectMinutes: 'Select minutes',\n choosingHour: 'Selecting the hour',\n choosingMinutes: 'Selecting the minutes',\n hour: 'Hour',\n minutes: 'Minutes',\n hourValue: (hour) => `${hour} o'clock`,\n minutesValue: (minute) => (minute === 1 ? '1 minute' : `${minute} minutes`),\n },\n timeInput: {\n clear: 'Clear time',\n openPicker: 'Open time picker',\n pickerLabel: 'Choose a time',\n meridiemValue: (value) => `AM or PM: ${value}`,\n maskPlaceholder: 'hh:mm',\n unavailable: 'This time is not available.',\n },\n fileInput: {\n openPicker: 'Choose files',\n clear: 'Clear files',\n files: (count) => `${count} file${count === 1 ? '' : 's'}`,\n placeholder: 'No file selected',\n },\n filePicker: {\n browse: 'Browse files',\n or: 'or',\n list: 'Selected files',\n },\n carousel: {\n label: 'Carousel',\n roleDescription: 'carousel',\n slideRoleDescription: 'slide',\n slides: 'Slides',\n slide: (index, total) => `${index} of ${total}`,\n previous: 'Previous slide',\n next: 'Next slide',\n indicators: 'Choose slide to display',\n },\n calendar: {\n label: 'Calendar',\n roleDescription: 'calendar',\n today: 'Today',\n view: 'View',\n viewDay: 'Day',\n view4Days: '4 days',\n viewWeek: 'Week',\n viewMonth: 'Month',\n viewYear: 'Year',\n viewCustom: (days) => `${days} days`,\n previousDay: 'Previous day',\n nextDay: 'Next day',\n previousWeek: 'Previous week',\n nextWeek: 'Next week',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n previousYear: 'Previous year',\n nextYear: 'Next year',\n previousPeriod: 'Previous period',\n nextPeriod: 'Next period',\n allDay: 'All day',\n moreEvents: (count) => `+${count} more`,\n openDay: (day) => `Open ${day}`,\n untitled: '(No title)',\n eventRoleDescription: 'event',\n eventHint:\n 'Press Enter to open this event. Press Space to take hold of it, then the arrow keys to move it and Shift with the arrow keys to change when it ends.',\n grabbed:\n 'Event held. Use the arrow keys to move it, Enter or Space to place it, Escape to cancel.',\n dropped: 'Event placed.',\n reverted: 'Move cancelled. The event is back where it was.',\n movedTo: (title, when) => `${title} moved to ${when}.`,\n },\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"en.js","names":[],"sources":["../../src/i18n/en.ts"],"sourcesContent":["/**\n * English is the bundled fallback. Labels are also used by tests and play-function queries;\n * update those contracts when changing wording.\n */\n\nimport type { Messages } from './types'\n\nexport const en: Messages = {\n common: {\n loading: 'Loading…',\n clear: 'Clear',\n close: 'Close',\n dismiss: 'Remove',\n remove: (name) => `Remove ${name}`,\n cancel: 'Cancel',\n confirm: 'OK',\n },\n pagination: {\n label: 'Pagination',\n previous: 'Previous page',\n next: 'Next page',\n page: (page) => `Page ${page}`,\n },\n tabs: {\n label: 'Tabs',\n previous: 'Previous tabs',\n next: 'Next tabs',\n },\n breadcrumb: {\n label: 'Breadcrumb',\n ellipsis: 'Show intermediate pages',\n },\n sideNavigation: { label: 'Navigation' },\n combobox: {\n empty: 'No results',\n clear: 'Clear selection',\n },\n dataTable: {\n empty: 'No data',\n loading: 'Loading data…',\n searchLabel: 'Search the table',\n searchPlaceholder: 'Search…',\n perPage: 'Rows per page',\n perPageValue: (label, value) => `${label}: ${value}`,\n selectAll: 'Select all',\n selectRow: (index) => `Select row ${index}`,\n // The plural is chosen right here, in the message itself. That one line is the whole\n // of the design system's handling of plurals, and it is meant to be.\n selection: (count) => `${count} item${count === 1 ? '' : 's'} selected`,\n range: ({ start, end, total }) => `${start}–${end} of ${total}`,\n pagination: 'Table pagination',\n },\n toaster: { label: 'Notifications' },\n snackbar: { label: 'Confirmation', action: 'Undo' },\n inputOTP: {\n label: 'Verification code',\n slot: (index, total) => `Character ${index} of ${total}`,\n },\n slider: {\n value: 'Value',\n start: 'Start',\n end: 'End',\n rangeStart: (label) => `${label} (start)`,\n rangeEnd: (label) => `${label} (end)`,\n },\n field: {\n limitExceeded: (max) => `Exceeds the limit of ${max} characters`,\n },\n progress: { percent: (percent) => `${percent}%`, label: 'Progress' },\n hotkeys: {\n command: 'Command',\n ctrl: 'Ctrl',\n alt: 'Alt',\n shift: 'Shift',\n windows: 'Win',\n super: 'Super',\n enter: 'Enter',\n escape: 'Esc',\n space: 'Space',\n backspace: 'Backspace',\n delete: 'Del',\n tab: 'Tab',\n up: 'Up arrow',\n down: 'Down arrow',\n left: 'Left arrow',\n right: 'Right arrow',\n label: (keys) => `Keyboard shortcut: ${keys}`,\n },\n datePicker: {\n label: 'Date picker',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n previousYear: 'Previous year',\n nextYear: 'Next year',\n monthPicker: 'Choose month',\n yearPicker: 'Choose year',\n },\n dateInput: {\n clear: 'Clear date',\n openPicker: 'Open calendar',\n pickerLabel: 'Choose a date',\n },\n timePicker: {\n label: 'Time picker',\n meridiem: 'AM or PM',\n am: 'AM',\n pm: 'PM',\n selectHour: 'Select hour',\n selectMinutes: 'Select minutes',\n choosingHour: 'Selecting the hour',\n choosingMinutes: 'Selecting the minutes',\n hour: 'Hour',\n minutes: 'Minutes',\n hourValue: (hour) => `${hour} o'clock`,\n minutesValue: (minute) => (minute === 1 ? '1 minute' : `${minute} minutes`),\n },\n timeInput: {\n clear: 'Clear time',\n openPicker: 'Open time picker',\n pickerLabel: 'Choose a time',\n meridiemValue: (value) => `AM or PM: ${value}`,\n maskPlaceholder: 'hh:mm',\n unavailable: 'This time is not available.',\n },\n fileInput: {\n openPicker: 'Choose files',\n clear: 'Clear files',\n files: (count) => `${count} file${count === 1 ? '' : 's'}`,\n placeholder: 'No file selected',\n },\n filePicker: {\n browse: 'Browse files',\n or: 'or',\n list: 'Selected files',\n },\n carousel: {\n label: 'Carousel',\n roleDescription: 'carousel',\n slideRoleDescription: 'slide',\n slides: 'Slides',\n slide: (index, total) => `${index} of ${total}`,\n previous: 'Previous slide',\n next: 'Next slide',\n indicators: 'Choose slide to display',\n },\n calendar: {\n label: 'Calendar',\n roleDescription: 'calendar',\n today: 'Today',\n view: 'View',\n viewDay: 'Day',\n view4Days: '4 days',\n viewWeek: 'Week',\n viewMonth: 'Month',\n viewYear: 'Year',\n viewCustom: (days) => `${days} days`,\n previousDay: 'Previous day',\n nextDay: 'Next day',\n previousWeek: 'Previous week',\n nextWeek: 'Next week',\n previousMonth: 'Previous month',\n nextMonth: 'Next month',\n previousYear: 'Previous year',\n nextYear: 'Next year',\n previousPeriod: 'Previous period',\n nextPeriod: 'Next period',\n allDay: 'All day',\n moreEvents: (count) => `+${count} more`,\n openDay: (day) => `Open ${day}`,\n untitled: '(No title)',\n eventRoleDescription: 'event',\n eventHint:\n 'Press Enter to open this event. Press Space to take hold of it, then the arrow keys to move it and Shift with the arrow keys to change when it ends.',\n grabbed:\n 'Event held. Use the arrow keys to move it, Enter or Space to place it, Escape to cancel.',\n dropped: 'Event placed.',\n reverted: 'Move cancelled. The event is back where it was.',\n movedTo: (title, when) => `${title} moved to ${when}.`,\n },\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"fr.js","names":[],"sources":["../../src/i18n/fr.ts"],"sourcesContent":["/**\n * French, opt-in by import: the package ships one module per file, so a project that never\n * imports this one never carries it.\n *\n * Enabling it and adding a language the library does not ship are the SAME gesture — there\n * are deliberately not two kinds of dictionary, one blessed and one hand-added:\n *\n * import { fr, registerMessages, setLocale } from 'vectis-ui'\n * registerMessages('fr', fr)\n * setLocale('fr-FR')\n *\n * TRAP — the curly apostrophes below are part of the text. Some tests assert these strings\n * letter for letter, and a straight apostrophe is a different character. The same goes for\n * the no-break space (`\\u00A0`) before a colon or a percent sign, which French typography\n * requires; `i18n.test.ts` checks both over the whole dictionary.\n */\n\nimport type { Messages } from './types'\n\nexport const fr: Messages = {\n common: {\n loading: 'Chargement…',\n clear: 'Effacer',\n close: 'Fermer',\n dismiss: 'Retirer',\n remove: (name) => `Retirer ${name}`,\n cancel: 'Annuler',\n confirm: 'OK',\n },\n pagination: {\n label: 'Pagination',\n previous: 'Page précédente',\n next: 'Page suivante',\n page: (page) => `Page ${page}`,\n },\n tabs: {\n label: 'Onglets',\n previous: 'Onglets précédents',\n next: 'Onglets suivants',\n },\n breadcrumb: {\n label: 'Fil d’Ariane',\n ellipsis: 'Afficher les pages intermédiaires',\n },\n sideNavigation: { label: 'Navigation' },\n combobox: {\n empty: 'Aucun résultat',\n clear: 'Effacer la sélection',\n },\n dataTable: {\n empty: 'Aucune donnée',\n loading: 'Chargement des données…',\n searchLabel: 'Rechercher dans le tableau',\n searchPlaceholder: 'Rechercher…',\n perPage: 'Lignes par page',\n perPageValue: (label, value) => `${label}\\u00A0: ${value}`,\n selectAll: 'Tout sélectionner',\n selectRow: (index) => `Sélectionner la ligne ${index}`,\n selection: (count) =>\n `${count} élément${count > 1 ? 's' : ''} sélectionné${count > 1 ? 's' : ''}`,\n range: ({ start, end, total }) => `${start}–${end} sur ${total}`,\n pagination: 'Pagination du tableau',\n },\n toaster: { label: 'Notifications' },\n snackbar: { label: 'Confirmation', action: 'Annuler' },\n inputOTP: {\n label: 'Code de vérification',\n slot: (index, total) => `Caractère ${index} sur ${total}`,\n },\n slider: {\n value: 'Valeur',\n start: 'Début',\n end: 'Fin',\n rangeStart: (label) => `${label} (début)`,\n rangeEnd: (label) => `${label} (fin)`,\n },\n field: {\n limitExceeded: (max) => `Dépasse la limite de ${max} caractères`,\n },\n // The space before the sign is a NON-BREAKING one, as French typography requires and\n // English does not. It is written as an escape rather than typed in: the linter refuses\n // the character itself, and it would be indistinguishable from an ordinary space in a\n // review.\n progress: { percent: (percent) => `${percent}\\u00A0%`, label: 'Progression' },\n hotkeys: {\n command: 'Commande',\n ctrl: 'Ctrl',\n alt: 'Alt',\n shift: 'Maj',\n windows: 'Win',\n super: 'Super',\n enter: 'Entrée',\n escape: 'Échap',\n space: 'Espace',\n backspace: 'Retour arrière',\n delete: 'Suppr',\n tab: 'Tab',\n up: 'Flèche haut',\n down: 'Flèche bas',\n left: 'Flèche gauche',\n right: 'Flèche droite',\n label: (keys) => `Raccourci clavier\\u00A0: ${keys}`,\n },\n datePicker: {\n label: 'Sélecteur de date',\n previousMonth: 'Mois précédent',\n nextMonth: 'Mois suivant',\n previousYear: 'Année précédente',\n nextYear: 'Année suivante',\n monthPicker: 'Choix du mois',\n yearPicker: 'Choix de l’année',\n },\n dateInput: {\n clear: 'Effacer la date',\n openPicker: 'Ouvrir le calendrier',\n pickerLabel: 'Choisir une date',\n },\n timePicker: {\n label: 'Sélecteur d’heure',\n meridiem: 'AM ou PM',\n am: 'AM',\n pm: 'PM',\n selectHour: 'Sélectionner l’heure',\n selectMinutes: 'Sélectionner les minutes',\n choosingHour: 'Sélection de l’heure',\n choosingMinutes: 'Sélection des minutes',\n hour: 'Heure',\n minutes: 'Minutes',\n // Singular below two, as French counts: 0 heure, 1 minute, 2 minutes.\n hourValue: (hour) => `${hour} ${hour < 2 ? 'heure' : 'heures'}`,\n minutesValue: (minute) => `${minute} ${minute < 2 ? 'minute' : 'minutes'}`,\n },\n timeInput: {\n clear: 'Effacer l’heure',\n openPicker: 'Ouvrir le sélecteur d’heure',\n pickerLabel: 'Choisir une heure',\n meridiemValue: (value) => `AM ou PM\\u00A0: ${value}`,\n maskPlaceholder: 'hh:mm',\n unavailable: 'Cette heure n’est pas disponible.',\n },\n fileInput: {\n openPicker: 'Choisir des fichiers',\n clear: 'Effacer les fichiers',\n // The French plural starts at two, the English one at zero — \"0 fichier\" against\n // \"0 files\". Each language therefore makes the choice on its own, and there is no\n // shared rule for either to inherit.\n files: (count) => `${count} fichier${count > 1 ? 's' : ''}`,\n placeholder: 'Aucun fichier sélectionné',\n },\n filePicker: {\n browse: 'Parcourir les fichiers',\n or: 'ou',\n list: 'Fichiers sélectionnés',\n },\n carousel: {\n label: 'Carrousel',\n roleDescription: 'carrousel',\n slideRoleDescription: 'diapositive',\n slides: 'Diapositives',\n slide: (index, total) => `${index} sur ${total}`,\n previous: 'Diapositive précédente',\n next: 'Diapositive suivante',\n indicators: 'Choisir la diapositive à afficher',\n },\n calendar: {\n label: 'Calendrier',\n roleDescription: 'calendrier',\n today: 'Aujourd’hui',\n view: 'Affichage',\n viewDay: 'Jour',\n view4Days: '4 jours',\n viewWeek: 'Semaine',\n viewMonth: 'Mois',\n viewYear: 'Année',\n viewCustom: (days) => `${days} jours`,\n previousDay: 'Jour précédent',\n nextDay: 'Jour suivant',\n previousWeek: 'Semaine précédente',\n nextWeek: 'Semaine suivante',\n previousMonth: 'Mois précédent',\n nextMonth: 'Mois suivant',\n previousYear: 'Année précédente',\n nextYear: 'Année suivante',\n previousPeriod: 'Période précédente',\n nextPeriod: 'Période suivante',\n allDay: 'Toute la journée',\n moreEvents: (count) => `+${count} autre${count > 1 ? 's' : ''}`,\n openDay: (day) => `Ouvrir le ${day}`,\n untitled: '(Sans titre)',\n eventRoleDescription: 'évènement',\n eventHint:\n 'Appuyez sur Entrée pour ouvrir cet évènement. Appuyez sur Espace pour le saisir, puis sur les flèches pour le déplacer et sur Maj avec les flèches pour changer son heure de fin.',\n grabbed:\n 'Évènement saisi. Utilisez les flèches pour le déplacer, Entrée ou Espace pour le poser, Échap pour annuler.',\n dropped: 'Évènement posé.',\n reverted: 'Déplacement annulé. L’évènement est revenu à sa place.',\n // A noun rather than a participle, which would agree with a title of any gender.\n movedTo: (title, when) => `Déplacement de ${title}\\u00A0: ${when}.`,\n },\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fr.js","names":[],"sources":["../../src/i18n/fr.ts"],"sourcesContent":["/**\n * Opt-in French dictionary registered through registerMessages. Preserve typographic\n * apostrophes and message signatures.\n */\n\nimport type { Messages } from './types'\n\nexport const fr: Messages = {\n common: {\n loading: 'Chargement…',\n clear: 'Effacer',\n close: 'Fermer',\n dismiss: 'Retirer',\n remove: (name) => `Retirer ${name}`,\n cancel: 'Annuler',\n confirm: 'OK',\n },\n pagination: {\n label: 'Pagination',\n previous: 'Page précédente',\n next: 'Page suivante',\n page: (page) => `Page ${page}`,\n },\n tabs: {\n label: 'Onglets',\n previous: 'Onglets précédents',\n next: 'Onglets suivants',\n },\n breadcrumb: {\n label: 'Fil d’Ariane',\n ellipsis: 'Afficher les pages intermédiaires',\n },\n sideNavigation: { label: 'Navigation' },\n combobox: {\n empty: 'Aucun résultat',\n clear: 'Effacer la sélection',\n },\n dataTable: {\n empty: 'Aucune donnée',\n loading: 'Chargement des données…',\n searchLabel: 'Rechercher dans le tableau',\n searchPlaceholder: 'Rechercher…',\n perPage: 'Lignes par page',\n perPageValue: (label, value) => `${label}\\u00A0: ${value}`,\n selectAll: 'Tout sélectionner',\n selectRow: (index) => `Sélectionner la ligne ${index}`,\n selection: (count) =>\n `${count} élément${count > 1 ? 's' : ''} sélectionné${count > 1 ? 's' : ''}`,\n range: ({ start, end, total }) => `${start}–${end} sur ${total}`,\n pagination: 'Pagination du tableau',\n },\n toaster: { label: 'Notifications' },\n snackbar: { label: 'Confirmation', action: 'Annuler' },\n inputOTP: {\n label: 'Code de vérification',\n slot: (index, total) => `Caractère ${index} sur ${total}`,\n },\n slider: {\n value: 'Valeur',\n start: 'Début',\n end: 'Fin',\n rangeStart: (label) => `${label} (début)`,\n rangeEnd: (label) => `${label} (fin)`,\n },\n field: {\n limitExceeded: (max) => `Dépasse la limite de ${max} caractères`,\n },\n // The space before the sign is a NON-BREAKING one, as French typography requires and\n // English does not. It is written as an escape rather than typed in: the linter refuses\n // the character itself, and it would be indistinguishable from an ordinary space in a\n // review.\n progress: { percent: (percent) => `${percent}\\u00A0%`, label: 'Progression' },\n hotkeys: {\n command: 'Commande',\n ctrl: 'Ctrl',\n alt: 'Alt',\n shift: 'Maj',\n windows: 'Win',\n super: 'Super',\n enter: 'Entrée',\n escape: 'Échap',\n space: 'Espace',\n backspace: 'Retour arrière',\n delete: 'Suppr',\n tab: 'Tab',\n up: 'Flèche haut',\n down: 'Flèche bas',\n left: 'Flèche gauche',\n right: 'Flèche droite',\n label: (keys) => `Raccourci clavier\\u00A0: ${keys}`,\n },\n datePicker: {\n label: 'Sélecteur de date',\n previousMonth: 'Mois précédent',\n nextMonth: 'Mois suivant',\n previousYear: 'Année précédente',\n nextYear: 'Année suivante',\n monthPicker: 'Choix du mois',\n yearPicker: 'Choix de l’année',\n },\n dateInput: {\n clear: 'Effacer la date',\n openPicker: 'Ouvrir le calendrier',\n pickerLabel: 'Choisir une date',\n },\n timePicker: {\n label: 'Sélecteur d’heure',\n meridiem: 'AM ou PM',\n am: 'AM',\n pm: 'PM',\n selectHour: 'Sélectionner l’heure',\n selectMinutes: 'Sélectionner les minutes',\n choosingHour: 'Sélection de l’heure',\n choosingMinutes: 'Sélection des minutes',\n hour: 'Heure',\n minutes: 'Minutes',\n hourValue: (hour) => `${hour} ${hour < 2 ? 'heure' : 'heures'}`,\n minutesValue: (minute) => `${minute} ${minute < 2 ? 'minute' : 'minutes'}`,\n },\n timeInput: {\n clear: 'Effacer l’heure',\n openPicker: 'Ouvrir le sélecteur d’heure',\n pickerLabel: 'Choisir une heure',\n meridiemValue: (value) => `AM ou PM\\u00A0: ${value}`,\n maskPlaceholder: 'hh:mm',\n unavailable: 'Cette heure n’est pas disponible.',\n },\n fileInput: {\n openPicker: 'Choisir des fichiers',\n clear: 'Effacer les fichiers',\n // The French plural starts at two, the English one at zero; \"0 fichier\" against \"0 files\".\n // Each language therefore makes the choice on its own, and there is no shared rule for\n // either to inherit.\n files: (count) => `${count} fichier${count > 1 ? 's' : ''}`,\n placeholder: 'Aucun fichier sélectionné',\n },\n filePicker: {\n browse: 'Parcourir les fichiers',\n or: 'ou',\n list: 'Fichiers sélectionnés',\n },\n carousel: {\n label: 'Carrousel',\n roleDescription: 'carrousel',\n slideRoleDescription: 'diapositive',\n slides: 'Diapositives',\n slide: (index, total) => `${index} sur ${total}`,\n previous: 'Diapositive précédente',\n next: 'Diapositive suivante',\n indicators: 'Choisir la diapositive à afficher',\n },\n calendar: {\n label: 'Calendrier',\n roleDescription: 'calendrier',\n today: 'Aujourd’hui',\n view: 'Affichage',\n viewDay: 'Jour',\n view4Days: '4 jours',\n viewWeek: 'Semaine',\n viewMonth: 'Mois',\n viewYear: 'Année',\n viewCustom: (days) => `${days} jours`,\n previousDay: 'Jour précédent',\n nextDay: 'Jour suivant',\n previousWeek: 'Semaine précédente',\n nextWeek: 'Semaine suivante',\n previousMonth: 'Mois précédent',\n nextMonth: 'Mois suivant',\n previousYear: 'Année précédente',\n nextYear: 'Année suivante',\n previousPeriod: 'Période précédente',\n nextPeriod: 'Période suivante',\n allDay: 'Toute la journée',\n moreEvents: (count) => `+${count} autre${count > 1 ? 's' : ''}`,\n openDay: (day) => `Ouvrir le ${day}`,\n untitled: '(Sans titre)',\n eventRoleDescription: 'évènement',\n eventHint:\n 'Appuyez sur Entrée pour ouvrir cet évènement. Appuyez sur Espace pour le saisir, puis sur les flèches pour le déplacer et sur Maj avec les flèches pour changer son heure de fin.',\n grabbed:\n 'Évènement saisi. Utilisez les flèches pour le déplacer, Entrée ou Espace pour le poser, Échap pour annuler.',\n dropped: 'Évènement posé.',\n reverted: 'Déplacement annulé. L’évènement est revenu à sa place.',\n movedTo: (title, when) => `Déplacement de ${title}\\u00A0: ${when}.`,\n },\n}\n"],"mappings":"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"}
@@ -3,45 +3,19 @@ import { Messages, MessagesInput } from './types.js';
3
3
  /** The language tag assumed until one is chosen. */
4
4
  export declare const DEFAULT_LOCALE = "en-US";
5
5
  /**
6
- * Chooses the locale the library speaks.
7
- *
8
- * Pass a COMPLETE tag (`fr-FR`, `en-GB`, `de-DE`), never a bare language, because it is put
9
- * to two uses: it picks the dictionary, where only the subtag matters, and it is what the
10
- * calendar and the pickers hand to `Intl`, where the region matters a great deal. A bare
11
- * `en` resolves to no region in particular: a 12-hour clock and weeks starting on Sunday,
12
- * which is not British English. Those components also take their own `locale`, which wins.
13
- *
14
- * Call it from a module such as a Nuxt plugin or `main.ts`, never inside a `setup()`. On a server
15
- * the choice lives as long as the process, which is right for configuration and wrong for
16
- * anything belonging to one visitor; setting it client-only makes the server and the client
17
- * render different languages, and hydration then visibly fails to line up.
6
+ * Chooses the locale the library speaks. Those components also take their own `locale`, which
7
+ * wins.
18
8
  */
19
9
  export declare function setLocale(locale: string): void;
20
10
  /**
21
11
  * Adds or adjusts the words of a LANGUAGE, filed under the subtag alone: `fr`, not `fr-FR`.
22
- *
23
- * The one way in, deliberately: enabling the French the library ships and adding a language
24
- * it does not ship are the SAME gesture.
25
- *
26
- * A partial dictionary is fine. What is left out falls back to whatever was registered
27
- * before, then to the English always carried, never to an empty string. Successive calls
28
- * for one language ADD UP, so registering `fr` then correcting one word keeps the rest.
29
- * Passing `undefined` removes the override and puts English back as it came.
12
+ * What is left out falls back to whatever was registered before, then to the English always
13
+ * carried, never to an empty string.
30
14
  */
31
15
  export declare function registerMessages(lang: string, messages: MessagesInput | undefined): void;
32
16
  /**
33
- * The dictionary in force. Internal: components read it, it is not public API.
34
- *
35
- * It hands back the `shallowRef` rather than its contents, which is what makes components
36
- * ALREADY mounted re-render when `setLocale` is called later.
37
- *
38
- * TRAP: reading `.value.x` once in a `setup()` body FREEZES that word. Read it where the
39
- * read repeats: inside a `computed`, or in the template.
40
- *
41
- * The composable shape is deliberate. The day a locale per subtree or per request is needed,
42
- * only this BODY becomes `inject(messagesKey, null) ?? currentMessages` and no component is
43
- * touched. It also stays callable outside a component, since all it does is return a ref;
44
- * a version that looked up the tree would need a `getCurrentInstance()` guard.
17
+ * Reading `.value.x` once in a `setup()` body FREEZES that word. Read it where the read
18
+ * repeats: inside a `computed`, or in the template.
45
19
  */
46
20
  export declare function useMessages(): ShallowRef<Messages>;
47
21
  /**
@@ -51,11 +25,8 @@ export declare function useMessages(): ShallowRef<Messages>;
51
25
  export declare function useLocale(): ShallowRef<string>;
52
26
  /**
53
27
  * The locale a component with a `locale` prop of its own actually uses: the prop when it is
54
- * given, the locale in force otherwise. Internal, like the two above.
55
- *
56
- * The prop has no literal default in any of the components that read it, and that is what
57
- * this relies on: `undefined` is the "not given" that lets the global locale have its
58
- * chance. Every read of the language inside such a component goes through the one computed
59
- * returned here, so the two sources are never consulted in a different order somewhere else.
28
+ * given, the locale in force otherwise. The prop has no literal default in any of the
29
+ * components that read it, and that is what this relies on: `undefined` is the "not given" that
30
+ * lets the global locale have its chance.
60
31
  */
61
32
  export declare function useResolvedLocale(locale: () => string | undefined): ComputedRef<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","names":[],"sources":["../../src/i18n/state.ts"],"sourcesContent":["/**\n * The locale the library speaks and the words it says. No user-facing text is written in a\n * component; all of it comes from here.\n *\n * Module-level state rather than provide/inject, because this is CONFIGURATION: the same\n * for every visitor, and settable from any `.ts` — a plugin, an entry file — with no\n * component involved.\n *\n * ACCEPTED LIMIT — one locale per process. A single Node process serving /en and /fr cannot\n * let the two disagree here; it passes the text props explicitly instead. Lifting the limit\n * would change only the body of `useMessages` below, and no component at all.\n */\nimport { computed, shallowRef, type ComputedRef, type ShallowRef } from 'vue'\n\nimport { isDev } from '../utils/env'\n\nimport { en } from './en'\nimport type { Messages, MessagesInput } from './types'\n\n/** The language tag assumed until one is chosen. */\nexport const DEFAULT_LOCALE = 'en-US'\nconst DEFAULT_LANG = 'en'\n\n/**\n * The dictionaries, filed under the LANGUAGE subtag alone — `en`, `fr`, `de`. `en-GB` and\n * `en-US` share every word; what separates them (field order, first day of week, hour cycle)\n * comes from `Intl` on the full tag and is never a matter of translation.\n *\n * The Map is deliberately inert: what components track is `currentMessages` below, which is\n * recomputed whenever it changes.\n */\nconst registry = new Map<string, Messages>([[DEFAULT_LANG, en]])\n\nconst currentLocale = shallowRef<string>(DEFAULT_LOCALE)\nconst currentMessages = shallowRef<Messages>(en)\n\n/**\n * The language part of a tag: British English is filed under English. A tag that makes no\n * sense comes back untouched, and will simply match no dictionary.\n */\nfunction langOf(locale: string): string {\n return locale.toLowerCase().split('-')[0] ?? locale\n}\n\n/**\n * The dictionary a tag resolves to, falling back to the default language.\n *\n * The last `?? en` never fires: `registry` is seeded with `DEFAULT_LANG` and the only path\n * that could remove it — `registerMessages` passing `undefined` — puts `en` straight back\n * instead of deleting. It stays because `Map.get` is typed `T | undefined`, so the compiler\n * demands an exhaustive expression; the alternative is a non-null assertion, which would\n * hide the reasoning rather than record it. Do not read it as a live third case.\n */\nfunction resolve(locale: string): Messages {\n return registry.get(langOf(locale)) ?? registry.get(DEFAULT_LANG) ?? en\n}\n\n/** Names that would reach into an object's own machinery instead of naming a section. */\nconst FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype'])\n\n/**\n * Lays a partial override over a complete dictionary.\n *\n * Depth EXACTLY 2, which the dictionary's shape guarantees is enough: below a namespace\n * there are only leaves, a string or a function returning one. Nothing recurses, so a\n * FUNCTION can never be mistaken for an object and taken apart — which would leave `{}`\n * behind and a message that renders as nothing.\n */\nfunction mergeMessages(base: Messages, patch: MessagesInput): Messages {\n const out: Record<string, object> = { ...base }\n for (const [namespace, section] of Object.entries(patch)) {\n // A dictionary parsed from a file can carry one of these as a namespace, and assigning\n // to it would replace the copy's own machinery instead of adding a section. Nothing\n // outside is affected, the object being fresh — but every lookup in it is then wrong,\n // and nothing says so.\n if (FORBIDDEN_KEYS.has(namespace)) continue\n if (!section) continue\n /*\n * A leaf with no word in it is left out, so the one underneath stays. A dictionary read\n * from JSON can carry a `null`, and one built with `x ?? undefined` an `undefined`:\n * spread as they stood, they replaced the English and a control was named by nothing.\n */\n const words = Object.entries(section).filter(([key, value]) => {\n const empty = value === undefined || value === null || value === ''\n if (empty && isDev) {\n console.warn(`[vectis] registerMessages: “${namespace}.${key}” is empty and was ignored.`)\n }\n return !empty\n })\n out[namespace] = { ...out[namespace], ...Object.fromEntries(words) }\n }\n return out as unknown as Messages\n}\n\n/**\n * Chooses the locale the library speaks.\n *\n * Pass a COMPLETE tag (`fr-FR`, `en-GB`, `de-DE`), never a bare language, because it is put\n * to two uses: it picks the dictionary, where only the subtag matters, and it is what the\n * calendar and the pickers hand to `Intl`, where the region matters a great deal. A bare\n * `en` resolves to no region in particular: a 12-hour clock and weeks starting on Sunday,\n * which is not British English. Those components also take their own `locale`, which wins.\n *\n * Call it from a module such as a Nuxt plugin or `main.ts`, never inside a `setup()`. On a server\n * the choice lives as long as the process, which is right for configuration and wrong for\n * anything belonging to one visitor; setting it client-only makes the server and the client\n * render different languages, and hydration then visibly fails to line up.\n */\nexport function setLocale(locale: string): void {\n const lang = langOf(locale)\n if (isDev && !registry.has(lang)) {\n console.warn(\n `[vectis] No dictionary registered for “${lang}”: the text stays in ` +\n `“${DEFAULT_LANG}”. French is shipped — import { fr } from 'vectis-ui' then ` +\n `registerMessages('fr', fr). For another language: registerMessages('${lang}', { … }).`,\n )\n }\n currentLocale.value = locale\n currentMessages.value = resolve(locale)\n}\n\n/**\n * Adds or adjusts the words of a LANGUAGE, filed under the subtag alone: `fr`, not `fr-FR`.\n *\n * The one way in, deliberately: enabling the French the library ships and adding a language\n * it does not ship are the SAME gesture.\n *\n * A partial dictionary is fine. What is left out falls back to whatever was registered\n * before, then to the English always carried, never to an empty string. Successive calls\n * for one language ADD UP, so registering `fr` then correcting one word keeps the rest.\n * Passing `undefined` removes the override and puts English back as it came.\n */\nexport function registerMessages(lang: string, messages: MessagesInput | undefined): void {\n const key = langOf(lang)\n if (isDev && key !== lang.toLowerCase()) {\n console.warn(\n `[vectis] registerMessages('${lang}', …): the expected key is a language subtag ` +\n `alone — registered under “${key}”, which covers all its regional variants.`,\n )\n }\n if (messages === undefined) {\n if (key === DEFAULT_LANG) registry.set(DEFAULT_LANG, en)\n else registry.delete(key)\n } else {\n registry.set(key, mergeMessages(registry.get(key) ?? en, messages))\n }\n currentMessages.value = resolve(currentLocale.value)\n}\n\n/**\n * The dictionary in force. Internal: components read it, it is not public API.\n *\n * It hands back the `shallowRef` rather than its contents, which is what makes components\n * ALREADY mounted re-render when `setLocale` is called later.\n *\n * TRAP: reading `.value.x` once in a `setup()` body FREEZES that word. Read it where the\n * read repeats: inside a `computed`, or in the template.\n *\n * The composable shape is deliberate. The day a locale per subtree or per request is needed,\n * only this BODY becomes `inject(messagesKey, null) ?? currentMessages` and no component is\n * touched. It also stays callable outside a component, since all it does is return a ref;\n * a version that looked up the tree would need a `getCurrentInstance()` guard.\n */\nexport function useMessages(): ShallowRef<Messages> {\n return currentMessages\n}\n\n/**\n * The locale tag in force. Internal: what the calendar and the pickers fall back on with no\n * `locale` of their own, and what VDataTable passes to `localeCompare` when it sorts.\n */\nexport function useLocale(): ShallowRef<string> {\n return currentLocale\n}\n\n/**\n * The locale a component with a `locale` prop of its own actually uses: the prop when it is\n * given, the locale in force otherwise. Internal, like the two above.\n *\n * The prop has no literal default in any of the components that read it, and that is what\n * this relies on: `undefined` is the \"not given\" that lets the global locale have its\n * chance. Every read of the language inside such a component goes through the one computed\n * returned here, so the two sources are never consulted in a different order somewhere else.\n */\nexport function useResolvedLocale(locale: () => string | undefined): ComputedRef<string> {\n // An empty tag is no tag: handed to `Intl` as it stands, it throws a RangeError.\n return computed(() => locale() || currentLocale.value)\n}\n"],"mappings":";;;;AAoBA,IAAa,IAAiB,SACxB,IAAe,MAUf,oBAAW,IAAI,IAAsB,CAAC,CAAC,GAAc,CAAE,CAAC,CAAC,GAEzD,IAAgB,EAAmB,CAAc,GACjD,IAAkB,EAAqB,CAAE;AAM/C,SAAS,EAAO,GAAwB;CACtC,OAAO,EAAO,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;AAC/C;AAWA,SAAS,EAAQ,GAA0B;CACzC,OAAO,EAAS,IAAI,EAAO,CAAM,CAAC,KAAK,EAAS,IAAI,CAAY,KAAK;AACvE;AAGA,IAAM,oBAAiB,IAAI,IAAI;CAAC;CAAa;CAAe;AAAW,CAAC;AAUxE,SAAS,EAAc,GAAgB,GAAgC;CACrE,IAAM,IAA8B,EAAE,GAAG,EAAK;CAC9C,KAAK,IAAM,CAAC,GAAW,MAAY,OAAO,QAAQ,CAAK,GAAG;EAMxD,IADI,EAAe,IAAI,CAAS,KAC5B,CAAC,GAAS;EAMd,IAAM,IAAQ,OAAO,QAAQ,CAAO,CAAC,CAAC,QAAQ,CAAC,GAAK,OAAW;GAC7D,IAAM,IAAQ,KAAiC,QAAQ,MAAU;GAIjE,OAHI,KAAS,KACX,QAAQ,KAAK,+BAA+B,EAAU,GAAG,EAAI,4BAA4B,GAEpF,CAAC;EACV,CAAC;EACD,EAAI,KAAa;GAAE,GAAG,EAAI;GAAY,GAAG,OAAO,YAAY,CAAK;EAAE;CACrE;CACA,OAAO;AACT;AAgBA,SAAgB,EAAU,GAAsB;CAC9C,IAAM,IAAO,EAAO,CAAM;CAS1B,AARI,KAAS,CAAC,EAAS,IAAI,CAAI,KAC7B,QAAQ,KACN,0CAA0C,EAAK,wBACzC,EAAa,iIACsD,EAAK,WAChF,GAEF,EAAc,QAAQ,GACtB,EAAgB,QAAQ,EAAQ,CAAM;AACxC;AAaA,SAAgB,EAAiB,GAAc,GAA2C;CACxF,IAAM,IAAM,EAAO,CAAI;CAavB,AAZI,KAAS,MAAQ,EAAK,YAAY,KACpC,QAAQ,KACN,8BAA8B,EAAK,yEACJ,EAAI,2CACrC,GAEE,MAAa,KAAA,IACX,MAAQ,IAAc,EAAS,IAAI,GAAc,CAAE,IAClD,EAAS,OAAO,CAAG,IAExB,EAAS,IAAI,GAAK,EAAc,EAAS,IAAI,CAAG,KAAK,GAAI,CAAQ,CAAC,GAEpE,EAAgB,QAAQ,EAAQ,EAAc,KAAK;AACrD;AAgBA,SAAgB,IAAoC;CAClD,OAAO;AACT;AAMA,SAAgB,IAAgC;CAC9C,OAAO;AACT;AAWA,SAAgB,EAAkB,GAAuD;CAEvF,OAAO,QAAe,EAAO,KAAK,EAAc,KAAK;AACvD"}
1
+ {"version":3,"file":"state.js","names":[],"sources":["../../src/i18n/state.ts"],"sourcesContent":["/**\n * Reactive process-wide locale configuration, callable outside components. Per-request\n * multilingual SSR requires explicit component text props.\n */\nimport { computed, shallowRef, type ComputedRef, type ShallowRef } from 'vue'\n\nimport { isDev } from '../utils/env'\n\nimport { en } from './en'\nimport type { Messages, MessagesInput } from './types'\n\n/** The language tag assumed until one is chosen. */\nexport const DEFAULT_LOCALE = 'en-US'\nconst DEFAULT_LANG = 'en'\n\n/** The dictionaries, filed under the LANGUAGE subtag alone; `en`, `fr`, `de`. */\nconst registry = new Map<string, Messages>([[DEFAULT_LANG, en]])\n\nconst currentLocale = shallowRef<string>(DEFAULT_LOCALE)\nconst currentMessages = shallowRef<Messages>(en)\n\n/**\n * The language part of a tag: British English is filed under English. A tag that makes no\n * sense comes back untouched, and will simply match no dictionary.\n */\nfunction langOf(locale: string): string {\n return locale.toLowerCase().split('-')[0] ?? locale\n}\n\n/**\n * The dictionary a tag resolves to, falling back to the default language. The last `?? en`\n * never fires: `registry` is seeded with `DEFAULT_LANG` and the only path that could remove it;\n * `registerMessages` passing `undefined`; puts `en` straight back instead of deleting.\n */\nfunction resolve(locale: string): Messages {\n return registry.get(langOf(locale)) ?? registry.get(DEFAULT_LANG) ?? en\n}\n\n/** Names that would reach into an object's own machinery instead of naming a section. */\nconst FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype'])\n\n/** Lays a partial override over a complete dictionary. */\nfunction mergeMessages(base: Messages, patch: MessagesInput): Messages {\n const out: Record<string, object> = { ...base }\n for (const [namespace, section] of Object.entries(patch)) {\n // A dictionary parsed from a file can carry one of these as a namespace, and assigning to\n // it would replace the copy's own machinery instead of adding a section. Nothing outside is\n // affected, the object being fresh; but every lookup in it is then wrong, and nothing says\n // so.\n if (FORBIDDEN_KEYS.has(namespace)) continue\n if (!section) continue\n /* Ignore nullish dictionary leaves so partial overrides cannot erase fallback labels. */\n const words = Object.entries(section).filter(([key, value]) => {\n const empty = value === undefined || value === null || value === ''\n if (empty && isDev) {\n console.warn(`[vectis] registerMessages: “${namespace}.${key}” is empty and was ignored.`)\n }\n return !empty\n })\n out[namespace] = { ...out[namespace], ...Object.fromEntries(words) }\n }\n return out as unknown as Messages\n}\n\n/**\n * Chooses the locale the library speaks. Those components also take their own `locale`, which\n * wins.\n */\nexport function setLocale(locale: string): void {\n const lang = langOf(locale)\n if (isDev && !registry.has(lang)) {\n console.warn(\n `[vectis] No dictionary registered for “${lang}”: the text stays in ` +\n `“${DEFAULT_LANG}”. French is shipped — import { fr } from 'vectis-ui' then ` +\n `registerMessages('fr', fr). For another language: registerMessages('${lang}', { … }).`,\n )\n }\n currentLocale.value = locale\n currentMessages.value = resolve(locale)\n}\n\n/**\n * Adds or adjusts the words of a LANGUAGE, filed under the subtag alone: `fr`, not `fr-FR`.\n * What is left out falls back to whatever was registered before, then to the English always\n * carried, never to an empty string.\n */\nexport function registerMessages(lang: string, messages: MessagesInput | undefined): void {\n const key = langOf(lang)\n if (isDev && key !== lang.toLowerCase()) {\n console.warn(\n `[vectis] registerMessages('${lang}', …): the expected key is a language subtag ` +\n `alone — registered under “${key}”, which covers all its regional variants.`,\n )\n }\n if (messages === undefined) {\n if (key === DEFAULT_LANG) registry.set(DEFAULT_LANG, en)\n else registry.delete(key)\n } else {\n registry.set(key, mergeMessages(registry.get(key) ?? en, messages))\n }\n currentMessages.value = resolve(currentLocale.value)\n}\n\n/**\n * Reading `.value.x` once in a `setup()` body FREEZES that word. Read it where the read\n * repeats: inside a `computed`, or in the template.\n */\nexport function useMessages(): ShallowRef<Messages> {\n return currentMessages\n}\n\n/**\n * The locale tag in force. Internal: what the calendar and the pickers fall back on with no\n * `locale` of their own, and what VDataTable passes to `localeCompare` when it sorts.\n */\nexport function useLocale(): ShallowRef<string> {\n return currentLocale\n}\n\n/**\n * The locale a component with a `locale` prop of its own actually uses: the prop when it is\n * given, the locale in force otherwise. The prop has no literal default in any of the\n * components that read it, and that is what this relies on: `undefined` is the \"not given\" that\n * lets the global locale have its chance.\n */\nexport function useResolvedLocale(locale: () => string | undefined): ComputedRef<string> {\n // An empty tag is no tag: handed to `Intl` as it stands, it throws a RangeError.\n return computed(() => locale() || currentLocale.value)\n}\n"],"mappings":";;;;AAYA,IAAa,IAAiB,SACxB,IAAe,MAGf,oBAAW,IAAI,IAAsB,CAAC,CAAC,GAAc,CAAE,CAAC,CAAC,GAEzD,IAAgB,EAAmB,CAAc,GACjD,IAAkB,EAAqB,CAAE;AAM/C,SAAS,EAAO,GAAwB;CACtC,OAAO,EAAO,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;AAC/C;AAOA,SAAS,EAAQ,GAA0B;CACzC,OAAO,EAAS,IAAI,EAAO,CAAM,CAAC,KAAK,EAAS,IAAI,CAAY,KAAK;AACvE;AAGA,IAAM,oBAAiB,IAAI,IAAI;CAAC;CAAa;CAAe;AAAW,CAAC;AAGxE,SAAS,EAAc,GAAgB,GAAgC;CACrE,IAAM,IAA8B,EAAE,GAAG,EAAK;CAC9C,KAAK,IAAM,CAAC,GAAW,MAAY,OAAO,QAAQ,CAAK,GAAG;EAMxD,IADI,EAAe,IAAI,CAAS,KAC5B,CAAC,GAAS;EAEd,IAAM,IAAQ,OAAO,QAAQ,CAAO,CAAC,CAAC,QAAQ,CAAC,GAAK,OAAW;GAC7D,IAAM,IAAQ,KAAiC,QAAQ,MAAU;GAIjE,OAHI,KAAS,KACX,QAAQ,KAAK,+BAA+B,EAAU,GAAG,EAAI,4BAA4B,GAEpF,CAAC;EACV,CAAC;EACD,EAAI,KAAa;GAAE,GAAG,EAAI;GAAY,GAAG,OAAO,YAAY,CAAK;EAAE;CACrE;CACA,OAAO;AACT;AAMA,SAAgB,EAAU,GAAsB;CAC9C,IAAM,IAAO,EAAO,CAAM;CAS1B,AARI,KAAS,CAAC,EAAS,IAAI,CAAI,KAC7B,QAAQ,KACN,0CAA0C,EAAK,wBACzC,EAAa,iIACsD,EAAK,WAChF,GAEF,EAAc,QAAQ,GACtB,EAAgB,QAAQ,EAAQ,CAAM;AACxC;AAOA,SAAgB,EAAiB,GAAc,GAA2C;CACxF,IAAM,IAAM,EAAO,CAAI;CAavB,AAZI,KAAS,MAAQ,EAAK,YAAY,KACpC,QAAQ,KACN,8BAA8B,EAAK,yEACJ,EAAI,2CACrC,GAEE,MAAa,KAAA,IACX,MAAQ,IAAc,EAAS,IAAI,GAAc,CAAE,IAClD,EAAS,OAAO,CAAG,IAExB,EAAS,IAAI,GAAK,EAAc,EAAS,IAAI,CAAG,KAAK,GAAI,CAAQ,CAAC,GAEpE,EAAgB,QAAQ,EAAQ,EAAc,KAAK;AACrD;AAMA,SAAgB,IAAoC;CAClD,OAAO;AACT;AAMA,SAAgB,IAAgC;CAC9C,OAAO;AACT;AAQA,SAAgB,EAAkB,GAAuD;CAEvF,OAAO,QAAe,EAAO,KAAK,EAAc,KAAK;AACvD"}