vectis-ui 0.8.1 → 0.9.1

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 (432) hide show
  1. package/README.md +3 -3
  2. package/dist/components/VAccordion/VAccordionItem.d.ts +4 -6
  3. package/dist/components/VAccordion/VAccordionItem.js.map +1 -1
  4. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js +21 -19
  5. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/VAccordion/context.d.ts +6 -1
  7. package/dist/components/VAccordion/context.js.map +1 -1
  8. package/dist/components/VAvatar/VAvatar.css +1 -1
  9. package/dist/components/VAvatar/VAvatar.d.ts +5 -3
  10. package/dist/components/VAvatar/VAvatar.js.map +1 -1
  11. package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js +53 -39
  12. package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  13. package/dist/components/VAvatar/VAvatarGroup.d.ts +12 -3
  14. package/dist/components/VAvatar/VAvatarGroup.js.map +1 -1
  15. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js +27 -20
  16. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/components/VAvatar/context.d.ts +2 -2
  18. package/dist/components/VAvatar/context.js.map +1 -1
  19. package/dist/components/VBadge/VBadge.css +1 -1
  20. package/dist/components/VBadge/VBadge.d.ts +8 -4
  21. package/dist/components/VBadge/VBadge.js.map +1 -1
  22. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js +6 -3
  23. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/VBreadcrumb/VBreadcrumb.d.ts +5 -4
  25. package/dist/components/VBreadcrumb/VBreadcrumb.js.map +1 -1
  26. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js +8 -3
  27. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/components/VButton/VButton.css +1 -1
  29. package/dist/components/VButton/VButton.d.ts +4 -1
  30. package/dist/components/VButton/VButton.js.map +1 -1
  31. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js +8 -7
  32. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/VButton/VButtonGroup.js.map +1 -1
  34. package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/components/VCalendar/VCalendar.css +1 -1
  36. package/dist/components/VCalendar/VCalendar.d.ts +15 -6
  37. package/dist/components/VCalendar/VCalendar.js.map +1 -1
  38. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js +144 -126
  39. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  40. package/dist/components/VCalendar/VCalendarEvent.css +1 -1
  41. package/dist/components/VCalendar/VCalendarEvent.d.ts +1 -1
  42. package/dist/components/VCalendar/VCalendarEvent.js.map +1 -1
  43. package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  44. package/dist/components/VCalendar/VCalendarMonth.css +1 -1
  45. package/dist/components/VCalendar/VCalendarMonth.d.ts +1 -1
  46. package/dist/components/VCalendar/VCalendarMonth.js.map +1 -1
  47. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js +99 -90
  48. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/VCalendar/VCalendarTimeGrid.css +1 -1
  50. package/dist/components/VCalendar/VCalendarTimeGrid.d.ts +3 -3
  51. package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -1
  52. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js +256 -246
  53. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  54. package/dist/components/VCalendar/VCalendarYear.css +1 -1
  55. package/dist/components/VCalendar/VCalendarYear.d.ts +8 -1
  56. package/dist/components/VCalendar/VCalendarYear.js.map +1 -1
  57. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js +39 -32
  58. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  59. package/dist/components/VCalendar/color.d.ts +1 -1
  60. package/dist/components/VCalendar/color.js.map +1 -1
  61. package/dist/components/VCalendar/edgeStep.d.ts +3 -3
  62. package/dist/components/VCalendar/edgeStep.js +5 -0
  63. package/dist/components/VCalendar/edgeStep.js.map +1 -1
  64. package/dist/components/VCalendar/gesture.d.ts +10 -9
  65. package/dist/components/VCalendar/gesture.js +60 -45
  66. package/dist/components/VCalendar/gesture.js.map +1 -1
  67. package/dist/components/VCalendar/keyboard.d.ts +22 -5
  68. package/dist/components/VCalendar/keyboard.js +17 -16
  69. package/dist/components/VCalendar/keyboard.js.map +1 -1
  70. package/dist/components/VCalendar/layout.d.ts +47 -37
  71. package/dist/components/VCalendar/layout.js +47 -37
  72. package/dist/components/VCalendar/layout.js.map +1 -1
  73. package/dist/components/VCalendar/timeGrid.d.ts +4 -4
  74. package/dist/components/VCalendar/timeGrid.js +6 -6
  75. package/dist/components/VCalendar/timeGrid.js.map +1 -1
  76. package/dist/components/VCalendar/types.d.ts +5 -5
  77. package/dist/components/VCarousel/VCarousel.css +1 -1
  78. package/dist/components/VCarousel/VCarousel.d.ts +59 -38
  79. package/dist/components/VCarousel/VCarousel.js.map +1 -1
  80. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js +161 -132
  81. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  82. package/dist/components/VCarousel/VCarouselItem.d.ts +1 -1
  83. package/dist/components/VCarousel/VCarouselItem.js.map +1 -1
  84. package/dist/components/VCarousel/VCarouselItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  85. package/dist/components/VCarousel/context.d.ts +1 -1
  86. package/dist/components/VCarousel/context.js.map +1 -1
  87. package/dist/components/VCheckbox/VCheckbox.css +1 -1
  88. package/dist/components/VCheckbox/VCheckbox.d.ts +2 -2
  89. package/dist/components/VCheckbox/VCheckbox.js.map +1 -1
  90. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js +10 -8
  91. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  92. package/dist/components/VChip/VChip.css +1 -1
  93. package/dist/components/VChip/VChip.d.ts +7 -2
  94. package/dist/components/VChip/VChip.js.map +1 -1
  95. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js +69 -55
  96. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  97. package/dist/components/VCombobox/VCombobox.css +1 -1
  98. package/dist/components/VCombobox/VCombobox.d.ts +50 -36
  99. package/dist/components/VCombobox/VCombobox.js.map +1 -1
  100. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +167 -161
  101. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  102. package/dist/components/VCombobox/VComboboxGroup.css +1 -1
  103. package/dist/components/VCombobox/VComboboxGroup.js.map +1 -1
  104. package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  105. package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  106. package/dist/components/VCombobox/infiniteScroll.d.ts +12 -3
  107. package/dist/components/VCombobox/infiniteScroll.js +18 -12
  108. package/dist/components/VCombobox/infiniteScroll.js.map +1 -1
  109. package/dist/components/VDataTable/VDataTable.css +1 -1
  110. package/dist/components/VDataTable/VDataTable.d.ts +55 -24
  111. package/dist/components/VDataTable/VDataTable.js.map +1 -1
  112. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +192 -155
  113. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  114. package/dist/components/VDateInput/VDateInput.css +1 -1
  115. package/dist/components/VDateInput/VDateInput.d.ts +15 -12
  116. package/dist/components/VDateInput/VDateInput.js.map +1 -1
  117. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js +180 -160
  118. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  119. package/dist/components/VDateInput/mask.d.ts +95 -0
  120. package/dist/components/VDateInput/mask.js +118 -0
  121. package/dist/components/VDateInput/mask.js.map +1 -0
  122. package/dist/components/VDatePicker/VDatePicker.css +1 -1
  123. package/dist/components/VDatePicker/VDatePicker.d.ts +6 -5
  124. package/dist/components/VDatePicker/VDatePicker.js.map +1 -1
  125. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js +204 -173
  126. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  127. package/dist/components/VDatePicker/keyboard.d.ts +3 -3
  128. package/dist/components/VDatePicker/keyboard.js.map +1 -1
  129. package/dist/components/VDatePicker/names.d.ts +34 -0
  130. package/dist/components/VDatePicker/names.js +42 -0
  131. package/dist/components/VDatePicker/names.js.map +1 -0
  132. package/dist/components/VDialog/VDialog.css +1 -1
  133. package/dist/components/VDialog/VDialog.d.ts +2 -2
  134. package/dist/components/VDialog/VDialog.js.map +1 -1
  135. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js +63 -41
  136. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  137. package/dist/components/VFileInput/VFileInput.d.ts +38 -25
  138. package/dist/components/VFileInput/VFileInput.js.map +1 -1
  139. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js +74 -71
  140. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  141. package/dist/components/VFileInput/truncate.d.ts +4 -4
  142. package/dist/components/VFileInput/truncate.js.map +1 -1
  143. package/dist/components/VFilePicker/VFilePicker.css +1 -1
  144. package/dist/components/VFilePicker/VFilePicker.d.ts +54 -37
  145. package/dist/components/VFilePicker/VFilePicker.js.map +1 -1
  146. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js +152 -135
  147. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  148. package/dist/components/VFilePicker/fileKind.d.ts +2 -2
  149. package/dist/components/VFilePicker/fileKind.js.map +1 -1
  150. package/dist/components/VHotkeys/VHotkeys.css +1 -1
  151. package/dist/components/VHotkeys/VHotkeys.d.ts +10 -8
  152. package/dist/components/VHotkeys/VHotkeys.js.map +1 -1
  153. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js +22 -20
  154. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
  155. package/dist/components/VHotkeys/platform.d.ts +9 -7
  156. package/dist/components/VHotkeys/platform.js +41 -30
  157. package/dist/components/VHotkeys/platform.js.map +1 -1
  158. package/dist/components/VIcon/VIcon.css +1 -1
  159. package/dist/components/VIcon/VIcon.d.ts +6 -6
  160. package/dist/components/VIcon/VIcon.js.map +1 -1
  161. package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  162. package/dist/components/VIcon/iconProps.d.ts +4 -4
  163. package/dist/components/VIcon/iconProps.js.map +1 -1
  164. package/dist/components/VIcon/icons/index.d.ts +1 -1
  165. package/dist/components/VIcon/icons/index.js.map +1 -1
  166. package/dist/components/VIcon/icons/names.d.ts +1 -1
  167. package/dist/components/VIcon/icons/names.js.map +1 -1
  168. package/dist/components/VIcon/resolver.d.ts +3 -3
  169. package/dist/components/VIcon/resolver.js +23 -20
  170. package/dist/components/VIcon/resolver.js.map +1 -1
  171. package/dist/components/VIcon/types.d.ts +4 -4
  172. package/dist/components/VIconButton/VIconButton.d.ts +4 -4
  173. package/dist/components/VIconButton/VIconButton.js.map +1 -1
  174. package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  175. package/dist/components/VInput/VInput.d.ts +16 -8
  176. package/dist/components/VInput/VInput.js.map +1 -1
  177. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js +22 -16
  178. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  179. package/dist/components/VInput/VInputGroup.css +1 -1
  180. package/dist/components/VInput/VInputGroup.js.map +1 -1
  181. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js +43 -28
  182. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  183. package/dist/components/VInputOTP/VInputOTP.css +1 -1
  184. package/dist/components/VInputOTP/VInputOTP.d.ts +3 -3
  185. package/dist/components/VInputOTP/VInputOTP.js.map +1 -1
  186. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +152 -85
  187. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -1
  188. package/dist/components/VMenu/VMenu.d.ts +4 -4
  189. package/dist/components/VMenu/VMenu.js.map +1 -1
  190. package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  191. package/dist/components/VMenu/VMenuGroup.css +1 -1
  192. package/dist/components/VMenu/VMenuGroup.js.map +1 -1
  193. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js +18 -11
  194. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  195. package/dist/components/VMenu/VMenuItem.css +1 -1
  196. package/dist/components/VMenu/VMenuItem.d.ts +6 -6
  197. package/dist/components/VMenu/VMenuItem.js.map +1 -1
  198. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js +83 -69
  199. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  200. package/dist/components/VMenu/VMenuPanel.css +1 -1
  201. package/dist/components/VMenu/VMenuPanel.d.ts +2 -2
  202. package/dist/components/VMenu/VMenuPanel.js.map +1 -1
  203. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +56 -55
  204. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  205. package/dist/components/VMenu/context.d.ts +2 -2
  206. package/dist/components/VMenu/context.js.map +1 -1
  207. package/dist/components/VPagination/VPagination.css +1 -1
  208. package/dist/components/VPagination/VPagination.d.ts +31 -9
  209. package/dist/components/VPagination/VPagination.js.map +1 -1
  210. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js +82 -52
  211. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  212. package/dist/components/VPopover/VPopover.css +1 -1
  213. package/dist/components/VPopover/VPopover.d.ts +1 -1
  214. package/dist/components/VPopover/VPopover.js.map +1 -1
  215. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
  216. package/dist/components/VProgressCircular/VProgressCircular.css +1 -1
  217. package/dist/components/VProgressCircular/VProgressCircular.d.ts +12 -7
  218. package/dist/components/VProgressCircular/VProgressCircular.js.map +1 -1
  219. package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js.map +1 -1
  220. package/dist/components/VProgressLinear/VProgressLinear.css +1 -1
  221. package/dist/components/VProgressLinear/VProgressLinear.d.ts +15 -10
  222. package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -1
  223. package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  224. package/dist/components/VRadio/VRadio.css +1 -1
  225. package/dist/components/VRadio/VRadio.js.map +1 -1
  226. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js +3 -3
  227. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  228. package/dist/components/VSeparator/VSeparator.d.ts +1 -1
  229. package/dist/components/VSeparator/VSeparator.js.map +1 -1
  230. package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  231. package/dist/components/VSideNavigation/VSideNavigation.d.ts +2 -2
  232. package/dist/components/VSideNavigation/VSideNavigation.js.map +1 -1
  233. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js +1 -1
  234. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js.map +1 -1
  235. package/dist/components/VSideNavigation/VSideNavigationGroup.css +1 -1
  236. package/dist/components/VSideNavigation/VSideNavigationGroup.js.map +1 -1
  237. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  238. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  239. package/dist/components/VSideNavigation/VSideNavigationItem.css +1 -1
  240. package/dist/components/VSideNavigation/VSideNavigationItem.d.ts +12 -13
  241. package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -1
  242. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +87 -68
  243. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  244. package/dist/components/VSkeletonLoader/VSkeletonLoader.css +1 -1
  245. package/dist/components/VSkeletonLoader/VSkeletonLoader.d.ts +10 -7
  246. package/dist/components/VSkeletonLoader/VSkeletonLoader.js.map +1 -1
  247. package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js +5 -5
  248. package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  249. package/dist/components/VSlider/VSlider.css +1 -1
  250. package/dist/components/VSlider/VSlider.d.ts +21 -7
  251. package/dist/components/VSlider/VSlider.js.map +1 -1
  252. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js +159 -140
  253. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  254. package/dist/components/VSnackbar/VSnackbar.css +1 -1
  255. package/dist/components/VSnackbar/VSnackbar.d.ts +4 -4
  256. package/dist/components/VSnackbar/VSnackbar.js.map +1 -1
  257. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js +85 -59
  258. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  259. package/dist/components/VSnackbar/state.d.ts +7 -7
  260. package/dist/components/VSnackbar/state.js +13 -11
  261. package/dist/components/VSnackbar/state.js.map +1 -1
  262. package/dist/components/VSpinner/VSpinner.css +1 -1
  263. package/dist/components/VSpinner/VSpinner.js.map +1 -1
  264. package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  265. package/dist/components/VSwitch/VSwitch.css +1 -1
  266. package/dist/components/VSwitch/VSwitch.d.ts +1 -1
  267. package/dist/components/VSwitch/VSwitch.js.map +1 -1
  268. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js +4 -4
  269. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  270. package/dist/components/VTabs/VTab.css +1 -1
  271. package/dist/components/VTabs/VTab.d.ts +4 -0
  272. package/dist/components/VTabs/VTab.js.map +1 -1
  273. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js +9 -8
  274. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
  275. package/dist/components/VTabs/VTabs.css +1 -1
  276. package/dist/components/VTabs/VTabs.d.ts +17 -7
  277. package/dist/components/VTabs/VTabs.js.map +1 -1
  278. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js +84 -77
  279. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  280. package/dist/components/VTextarea/VTextarea.d.ts +8 -8
  281. package/dist/components/VTextarea/VTextarea.js.map +1 -1
  282. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js +71 -69
  283. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  284. package/dist/components/VTimeInput/VTimeInput.css +1 -1
  285. package/dist/components/VTimeInput/VTimeInput.d.ts +21 -12
  286. package/dist/components/VTimeInput/VTimeInput.js.map +1 -1
  287. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js +230 -206
  288. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  289. package/dist/components/VTimeInput/search.d.ts +17 -2
  290. package/dist/components/VTimeInput/search.js +19 -9
  291. package/dist/components/VTimeInput/search.js.map +1 -1
  292. package/dist/components/VTimePicker/VTimePicker.css +1 -1
  293. package/dist/components/VTimePicker/VTimePicker.d.ts +8 -7
  294. package/dist/components/VTimePicker/VTimePicker.js.map +1 -1
  295. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js +128 -106
  296. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  297. package/dist/components/VTimePicker/limits.d.ts +11 -4
  298. package/dist/components/VTimePicker/limits.js +3 -2
  299. package/dist/components/VTimePicker/limits.js.map +1 -1
  300. package/dist/components/VToast/VToast.css +1 -1
  301. package/dist/components/VToast/VToast.js.map +1 -1
  302. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js +33 -37
  303. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js.map +1 -1
  304. package/dist/components/VToast/VToaster.js.map +1 -1
  305. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js +91 -61
  306. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
  307. package/dist/components/VToast/state.d.ts +8 -6
  308. package/dist/components/VToast/state.js +15 -13
  309. package/dist/components/VToast/state.js.map +1 -1
  310. package/dist/components/VToggle/VToggle.css +1 -1
  311. package/dist/components/VToggle/VToggle.d.ts +9 -4
  312. package/dist/components/VToggle/VToggle.js.map +1 -1
  313. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js +2 -1
  314. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js.map +1 -1
  315. package/dist/components/VToggle/VToggleItem.d.ts +4 -0
  316. package/dist/components/VToggle/VToggleItem.js.map +1 -1
  317. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js +5 -5
  318. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  319. package/dist/components/VTooltip/VTooltip.css +1 -1
  320. package/dist/components/VTooltip/VTooltip.d.ts +17 -10
  321. package/dist/components/VTooltip/VTooltip.js.map +1 -1
  322. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js +46 -26
  323. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  324. package/dist/components/VTypography/VTypography.css +1 -1
  325. package/dist/components/VTypography/VTypography.d.ts +6 -4
  326. package/dist/components/VTypography/VTypography.js.map +1 -1
  327. package/dist/components/VTypography/VTypography.vue_vue_type_script_setup_true_lang.js.map +1 -1
  328. package/dist/composables/useAriaLabel.js +1 -1
  329. package/dist/composables/useAriaLabel.js.map +1 -1
  330. package/dist/composables/useClearable.d.ts +2 -2
  331. package/dist/composables/useClearable.js.map +1 -1
  332. package/dist/composables/useDetailsOpen.d.ts +3 -3
  333. package/dist/composables/useDetailsOpen.js +14 -12
  334. package/dist/composables/useDetailsOpen.js.map +1 -1
  335. package/dist/composables/useFieldIds.d.ts +2 -1
  336. package/dist/composables/useFieldIds.js +6 -5
  337. package/dist/composables/useFieldIds.js.map +1 -1
  338. package/dist/composables/useFieldPanel.d.ts +2 -2
  339. package/dist/composables/useFieldPanel.js +47 -37
  340. package/dist/composables/useFieldPanel.js.map +1 -1
  341. package/dist/composables/useFileDrop.js +3 -3
  342. package/dist/composables/useFileDrop.js.map +1 -1
  343. package/dist/composables/useFileField.d.ts +1 -1
  344. package/dist/composables/useFileField.js +62 -41
  345. package/dist/composables/useFileField.js.map +1 -1
  346. package/dist/composables/useIconClickHandlers.d.ts +3 -3
  347. package/dist/composables/useIconClickHandlers.js +14 -13
  348. package/dist/composables/useIconClickHandlers.js.map +1 -1
  349. package/dist/composables/useInertLink.js +12 -10
  350. package/dist/composables/useInertLink.js.map +1 -1
  351. package/dist/composables/useLiveAnnouncer.d.ts +5 -0
  352. package/dist/composables/useLiveAnnouncer.js +23 -0
  353. package/dist/composables/useLiveAnnouncer.js.map +1 -0
  354. package/dist/composables/useMaskedField.d.ts +5 -5
  355. package/dist/composables/useMaskedField.js.map +1 -1
  356. package/dist/composables/usePopover.d.ts +3 -3
  357. package/dist/composables/usePopover.js +6 -4
  358. package/dist/composables/usePopover.js.map +1 -1
  359. package/dist/composables/useProgressValue.js +11 -2
  360. package/dist/composables/useProgressValue.js.map +1 -1
  361. package/dist/composables/useRootAttrs.d.ts +1 -1
  362. package/dist/composables/useRootAttrs.js.map +1 -1
  363. package/dist/composables/useSlotNodes.d.ts +18 -0
  364. package/dist/composables/useSlotNodes.js +13 -0
  365. package/dist/composables/useSlotNodes.js.map +1 -0
  366. package/dist/composables/useTextLimit.d.ts +2 -1
  367. package/dist/composables/useTextLimit.js +2 -2
  368. package/dist/composables/useTextLimit.js.map +1 -1
  369. package/dist/composables/useTimer.d.ts +5 -0
  370. package/dist/composables/useTimer.js +22 -11
  371. package/dist/composables/useTimer.js.map +1 -1
  372. package/dist/i18n/en.js +1 -1
  373. package/dist/i18n/en.js.map +1 -1
  374. package/dist/i18n/fr.js +14 -14
  375. package/dist/i18n/fr.js.map +1 -1
  376. package/dist/i18n/state.d.ts +7 -7
  377. package/dist/i18n/state.js +37 -28
  378. package/dist/i18n/state.js.map +1 -1
  379. package/dist/i18n/types.d.ts +12 -12
  380. package/dist/icons.d.ts +2 -2
  381. package/dist/index.d.ts +12 -11
  382. package/dist/styles.css +1 -1
  383. package/dist/tokens/css.d.ts +1 -1
  384. package/dist/tokens/css.js.map +1 -1
  385. package/dist/tokens/index.d.ts +6 -0
  386. package/dist/tokens/semantic.d.ts +6 -0
  387. package/dist/tokens/semantic.js +66 -60
  388. package/dist/tokens/semantic.js.map +1 -1
  389. package/dist/tokens/themes/dark.js +3 -3
  390. package/dist/tokens/themes/dark.js.map +1 -1
  391. package/dist/tokens.json +130 -66
  392. package/dist/types.d.ts +1 -1
  393. package/dist/utils/arrowNav.d.ts +4 -1
  394. package/dist/utils/arrowNav.js +7 -7
  395. package/dist/utils/arrowNav.js.map +1 -1
  396. package/dist/utils/chip.d.ts +1 -1
  397. package/dist/utils/chip.js.map +1 -1
  398. package/dist/utils/clock.d.ts +113 -0
  399. package/dist/utils/clock.js +84 -0
  400. package/dist/utils/clock.js.map +1 -0
  401. package/dist/utils/css.d.ts +6 -4
  402. package/dist/utils/css.js +2 -2
  403. package/dist/utils/css.js.map +1 -1
  404. package/dist/utils/date.d.ts +7 -102
  405. package/dist/utils/date.js +33 -160
  406. package/dist/utils/date.js.map +1 -1
  407. package/dist/utils/direction.d.ts +1 -1
  408. package/dist/utils/direction.js.map +1 -1
  409. package/dist/utils/env.d.ts +12 -3
  410. package/dist/utils/env.js +6 -0
  411. package/dist/utils/env.js.map +1 -0
  412. package/dist/utils/file.d.ts +3 -3
  413. package/dist/utils/file.js +1 -1
  414. package/dist/utils/file.js.map +1 -1
  415. package/dist/utils/focus.d.ts +1 -1
  416. package/dist/utils/focus.js.map +1 -1
  417. package/dist/utils/hostWarns.d.ts +1 -1
  418. package/dist/utils/hostWarns.js.map +1 -1
  419. package/dist/utils/ids.d.ts +1 -1
  420. package/dist/utils/ids.js.map +1 -1
  421. package/dist/utils/matcher.d.ts +2 -2
  422. package/dist/utils/matcher.js.map +1 -1
  423. package/dist/utils/memo.d.ts +1 -1
  424. package/dist/utils/memo.js.map +1 -1
  425. package/dist/utils/text.d.ts +3 -3
  426. package/dist/utils/text.js.map +1 -1
  427. package/dist/utils/time.d.ts +2 -101
  428. package/dist/utils/time.js +22 -98
  429. package/dist/utils/time.js.map +1 -1
  430. package/dist/utils/vnode.d.ts +5 -3
  431. package/dist/utils/vnode.js.map +1 -1
  432. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"VProgressCircular.js","names":[],"sources":["../../../src/components/VProgressCircular/VProgressCircular.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core — no behavioural JS at all: value normalization and the display string.\n/**\n * Progress drawn as a ring, an SVG whose geometry is described entirely in CSS with no JS\n * computing anything.\n *\n * Two things make that possible. There is no `viewBox`, so one user unit is one pixel and\n * the circles take plain lengths — a fixed coordinate system would mean converting the\n * thickness into its units, hence knowing the ratio in code and recomputing it at every\n * change of size. And `pathLength=\"100\"` declares the outline 100 units long whatever its\n * real circumference, so the portion drawn is a percentage with no π anywhere.\n *\n * NAMING — pass a `label` saying what is progressing. The figure in the middle cannot\n * serve: `role=\"progressbar\"` makes its content presentational, so it is never announced.\n */\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useProgressValue } from '../../composables/useProgressValue'\nimport { useMessages } from '../../i18n/state'\nimport { px } from '../../utils/css'\n\n/** What the progress means, in colour. */\nexport type ProgressCircularTone = 'accent' | 'success' | 'warning' | 'danger' | 'neutral'\n\n/** How the arc ends. */\nexport type ProgressCircularShape = 'rounded' | 'square'\n\ninterface ProgressCircularProps {\n /** How far along it is. Anything outside the range is brought back into it. */\n value?: number\n /**\n * What is progressing, in words, for screen readers. It draws nothing on screen, and falls\n * back to the design system dictionary; an `aria-label` or `aria-labelledby` of your own\n * takes precedence over it.\n */\n label?: string\n /** What counts as finished. The other end is always zero. */\n max?: number\n /**\n * Says that the progress cannot be measured: the ring turns continuously and the\n * value is ignored.\n */\n indeterminate?: boolean\n /** What the progress means, expressed as a colour. */\n tone?: ProgressCircularTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. The\n * unfilled ring's shade is derived from it against the theme, so it follows the light\n * and the dark one.\n */\n color?: string\n /** The diameter, always IN PIXELS: `96` and `'96'` both give 96px. */\n size?: number | string\n /** How thick the ring is, always IN PIXELS: `8` and `'8'` both give 8px. */\n thickness?: number | string\n /** Whether the ends of the drawn arc are rounded or cut square. */\n shape?: ProgressCircularShape\n /**\n * Writes the percentage in the middle of the ring. It is ignored while the progress is\n * unmeasurable, there being no figure to write.\n */\n showValue?: boolean\n}\n\nconst props = withDefaults(defineProps<ProgressCircularProps>(), {\n value: 0,\n label: undefined,\n max: 100,\n indeterminate: false,\n tone: 'accent',\n color: undefined,\n size: undefined,\n thickness: undefined,\n shape: 'rounded',\n showValue: false,\n})\n\ndefineSlots<{\n /**\n * What to put in the middle of the ring instead of the percentage — a count of files,\n * an icon, a shortened figure.\n */\n default?(props: { value: number; max: number; percent: number }): unknown\n}>()\n\n/* The percent sign, and the non-breaking space French puts before it where English puts\n nothing, are a convention of the language: they belong in the dictionary rather than\n in this file. Any other format goes through the slot above. */\nconst m = useMessages()\n\nconst {\n max: normalizedMax,\n clamped,\n fraction,\n percent,\n roundedPercent,\n} = useProgressValue(\n () => props.value,\n () => props.max,\n)\n\n// @a11y\n// The canonical cascade: a consumer's `aria-labelledby`, then their `aria-label`, then the\n// `label` prop, then the dictionary. An indicator takes no name from the text inside it, so\n// without the last step it would have none at all.\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.progress.label)\n</script>\n\n<template>\n <span\n class=\"v-progress-circular v-tone\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :data-tone=\"tone\"\n :data-custom=\"color !== undefined ? '' : undefined\"\n :data-shape=\"shape\"\n :data-indeterminate=\"indeterminate ? '' : undefined\"\n :aria-valuenow=\"indeterminate ? undefined : clamped\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"normalizedMax\"\n :style=\"{\n '--fill-fraction': String(fraction),\n '--custom-color': color,\n '--progress-diameter': px(size),\n '--progress-thickness': px(thickness),\n }\"\n >\n <svg class=\"v-progress-circular-svg\" aria-hidden=\"true\">\n <circle class=\"v-progress-circular-track\" pathLength=\"100\" />\n <circle class=\"v-progress-circular-bar\" pathLength=\"100\" />\n </svg>\n <span v-if=\"!indeterminate && (showValue || $slots.default)\" class=\"v-progress-circular-label\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The two dimensions are declared here as defaults, on the very element the props\n write to inline — which is what makes an explicit size or thickness always win. */\n .v-progress-circular {\n --progress-diameter: var(--vectis-control-size-progress-circular-diameter);\n --progress-thickness: var(--vectis-control-size-progress-circular-thickness);\n /* Arc and track are the tone's solid and soft colours, read from the shared table\n (`.v-tone`, set in the template). No text colour is taken from it: the figure sits\n in the hole of the ring, against the page, in the ordinary text colour. */\n --progress-fill: var(--tone-bg-solid);\n --progress-track: var(--tone-bg-soft);\n display: inline-grid;\n inline-size: var(--progress-diameter);\n block-size: var(--progress-diameter);\n vertical-align: middle;\n }\n\n .v-progress-circular-svg,\n .v-progress-circular-label {\n grid-area: 1 / 1;\n }\n\n .v-progress-circular-svg {\n inline-size: 100%;\n block-size: 100%;\n /* Turns the ring so that it starts at twelve o'clock rather than at three. It is\n written as its own property and not as a transform, so that it COMPOSES with the\n spinning of the unmeasurable mode instead of being overwritten by it. */\n rotate: -90deg;\n }\n\n /* In a right-to-left page the ring fills the other way round, following the reading\n direction. These individual properties are applied in a fixed order — move, turn,\n then mirror — so the mirroring is taken into account before the quarter turn above. */\n .v-progress-circular:dir(rtl) .v-progress-circular-svg {\n scale: 1 -1;\n }\n\n /* The geometry, entirely in CSS and in plain lengths. Percentages are avoided\n deliberately: a radius given as a percentage is resolved against a normalized\n diagonal rather than against the width, and there is no reason to expose the\n component to that when the diameter is always a length to begin with. */\n .v-progress-circular-track,\n .v-progress-circular-bar {\n cx: calc(var(--progress-diameter) / 2);\n cy: calc(var(--progress-diameter) / 2);\n /* A thickness as large as the diameter would give a NEGATIVE radius, which is an\n error in SVG: the circle would simply not be drawn. The floor degrades that case\n to a radius of zero instead. */\n r: max(0px, calc((var(--progress-diameter) - var(--progress-thickness)) / 2));\n fill: none;\n stroke-width: var(--progress-thickness);\n }\n\n .v-progress-circular-track {\n stroke: var(--progress-track);\n }\n\n .v-progress-circular-bar {\n stroke: var(--progress-fill);\n stroke-linecap: round;\n stroke-dasharray: 100;\n stroke-dashoffset: calc(100 - 100 * var(--fill-fraction));\n transition: stroke-dashoffset var(--vectis-duration-base) var(--vectis-ease-default);\n }\n\n .v-progress-circular[data-shape='square'] .v-progress-circular-bar {\n stroke-linecap: butt;\n }\n\n /* A custom colour replaces the tone: at (0,2,0) it beats the base rule's mapping\n whatever the order the two are written in. */\n .v-progress-circular[data-custom] {\n --progress-fill: var(--custom-color);\n --progress-track: color-mix(in oklab, var(--custom-color), var(--vectis-color-surface) 85%);\n }\n\n .v-progress-circular-label {\n display: flex;\n align-items: center;\n justify-content: center;\n /* TRAP — this centres the BOX itself in its cell, and it is not redundant with the\n centring above. The maximum width below stops the box from being stretched to\n fill the cell, and a stretch that cannot apply falls back to the START edge: the\n figure would end up against the side of the ring. */\n place-self: center;\n max-inline-size: calc(var(--progress-diameter) - var(--progress-thickness) * 2);\n color: var(--vectis-color-text);\n font-family: var(--vectis-text-family);\n /* Sized as a fraction of the diameter so it stays in proportion at every size — the\n same tolerance already granted to VSpinner's stroke — with a floor at the smallest\n type token, below which it would be unreadable. */\n font-size: max(var(--vectis-text-caption-size), calc(var(--progress-diameter) / 4));\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n text-align: center;\n }\n\n /* When the progress cannot be measured, two animations run at once: the whole ring\n turns, and the arc drawn on it lengthens and shortens. Their periods are deliberately\n not multiples of one another — were the arc to restart on every rotation, the pair\n would repeat the same picture over and over and read as a mechanical beat. At 1s and\n 1.5s they only realign every third turn; the slowed-down pair below is 3s and 5s, so\n every fifth. Keep any change to those four values out of a whole-number ratio. */\n .v-progress-circular[data-indeterminate] .v-progress-circular-svg {\n animation: v-spin var(--vectis-duration-1000) linear infinite;\n }\n\n .v-progress-circular[data-indeterminate] .v-progress-circular-bar {\n animation: v-progress-circular-dash var(--vectis-duration-1500) var(--vectis-ease-default)\n infinite;\n transition: none;\n }\n\n /* Both ends of the arc move, so it lengthens, shortens and travels around the circle\n at once. The spin it rides on is the shared one from styles/utilities.css; only\n these keyframes, which belong to this component alone, stay here. */\n @keyframes v-progress-circular-dash {\n 0% {\n stroke-dasharray: 5 100;\n stroke-dashoffset: 0;\n }\n\n 50% {\n stroke-dasharray: 70 100;\n stroke-dashoffset: -20;\n }\n\n 100% {\n stroke-dasharray: 5 100;\n stroke-dashoffset: -100;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-progress-circular-bar {\n transition: none;\n }\n\n /* Slowed down and not stopped: a motionless loader no longer says that anything is\n happening, which is the one thing it exists to say. */\n .v-progress-circular[data-indeterminate] .v-progress-circular-svg {\n animation-duration: var(--vectis-duration-3000);\n }\n\n .v-progress-circular[data-indeterminate] .v-progress-circular-bar {\n animation-duration: var(--vectis-duration-5000);\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"VProgressCircular.js","names":[],"sources":["../../../src/components/VProgressCircular/VProgressCircular.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * Progress drawn as a ring, an SVG whose geometry is described entirely in CSS with no JS\n * computing anything.\n *\n * Two things make that possible. There is no `viewBox`, so one user unit is one pixel and\n * the circles take plain lengths — a fixed coordinate system would mean converting the\n * thickness into its units, hence knowing the ratio in code and recomputing it at every\n * change of size. And `pathLength=\"100\"` declares the outline 100 units long whatever its\n * real circumference, so the portion drawn is a percentage with no π anywhere.\n *\n * NAMING — pass a `label` saying what is progressing. The figure in the middle cannot\n * serve: `role=\"progressbar\"` makes its content presentational, so it is never announced.\n */\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useProgressValue } from '../../composables/useProgressValue'\nimport { useMessages } from '../../i18n/state'\nimport { px } from '../../utils/css'\n\n/** What the progress means, in colour. */\nexport type ProgressCircularTone = 'neutral' | 'accent' | 'danger' | 'success' | 'warning'\n\n/** How the arc ends. */\nexport type ProgressCircularShape = 'rounded' | 'square'\n\n/** What the default slot receives. */\nexport interface ProgressCircularSlotProps {\n /** The value, brought back into the range. */\n value: number\n /** The bound, zero or more. */\n max: number\n /** How far along it is, as a percentage and unrounded. */\n percent: number\n}\n\ninterface ProgressCircularProps {\n /** How far along it is. Anything outside the range is brought back into it. */\n value?: number\n /**\n * What is progressing, in words, for screen readers. It draws nothing on screen, and falls\n * back to the design system dictionary; an `aria-label` or `aria-labelledby` of your own\n * takes precedence over it.\n */\n label?: string\n /** What counts as finished. The other end is always zero. */\n max?: number\n /**\n * Says that the progress cannot be measured: the ring turns continuously and the\n * value is ignored.\n */\n indeterminate?: boolean\n /** What the progress means, expressed as a colour. */\n tone?: ProgressCircularTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. The\n * unfilled ring's shade is derived from it against the theme, so it follows the light\n * and the dark one.\n */\n color?: string\n /** The diameter, always IN PIXELS: `96` and `'96'` both give 96px. */\n size?: number | string\n /** How thick the ring is, always IN PIXELS: `8` and `'8'` both give 8px. */\n thickness?: number | string\n /** Whether the ends of the drawn arc are rounded or cut square. */\n shape?: ProgressCircularShape\n /**\n * Writes the percentage in the middle of the ring. It is ignored while the progress is\n * unmeasurable, there being no figure to write.\n */\n showValue?: boolean\n}\n\nconst props = withDefaults(defineProps<ProgressCircularProps>(), {\n value: 0,\n label: undefined,\n max: 100,\n indeterminate: false,\n tone: 'accent',\n color: undefined,\n size: undefined,\n thickness: undefined,\n shape: 'rounded',\n showValue: false,\n})\n\ndefineSlots<{\n /**\n * What to put in the middle of the ring instead of the percentage: a count of files,\n * an icon, a shortened figure.\n */\n default?(props: ProgressCircularSlotProps): unknown\n}>()\n\n/* The percent sign, and the non-breaking space French puts before it where English puts\n nothing, are a convention of the language: they belong in the dictionary rather than\n in this file. Any other format goes through the slot above. */\nconst m = useMessages()\n\nconst {\n max: normalizedMax,\n clamped,\n fraction,\n percent,\n roundedPercent,\n} = useProgressValue(\n () => props.value,\n () => props.max,\n)\n\n// @a11y\n// The canonical cascade: a consumer's `aria-labelledby`, then their `aria-label`, then the\n// `label` prop, then the dictionary. An indicator takes no name from the text inside it, so\n// without the last step it would have none at all.\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.progress.label)\n</script>\n\n<template>\n <span\n class=\"v-progress-circular v-tone\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :data-tone=\"tone\"\n :data-custom=\"color !== undefined ? '' : undefined\"\n :data-shape=\"shape\"\n :data-indeterminate=\"indeterminate ? '' : undefined\"\n :aria-valuenow=\"indeterminate ? undefined : clamped\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"normalizedMax\"\n :style=\"{\n '--fill-fraction': String(fraction),\n '--custom-color': color,\n '--progress-diameter': px(size),\n '--progress-thickness': px(thickness),\n }\"\n >\n <svg class=\"v-progress-circular-svg\" aria-hidden=\"true\">\n <circle class=\"v-progress-circular-track\" pathLength=\"100\" />\n <circle class=\"v-progress-circular-bar\" pathLength=\"100\" />\n </svg>\n <span v-if=\"!indeterminate && (showValue || $slots.default)\" class=\"v-progress-circular-label\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The two dimensions are declared here as defaults, on the very element the props\n write to inline — which is what makes an explicit size or thickness always win. */\n .v-progress-circular {\n --progress-diameter: var(--vectis-control-size-progress-circular-diameter);\n --progress-thickness: var(--vectis-control-size-progress-circular-thickness);\n /* Arc and track are the tone's solid and soft colours, read from the shared table\n (`.v-tone`, set in the template). No text colour is taken from it: the figure sits\n in the hole of the ring, against the page, in the ordinary text colour. */\n --progress-fill: var(--tone-bg-solid);\n --progress-track: var(--tone-bg-soft);\n display: inline-grid;\n inline-size: var(--progress-diameter);\n block-size: var(--progress-diameter);\n vertical-align: middle;\n }\n\n .v-progress-circular-svg,\n .v-progress-circular-label {\n grid-area: 1 / 1;\n }\n\n .v-progress-circular-svg {\n inline-size: 100%;\n block-size: 100%;\n /* Turns the ring so that it starts at twelve o'clock rather than at three. It is\n written as its own property and not as a transform, so that it COMPOSES with the\n spinning of the unmeasurable mode instead of being overwritten by it. */\n rotate: -90deg;\n }\n\n /* In a right-to-left page the ring fills the other way round, following the reading\n direction. These individual properties are applied in a fixed order — move, turn,\n then mirror — so the mirroring is taken into account before the quarter turn above. */\n .v-progress-circular:dir(rtl) .v-progress-circular-svg {\n scale: 1 -1;\n }\n\n /* The geometry, entirely in CSS and in plain lengths. Percentages are avoided\n deliberately: a radius given as a percentage is resolved against a normalized\n diagonal rather than against the width, and there is no reason to expose the\n component to that when the diameter is always a length to begin with. */\n .v-progress-circular-track,\n .v-progress-circular-bar {\n cx: calc(var(--progress-diameter) / 2);\n cy: calc(var(--progress-diameter) / 2);\n /* A thickness as large as the diameter would give a NEGATIVE radius, which is an\n error in SVG: the circle would simply not be drawn. The floor degrades that case\n to a radius of zero instead. */\n r: max(0px, calc((var(--progress-diameter) - var(--progress-thickness)) / 2));\n fill: none;\n stroke-width: var(--progress-thickness);\n }\n\n .v-progress-circular-track {\n stroke: var(--progress-track);\n }\n\n .v-progress-circular-bar {\n stroke: var(--progress-fill);\n stroke-linecap: round;\n stroke-dasharray: 100;\n stroke-dashoffset: calc(100 - 100 * var(--fill-fraction));\n transition: stroke-dashoffset var(--vectis-duration-base) var(--vectis-ease-default);\n }\n\n .v-progress-circular[data-shape='square'] .v-progress-circular-bar {\n stroke-linecap: butt;\n }\n\n .v-progress-circular-label {\n display: flex;\n align-items: center;\n justify-content: center;\n /* TRAP — this centres the BOX itself in its cell, and it is not redundant with the\n centring above. The maximum width below stops the box from being stretched to\n fill the cell, and a stretch that cannot apply falls back to the START edge: the\n figure would end up against the side of the ring. */\n place-self: center;\n max-inline-size: calc(var(--progress-diameter) - var(--progress-thickness) * 2);\n color: var(--vectis-color-text);\n font-family: var(--vectis-text-family);\n /* Sized as a fraction of the diameter so it stays in proportion at every size — the\n same tolerance already granted to VSpinner's stroke — with a floor at the smallest\n type token, below which it would be unreadable. */\n font-size: max(var(--vectis-text-caption-size), calc(var(--progress-diameter) / 4));\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n text-align: center;\n }\n\n /* When the progress cannot be measured, two animations run at once: the whole ring\n turns, and the arc drawn on it lengthens and shortens. Their periods are deliberately\n not multiples of one another — were the arc to restart on every rotation, the pair\n would repeat the same picture over and over and read as a mechanical beat. At 1s and\n 1.5s they only realign every third turn; the slowed-down pair below is 3s and 5s, so\n every fifth. Keep any change to those four values out of a whole-number ratio. */\n .v-progress-circular[data-indeterminate] .v-progress-circular-svg {\n animation: v-progress-circular-spin var(--vectis-duration-1000) linear infinite;\n }\n\n .v-progress-circular[data-indeterminate] .v-progress-circular-bar {\n animation: v-progress-circular-dash var(--vectis-duration-1500) var(--vectis-ease-default)\n infinite;\n transition: none;\n }\n\n /* The turn of the whole ring. VSpinner writes the same one under its own name: shared\n in the core sheet it cost every consumer the bytes, where the two copies only meet in\n an application that loads both components. */\n @keyframes v-progress-circular-spin {\n to {\n transform: rotate(1turn);\n }\n }\n\n /* Both ends of the arc move, so it lengthens, shortens and travels around the circle\n at once. */\n @keyframes v-progress-circular-dash {\n 0% {\n stroke-dasharray: 5 100;\n stroke-dashoffset: 0;\n }\n\n 50% {\n stroke-dasharray: 70 100;\n stroke-dashoffset: -20;\n }\n\n 100% {\n stroke-dasharray: 5 100;\n stroke-dashoffset: -100;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-progress-circular-bar {\n transition: none;\n }\n\n /* Slowed down and not stopped: a motionless loader no longer says that anything is\n happening, which is the one thing it exists to say. */\n .v-progress-circular[data-indeterminate] .v-progress-circular-svg {\n animation-duration: var(--vectis-duration-3000);\n }\n\n .v-progress-circular[data-indeterminate] .v-progress-circular-bar {\n animation-duration: var(--vectis-duration-5000);\n }\n }\n\n /* An SVG keeps its authored colours under Windows forced colours, so the ring would\n stay pale indigo on a system palette. It is drawn in the system colours instead: the\n remaining part in GrayText, the progress in Highlight. */\n @media (forced-colors: active) {\n .v-progress-circular {\n forced-color-adjust: none;\n }\n\n .v-progress-circular-track {\n stroke: GrayText;\n }\n\n .v-progress-circular-bar {\n stroke: Highlight;\n }\n\n .v-progress-circular-label {\n color: CanvasText;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"VProgressCircular.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VProgressCircular/VProgressCircular.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core — no behavioural JS at all: value normalization and the display string.\n/**\n * Progress drawn as a ring, an SVG whose geometry is described entirely in CSS with no JS\n * computing anything.\n *\n * Two things make that possible. There is no `viewBox`, so one user unit is one pixel and\n * the circles take plain lengths — a fixed coordinate system would mean converting the\n * thickness into its units, hence knowing the ratio in code and recomputing it at every\n * change of size. And `pathLength=\"100\"` declares the outline 100 units long whatever its\n * real circumference, so the portion drawn is a percentage with no π anywhere.\n *\n * NAMING — pass a `label` saying what is progressing. The figure in the middle cannot\n * serve: `role=\"progressbar\"` makes its content presentational, so it is never announced.\n */\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useProgressValue } from '../../composables/useProgressValue'\nimport { useMessages } from '../../i18n/state'\nimport { px } from '../../utils/css'\n\n/** What the progress means, in colour. */\nexport type ProgressCircularTone = 'accent' | 'success' | 'warning' | 'danger' | 'neutral'\n\n/** How the arc ends. */\nexport type ProgressCircularShape = 'rounded' | 'square'\n\ninterface ProgressCircularProps {\n /** How far along it is. Anything outside the range is brought back into it. */\n value?: number\n /**\n * What is progressing, in words, for screen readers. It draws nothing on screen, and falls\n * back to the design system dictionary; an `aria-label` or `aria-labelledby` of your own\n * takes precedence over it.\n */\n label?: string\n /** What counts as finished. The other end is always zero. */\n max?: number\n /**\n * Says that the progress cannot be measured: the ring turns continuously and the\n * value is ignored.\n */\n indeterminate?: boolean\n /** What the progress means, expressed as a colour. */\n tone?: ProgressCircularTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. The\n * unfilled ring's shade is derived from it against the theme, so it follows the light\n * and the dark one.\n */\n color?: string\n /** The diameter, always IN PIXELS: `96` and `'96'` both give 96px. */\n size?: number | string\n /** How thick the ring is, always IN PIXELS: `8` and `'8'` both give 8px. */\n thickness?: number | string\n /** Whether the ends of the drawn arc are rounded or cut square. */\n shape?: ProgressCircularShape\n /**\n * Writes the percentage in the middle of the ring. It is ignored while the progress is\n * unmeasurable, there being no figure to write.\n */\n showValue?: boolean\n}\n\nconst props = withDefaults(defineProps<ProgressCircularProps>(), {\n value: 0,\n label: undefined,\n max: 100,\n indeterminate: false,\n tone: 'accent',\n color: undefined,\n size: undefined,\n thickness: undefined,\n shape: 'rounded',\n showValue: false,\n})\n\ndefineSlots<{\n /**\n * What to put in the middle of the ring instead of the percentage — a count of files,\n * an icon, a shortened figure.\n */\n default?(props: { value: number; max: number; percent: number }): unknown\n}>()\n\n/* The percent sign, and the non-breaking space French puts before it where English puts\n nothing, are a convention of the language: they belong in the dictionary rather than\n in this file. Any other format goes through the slot above. */\nconst m = useMessages()\n\nconst {\n max: normalizedMax,\n clamped,\n fraction,\n percent,\n roundedPercent,\n} = useProgressValue(\n () => props.value,\n () => props.max,\n)\n\n// @a11y\n// The canonical cascade: a consumer's `aria-labelledby`, then their `aria-label`, then the\n// `label` prop, then the dictionary. An indicator takes no name from the text inside it, so\n// without the last step it would have none at all.\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.progress.label)\n</script>\n\n<template>\n <span\n class=\"v-progress-circular v-tone\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :data-tone=\"tone\"\n :data-custom=\"color !== undefined ? '' : undefined\"\n :data-shape=\"shape\"\n :data-indeterminate=\"indeterminate ? '' : undefined\"\n :aria-valuenow=\"indeterminate ? undefined : clamped\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"normalizedMax\"\n :style=\"{\n '--fill-fraction': String(fraction),\n '--custom-color': color,\n '--progress-diameter': px(size),\n '--progress-thickness': px(thickness),\n }\"\n >\n <svg class=\"v-progress-circular-svg\" aria-hidden=\"true\">\n <circle class=\"v-progress-circular-track\" pathLength=\"100\" />\n <circle class=\"v-progress-circular-bar\" pathLength=\"100\" />\n </svg>\n <span v-if=\"!indeterminate && (showValue || $slots.default)\" class=\"v-progress-circular-label\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The two dimensions are declared here as defaults, on the very element the props\n write to inline — which is what makes an explicit size or thickness always win. */\n .v-progress-circular {\n --progress-diameter: var(--vectis-control-size-progress-circular-diameter);\n --progress-thickness: var(--vectis-control-size-progress-circular-thickness);\n /* Arc and track are the tone's solid and soft colours, read from the shared table\n (`.v-tone`, set in the template). No text colour is taken from it: the figure sits\n in the hole of the ring, against the page, in the ordinary text colour. */\n --progress-fill: var(--tone-bg-solid);\n --progress-track: var(--tone-bg-soft);\n display: inline-grid;\n inline-size: var(--progress-diameter);\n block-size: var(--progress-diameter);\n vertical-align: middle;\n }\n\n .v-progress-circular-svg,\n .v-progress-circular-label {\n grid-area: 1 / 1;\n }\n\n .v-progress-circular-svg {\n inline-size: 100%;\n block-size: 100%;\n /* Turns the ring so that it starts at twelve o'clock rather than at three. It is\n written as its own property and not as a transform, so that it COMPOSES with the\n spinning of the unmeasurable mode instead of being overwritten by it. */\n rotate: -90deg;\n }\n\n /* In a right-to-left page the ring fills the other way round, following the reading\n direction. These individual properties are applied in a fixed order — move, turn,\n then mirror — so the mirroring is taken into account before the quarter turn above. */\n .v-progress-circular:dir(rtl) .v-progress-circular-svg {\n scale: 1 -1;\n }\n\n /* The geometry, entirely in CSS and in plain lengths. Percentages are avoided\n deliberately: a radius given as a percentage is resolved against a normalized\n diagonal rather than against the width, and there is no reason to expose the\n component to that when the diameter is always a length to begin with. */\n .v-progress-circular-track,\n .v-progress-circular-bar {\n cx: calc(var(--progress-diameter) / 2);\n cy: calc(var(--progress-diameter) / 2);\n /* A thickness as large as the diameter would give a NEGATIVE radius, which is an\n error in SVG: the circle would simply not be drawn. The floor degrades that case\n to a radius of zero instead. */\n r: max(0px, calc((var(--progress-diameter) - var(--progress-thickness)) / 2));\n fill: none;\n stroke-width: var(--progress-thickness);\n }\n\n .v-progress-circular-track {\n stroke: var(--progress-track);\n }\n\n .v-progress-circular-bar {\n stroke: var(--progress-fill);\n stroke-linecap: round;\n stroke-dasharray: 100;\n stroke-dashoffset: calc(100 - 100 * var(--fill-fraction));\n transition: stroke-dashoffset var(--vectis-duration-base) var(--vectis-ease-default);\n }\n\n .v-progress-circular[data-shape='square'] .v-progress-circular-bar {\n stroke-linecap: butt;\n }\n\n /* A custom colour replaces the tone: at (0,2,0) it beats the base rule's mapping\n whatever the order the two are written in. */\n .v-progress-circular[data-custom] {\n --progress-fill: var(--custom-color);\n --progress-track: color-mix(in oklab, var(--custom-color), var(--vectis-color-surface) 85%);\n }\n\n .v-progress-circular-label {\n display: flex;\n align-items: center;\n justify-content: center;\n /* TRAP — this centres the BOX itself in its cell, and it is not redundant with the\n centring above. The maximum width below stops the box from being stretched to\n fill the cell, and a stretch that cannot apply falls back to the START edge: the\n figure would end up against the side of the ring. */\n place-self: center;\n max-inline-size: calc(var(--progress-diameter) - var(--progress-thickness) * 2);\n color: var(--vectis-color-text);\n font-family: var(--vectis-text-family);\n /* Sized as a fraction of the diameter so it stays in proportion at every size — the\n same tolerance already granted to VSpinner's stroke — with a floor at the smallest\n type token, below which it would be unreadable. */\n font-size: max(var(--vectis-text-caption-size), calc(var(--progress-diameter) / 4));\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n text-align: center;\n }\n\n /* When the progress cannot be measured, two animations run at once: the whole ring\n turns, and the arc drawn on it lengthens and shortens. Their periods are deliberately\n not multiples of one another — were the arc to restart on every rotation, the pair\n would repeat the same picture over and over and read as a mechanical beat. At 1s and\n 1.5s they only realign every third turn; the slowed-down pair below is 3s and 5s, so\n every fifth. Keep any change to those four values out of a whole-number ratio. */\n .v-progress-circular[data-indeterminate] .v-progress-circular-svg {\n animation: v-spin var(--vectis-duration-1000) linear infinite;\n }\n\n .v-progress-circular[data-indeterminate] .v-progress-circular-bar {\n animation: v-progress-circular-dash var(--vectis-duration-1500) var(--vectis-ease-default)\n infinite;\n transition: none;\n }\n\n /* Both ends of the arc move, so it lengthens, shortens and travels around the circle\n at once. The spin it rides on is the shared one from styles/utilities.css; only\n these keyframes, which belong to this component alone, stay here. */\n @keyframes v-progress-circular-dash {\n 0% {\n stroke-dasharray: 5 100;\n stroke-dashoffset: 0;\n }\n\n 50% {\n stroke-dasharray: 70 100;\n stroke-dashoffset: -20;\n }\n\n 100% {\n stroke-dasharray: 5 100;\n stroke-dashoffset: -100;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-progress-circular-bar {\n transition: none;\n }\n\n /* Slowed down and not stopped: a motionless loader no longer says that anything is\n happening, which is the one thing it exists to say. */\n .v-progress-circular[data-indeterminate] .v-progress-circular-svg {\n animation-duration: var(--vectis-duration-3000);\n }\n\n .v-progress-circular[data-indeterminate] .v-progress-circular-bar {\n animation-duration: var(--vectis-duration-5000);\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+DA,IAAM,IAAQ,GAwBR,IAAI,EAAY,GAEhB,EACJ,KAAK,GACL,YACA,aACA,YACA,sBACE,QACI,EAAM,aACN,EAAM,GACd,GAMM,IAAY,QAAmB,EAAM,SAAS,EAAE,MAAM,SAAS,KAAK;yBAIxE,EA2BO,QAAA;GA1BL,OAAM;GACN,MAAK;GACJ,cAAY,EAAA,CAAA;GACZ,aAAW,EAAA;GACX,eAAa,EAAA,UAAU,KAAA,IAAiB,KAAA,IAAR;GAChC,cAAY,EAAA;GACZ,sBAAoB,EAAA,gBAAa,KAAQ,KAAA;GACzC,iBAAe,EAAA,gBAAgB,KAAA,IAAY,EAAA,CAAA;GAC5C,iBAAc;GACb,iBAAe,EAAA,CAAA;GACf,OAAK,EAAA;uBAA6B,OAAO,EAAA,CAAA,CAAQ;sBAA2B,EAAA;2BAAoC,EAAA,CAAA,CAAE,CAAC,EAAA,IAAI;4BAAiC,EAAA,CAAA,CAAE,CAAC,EAAA,SAAS;;eAOrK,EAGM,OAAA;GAHD,OAAM;GAA0B,eAAY;MAC/C,EAA6D,UAAA;GAArD,OAAM;GAA4B,YAAW;MACrD,EAA2D,UAAA;GAAnD,OAAM;GAA0B,YAAW;aAExC,EAAA,kBAAkB,EAAA,aAAaA,EAAAA,OAAO,YAAA,EAAA,GAAnD,EAIO,QAJP,GAIO,CAHL,EAEO,EAAA,QAAA,WAAA;GAFA,OAAO,EAAA,CAAA;GAAU,KAAK,EAAA,CAAA;GAAgB,SAAS,EAAA,CAAA;WAE/C,CAAA,EAAA,EADF,EAAA,CAAA,CAAC,CAAC,SAAS,QAAQ,EAAA,CAAA,CAAc,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,IAAA,CAAA"}
1
+ {"version":3,"file":"VProgressCircular.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VProgressCircular/VProgressCircular.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * Progress drawn as a ring, an SVG whose geometry is described entirely in CSS with no JS\n * computing anything.\n *\n * Two things make that possible. There is no `viewBox`, so one user unit is one pixel and\n * the circles take plain lengths — a fixed coordinate system would mean converting the\n * thickness into its units, hence knowing the ratio in code and recomputing it at every\n * change of size. And `pathLength=\"100\"` declares the outline 100 units long whatever its\n * real circumference, so the portion drawn is a percentage with no π anywhere.\n *\n * NAMING — pass a `label` saying what is progressing. The figure in the middle cannot\n * serve: `role=\"progressbar\"` makes its content presentational, so it is never announced.\n */\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useProgressValue } from '../../composables/useProgressValue'\nimport { useMessages } from '../../i18n/state'\nimport { px } from '../../utils/css'\n\n/** What the progress means, in colour. */\nexport type ProgressCircularTone = 'neutral' | 'accent' | 'danger' | 'success' | 'warning'\n\n/** How the arc ends. */\nexport type ProgressCircularShape = 'rounded' | 'square'\n\n/** What the default slot receives. */\nexport interface ProgressCircularSlotProps {\n /** The value, brought back into the range. */\n value: number\n /** The bound, zero or more. */\n max: number\n /** How far along it is, as a percentage and unrounded. */\n percent: number\n}\n\ninterface ProgressCircularProps {\n /** How far along it is. Anything outside the range is brought back into it. */\n value?: number\n /**\n * What is progressing, in words, for screen readers. It draws nothing on screen, and falls\n * back to the design system dictionary; an `aria-label` or `aria-labelledby` of your own\n * takes precedence over it.\n */\n label?: string\n /** What counts as finished. The other end is always zero. */\n max?: number\n /**\n * Says that the progress cannot be measured: the ring turns continuously and the\n * value is ignored.\n */\n indeterminate?: boolean\n /** What the progress means, expressed as a colour. */\n tone?: ProgressCircularTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. The\n * unfilled ring's shade is derived from it against the theme, so it follows the light\n * and the dark one.\n */\n color?: string\n /** The diameter, always IN PIXELS: `96` and `'96'` both give 96px. */\n size?: number | string\n /** How thick the ring is, always IN PIXELS: `8` and `'8'` both give 8px. */\n thickness?: number | string\n /** Whether the ends of the drawn arc are rounded or cut square. */\n shape?: ProgressCircularShape\n /**\n * Writes the percentage in the middle of the ring. It is ignored while the progress is\n * unmeasurable, there being no figure to write.\n */\n showValue?: boolean\n}\n\nconst props = withDefaults(defineProps<ProgressCircularProps>(), {\n value: 0,\n label: undefined,\n max: 100,\n indeterminate: false,\n tone: 'accent',\n color: undefined,\n size: undefined,\n thickness: undefined,\n shape: 'rounded',\n showValue: false,\n})\n\ndefineSlots<{\n /**\n * What to put in the middle of the ring instead of the percentage: a count of files,\n * an icon, a shortened figure.\n */\n default?(props: ProgressCircularSlotProps): unknown\n}>()\n\n/* The percent sign, and the non-breaking space French puts before it where English puts\n nothing, are a convention of the language: they belong in the dictionary rather than\n in this file. Any other format goes through the slot above. */\nconst m = useMessages()\n\nconst {\n max: normalizedMax,\n clamped,\n fraction,\n percent,\n roundedPercent,\n} = useProgressValue(\n () => props.value,\n () => props.max,\n)\n\n// @a11y\n// The canonical cascade: a consumer's `aria-labelledby`, then their `aria-label`, then the\n// `label` prop, then the dictionary. An indicator takes no name from the text inside it, so\n// without the last step it would have none at all.\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.progress.label)\n</script>\n\n<template>\n <span\n class=\"v-progress-circular v-tone\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :data-tone=\"tone\"\n :data-custom=\"color !== undefined ? '' : undefined\"\n :data-shape=\"shape\"\n :data-indeterminate=\"indeterminate ? '' : undefined\"\n :aria-valuenow=\"indeterminate ? undefined : clamped\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"normalizedMax\"\n :style=\"{\n '--fill-fraction': String(fraction),\n '--custom-color': color,\n '--progress-diameter': px(size),\n '--progress-thickness': px(thickness),\n }\"\n >\n <svg class=\"v-progress-circular-svg\" aria-hidden=\"true\">\n <circle class=\"v-progress-circular-track\" pathLength=\"100\" />\n <circle class=\"v-progress-circular-bar\" pathLength=\"100\" />\n </svg>\n <span v-if=\"!indeterminate && (showValue || $slots.default)\" class=\"v-progress-circular-label\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The two dimensions are declared here as defaults, on the very element the props\n write to inline — which is what makes an explicit size or thickness always win. */\n .v-progress-circular {\n --progress-diameter: var(--vectis-control-size-progress-circular-diameter);\n --progress-thickness: var(--vectis-control-size-progress-circular-thickness);\n /* Arc and track are the tone's solid and soft colours, read from the shared table\n (`.v-tone`, set in the template). No text colour is taken from it: the figure sits\n in the hole of the ring, against the page, in the ordinary text colour. */\n --progress-fill: var(--tone-bg-solid);\n --progress-track: var(--tone-bg-soft);\n display: inline-grid;\n inline-size: var(--progress-diameter);\n block-size: var(--progress-diameter);\n vertical-align: middle;\n }\n\n .v-progress-circular-svg,\n .v-progress-circular-label {\n grid-area: 1 / 1;\n }\n\n .v-progress-circular-svg {\n inline-size: 100%;\n block-size: 100%;\n /* Turns the ring so that it starts at twelve o'clock rather than at three. It is\n written as its own property and not as a transform, so that it COMPOSES with the\n spinning of the unmeasurable mode instead of being overwritten by it. */\n rotate: -90deg;\n }\n\n /* In a right-to-left page the ring fills the other way round, following the reading\n direction. These individual properties are applied in a fixed order — move, turn,\n then mirror — so the mirroring is taken into account before the quarter turn above. */\n .v-progress-circular:dir(rtl) .v-progress-circular-svg {\n scale: 1 -1;\n }\n\n /* The geometry, entirely in CSS and in plain lengths. Percentages are avoided\n deliberately: a radius given as a percentage is resolved against a normalized\n diagonal rather than against the width, and there is no reason to expose the\n component to that when the diameter is always a length to begin with. */\n .v-progress-circular-track,\n .v-progress-circular-bar {\n cx: calc(var(--progress-diameter) / 2);\n cy: calc(var(--progress-diameter) / 2);\n /* A thickness as large as the diameter would give a NEGATIVE radius, which is an\n error in SVG: the circle would simply not be drawn. The floor degrades that case\n to a radius of zero instead. */\n r: max(0px, calc((var(--progress-diameter) - var(--progress-thickness)) / 2));\n fill: none;\n stroke-width: var(--progress-thickness);\n }\n\n .v-progress-circular-track {\n stroke: var(--progress-track);\n }\n\n .v-progress-circular-bar {\n stroke: var(--progress-fill);\n stroke-linecap: round;\n stroke-dasharray: 100;\n stroke-dashoffset: calc(100 - 100 * var(--fill-fraction));\n transition: stroke-dashoffset var(--vectis-duration-base) var(--vectis-ease-default);\n }\n\n .v-progress-circular[data-shape='square'] .v-progress-circular-bar {\n stroke-linecap: butt;\n }\n\n .v-progress-circular-label {\n display: flex;\n align-items: center;\n justify-content: center;\n /* TRAP — this centres the BOX itself in its cell, and it is not redundant with the\n centring above. The maximum width below stops the box from being stretched to\n fill the cell, and a stretch that cannot apply falls back to the START edge: the\n figure would end up against the side of the ring. */\n place-self: center;\n max-inline-size: calc(var(--progress-diameter) - var(--progress-thickness) * 2);\n color: var(--vectis-color-text);\n font-family: var(--vectis-text-family);\n /* Sized as a fraction of the diameter so it stays in proportion at every size — the\n same tolerance already granted to VSpinner's stroke — with a floor at the smallest\n type token, below which it would be unreadable. */\n font-size: max(var(--vectis-text-caption-size), calc(var(--progress-diameter) / 4));\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n text-align: center;\n }\n\n /* When the progress cannot be measured, two animations run at once: the whole ring\n turns, and the arc drawn on it lengthens and shortens. Their periods are deliberately\n not multiples of one another — were the arc to restart on every rotation, the pair\n would repeat the same picture over and over and read as a mechanical beat. At 1s and\n 1.5s they only realign every third turn; the slowed-down pair below is 3s and 5s, so\n every fifth. Keep any change to those four values out of a whole-number ratio. */\n .v-progress-circular[data-indeterminate] .v-progress-circular-svg {\n animation: v-progress-circular-spin var(--vectis-duration-1000) linear infinite;\n }\n\n .v-progress-circular[data-indeterminate] .v-progress-circular-bar {\n animation: v-progress-circular-dash var(--vectis-duration-1500) var(--vectis-ease-default)\n infinite;\n transition: none;\n }\n\n /* The turn of the whole ring. VSpinner writes the same one under its own name: shared\n in the core sheet it cost every consumer the bytes, where the two copies only meet in\n an application that loads both components. */\n @keyframes v-progress-circular-spin {\n to {\n transform: rotate(1turn);\n }\n }\n\n /* Both ends of the arc move, so it lengthens, shortens and travels around the circle\n at once. */\n @keyframes v-progress-circular-dash {\n 0% {\n stroke-dasharray: 5 100;\n stroke-dashoffset: 0;\n }\n\n 50% {\n stroke-dasharray: 70 100;\n stroke-dashoffset: -20;\n }\n\n 100% {\n stroke-dasharray: 5 100;\n stroke-dashoffset: -100;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-progress-circular-bar {\n transition: none;\n }\n\n /* Slowed down and not stopped: a motionless loader no longer says that anything is\n happening, which is the one thing it exists to say. */\n .v-progress-circular[data-indeterminate] .v-progress-circular-svg {\n animation-duration: var(--vectis-duration-3000);\n }\n\n .v-progress-circular[data-indeterminate] .v-progress-circular-bar {\n animation-duration: var(--vectis-duration-5000);\n }\n }\n\n /* An SVG keeps its authored colours under Windows forced colours, so the ring would\n stay pale indigo on a system palette. It is drawn in the system colours instead: the\n remaining part in GrayText, the progress in Highlight. */\n @media (forced-colors: active) {\n .v-progress-circular {\n forced-color-adjust: none;\n }\n\n .v-progress-circular-track {\n stroke: GrayText;\n }\n\n .v-progress-circular-bar {\n stroke: Highlight;\n }\n\n .v-progress-circular-label {\n color: CanvasText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwEA,IAAM,IAAQ,GAwBR,IAAI,EAAY,GAEhB,EACJ,KAAK,GACL,YACA,aACA,YACA,sBACE,QACI,EAAM,aACN,EAAM,GACd,GAMM,IAAY,QAAmB,EAAM,SAAS,EAAE,MAAM,SAAS,KAAK;yBAIxE,EA2BO,QAAA;GA1BL,OAAM;GACN,MAAK;GACJ,cAAY,EAAA,CAAA;GACZ,aAAW,EAAA;GACX,eAAa,EAAA,UAAU,KAAA,IAAiB,KAAA,IAAR;GAChC,cAAY,EAAA;GACZ,sBAAoB,EAAA,gBAAa,KAAQ,KAAA;GACzC,iBAAe,EAAA,gBAAgB,KAAA,IAAY,EAAA,CAAA;GAC5C,iBAAc;GACb,iBAAe,EAAA,CAAA;GACf,OAAK,EAAA;uBAA6B,OAAO,EAAA,CAAA,CAAQ;sBAA2B,EAAA;2BAAoC,EAAA,CAAA,CAAE,CAAC,EAAA,IAAI;4BAAiC,EAAA,CAAA,CAAE,CAAC,EAAA,SAAS;;eAOrK,EAGM,OAAA;GAHD,OAAM;GAA0B,eAAY;MAC/C,EAA6D,UAAA;GAArD,OAAM;GAA4B,YAAW;MACrD,EAA2D,UAAA;GAAnD,OAAM;GAA0B,YAAW;aAExC,EAAA,kBAAkB,EAAA,aAAaA,EAAAA,OAAO,YAAA,EAAA,GAAnD,EAIO,QAJP,GAIO,CAHL,EAEO,EAAA,QAAA,WAAA;GAFA,OAAO,EAAA,CAAA;GAAU,KAAK,EAAA,CAAA;GAAgB,SAAS,EAAA,CAAA;WAE/C,CAAA,EAAA,EADF,EAAA,CAAA,CAAC,CAAC,SAAS,QAAQ,EAAA,CAAA,CAAc,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,IAAA,CAAA"}
@@ -1,2 +1,2 @@
1
1
  @layer vectis.reset, vectis.tokens, vectis.components, vectis.utilities;
2
- @layer vectis.components{.v-progress-linear{--progress-thickness:var(--vectis-control-size-progress-linear-thickness);--progress-fill:var(--tone-bg-solid);--progress-track:var(--tone-bg-soft);--progress-text-fallback:var(--tone-text-solid);inline-size:100%;block-size:var(--progress-thickness);border-radius:var(--vectis-radius-pill);background:var(--progress-track);font-family:var(--vectis-text-family);font-size:var(--vectis-text-caption-size);font-weight:var(--vectis-text-control-weight);line-height:var(--vectis-text-control-leading);display:block;position:relative}.v-progress-linear[data-shape=square]{border-radius:0}.v-progress-linear-fill{inline-size:calc(100% * var(--fill-fraction));border-radius:inherit;background:var(--progress-fill);transition:inline-size var(--vectis-duration-base) var(--vectis-ease-default);position:absolute;inset-block:0;inset-inline-start:0}.v-progress-linear[data-custom]{--progress-fill:var(--custom-color);--progress-track:color-mix(in oklab, var(--custom-color), var(--vectis-color-surface) 85%);--progress-text-fallback:var(--vectis-color-text-on-accent)}.v-progress-linear-text{--progress-clip-start:calc(100% * var(--fill-fraction));--progress-clip-end:-100vmax;padding-inline:var(--vectis-space-2);color:var(--vectis-color-text);clip-path:inset(-100vmax var(--progress-clip-end) -100vmax var(--progress-clip-start));transition:clip-path var(--vectis-duration-base) var(--vectis-ease-default);writing-mode:horizontal-tb;white-space:nowrap;pointer-events:none;justify-content:center;align-items:center;display:flex;position:absolute;inset:0}.v-progress-linear[data-value-position=start] .v-progress-linear-text{justify-content:start}.v-progress-linear[data-value-position=end] .v-progress-linear-text{justify-content:end}.v-progress-linear-text[data-on-fill]{--progress-clip-start:-100vmax;--progress-clip-end:calc(100% * (1 - var(--fill-fraction)));color:var(--progress-text-fallback)}@supports (color:contrast-color(red)){.v-progress-linear-text[data-on-fill]{color:contrast-color(var(--progress-fill))}}.v-progress-linear:dir(rtl) .v-progress-linear-text{clip-path:inset(-100vmax var(--progress-clip-start) -100vmax var(--progress-clip-end))}.v-progress-linear[data-orientation=vertical]{writing-mode:vertical-lr;inline-size:var(--vectis-control-size-progress-linear-length)}.v-progress-linear[data-orientation=vertical] .v-progress-linear-fill{inset-inline:auto 0}.v-progress-linear[data-orientation=vertical] .v-progress-linear-text{padding-inline:0;padding-block:var(--vectis-space-2);flex-direction:column-reverse}.v-progress-linear[data-orientation=vertical] .v-progress-linear-text,.v-progress-linear[data-orientation=vertical]:dir(rtl) .v-progress-linear-text{clip-path:inset(var(--progress-clip-end) -100vmax var(--progress-clip-start) -100vmax)}.v-progress-linear[data-indeterminate]{overflow:hidden}.v-progress-linear[data-indeterminate] .v-progress-linear-fill{--progress-bar:40%;inline-size:var(--progress-bar);animation:v-progress-linear-indeterminate var(--vectis-duration-1500) var(--vectis-ease-in-out) infinite;transition:none;inset-inline:0 auto}@keyframes v-progress-linear-indeterminate{0%{inset-inline-start:calc(-1 * var(--progress-bar))}to{inset-inline-start:100%}}.v-progress-linear[data-orientation=vertical][data-indeterminate] .v-progress-linear-fill{animation-direction:reverse}@media (prefers-reduced-motion:reduce){.v-progress-linear-fill,.v-progress-linear-text{transition:none}.v-progress-linear[data-indeterminate] .v-progress-linear-fill{animation-duration:var(--vectis-duration-5000)}}}
2
+ @layer vectis.components{.v-progress-linear{--progress-thickness:var(--vectis-control-size-progress-linear-thickness);--progress-fill:var(--tone-bg-solid);--progress-track:var(--tone-bg-soft);--progress-text-fallback:var(--tone-text-solid);inline-size:100%;block-size:var(--progress-thickness);border-radius:var(--vectis-radius-pill);background:var(--progress-track);font-family:var(--vectis-text-family);font-size:var(--vectis-text-caption-size);font-weight:var(--vectis-text-control-weight);line-height:var(--vectis-text-control-leading);display:block;position:relative}.v-progress-linear[data-shape=square]{border-radius:0}.v-progress-linear-fill{inline-size:calc(100% * var(--fill-fraction));border-radius:inherit;background:var(--progress-fill);transition:inline-size var(--vectis-duration-base) var(--vectis-ease-default);position:absolute;inset-block:0;inset-inline-start:0}.v-progress-linear-text{--progress-clip-start:calc(100% * var(--fill-fraction));--progress-clip-end:-100vmax;padding-inline:var(--vectis-space-2);color:var(--vectis-color-text);clip-path:inset(-100vmax var(--progress-clip-end) -100vmax var(--progress-clip-start));transition:clip-path var(--vectis-duration-base) var(--vectis-ease-default);writing-mode:horizontal-tb;white-space:nowrap;pointer-events:none;justify-content:center;align-items:center;display:flex;position:absolute;inset:0}.v-progress-linear[data-value-position=start] .v-progress-linear-text{justify-content:start}.v-progress-linear[data-value-position=end] .v-progress-linear-text{justify-content:end}.v-progress-linear-text[data-on-fill]{--progress-clip-start:-100vmax;--progress-clip-end:calc(100% * (1 - var(--fill-fraction)));color:var(--progress-text-fallback)}@supports (color:contrast-color(red)){.v-progress-linear-text[data-on-fill]{color:contrast-color(var(--progress-fill))}}.v-progress-linear:dir(rtl) .v-progress-linear-text{clip-path:inset(-100vmax var(--progress-clip-start) -100vmax var(--progress-clip-end))}.v-progress-linear[data-orientation=vertical]{writing-mode:vertical-lr;inline-size:var(--vectis-control-size-progress-linear-length)}.v-progress-linear[data-orientation=vertical] .v-progress-linear-fill{inset-inline:auto 0}.v-progress-linear[data-orientation=vertical]:dir(rtl) .v-progress-linear-fill{inset-inline:0 auto}.v-progress-linear[data-orientation=vertical] .v-progress-linear-text{padding-inline:0;padding-block:var(--vectis-space-2);flex-direction:column-reverse}.v-progress-linear[data-orientation=vertical] .v-progress-linear-text,.v-progress-linear[data-orientation=vertical]:dir(rtl) .v-progress-linear-text{clip-path:inset(var(--progress-clip-end) -100vmax var(--progress-clip-start) -100vmax)}.v-progress-linear[data-indeterminate]{overflow:hidden}.v-progress-linear[data-indeterminate] .v-progress-linear-fill{--progress-bar:40%;inline-size:var(--progress-bar);animation:v-progress-linear-indeterminate var(--vectis-duration-1500) var(--vectis-ease-in-out) infinite;transition:none;inset-inline:0 auto}@keyframes v-progress-linear-indeterminate{0%{inset-inline-start:calc(-1 * var(--progress-bar))}to{inset-inline-start:100%}}.v-progress-linear[data-orientation=vertical][data-indeterminate] .v-progress-linear-fill{animation-direction:reverse}.v-progress-linear[data-orientation=vertical][data-indeterminate]:dir(rtl) .v-progress-linear-fill{animation-direction:normal}@media (prefers-reduced-motion:reduce){.v-progress-linear-fill,.v-progress-linear-text{transition:none}.v-progress-linear[data-indeterminate] .v-progress-linear-fill{animation-duration:var(--vectis-duration-5000)}}@media (forced-colors:active){.v-progress-linear{forced-color-adjust:none;box-shadow:inset 0 0 0 var(--vectis-control-border-width) CanvasText;background:canvas}.v-progress-linear-fill{background:highlight}.v-progress-linear-text{color:canvastext}.v-progress-linear-text[data-on-fill]{color:highlighttext}}}
@@ -1,11 +1,20 @@
1
1
  /** What the progress means, in colour. */
2
- export type ProgressLinearTone = 'accent' | 'success' | 'warning' | 'danger' | 'neutral';
2
+ export type ProgressLinearTone = 'neutral' | 'accent' | 'danger' | 'success' | 'warning';
3
3
  /** How the track and the fill end. */
4
4
  export type ProgressLinearShape = 'rounded' | 'square';
5
5
  /** Where the value sits along the bar. */
6
6
  export type ProgressLinearValuePosition = 'start' | 'center' | 'end';
7
7
  /** Which way the bar fills. */
8
8
  export type ProgressLinearOrientation = 'horizontal' | 'vertical';
9
+ /** What the default slot receives. */
10
+ export interface ProgressLinearSlotProps {
11
+ /** The value, brought back into the range. */
12
+ value: number;
13
+ /** The bound, zero or more. */
14
+ max: number;
15
+ /** How far along it is, as a percentage and unrounded. */
16
+ percent: number;
17
+ }
9
18
  interface ProgressLinearProps {
10
19
  /** How far along it is. Anything outside the range is brought back into it. */
11
20
  value?: number;
@@ -33,7 +42,7 @@ interface ProgressLinearProps {
33
42
  color?: string;
34
43
  /**
35
44
  * How thick the bar is, always IN PIXELS: `12` and `'12'` both give 12px. It is 4px
36
- * by default — bear in mind that showing text inside a bar that thin needs an
45
+ * by default, and showing text inside a bar that thin needs an
37
46
  * explicit thickness.
38
47
  */
39
48
  thickness?: number | string;
@@ -56,15 +65,11 @@ type __VLS_Slots = {
56
65
  /**
57
66
  * What to write inside the bar instead of the percentage.
58
67
  *
59
- * TRAP — it is rendered TWICE, once over the empty track and once over the filled
60
- * part in a colour that contrasts with it, each copy cut at the fill's edge. So
61
- * whatever it renders must be pure: anything with a side effect would happen twice.
68
+ * It is rendered TWICE, once over the empty track and once over the filled part in a
69
+ * colour that contrasts with it, each copy cut at the fill's edge. So whatever it renders
70
+ * must be pure: anything with a side effect would happen twice.
62
71
  */
63
- default?(props: {
64
- value: number;
65
- max: number;
66
- percent: number;
67
- }): unknown;
72
+ default?(props: ProgressLinearSlotProps): unknown;
68
73
  };
69
74
  declare const __VLS_base: import('vue').DefineComponent<ProgressLinearProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<ProgressLinearProps> & Readonly<{}>, {
70
75
  label: string;
@@ -1 +1 @@
1
- {"version":3,"file":"VProgressLinear.js","names":[],"sources":["../../../src/components/VProgressLinear/VProgressLinear.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core — no behavioural JS at all: value normalization and the display string.\n/**\n * A bar filling up as something progresses. The element rendered IS the track, and the\n * whole geometry follows from a single number set on it — the fraction filled, with no\n * unit. Everything is written in logical properties, so turning the bar vertical needs\n * nothing but a change of writing direction.\n *\n * There is no behavioural JavaScript: the value is clamped and a percentage is\n * formatted, and that is all.\n *\n * On naming: pass a `label` saying what is progressing. The text shown inside the\n * bar cannot serve as that name — the role a progress bar carries makes its content\n * presentational, so screen readers do not announce it.\n */\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useProgressValue } from '../../composables/useProgressValue'\nimport { useMessages } from '../../i18n/state'\nimport { px } from '../../utils/css'\n\n/** What the progress means, in colour. */\nexport type ProgressLinearTone = 'accent' | 'success' | 'warning' | 'danger' | 'neutral'\n\n/** How the track and the fill end. */\nexport type ProgressLinearShape = 'rounded' | 'square'\n\n/** Where the value sits along the bar. */\nexport type ProgressLinearValuePosition = 'start' | 'center' | 'end'\n\n/** Which way the bar fills. */\nexport type ProgressLinearOrientation = 'horizontal' | 'vertical'\n\ninterface ProgressLinearProps {\n /** How far along it is. Anything outside the range is brought back into it. */\n value?: number\n /**\n * What is progressing, in words, for screen readers. It draws nothing on screen, and falls\n * back to the design system dictionary; an `aria-label` or `aria-labelledby` of your own\n * takes precedence over it.\n */\n label?: string\n /** What counts as finished. The other end is always zero. */\n max?: number\n /**\n * Says that the progress cannot be measured: the bar animates continuously and the\n * value is ignored. It is what to use while waiting for a server that reports no\n * percentage.\n */\n indeterminate?: boolean\n /** What the progress means, expressed as a colour. */\n tone?: ProgressLinearTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. The\n * track's own shade is derived from it against the theme, so it follows the light and\n * the dark one.\n */\n color?: string\n /**\n * How thick the bar is, always IN PIXELS: `12` and `'12'` both give 12px. It is 4px\n * by default — bear in mind that showing text inside a bar that thin needs an\n * explicit thickness.\n */\n thickness?: number | string\n /** Whether the ends of the bar are rounded or square. */\n shape?: ProgressLinearShape\n /**\n * Writes the percentage inside the bar. It is ignored while the progress is\n * unmeasurable, there being no figure to write.\n */\n showValue?: boolean\n /**\n * Where that text sits along the bar. On a vertical bar the start is the zero end,\n * hence the bottom.\n */\n valuePosition?: ProgressLinearValuePosition\n /** Turns the bar upright, filling from the bottom up. */\n orientation?: ProgressLinearOrientation\n}\n\nconst props = withDefaults(defineProps<ProgressLinearProps>(), {\n value: 0,\n label: undefined,\n max: 100,\n indeterminate: false,\n tone: 'accent',\n color: undefined,\n thickness: undefined,\n shape: 'rounded',\n showValue: false,\n valuePosition: 'center',\n orientation: 'horizontal',\n})\n\ndefineSlots<{\n /**\n * What to write inside the bar instead of the percentage.\n *\n * TRAP — it is rendered TWICE, once over the empty track and once over the filled\n * part in a colour that contrasts with it, each copy cut at the fill's edge. So\n * whatever it renders must be pure: anything with a side effect would happen twice.\n */\n default?(props: { value: number; max: number; percent: number }): unknown\n}>()\n\n/* The percent sign, and the non-breaking space French puts before it where English puts\n nothing, are a convention of the language: they belong in the dictionary rather than\n in this file. Any other format goes through the slot above. */\nconst m = useMessages()\n\nconst {\n max: normalizedMax,\n clamped,\n fraction,\n percent,\n roundedPercent,\n} = useProgressValue(\n () => props.value,\n () => props.max,\n)\n\n// @a11y\n// The canonical cascade: a consumer's `aria-labelledby`, then their `aria-label`, then the\n// `label` prop, then the dictionary. An indicator takes no name from the text inside it, so\n// without the last step it would have none at all.\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.progress.label)\n</script>\n\n<template>\n <div\n class=\"v-progress-linear v-tone\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :data-tone=\"tone\"\n :data-custom=\"color !== undefined ? '' : undefined\"\n :data-shape=\"shape\"\n :data-orientation=\"orientation\"\n :data-value-position=\"valuePosition\"\n :data-indeterminate=\"indeterminate ? '' : undefined\"\n :aria-valuenow=\"indeterminate ? undefined : clamped\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"normalizedMax\"\n :style=\"{\n '--fill-fraction': String(fraction),\n '--custom-color': color,\n '--progress-thickness': px(thickness),\n }\"\n >\n <span class=\"v-progress-linear-fill\" />\n <!--\n The same text twice, each copy cut at the fill's edge so that the two complete\n each other exactly: the first in the ordinary text colour over the empty track,\n the second over the filled part, coloured to contrast with it. The second is\n hidden from screen readers, being a duplicate of text already there.\n -->\n <template v-if=\"!indeterminate && (showValue || $slots.default)\">\n <span class=\"v-progress-linear-text\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n <span class=\"v-progress-linear-text\" data-on-fill aria-hidden=\"true\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n </template>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n /*\n * The element IS the track, and it takes the whole length available. Sizing it is the\n * consumer's business, through the parent or through a width of their own — a\n * consumer's style sits outside our layers and always wins.\n */\n .v-progress-linear {\n --progress-thickness: var(--vectis-control-size-progress-linear-thickness);\n /* Fill, track and the text over the fill are the tone's solid, soft and on-solid\n colours, read from the shared table (`.v-tone`, set in the template). */\n --progress-fill: var(--tone-bg-solid);\n --progress-track: var(--tone-bg-soft);\n --progress-text-fallback: var(--tone-text-solid);\n position: relative;\n display: block;\n inline-size: 100%;\n block-size: var(--progress-thickness);\n border-radius: var(--vectis-radius-pill);\n background: var(--progress-track);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n }\n\n .v-progress-linear[data-shape='square'] {\n border-radius: 0;\n }\n\n .v-progress-linear-fill {\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n inline-size: calc(100% * var(--fill-fraction));\n border-radius: inherit;\n background: var(--progress-fill);\n /*\n * The fill is animated by changing its LENGTH, which the browser has to lay out\n * again on every frame. Scaling it would be cheaper, but a scale is physical: it\n * would have to be undone for the vertical orientation and again for a\n * right-to-left page, where a logical length simply works.\n *\n * The duration and easing are repeated by the clip of the text over the fill, or the\n * colour boundary would drift away from the fill's own edge for the length of the\n * transition.\n */\n transition: inline-size var(--vectis-duration-base) var(--vectis-ease-default);\n }\n\n /* A custom colour replaces the tone: at (0,2,0) it beats the base rule's mapping\n whatever the order the two are written in. */\n .v-progress-linear[data-custom] {\n --progress-fill: var(--custom-color);\n --progress-track: color-mix(in oklab, var(--custom-color), var(--vectis-color-surface) 85%);\n --progress-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n /* The text inside the bar, in two copies laid over the same box — the track's own,\n which is why a cut expressed as a fraction of it lands exactly on the fill's edge.\n Bear in mind that the default 4px thickness cannot hold text at all: showing any\n implies asking for a thicker bar.\n\n TRAP — the two copies are COMPLEMENTARY and never superimposed: this one is cut OUT\n of the filled part, the other cut TO it, so every letter is painted exactly once.\n Removing either clip raises no error and stays invisible for as long as both copies\n resolve to the SAME colour, which is what happens wherever the adaptive colour\n function is unsupported. Where it IS supported and the two disagree — black over an\n accent fill against white text in the dark theme — the copy underneath shows its\n antialiased edges all around the letters of the one on top, and the label reads as\n a halo. */\n .v-progress-linear-text {\n /* The two insets of the cut: one on the edge the fill grows FROM, one on the edge it\n grows towards. They are named after those roles rather than after physical sides,\n so the three geometry rules further down — horizontal, right-to-left, vertical —\n all read the same pair. This copy cuts on the start side; the one over the fill\n swaps them. */\n --progress-clip-start: calc(100% * var(--fill-fraction));\n --progress-clip-end: -100vmax;\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding-inline: var(--vectis-space-2);\n color: var(--vectis-color-text);\n /* The large negative inset on the two sides that do NOT carry the cut is what stops\n text taller or wider than the bar from being cropped by its own clip. */\n clip-path: inset(-100vmax var(--progress-clip-end) -100vmax var(--progress-clip-start));\n /* The same duration and easing as the fill's own length, or the colour boundary\n would drift away from the fill's edge for the length of the transition. */\n transition: clip-path var(--vectis-duration-base) var(--vectis-ease-default);\n /* The bar itself is turned on its side in vertical mode; the text is put back\n upright here, since a label read sideways is not the point. */\n writing-mode: horizontal-tb;\n white-space: nowrap;\n pointer-events: none;\n }\n\n .v-progress-linear[data-value-position='start'] .v-progress-linear-text {\n justify-content: start;\n }\n\n .v-progress-linear[data-value-position='end'] .v-progress-linear-text {\n justify-content: end;\n }\n\n .v-progress-linear-text[data-on-fill] {\n /* The exact complement of the copy above: the cut moves to the other end of the\n axis, so the two together cover the whole bar and overlap nowhere. */\n --progress-clip-start: -100vmax;\n --progress-clip-end: calc(100% * (1 - var(--fill-fraction)));\n /* The per-tone fallback colour. The adaptive one cannot simply be written as a\n second declaration after it: because that declaration contains a var(), a browser\n with no support does not reject it at parse time — it would win the cascade and\n only then turn invalid, which resets the colour to inherited and leaves the\n fallback never applied. The block below is the way round it, being evaluated\n before any var() substitution. */\n color: var(--progress-text-fallback);\n }\n\n /* Where the adaptive colour function exists, the text picks black or white against\n whatever colour the fill ended up with. */\n @supports (color: contrast-color(red)) {\n .v-progress-linear-text[data-on-fill] {\n color: contrast-color(var(--progress-fill));\n }\n }\n\n /* In a right-to-left page the fill grows from the right, so the two insets change\n physical sides — the variables themselves keep their meaning. */\n .v-progress-linear:dir(rtl) .v-progress-linear-text {\n clip-path: inset(-100vmax var(--progress-clip-start) -100vmax var(--progress-clip-end));\n }\n\n /* Upright, the bar fills from the bottom.\n\n Changing the writing direction on the element is enough to turn everything: the\n axis the fill grows along becomes vertical, so the length and the thickness swap\n places, and both the fill and the animation follow with no rule written twice.\n\n TRAP — putting zero at the bottom is NOT done by reversing the direction, which\n would also apply to the text of the two copies: bidirectional reordering would then\n display \"50 %\" as \"% 50\". The fill is anchored to the far end of the axis instead.\n\n The length comes from a token because there is nothing to inherit it from: in a\n parent of automatic height the bar would collapse to nothing. A consumer's own\n height overrides it, sitting outside our layers. */\n .v-progress-linear[data-orientation='vertical'] {\n writing-mode: vertical-lr;\n inline-size: var(--vectis-control-size-progress-linear-length);\n }\n\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-fill {\n inset-inline-start: auto;\n inset-inline-end: 0;\n }\n\n /* The text now stacks along the vertical axis, whose start is the zero end — the\n bottom of the bar. */\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-text {\n flex-direction: column-reverse;\n padding-inline: 0;\n padding-block: var(--vectis-space-2);\n }\n\n /* The cut moves to the vertical axis: the fill rises from the bottom, which is that\n axis' start. It is therefore the same in both reading directions, which means the\n right-to-left rule further up has to be neutralized.\n\n TRAP — the second selector is what neutralizes it, and it is written that way on\n purpose: it is one step MORE specific than that rule, where the first selector alone\n would merely tie with it and win by source order — a far more fragile arrangement. */\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-text,\n .v-progress-linear[data-orientation='vertical']:dir(rtl) .v-progress-linear-text {\n clip-path: inset(var(--progress-clip-end) -100vmax var(--progress-clip-start) -100vmax);\n }\n\n /* When the progress cannot be measured, a bar of fixed size crosses the track from\n just outside one end to just outside the other. At each extreme it is exactly flush\n with the edge without ever pulling away from it, which is what makes the loop\n invisible and keeps the track from ever looking empty — no second bar is needed.\n\n The easing carries the whole impression: a gradual entry, a quick crossing, a damped\n exit. A linear run, or an asymmetric curve, immediately reads as mechanical.\n\n The movement is expressed in LOGICAL properties — a position and a size as\n percentages of the track — rather than as a transform. One definition then serves\n the horizontal, the vertical and the right-to-left cases, where a transform, being\n physical, would need its own keyframes per axis and a flip per direction. */\n .v-progress-linear[data-indeterminate] {\n overflow: hidden;\n }\n\n .v-progress-linear[data-indeterminate] .v-progress-linear-fill {\n /* The starting position is derived from this size, and the two must stay tied: that\n is what has the bar begin exactly off the track rather than half on it. */\n --progress-bar: 40%;\n /* The anchoring is put back at the start of the axis, vertical case included — where\n a measurable progress anchors at the far end instead. */\n inset-inline-start: 0;\n inset-inline-end: auto;\n inline-size: var(--progress-bar);\n /* The transition of a measurable progress has no place here: switching to this mode\n would otherwise be animated as the bar growing to its new size. */\n transition: none;\n animation: v-progress-linear-indeterminate var(--vectis-duration-1500) var(--vectis-ease-in-out)\n infinite;\n }\n\n @keyframes v-progress-linear-indeterminate {\n from {\n inset-inline-start: calc(-1 * var(--progress-bar));\n }\n\n to {\n inset-inline-start: 100%;\n }\n }\n\n /* Turned upright, the axis runs downwards, so the bar would travel from the top down —\n the opposite of a measurable fill, which rises from the bottom. The same keyframes\n are simply read backwards, which changes nothing else BECAUSE the easing curve is\n symmetric; an asymmetric one would need a second set of keyframes.\n\n Nothing is needed for a right-to-left page: the logical inset already follows the\n reading direction. */\n .v-progress-linear[data-orientation='vertical'][data-indeterminate] .v-progress-linear-fill {\n animation-direction: reverse;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-progress-linear-fill,\n .v-progress-linear-text {\n transition: none;\n }\n\n /* Slowed down and not stopped: a motionless loader no longer says that anything is\n happening, which is the one thing it exists to say. */\n .v-progress-linear[data-indeterminate] .v-progress-linear-fill {\n animation-duration: var(--vectis-duration-5000);\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"VProgressLinear.js","names":[],"sources":["../../../src/components/VProgressLinear/VProgressLinear.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * A bar filling up as something progresses. The element rendered IS the track, and the\n * whole geometry follows from a single number set on it — the fraction filled, with no\n * unit. Everything is written in logical properties, so turning the bar vertical needs\n * nothing but a change of writing direction.\n *\n * There is no behavioural JavaScript: the value is clamped and a percentage is\n * formatted, and that is all.\n *\n * On naming: pass a `label` saying what is progressing. The text shown inside the\n * bar cannot serve as that name — the role a progress bar carries makes its content\n * presentational, so screen readers do not announce it.\n */\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useProgressValue } from '../../composables/useProgressValue'\nimport { useMessages } from '../../i18n/state'\nimport { px } from '../../utils/css'\n\n/** What the progress means, in colour. */\nexport type ProgressLinearTone = 'neutral' | 'accent' | 'danger' | 'success' | 'warning'\n\n/** How the track and the fill end. */\nexport type ProgressLinearShape = 'rounded' | 'square'\n\n/** Where the value sits along the bar. */\nexport type ProgressLinearValuePosition = 'start' | 'center' | 'end'\n\n/** Which way the bar fills. */\nexport type ProgressLinearOrientation = 'horizontal' | 'vertical'\n\n/** What the default slot receives. */\nexport interface ProgressLinearSlotProps {\n /** The value, brought back into the range. */\n value: number\n /** The bound, zero or more. */\n max: number\n /** How far along it is, as a percentage and unrounded. */\n percent: number\n}\n\ninterface ProgressLinearProps {\n /** How far along it is. Anything outside the range is brought back into it. */\n value?: number\n /**\n * What is progressing, in words, for screen readers. It draws nothing on screen, and falls\n * back to the design system dictionary; an `aria-label` or `aria-labelledby` of your own\n * takes precedence over it.\n */\n label?: string\n /** What counts as finished. The other end is always zero. */\n max?: number\n /**\n * Says that the progress cannot be measured: the bar animates continuously and the\n * value is ignored. It is what to use while waiting for a server that reports no\n * percentage.\n */\n indeterminate?: boolean\n /** What the progress means, expressed as a colour. */\n tone?: ProgressLinearTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. The\n * track's own shade is derived from it against the theme, so it follows the light and\n * the dark one.\n */\n color?: string\n /**\n * How thick the bar is, always IN PIXELS: `12` and `'12'` both give 12px. It is 4px\n * by default, and showing text inside a bar that thin needs an\n * explicit thickness.\n */\n thickness?: number | string\n /** Whether the ends of the bar are rounded or square. */\n shape?: ProgressLinearShape\n /**\n * Writes the percentage inside the bar. It is ignored while the progress is\n * unmeasurable, there being no figure to write.\n */\n showValue?: boolean\n /**\n * Where that text sits along the bar. On a vertical bar the start is the zero end,\n * hence the bottom.\n */\n valuePosition?: ProgressLinearValuePosition\n /** Turns the bar upright, filling from the bottom up. */\n orientation?: ProgressLinearOrientation\n}\n\nconst props = withDefaults(defineProps<ProgressLinearProps>(), {\n value: 0,\n label: undefined,\n max: 100,\n indeterminate: false,\n tone: 'accent',\n color: undefined,\n thickness: undefined,\n shape: 'rounded',\n showValue: false,\n valuePosition: 'center',\n orientation: 'horizontal',\n})\n\ndefineSlots<{\n /**\n * What to write inside the bar instead of the percentage.\n *\n * It is rendered TWICE, once over the empty track and once over the filled part in a\n * colour that contrasts with it, each copy cut at the fill's edge. So whatever it renders\n * must be pure: anything with a side effect would happen twice.\n */\n default?(props: ProgressLinearSlotProps): unknown\n}>()\n\n/* The percent sign, and the non-breaking space French puts before it where English puts\n nothing, are a convention of the language: they belong in the dictionary rather than\n in this file. Any other format goes through the slot above. */\nconst m = useMessages()\n\nconst {\n max: normalizedMax,\n clamped,\n fraction,\n percent,\n roundedPercent,\n} = useProgressValue(\n () => props.value,\n () => props.max,\n)\n\n// @a11y\n// The canonical cascade: a consumer's `aria-labelledby`, then their `aria-label`, then the\n// `label` prop, then the dictionary. An indicator takes no name from the text inside it, so\n// without the last step it would have none at all.\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.progress.label)\n</script>\n\n<template>\n <div\n class=\"v-progress-linear v-tone\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :data-tone=\"tone\"\n :data-custom=\"color !== undefined ? '' : undefined\"\n :data-shape=\"shape\"\n :data-orientation=\"orientation\"\n :data-value-position=\"valuePosition\"\n :data-indeterminate=\"indeterminate ? '' : undefined\"\n :aria-valuenow=\"indeterminate ? undefined : clamped\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"normalizedMax\"\n :style=\"{\n '--fill-fraction': String(fraction),\n '--custom-color': color,\n '--progress-thickness': px(thickness),\n }\"\n >\n <span class=\"v-progress-linear-fill\" />\n <!--\n The same text twice, each copy cut at the fill's edge so that the two complete\n each other exactly: the first in the ordinary text colour over the empty track,\n the second over the filled part, coloured to contrast with it. The second is\n hidden from screen readers, being a duplicate of text already there.\n -->\n <template v-if=\"!indeterminate && (showValue || $slots.default)\">\n <span class=\"v-progress-linear-text\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n <span class=\"v-progress-linear-text\" data-on-fill aria-hidden=\"true\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n </template>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n /*\n * The element IS the track, and it takes the whole length available. Sizing it is the\n * consumer's business, through the parent or through a width of their own — a\n * consumer's style sits outside our layers and always wins.\n */\n .v-progress-linear {\n --progress-thickness: var(--vectis-control-size-progress-linear-thickness);\n /* Fill, track and the text over the fill are the tone's solid, soft and on-solid\n colours, read from the shared table (`.v-tone`, set in the template). */\n --progress-fill: var(--tone-bg-solid);\n --progress-track: var(--tone-bg-soft);\n --progress-text-fallback: var(--tone-text-solid);\n position: relative;\n display: block;\n inline-size: 100%;\n block-size: var(--progress-thickness);\n border-radius: var(--vectis-radius-pill);\n background: var(--progress-track);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n }\n\n .v-progress-linear[data-shape='square'] {\n border-radius: 0;\n }\n\n .v-progress-linear-fill {\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n inline-size: calc(100% * var(--fill-fraction));\n border-radius: inherit;\n background: var(--progress-fill);\n /*\n * The fill is animated by changing its LENGTH, which the browser has to lay out\n * again on every frame. Scaling it would be cheaper, but a scale is physical: it\n * would have to be undone for the vertical orientation and again for a\n * right-to-left page, where a logical length simply works.\n *\n * The duration and easing are repeated by the clip of the text over the fill, or the\n * colour boundary would drift away from the fill's own edge for the length of the\n * transition.\n */\n transition: inline-size var(--vectis-duration-base) var(--vectis-ease-default);\n }\n\n /* The text inside the bar, in two copies laid over the same box — the track's own,\n which is why a cut expressed as a fraction of it lands exactly on the fill's edge.\n Bear in mind that the default 4px thickness cannot hold text at all: showing any\n implies asking for a thicker bar.\n\n TRAP — the two copies are COMPLEMENTARY and never superimposed: this one is cut OUT\n of the filled part, the other cut TO it, so every letter is painted exactly once.\n Removing either clip raises no error and stays invisible for as long as both copies\n resolve to the SAME colour, which is what happens wherever the adaptive colour\n function is unsupported. Where it IS supported and the two disagree — black over an\n accent fill against white text in the dark theme — the copy underneath shows its\n antialiased edges all around the letters of the one on top, and the label reads as\n a halo. */\n .v-progress-linear-text {\n /* The two insets of the cut: one on the edge the fill grows FROM, one on the edge it\n grows towards. They are named after those roles rather than after physical sides,\n so the three geometry rules further down — horizontal, right-to-left, vertical —\n all read the same pair. This copy cuts on the start side; the one over the fill\n swaps them. */\n --progress-clip-start: calc(100% * var(--fill-fraction));\n --progress-clip-end: -100vmax;\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding-inline: var(--vectis-space-2);\n color: var(--vectis-color-text);\n /* The large negative inset on the two sides that do NOT carry the cut is what stops\n text taller or wider than the bar from being cropped by its own clip. */\n clip-path: inset(-100vmax var(--progress-clip-end) -100vmax var(--progress-clip-start));\n /* The same duration and easing as the fill's own length, or the colour boundary\n would drift away from the fill's edge for the length of the transition. */\n transition: clip-path var(--vectis-duration-base) var(--vectis-ease-default);\n /* The bar itself is turned on its side in vertical mode; the text is put back\n upright here, since a label read sideways is not the point. */\n writing-mode: horizontal-tb;\n white-space: nowrap;\n pointer-events: none;\n }\n\n .v-progress-linear[data-value-position='start'] .v-progress-linear-text {\n justify-content: start;\n }\n\n .v-progress-linear[data-value-position='end'] .v-progress-linear-text {\n justify-content: end;\n }\n\n .v-progress-linear-text[data-on-fill] {\n /* The exact complement of the copy above: the cut moves to the other end of the\n axis, so the two together cover the whole bar and overlap nowhere. */\n --progress-clip-start: -100vmax;\n --progress-clip-end: calc(100% * (1 - var(--fill-fraction)));\n /* The per-tone fallback colour. The adaptive one cannot simply be written as a\n second declaration after it: because that declaration contains a var(), a browser\n with no support does not reject it at parse time — it would win the cascade and\n only then turn invalid, which resets the colour to inherited and leaves the\n fallback never applied. The block below is the way round it, being evaluated\n before any var() substitution. */\n color: var(--progress-text-fallback);\n }\n\n /* Where the adaptive colour function exists, the text picks black or white against\n whatever colour the fill ended up with. */\n @supports (color: contrast-color(red)) {\n .v-progress-linear-text[data-on-fill] {\n color: contrast-color(var(--progress-fill));\n }\n }\n\n /* In a right-to-left page the fill grows from the right, so the two insets change\n physical sides — the variables themselves keep their meaning. */\n .v-progress-linear:dir(rtl) .v-progress-linear-text {\n clip-path: inset(-100vmax var(--progress-clip-start) -100vmax var(--progress-clip-end));\n }\n\n /* Upright, the bar fills from the bottom.\n\n Changing the writing direction on the element is enough to turn everything: the\n axis the fill grows along becomes vertical, so the length and the thickness swap\n places, and both the fill and the animation follow with no rule written twice.\n\n TRAP — putting zero at the bottom is NOT done by reversing the direction, which\n would also apply to the text of the two copies: bidirectional reordering would then\n display \"50 %\" as \"% 50\". The fill is anchored to the far end of the axis instead.\n\n The length comes from a token because there is nothing to inherit it from: in a\n parent of automatic height the bar would collapse to nothing. A consumer's own\n height overrides it, sitting outside our layers. */\n .v-progress-linear[data-orientation='vertical'] {\n writing-mode: vertical-lr;\n inline-size: var(--vectis-control-size-progress-linear-length);\n }\n\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-fill {\n inset-inline-start: auto;\n inset-inline-end: 0;\n }\n\n /* TRAP — a right-to-left page reverses the inline axis of a vertical writing mode too:\n `vertical-lr` then runs from the bottom up, so the far end anchored above is the TOP.\n The fill goes back to the start of the axis, which is now the bottom. Without this\n rule the bar fills downwards, and the clip of the text, which assumes a fill rising\n from the bottom, paints each copy over the wrong ground. */\n .v-progress-linear[data-orientation='vertical']:dir(rtl) .v-progress-linear-fill {\n inset-inline-start: 0;\n inset-inline-end: auto;\n }\n\n /* The text now stacks along the vertical axis, whose start is the zero end — the\n bottom of the bar. */\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-text {\n flex-direction: column-reverse;\n padding-inline: 0;\n padding-block: var(--vectis-space-2);\n }\n\n /* The cut moves to the vertical axis: the fill rises from the bottom, which is that\n axis' start. It is therefore the same in both reading directions, which means the\n right-to-left rule further up has to be neutralized.\n\n TRAP — the second selector is what neutralizes it, and it is written that way on\n purpose: it is one step MORE specific than that rule, where the first selector alone\n would merely tie with it and win by source order — a far more fragile arrangement. */\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-text,\n .v-progress-linear[data-orientation='vertical']:dir(rtl) .v-progress-linear-text {\n clip-path: inset(var(--progress-clip-end) -100vmax var(--progress-clip-start) -100vmax);\n }\n\n /* When the progress cannot be measured, a bar of fixed size crosses the track from\n just outside one end to just outside the other. At each extreme it is exactly flush\n with the edge without ever pulling away from it, which is what makes the loop\n invisible and keeps the track from ever looking empty — no second bar is needed.\n\n The easing carries the whole impression: a gradual entry, a quick crossing, a damped\n exit. A linear run, or an asymmetric curve, immediately reads as mechanical.\n\n The movement is expressed in LOGICAL properties — a position and a size as\n percentages of the track — rather than as a transform. One definition then serves\n the horizontal, the vertical and the right-to-left cases, where a transform, being\n physical, would need its own keyframes per axis and a flip per direction. */\n .v-progress-linear[data-indeterminate] {\n overflow: hidden;\n }\n\n .v-progress-linear[data-indeterminate] .v-progress-linear-fill {\n /* The starting position is derived from this size, and the two must stay tied: that\n is what has the bar begin exactly off the track rather than half on it. */\n --progress-bar: 40%;\n /* The anchoring is put back at the start of the axis, vertical case included — where\n a measurable progress anchors at the far end instead. */\n inset-inline-start: 0;\n inset-inline-end: auto;\n inline-size: var(--progress-bar);\n /* The transition of a measurable progress has no place here: switching to this mode\n would otherwise be animated as the bar growing to its new size. */\n transition: none;\n animation: v-progress-linear-indeterminate var(--vectis-duration-1500) var(--vectis-ease-in-out)\n infinite;\n }\n\n @keyframes v-progress-linear-indeterminate {\n from {\n inset-inline-start: calc(-1 * var(--progress-bar));\n }\n\n to {\n inset-inline-start: 100%;\n }\n }\n\n /* Turned upright, the axis runs downwards, so the bar would travel from the top down —\n the opposite of a measurable fill, which rises from the bottom. The same keyframes\n are simply read backwards, which changes nothing else BECAUSE the easing curve is\n symmetric; an asymmetric one would need a second set of keyframes.\n\n A horizontal right-to-left page needs nothing: the logical inset already follows the\n reading direction. A vertical one does, below. */\n .v-progress-linear[data-orientation='vertical'][data-indeterminate] .v-progress-linear-fill {\n animation-direction: reverse;\n }\n\n /* On a right-to-left page the vertical axis already runs upwards (see the trap above),\n so the keyframes are read forwards again. */\n .v-progress-linear[data-orientation='vertical'][data-indeterminate]:dir(rtl)\n .v-progress-linear-fill {\n animation-direction: normal;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-progress-linear-fill,\n .v-progress-linear-text {\n transition: none;\n }\n\n /* Slowed down and not stopped: a motionless loader no longer says that anything is\n happening, which is the one thing it exists to say. */\n .v-progress-linear[data-indeterminate] .v-progress-linear-fill {\n animation-duration: var(--vectis-duration-5000);\n }\n }\n\n /* Windows forced colours repaint every background as Canvas, which takes the track and\n the fill away together and leaves a floating figure at best. The bar is drawn in the\n system colours instead, the VSlider pair: an edge in CanvasText for the track, the\n Highlight pair for the fill and the text over it. `forced-color-adjust` inherits, so\n both copies of the text are given their colour here too. */\n @media (forced-colors: active) {\n .v-progress-linear {\n forced-color-adjust: none;\n background: Canvas;\n box-shadow: inset 0 0 0 var(--vectis-control-border-width) CanvasText;\n }\n\n .v-progress-linear-fill {\n background: Highlight;\n }\n\n .v-progress-linear-text {\n color: CanvasText;\n }\n\n .v-progress-linear-text[data-on-fill] {\n color: HighlightText;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"VProgressLinear.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VProgressLinear/VProgressLinear.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core — no behavioural JS at all: value normalization and the display string.\n/**\n * A bar filling up as something progresses. The element rendered IS the track, and the\n * whole geometry follows from a single number set on it — the fraction filled, with no\n * unit. Everything is written in logical properties, so turning the bar vertical needs\n * nothing but a change of writing direction.\n *\n * There is no behavioural JavaScript: the value is clamped and a percentage is\n * formatted, and that is all.\n *\n * On naming: pass a `label` saying what is progressing. The text shown inside the\n * bar cannot serve as that name — the role a progress bar carries makes its content\n * presentational, so screen readers do not announce it.\n */\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useProgressValue } from '../../composables/useProgressValue'\nimport { useMessages } from '../../i18n/state'\nimport { px } from '../../utils/css'\n\n/** What the progress means, in colour. */\nexport type ProgressLinearTone = 'accent' | 'success' | 'warning' | 'danger' | 'neutral'\n\n/** How the track and the fill end. */\nexport type ProgressLinearShape = 'rounded' | 'square'\n\n/** Where the value sits along the bar. */\nexport type ProgressLinearValuePosition = 'start' | 'center' | 'end'\n\n/** Which way the bar fills. */\nexport type ProgressLinearOrientation = 'horizontal' | 'vertical'\n\ninterface ProgressLinearProps {\n /** How far along it is. Anything outside the range is brought back into it. */\n value?: number\n /**\n * What is progressing, in words, for screen readers. It draws nothing on screen, and falls\n * back to the design system dictionary; an `aria-label` or `aria-labelledby` of your own\n * takes precedence over it.\n */\n label?: string\n /** What counts as finished. The other end is always zero. */\n max?: number\n /**\n * Says that the progress cannot be measured: the bar animates continuously and the\n * value is ignored. It is what to use while waiting for a server that reports no\n * percentage.\n */\n indeterminate?: boolean\n /** What the progress means, expressed as a colour. */\n tone?: ProgressLinearTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. The\n * track's own shade is derived from it against the theme, so it follows the light and\n * the dark one.\n */\n color?: string\n /**\n * How thick the bar is, always IN PIXELS: `12` and `'12'` both give 12px. It is 4px\n * by default — bear in mind that showing text inside a bar that thin needs an\n * explicit thickness.\n */\n thickness?: number | string\n /** Whether the ends of the bar are rounded or square. */\n shape?: ProgressLinearShape\n /**\n * Writes the percentage inside the bar. It is ignored while the progress is\n * unmeasurable, there being no figure to write.\n */\n showValue?: boolean\n /**\n * Where that text sits along the bar. On a vertical bar the start is the zero end,\n * hence the bottom.\n */\n valuePosition?: ProgressLinearValuePosition\n /** Turns the bar upright, filling from the bottom up. */\n orientation?: ProgressLinearOrientation\n}\n\nconst props = withDefaults(defineProps<ProgressLinearProps>(), {\n value: 0,\n label: undefined,\n max: 100,\n indeterminate: false,\n tone: 'accent',\n color: undefined,\n thickness: undefined,\n shape: 'rounded',\n showValue: false,\n valuePosition: 'center',\n orientation: 'horizontal',\n})\n\ndefineSlots<{\n /**\n * What to write inside the bar instead of the percentage.\n *\n * TRAP — it is rendered TWICE, once over the empty track and once over the filled\n * part in a colour that contrasts with it, each copy cut at the fill's edge. So\n * whatever it renders must be pure: anything with a side effect would happen twice.\n */\n default?(props: { value: number; max: number; percent: number }): unknown\n}>()\n\n/* The percent sign, and the non-breaking space French puts before it where English puts\n nothing, are a convention of the language: they belong in the dictionary rather than\n in this file. Any other format goes through the slot above. */\nconst m = useMessages()\n\nconst {\n max: normalizedMax,\n clamped,\n fraction,\n percent,\n roundedPercent,\n} = useProgressValue(\n () => props.value,\n () => props.max,\n)\n\n// @a11y\n// The canonical cascade: a consumer's `aria-labelledby`, then their `aria-label`, then the\n// `label` prop, then the dictionary. An indicator takes no name from the text inside it, so\n// without the last step it would have none at all.\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.progress.label)\n</script>\n\n<template>\n <div\n class=\"v-progress-linear v-tone\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :data-tone=\"tone\"\n :data-custom=\"color !== undefined ? '' : undefined\"\n :data-shape=\"shape\"\n :data-orientation=\"orientation\"\n :data-value-position=\"valuePosition\"\n :data-indeterminate=\"indeterminate ? '' : undefined\"\n :aria-valuenow=\"indeterminate ? undefined : clamped\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"normalizedMax\"\n :style=\"{\n '--fill-fraction': String(fraction),\n '--custom-color': color,\n '--progress-thickness': px(thickness),\n }\"\n >\n <span class=\"v-progress-linear-fill\" />\n <!--\n The same text twice, each copy cut at the fill's edge so that the two complete\n each other exactly: the first in the ordinary text colour over the empty track,\n the second over the filled part, coloured to contrast with it. The second is\n hidden from screen readers, being a duplicate of text already there.\n -->\n <template v-if=\"!indeterminate && (showValue || $slots.default)\">\n <span class=\"v-progress-linear-text\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n <span class=\"v-progress-linear-text\" data-on-fill aria-hidden=\"true\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n </template>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n /*\n * The element IS the track, and it takes the whole length available. Sizing it is the\n * consumer's business, through the parent or through a width of their own — a\n * consumer's style sits outside our layers and always wins.\n */\n .v-progress-linear {\n --progress-thickness: var(--vectis-control-size-progress-linear-thickness);\n /* Fill, track and the text over the fill are the tone's solid, soft and on-solid\n colours, read from the shared table (`.v-tone`, set in the template). */\n --progress-fill: var(--tone-bg-solid);\n --progress-track: var(--tone-bg-soft);\n --progress-text-fallback: var(--tone-text-solid);\n position: relative;\n display: block;\n inline-size: 100%;\n block-size: var(--progress-thickness);\n border-radius: var(--vectis-radius-pill);\n background: var(--progress-track);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n }\n\n .v-progress-linear[data-shape='square'] {\n border-radius: 0;\n }\n\n .v-progress-linear-fill {\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n inline-size: calc(100% * var(--fill-fraction));\n border-radius: inherit;\n background: var(--progress-fill);\n /*\n * The fill is animated by changing its LENGTH, which the browser has to lay out\n * again on every frame. Scaling it would be cheaper, but a scale is physical: it\n * would have to be undone for the vertical orientation and again for a\n * right-to-left page, where a logical length simply works.\n *\n * The duration and easing are repeated by the clip of the text over the fill, or the\n * colour boundary would drift away from the fill's own edge for the length of the\n * transition.\n */\n transition: inline-size var(--vectis-duration-base) var(--vectis-ease-default);\n }\n\n /* A custom colour replaces the tone: at (0,2,0) it beats the base rule's mapping\n whatever the order the two are written in. */\n .v-progress-linear[data-custom] {\n --progress-fill: var(--custom-color);\n --progress-track: color-mix(in oklab, var(--custom-color), var(--vectis-color-surface) 85%);\n --progress-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n /* The text inside the bar, in two copies laid over the same box — the track's own,\n which is why a cut expressed as a fraction of it lands exactly on the fill's edge.\n Bear in mind that the default 4px thickness cannot hold text at all: showing any\n implies asking for a thicker bar.\n\n TRAP — the two copies are COMPLEMENTARY and never superimposed: this one is cut OUT\n of the filled part, the other cut TO it, so every letter is painted exactly once.\n Removing either clip raises no error and stays invisible for as long as both copies\n resolve to the SAME colour, which is what happens wherever the adaptive colour\n function is unsupported. Where it IS supported and the two disagree — black over an\n accent fill against white text in the dark theme — the copy underneath shows its\n antialiased edges all around the letters of the one on top, and the label reads as\n a halo. */\n .v-progress-linear-text {\n /* The two insets of the cut: one on the edge the fill grows FROM, one on the edge it\n grows towards. They are named after those roles rather than after physical sides,\n so the three geometry rules further down — horizontal, right-to-left, vertical —\n all read the same pair. This copy cuts on the start side; the one over the fill\n swaps them. */\n --progress-clip-start: calc(100% * var(--fill-fraction));\n --progress-clip-end: -100vmax;\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding-inline: var(--vectis-space-2);\n color: var(--vectis-color-text);\n /* The large negative inset on the two sides that do NOT carry the cut is what stops\n text taller or wider than the bar from being cropped by its own clip. */\n clip-path: inset(-100vmax var(--progress-clip-end) -100vmax var(--progress-clip-start));\n /* The same duration and easing as the fill's own length, or the colour boundary\n would drift away from the fill's edge for the length of the transition. */\n transition: clip-path var(--vectis-duration-base) var(--vectis-ease-default);\n /* The bar itself is turned on its side in vertical mode; the text is put back\n upright here, since a label read sideways is not the point. */\n writing-mode: horizontal-tb;\n white-space: nowrap;\n pointer-events: none;\n }\n\n .v-progress-linear[data-value-position='start'] .v-progress-linear-text {\n justify-content: start;\n }\n\n .v-progress-linear[data-value-position='end'] .v-progress-linear-text {\n justify-content: end;\n }\n\n .v-progress-linear-text[data-on-fill] {\n /* The exact complement of the copy above: the cut moves to the other end of the\n axis, so the two together cover the whole bar and overlap nowhere. */\n --progress-clip-start: -100vmax;\n --progress-clip-end: calc(100% * (1 - var(--fill-fraction)));\n /* The per-tone fallback colour. The adaptive one cannot simply be written as a\n second declaration after it: because that declaration contains a var(), a browser\n with no support does not reject it at parse time — it would win the cascade and\n only then turn invalid, which resets the colour to inherited and leaves the\n fallback never applied. The block below is the way round it, being evaluated\n before any var() substitution. */\n color: var(--progress-text-fallback);\n }\n\n /* Where the adaptive colour function exists, the text picks black or white against\n whatever colour the fill ended up with. */\n @supports (color: contrast-color(red)) {\n .v-progress-linear-text[data-on-fill] {\n color: contrast-color(var(--progress-fill));\n }\n }\n\n /* In a right-to-left page the fill grows from the right, so the two insets change\n physical sides — the variables themselves keep their meaning. */\n .v-progress-linear:dir(rtl) .v-progress-linear-text {\n clip-path: inset(-100vmax var(--progress-clip-start) -100vmax var(--progress-clip-end));\n }\n\n /* Upright, the bar fills from the bottom.\n\n Changing the writing direction on the element is enough to turn everything: the\n axis the fill grows along becomes vertical, so the length and the thickness swap\n places, and both the fill and the animation follow with no rule written twice.\n\n TRAP — putting zero at the bottom is NOT done by reversing the direction, which\n would also apply to the text of the two copies: bidirectional reordering would then\n display \"50 %\" as \"% 50\". The fill is anchored to the far end of the axis instead.\n\n The length comes from a token because there is nothing to inherit it from: in a\n parent of automatic height the bar would collapse to nothing. A consumer's own\n height overrides it, sitting outside our layers. */\n .v-progress-linear[data-orientation='vertical'] {\n writing-mode: vertical-lr;\n inline-size: var(--vectis-control-size-progress-linear-length);\n }\n\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-fill {\n inset-inline-start: auto;\n inset-inline-end: 0;\n }\n\n /* The text now stacks along the vertical axis, whose start is the zero end — the\n bottom of the bar. */\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-text {\n flex-direction: column-reverse;\n padding-inline: 0;\n padding-block: var(--vectis-space-2);\n }\n\n /* The cut moves to the vertical axis: the fill rises from the bottom, which is that\n axis' start. It is therefore the same in both reading directions, which means the\n right-to-left rule further up has to be neutralized.\n\n TRAP — the second selector is what neutralizes it, and it is written that way on\n purpose: it is one step MORE specific than that rule, where the first selector alone\n would merely tie with it and win by source order — a far more fragile arrangement. */\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-text,\n .v-progress-linear[data-orientation='vertical']:dir(rtl) .v-progress-linear-text {\n clip-path: inset(var(--progress-clip-end) -100vmax var(--progress-clip-start) -100vmax);\n }\n\n /* When the progress cannot be measured, a bar of fixed size crosses the track from\n just outside one end to just outside the other. At each extreme it is exactly flush\n with the edge without ever pulling away from it, which is what makes the loop\n invisible and keeps the track from ever looking empty — no second bar is needed.\n\n The easing carries the whole impression: a gradual entry, a quick crossing, a damped\n exit. A linear run, or an asymmetric curve, immediately reads as mechanical.\n\n The movement is expressed in LOGICAL properties — a position and a size as\n percentages of the track — rather than as a transform. One definition then serves\n the horizontal, the vertical and the right-to-left cases, where a transform, being\n physical, would need its own keyframes per axis and a flip per direction. */\n .v-progress-linear[data-indeterminate] {\n overflow: hidden;\n }\n\n .v-progress-linear[data-indeterminate] .v-progress-linear-fill {\n /* The starting position is derived from this size, and the two must stay tied: that\n is what has the bar begin exactly off the track rather than half on it. */\n --progress-bar: 40%;\n /* The anchoring is put back at the start of the axis, vertical case included — where\n a measurable progress anchors at the far end instead. */\n inset-inline-start: 0;\n inset-inline-end: auto;\n inline-size: var(--progress-bar);\n /* The transition of a measurable progress has no place here: switching to this mode\n would otherwise be animated as the bar growing to its new size. */\n transition: none;\n animation: v-progress-linear-indeterminate var(--vectis-duration-1500) var(--vectis-ease-in-out)\n infinite;\n }\n\n @keyframes v-progress-linear-indeterminate {\n from {\n inset-inline-start: calc(-1 * var(--progress-bar));\n }\n\n to {\n inset-inline-start: 100%;\n }\n }\n\n /* Turned upright, the axis runs downwards, so the bar would travel from the top down —\n the opposite of a measurable fill, which rises from the bottom. The same keyframes\n are simply read backwards, which changes nothing else BECAUSE the easing curve is\n symmetric; an asymmetric one would need a second set of keyframes.\n\n Nothing is needed for a right-to-left page: the logical inset already follows the\n reading direction. */\n .v-progress-linear[data-orientation='vertical'][data-indeterminate] .v-progress-linear-fill {\n animation-direction: reverse;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-progress-linear-fill,\n .v-progress-linear-text {\n transition: none;\n }\n\n /* Slowed down and not stopped: a motionless loader no longer says that anything is\n happening, which is the one thing it exists to say. */\n .v-progress-linear[data-indeterminate] .v-progress-linear-fill {\n animation-duration: var(--vectis-duration-5000);\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+EA,IAAM,IAAQ,GA4BR,IAAI,EAAY,GAEhB,EACJ,KAAK,GACL,YACA,aACA,YACA,sBACE,QACI,EAAM,aACN,EAAM,GACd,GAMM,IAAY,QAAmB,EAAM,SAAS,EAAE,MAAM,SAAS,KAAK;yBAIxE,EAsCM,OAAA;GArCJ,OAAM;GACN,MAAK;GACJ,cAAY,EAAA,CAAA;GACZ,aAAW,EAAA;GACX,eAAa,EAAA,UAAU,KAAA,IAAiB,KAAA,IAAR;GAChC,cAAY,EAAA;GACZ,oBAAkB,EAAA;GAClB,uBAAqB,EAAA;GACrB,sBAAoB,EAAA,gBAAa,KAAQ,KAAA;GACzC,iBAAe,EAAA,gBAAgB,KAAA,IAAY,EAAA,CAAA;GAC5C,iBAAc;GACb,iBAAe,EAAA,CAAA;GACf,OAAK,EAAA;uBAA6B,OAAO,EAAA,CAAA,CAAQ;sBAA2B,EAAA;4BAAqC,EAAA,CAAA,CAAE,CAAC,EAAA,SAAS;;eAM9H,EAAuC,QAAA,EAAjC,OAAM,yBAAwB,GAAA,MAAA,EAAA,GAAA,CAOnB,EAAA,kBAAkB,EAAA,aAAaA,EAAAA,OAAO,YAAA,EAAA,GAAvD,EAWW,GAAA,EAAA,KAAA,EAAA,GAAA,CAVT,EAIO,QAJP,GAIO,CAHL,EAEO,EAAA,QAAA,WAAA;GAFA,OAAO,EAAA,CAAA;GAAU,KAAK,EAAA,CAAA;GAAgB,SAAS,EAAA,CAAA;WAE/C,CAAA,EAAA,EADF,EAAA,CAAA,CAAC,CAAC,SAAS,QAAQ,EAAA,CAAA,CAAc,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAGxC,EAIO,QAJP,GAIO,CAHL,EAEO,EAAA,QAAA,WAAA;GAFA,OAAO,EAAA,CAAA;GAAU,KAAK,EAAA,CAAA;GAAgB,SAAS,EAAA,CAAA;WAE/C,CAAA,EAAA,EADF,EAAA,CAAA,CAAC,CAAC,SAAS,QAAQ,EAAA,CAAA,CAAc,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,IAAA,CAAA"}
1
+ {"version":3,"file":"VProgressLinear.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VProgressLinear/VProgressLinear.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * A bar filling up as something progresses. The element rendered IS the track, and the\n * whole geometry follows from a single number set on it — the fraction filled, with no\n * unit. Everything is written in logical properties, so turning the bar vertical needs\n * nothing but a change of writing direction.\n *\n * There is no behavioural JavaScript: the value is clamped and a percentage is\n * formatted, and that is all.\n *\n * On naming: pass a `label` saying what is progressing. The text shown inside the\n * bar cannot serve as that name — the role a progress bar carries makes its content\n * presentational, so screen readers do not announce it.\n */\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useProgressValue } from '../../composables/useProgressValue'\nimport { useMessages } from '../../i18n/state'\nimport { px } from '../../utils/css'\n\n/** What the progress means, in colour. */\nexport type ProgressLinearTone = 'neutral' | 'accent' | 'danger' | 'success' | 'warning'\n\n/** How the track and the fill end. */\nexport type ProgressLinearShape = 'rounded' | 'square'\n\n/** Where the value sits along the bar. */\nexport type ProgressLinearValuePosition = 'start' | 'center' | 'end'\n\n/** Which way the bar fills. */\nexport type ProgressLinearOrientation = 'horizontal' | 'vertical'\n\n/** What the default slot receives. */\nexport interface ProgressLinearSlotProps {\n /** The value, brought back into the range. */\n value: number\n /** The bound, zero or more. */\n max: number\n /** How far along it is, as a percentage and unrounded. */\n percent: number\n}\n\ninterface ProgressLinearProps {\n /** How far along it is. Anything outside the range is brought back into it. */\n value?: number\n /**\n * What is progressing, in words, for screen readers. It draws nothing on screen, and falls\n * back to the design system dictionary; an `aria-label` or `aria-labelledby` of your own\n * takes precedence over it.\n */\n label?: string\n /** What counts as finished. The other end is always zero. */\n max?: number\n /**\n * Says that the progress cannot be measured: the bar animates continuously and the\n * value is ignored. It is what to use while waiting for a server that reports no\n * percentage.\n */\n indeterminate?: boolean\n /** What the progress means, expressed as a colour. */\n tone?: ProgressLinearTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. The\n * track's own shade is derived from it against the theme, so it follows the light and\n * the dark one.\n */\n color?: string\n /**\n * How thick the bar is, always IN PIXELS: `12` and `'12'` both give 12px. It is 4px\n * by default, and showing text inside a bar that thin needs an\n * explicit thickness.\n */\n thickness?: number | string\n /** Whether the ends of the bar are rounded or square. */\n shape?: ProgressLinearShape\n /**\n * Writes the percentage inside the bar. It is ignored while the progress is\n * unmeasurable, there being no figure to write.\n */\n showValue?: boolean\n /**\n * Where that text sits along the bar. On a vertical bar the start is the zero end,\n * hence the bottom.\n */\n valuePosition?: ProgressLinearValuePosition\n /** Turns the bar upright, filling from the bottom up. */\n orientation?: ProgressLinearOrientation\n}\n\nconst props = withDefaults(defineProps<ProgressLinearProps>(), {\n value: 0,\n label: undefined,\n max: 100,\n indeterminate: false,\n tone: 'accent',\n color: undefined,\n thickness: undefined,\n shape: 'rounded',\n showValue: false,\n valuePosition: 'center',\n orientation: 'horizontal',\n})\n\ndefineSlots<{\n /**\n * What to write inside the bar instead of the percentage.\n *\n * It is rendered TWICE, once over the empty track and once over the filled part in a\n * colour that contrasts with it, each copy cut at the fill's edge. So whatever it renders\n * must be pure: anything with a side effect would happen twice.\n */\n default?(props: ProgressLinearSlotProps): unknown\n}>()\n\n/* The percent sign, and the non-breaking space French puts before it where English puts\n nothing, are a convention of the language: they belong in the dictionary rather than\n in this file. Any other format goes through the slot above. */\nconst m = useMessages()\n\nconst {\n max: normalizedMax,\n clamped,\n fraction,\n percent,\n roundedPercent,\n} = useProgressValue(\n () => props.value,\n () => props.max,\n)\n\n// @a11y\n// The canonical cascade: a consumer's `aria-labelledby`, then their `aria-label`, then the\n// `label` prop, then the dictionary. An indicator takes no name from the text inside it, so\n// without the last step it would have none at all.\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.progress.label)\n</script>\n\n<template>\n <div\n class=\"v-progress-linear v-tone\"\n role=\"progressbar\"\n :aria-label=\"ariaLabel\"\n :data-tone=\"tone\"\n :data-custom=\"color !== undefined ? '' : undefined\"\n :data-shape=\"shape\"\n :data-orientation=\"orientation\"\n :data-value-position=\"valuePosition\"\n :data-indeterminate=\"indeterminate ? '' : undefined\"\n :aria-valuenow=\"indeterminate ? undefined : clamped\"\n aria-valuemin=\"0\"\n :aria-valuemax=\"normalizedMax\"\n :style=\"{\n '--fill-fraction': String(fraction),\n '--custom-color': color,\n '--progress-thickness': px(thickness),\n }\"\n >\n <span class=\"v-progress-linear-fill\" />\n <!--\n The same text twice, each copy cut at the fill's edge so that the two complete\n each other exactly: the first in the ordinary text colour over the empty track,\n the second over the filled part, coloured to contrast with it. The second is\n hidden from screen readers, being a duplicate of text already there.\n -->\n <template v-if=\"!indeterminate && (showValue || $slots.default)\">\n <span class=\"v-progress-linear-text\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n <span class=\"v-progress-linear-text\" data-on-fill aria-hidden=\"true\">\n <slot :value=\"clamped\" :max=\"normalizedMax\" :percent=\"percent\">\n {{ m.progress.percent(roundedPercent) }}\n </slot>\n </span>\n </template>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n /*\n * The element IS the track, and it takes the whole length available. Sizing it is the\n * consumer's business, through the parent or through a width of their own — a\n * consumer's style sits outside our layers and always wins.\n */\n .v-progress-linear {\n --progress-thickness: var(--vectis-control-size-progress-linear-thickness);\n /* Fill, track and the text over the fill are the tone's solid, soft and on-solid\n colours, read from the shared table (`.v-tone`, set in the template). */\n --progress-fill: var(--tone-bg-solid);\n --progress-track: var(--tone-bg-soft);\n --progress-text-fallback: var(--tone-text-solid);\n position: relative;\n display: block;\n inline-size: 100%;\n block-size: var(--progress-thickness);\n border-radius: var(--vectis-radius-pill);\n background: var(--progress-track);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n }\n\n .v-progress-linear[data-shape='square'] {\n border-radius: 0;\n }\n\n .v-progress-linear-fill {\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n inline-size: calc(100% * var(--fill-fraction));\n border-radius: inherit;\n background: var(--progress-fill);\n /*\n * The fill is animated by changing its LENGTH, which the browser has to lay out\n * again on every frame. Scaling it would be cheaper, but a scale is physical: it\n * would have to be undone for the vertical orientation and again for a\n * right-to-left page, where a logical length simply works.\n *\n * The duration and easing are repeated by the clip of the text over the fill, or the\n * colour boundary would drift away from the fill's own edge for the length of the\n * transition.\n */\n transition: inline-size var(--vectis-duration-base) var(--vectis-ease-default);\n }\n\n /* The text inside the bar, in two copies laid over the same box — the track's own,\n which is why a cut expressed as a fraction of it lands exactly on the fill's edge.\n Bear in mind that the default 4px thickness cannot hold text at all: showing any\n implies asking for a thicker bar.\n\n TRAP — the two copies are COMPLEMENTARY and never superimposed: this one is cut OUT\n of the filled part, the other cut TO it, so every letter is painted exactly once.\n Removing either clip raises no error and stays invisible for as long as both copies\n resolve to the SAME colour, which is what happens wherever the adaptive colour\n function is unsupported. Where it IS supported and the two disagree — black over an\n accent fill against white text in the dark theme — the copy underneath shows its\n antialiased edges all around the letters of the one on top, and the label reads as\n a halo. */\n .v-progress-linear-text {\n /* The two insets of the cut: one on the edge the fill grows FROM, one on the edge it\n grows towards. They are named after those roles rather than after physical sides,\n so the three geometry rules further down — horizontal, right-to-left, vertical —\n all read the same pair. This copy cuts on the start side; the one over the fill\n swaps them. */\n --progress-clip-start: calc(100% * var(--fill-fraction));\n --progress-clip-end: -100vmax;\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding-inline: var(--vectis-space-2);\n color: var(--vectis-color-text);\n /* The large negative inset on the two sides that do NOT carry the cut is what stops\n text taller or wider than the bar from being cropped by its own clip. */\n clip-path: inset(-100vmax var(--progress-clip-end) -100vmax var(--progress-clip-start));\n /* The same duration and easing as the fill's own length, or the colour boundary\n would drift away from the fill's edge for the length of the transition. */\n transition: clip-path var(--vectis-duration-base) var(--vectis-ease-default);\n /* The bar itself is turned on its side in vertical mode; the text is put back\n upright here, since a label read sideways is not the point. */\n writing-mode: horizontal-tb;\n white-space: nowrap;\n pointer-events: none;\n }\n\n .v-progress-linear[data-value-position='start'] .v-progress-linear-text {\n justify-content: start;\n }\n\n .v-progress-linear[data-value-position='end'] .v-progress-linear-text {\n justify-content: end;\n }\n\n .v-progress-linear-text[data-on-fill] {\n /* The exact complement of the copy above: the cut moves to the other end of the\n axis, so the two together cover the whole bar and overlap nowhere. */\n --progress-clip-start: -100vmax;\n --progress-clip-end: calc(100% * (1 - var(--fill-fraction)));\n /* The per-tone fallback colour. The adaptive one cannot simply be written as a\n second declaration after it: because that declaration contains a var(), a browser\n with no support does not reject it at parse time — it would win the cascade and\n only then turn invalid, which resets the colour to inherited and leaves the\n fallback never applied. The block below is the way round it, being evaluated\n before any var() substitution. */\n color: var(--progress-text-fallback);\n }\n\n /* Where the adaptive colour function exists, the text picks black or white against\n whatever colour the fill ended up with. */\n @supports (color: contrast-color(red)) {\n .v-progress-linear-text[data-on-fill] {\n color: contrast-color(var(--progress-fill));\n }\n }\n\n /* In a right-to-left page the fill grows from the right, so the two insets change\n physical sides — the variables themselves keep their meaning. */\n .v-progress-linear:dir(rtl) .v-progress-linear-text {\n clip-path: inset(-100vmax var(--progress-clip-start) -100vmax var(--progress-clip-end));\n }\n\n /* Upright, the bar fills from the bottom.\n\n Changing the writing direction on the element is enough to turn everything: the\n axis the fill grows along becomes vertical, so the length and the thickness swap\n places, and both the fill and the animation follow with no rule written twice.\n\n TRAP — putting zero at the bottom is NOT done by reversing the direction, which\n would also apply to the text of the two copies: bidirectional reordering would then\n display \"50 %\" as \"% 50\". The fill is anchored to the far end of the axis instead.\n\n The length comes from a token because there is nothing to inherit it from: in a\n parent of automatic height the bar would collapse to nothing. A consumer's own\n height overrides it, sitting outside our layers. */\n .v-progress-linear[data-orientation='vertical'] {\n writing-mode: vertical-lr;\n inline-size: var(--vectis-control-size-progress-linear-length);\n }\n\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-fill {\n inset-inline-start: auto;\n inset-inline-end: 0;\n }\n\n /* TRAP — a right-to-left page reverses the inline axis of a vertical writing mode too:\n `vertical-lr` then runs from the bottom up, so the far end anchored above is the TOP.\n The fill goes back to the start of the axis, which is now the bottom. Without this\n rule the bar fills downwards, and the clip of the text, which assumes a fill rising\n from the bottom, paints each copy over the wrong ground. */\n .v-progress-linear[data-orientation='vertical']:dir(rtl) .v-progress-linear-fill {\n inset-inline-start: 0;\n inset-inline-end: auto;\n }\n\n /* The text now stacks along the vertical axis, whose start is the zero end — the\n bottom of the bar. */\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-text {\n flex-direction: column-reverse;\n padding-inline: 0;\n padding-block: var(--vectis-space-2);\n }\n\n /* The cut moves to the vertical axis: the fill rises from the bottom, which is that\n axis' start. It is therefore the same in both reading directions, which means the\n right-to-left rule further up has to be neutralized.\n\n TRAP — the second selector is what neutralizes it, and it is written that way on\n purpose: it is one step MORE specific than that rule, where the first selector alone\n would merely tie with it and win by source order — a far more fragile arrangement. */\n .v-progress-linear[data-orientation='vertical'] .v-progress-linear-text,\n .v-progress-linear[data-orientation='vertical']:dir(rtl) .v-progress-linear-text {\n clip-path: inset(var(--progress-clip-end) -100vmax var(--progress-clip-start) -100vmax);\n }\n\n /* When the progress cannot be measured, a bar of fixed size crosses the track from\n just outside one end to just outside the other. At each extreme it is exactly flush\n with the edge without ever pulling away from it, which is what makes the loop\n invisible and keeps the track from ever looking empty — no second bar is needed.\n\n The easing carries the whole impression: a gradual entry, a quick crossing, a damped\n exit. A linear run, or an asymmetric curve, immediately reads as mechanical.\n\n The movement is expressed in LOGICAL properties — a position and a size as\n percentages of the track — rather than as a transform. One definition then serves\n the horizontal, the vertical and the right-to-left cases, where a transform, being\n physical, would need its own keyframes per axis and a flip per direction. */\n .v-progress-linear[data-indeterminate] {\n overflow: hidden;\n }\n\n .v-progress-linear[data-indeterminate] .v-progress-linear-fill {\n /* The starting position is derived from this size, and the two must stay tied: that\n is what has the bar begin exactly off the track rather than half on it. */\n --progress-bar: 40%;\n /* The anchoring is put back at the start of the axis, vertical case included — where\n a measurable progress anchors at the far end instead. */\n inset-inline-start: 0;\n inset-inline-end: auto;\n inline-size: var(--progress-bar);\n /* The transition of a measurable progress has no place here: switching to this mode\n would otherwise be animated as the bar growing to its new size. */\n transition: none;\n animation: v-progress-linear-indeterminate var(--vectis-duration-1500) var(--vectis-ease-in-out)\n infinite;\n }\n\n @keyframes v-progress-linear-indeterminate {\n from {\n inset-inline-start: calc(-1 * var(--progress-bar));\n }\n\n to {\n inset-inline-start: 100%;\n }\n }\n\n /* Turned upright, the axis runs downwards, so the bar would travel from the top down —\n the opposite of a measurable fill, which rises from the bottom. The same keyframes\n are simply read backwards, which changes nothing else BECAUSE the easing curve is\n symmetric; an asymmetric one would need a second set of keyframes.\n\n A horizontal right-to-left page needs nothing: the logical inset already follows the\n reading direction. A vertical one does, below. */\n .v-progress-linear[data-orientation='vertical'][data-indeterminate] .v-progress-linear-fill {\n animation-direction: reverse;\n }\n\n /* On a right-to-left page the vertical axis already runs upwards (see the trap above),\n so the keyframes are read forwards again. */\n .v-progress-linear[data-orientation='vertical'][data-indeterminate]:dir(rtl)\n .v-progress-linear-fill {\n animation-direction: normal;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-progress-linear-fill,\n .v-progress-linear-text {\n transition: none;\n }\n\n /* Slowed down and not stopped: a motionless loader no longer says that anything is\n happening, which is the one thing it exists to say. */\n .v-progress-linear[data-indeterminate] .v-progress-linear-fill {\n animation-duration: var(--vectis-duration-5000);\n }\n }\n\n /* Windows forced colours repaint every background as Canvas, which takes the track and\n the fill away together and leaves a floating figure at best. The bar is drawn in the\n system colours instead, the VSlider pair: an edge in CanvasText for the track, the\n Highlight pair for the fill and the text over it. `forced-color-adjust` inherits, so\n both copies of the text are given their colour here too. */\n @media (forced-colors: active) {\n .v-progress-linear {\n forced-color-adjust: none;\n background: Canvas;\n box-shadow: inset 0 0 0 var(--vectis-control-border-width) CanvasText;\n }\n\n .v-progress-linear-fill {\n background: Highlight;\n }\n\n .v-progress-linear-text {\n color: CanvasText;\n }\n\n .v-progress-linear-text[data-on-fill] {\n color: HighlightText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwFA,IAAM,IAAQ,GA4BR,IAAI,EAAY,GAEhB,EACJ,KAAK,GACL,YACA,aACA,YACA,sBACE,QACI,EAAM,aACN,EAAM,GACd,GAMM,IAAY,QAAmB,EAAM,SAAS,EAAE,MAAM,SAAS,KAAK;yBAIxE,EAsCM,OAAA;GArCJ,OAAM;GACN,MAAK;GACJ,cAAY,EAAA,CAAA;GACZ,aAAW,EAAA;GACX,eAAa,EAAA,UAAU,KAAA,IAAiB,KAAA,IAAR;GAChC,cAAY,EAAA;GACZ,oBAAkB,EAAA;GAClB,uBAAqB,EAAA;GACrB,sBAAoB,EAAA,gBAAa,KAAQ,KAAA;GACzC,iBAAe,EAAA,gBAAgB,KAAA,IAAY,EAAA,CAAA;GAC5C,iBAAc;GACb,iBAAe,EAAA,CAAA;GACf,OAAK,EAAA;uBAA6B,OAAO,EAAA,CAAA,CAAQ;sBAA2B,EAAA;4BAAqC,EAAA,CAAA,CAAE,CAAC,EAAA,SAAS;;eAM9H,EAAuC,QAAA,EAAjC,OAAM,yBAAwB,GAAA,MAAA,EAAA,GAAA,CAOnB,EAAA,kBAAkB,EAAA,aAAaA,EAAAA,OAAO,YAAA,EAAA,GAAvD,EAWW,GAAA,EAAA,KAAA,EAAA,GAAA,CAVT,EAIO,QAJP,GAIO,CAHL,EAEO,EAAA,QAAA,WAAA;GAFA,OAAO,EAAA,CAAA;GAAU,KAAK,EAAA,CAAA;GAAgB,SAAS,EAAA,CAAA;WAE/C,CAAA,EAAA,EADF,EAAA,CAAA,CAAC,CAAC,SAAS,QAAQ,EAAA,CAAA,CAAc,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAGxC,EAIO,QAJP,GAIO,CAHL,EAEO,EAAA,QAAA,WAAA;GAFA,OAAO,EAAA,CAAA;GAAU,KAAK,EAAA,CAAA;GAAgB,SAAS,EAAA,CAAA;WAE/C,CAAA,EAAA,EADF,EAAA,CAAA,CAAC,CAAC,SAAS,QAAQ,EAAA,CAAA,CAAc,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,EAAA,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,IAAA,CAAA"}
@@ -1,2 +1,2 @@
1
1
  @layer vectis.reset, vectis.tokens, vectis.components, vectis.utilities;
2
- @layer vectis.components{.v-radio-dot{width:var(--vectis-control-size-check);height:var(--vectis-control-size-check);border:var(--vectis-control-border-width) solid var(--vectis-color-border-strong);border-radius:var(--vectis-radius-pill);color:var(--vectis-color-text-on-accent);transition:background-color var(--vectis-duration-fast) var(--vectis-ease-default), border-color var(--vectis-duration-fast) var(--vectis-ease-default);background:0 0;place-items:center;display:inline-grid}.v-radio-dot:before{content:"";width:var(--vectis-control-size-check-dot);height:var(--vectis-control-size-check-dot);border-radius:var(--vectis-radius-pill);opacity:0;transition:opacity var(--vectis-duration-fast) var(--vectis-ease-default);background:currentColor}.v-radio-input:checked+.v-radio-dot:before{opacity:1}.v-radio:not([data-readonly]) .v-choice-row:hover .v-radio-input:not(:disabled,:checked)+.v-radio-dot{border-color:color-mix(in oklab, var(--vectis-color-border-strong), var(--vectis-color-text) 15%)}.v-radio-input:checked+.v-radio-dot{background:var(--vectis-color-accent);border-color:var(--vectis-color-accent)}.v-radio:not([data-readonly]) .v-choice-row:hover .v-radio-input:not(:disabled):checked+.v-radio-dot{background:var(--vectis-color-accent-hover);border-color:var(--vectis-color-accent-hover)}:where(.v-radio[data-readonly]) .v-radio-input+.v-radio-dot{background:var(--vectis-color-surface-sunken);border-color:var(--vectis-color-border)}:where(.v-radio[data-readonly]) .v-radio-input:checked+.v-radio-dot{background:var(--vectis-color-text-muted);border-color:var(--vectis-color-text-muted);color:var(--vectis-color-surface)}:is(.v-radio-input:user-invalid+.v-radio-dot,.v-radio-input[aria-invalid=true]+.v-radio-dot){border-color:var(--vectis-color-danger)}.v-radio-input:disabled+.v-radio-dot{background:var(--vectis-color-surface-muted);border-color:var(--vectis-color-border);color:var(--vectis-color-text-subtle)}@media (prefers-reduced-motion:reduce){.v-radio-dot,.v-radio-dot:before{transition:none}}}
2
+ @layer vectis.components{.v-radio-dot{width:var(--vectis-control-size-check);height:var(--vectis-control-size-check);border:var(--vectis-control-border-width) solid var(--vectis-color-border-strong);border-radius:var(--vectis-radius-pill);color:var(--vectis-color-text-on-accent);transition:background-color var(--vectis-duration-fast) var(--vectis-ease-default), border-color var(--vectis-duration-fast) var(--vectis-ease-default);background:0 0;place-items:center;display:inline-grid}.v-radio-dot:before{content:"";width:var(--vectis-control-size-check-dot);height:var(--vectis-control-size-check-dot);border-radius:var(--vectis-radius-pill);opacity:0;transition:opacity var(--vectis-duration-fast) var(--vectis-ease-default);background:currentColor}.v-radio-input:checked+.v-radio-dot:before{opacity:1}.v-radio:not([data-readonly]) .v-choice-row:hover .v-radio-input:not(:disabled,:checked,:user-invalid,[aria-invalid=true])+.v-radio-dot{border-color:color-mix(in oklab, var(--vectis-color-border-strong), var(--vectis-color-text) 15%)}.v-radio-input:checked+.v-radio-dot{background:var(--vectis-color-accent);border-color:var(--vectis-color-accent)}.v-radio:not([data-readonly]) .v-choice-row:hover .v-radio-input:not(:disabled,:user-invalid,[aria-invalid=true]):checked+.v-radio-dot{background:var(--vectis-color-accent-hover);border-color:var(--vectis-color-accent-hover)}:where(.v-radio[data-readonly]) .v-radio-input+.v-radio-dot{background:var(--vectis-color-surface-sunken);border-color:var(--vectis-color-border)}:where(.v-radio[data-readonly]) .v-radio-input:checked+.v-radio-dot{background:var(--vectis-color-text-muted);border-color:var(--vectis-color-text-muted);color:var(--vectis-color-surface)}:is(.v-radio-input:user-invalid+.v-radio-dot,.v-radio-input[aria-invalid=true]+.v-radio-dot){border-color:var(--vectis-color-danger)}.v-radio-input:disabled+.v-radio-dot{background:var(--vectis-color-surface-muted);border-color:var(--vectis-color-border);color:var(--vectis-color-text-subtle)}@media (forced-colors:active){.v-radio-input.v-radio-input.v-radio-input.v-radio-input.v-radio-input:checked:not(:disabled)+.v-radio-dot{forced-color-adjust:none;color:highlighttext;background:highlight;border-color:highlight}}@media (prefers-reduced-motion:reduce){.v-radio-dot,.v-radio-dot:before{transition:none}}}
@@ -1 +1 @@
1
- {"version":3,"file":"VRadio.js","names":[],"sources":["../../../src/components/VRadio/VRadio.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * A radio button whose dot is drawn by the design system, on the same principle as\n * VCheckbox: the real `<input type=\"radio\">` stays in place and only its own drawing\n * is hidden.\n *\n * The group is native as well. Several VRadio sharing the same `name` and the same\n * v-model form one choice, and it is the browser that then makes the arrow keys move\n * between them, that lets only one be selected, and that gives the group a single\n * stop in the tab order. There is no JavaScript here for any of it; the only piece this\n * component writes is the refusal `readonly` asks for, which a radio has no native form of.\n */\n\nimport { ref } from 'vue'\n\nimport { useFieldIds } from '../../composables/useFieldIds'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport type { ItemValue } from '../../types'\n\n/** Which side of the dot the label sits on. */\nexport type RadioLabelPosition = 'start' | 'end'\n\ninterface RadioProps {\n /**\n * What choosing this button means. The group's v-model holds the value of the\n * selected button, so this is what it becomes when this one is picked.\n */\n value: ItemValue\n /** The text beside the dot, which names it. The default slot replaces it. */\n label?: string\n /**\n * A line of help under the label. It is tied to the radio button for assistive\n * technology, so it is read out after the label rather than as part of it.\n */\n hint?: string\n /** Which side of the dot the label sits on. */\n labelPosition?: RadioLabelPosition\n /**\n * Pushes the label and the dot to opposite ends of the line, the row taking the\n * full width available.\n */\n spread?: boolean\n /**\n * Marks the field as invalid, which colours the dot and tells assistive technology\n * so. It is for a rule the browser cannot check by itself.\n */\n invalid?: boolean\n /** Makes this choice unusable, greyed out through the colour tokens. */\n disabled?: boolean\n /**\n * Shows the selection without allowing it to be changed. The button can still be\n * focused and is still submitted with its form; a click or an arrow key simply selects\n * nothing. Set it on every button of the group.\n */\n readonly?: boolean\n}\n\nconst props = withDefaults(defineProps<RadioProps>(), {\n label: undefined,\n hint: undefined,\n labelPosition: 'end',\n spread: false,\n invalid: false,\n disabled: false,\n readonly: false,\n})\n\n// @a11y — the redirection buys the whole keyboard. Moving between the buttons of a group is\n// the browser's job, but it only groups inputs that share a `name` — so redirecting the\n// attributes is what makes the arrow keys work at all. The root being a layout box, `name`\n// left on it would reach nothing.\ndefineOptions({ inheritAttrs: false })\nconst { attrs, rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\nconst { hintId, describedBy } = useFieldIds(attrs, () => !!props.hint)\n\n/**\n * The value selected in the group, shared by every radio carrying the same `name`. It is\n * empty until one is chosen, and a radio is selected when it matches its own `value`.\n */\nconst model = defineModel<ItemValue>({ default: '' })\n\ndefineSlots<{\n /** The label, when it needs more than the `label` prop's text. It is clickable. */\n default?(): unknown\n}>()\n\nconst inputEl = ref<HTMLInputElement | null>(null)\n\n// @core\n// The native `readonly` attribute does nothing on a radio button. Cancelling the click is\n// what refuses the selection: the browser puts the group's previous selection back and fires\n// no `change`. It covers the arrow keys too, which select the next button of the group\n// through a click the browser dispatches on it — so the focus still moves, the selection\n// does not.\n//\n// No `aria-readonly` goes with it, unlike VCheckbox and VSwitch: ARIA allows it on a\n// `radiogroup` and not on a `radio`, and axe fails the page for it.\nfunction refuseWhenReadonly(event: MouseEvent) {\n if (props.readonly) event.preventDefault()\n}\n\n// The root is a wrapper, so a template ref on the component reaches the layout box and not\n// the control: these two are the way to the real radio button.\ndefineExpose({\n /** Moves the focus to the real radio button. */\n focus: (options?: FocusOptions) => inputEl.value?.focus(options),\n /** The real `<input type=\"radio\">`, for what `focus` does not cover. */\n el: inputEl,\n})\n</script>\n\n<template>\n <span\n class=\"v-radio v-choice\"\n :class=\"rootClass\"\n :style=\"rootStyle\"\n :data-label-position=\"labelPosition\"\n :data-spread=\"spread ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n >\n <label class=\"v-choice-row\">\n <input\n ref=\"inputEl\"\n v-model=\"model\"\n type=\"radio\"\n class=\"v-radio-input v-hidden-input\"\n v-bind=\"forwardedAttrs\"\n :value=\"value\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\n @click=\"refuseWhenReadonly\"\n />\n <span class=\"v-radio-dot\" aria-hidden=\"true\" />\n <span v-if=\"$slots.default || label\" class=\"v-radio-label v-choice-label\">\n <slot>{{ label }}</slot>\n </span>\n </label>\n <span v-if=\"hint\" :id=\"hintId\" class=\"v-radio-hint v-choice-hint\">{{ hint }}</span>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The dot works exactly like VCheckbox's box, the accent filling it once the input is\n checked, with the small inner disc drawn as a pseudo-element in currentcolor so it\n follows whatever colour the state gives the ring's content. */\n .v-radio-dot {\n display: inline-grid;\n place-items: center;\n width: var(--vectis-control-size-check);\n height: var(--vectis-control-size-check);\n background: transparent;\n border: var(--vectis-control-border-width) solid var(--vectis-color-border-strong);\n border-radius: var(--vectis-radius-pill);\n color: var(--vectis-color-text-on-accent);\n transition:\n background-color var(--vectis-duration-fast) var(--vectis-ease-default),\n border-color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-radio-dot::before {\n content: '';\n width: var(--vectis-control-size-check-dot);\n height: var(--vectis-control-size-check-dot);\n border-radius: var(--vectis-radius-pill);\n background: currentcolor;\n opacity: 0;\n transition: opacity var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-radio-input:checked + .v-radio-dot::before {\n opacity: 1;\n }\n\n /* The state painting, rule for rule the same as VCheckbox's with its own classes: keep the\n two ALIGNED. Every state below but the hovers weighs (0,3,0), so their ORDER arbitrates\n them: checked, read-only, invalid, then disabled last. The two hovers exclude every state\n they must not repaint, so no order argument reaches them. */\n .v-radio:not([data-readonly])\n .v-choice-row:hover\n .v-radio-input:not(:disabled, :checked)\n + .v-radio-dot {\n border-color: color-mix(\n in oklab,\n var(--vectis-color-border-strong),\n var(--vectis-color-text) 15%\n );\n }\n\n .v-radio-input:checked + .v-radio-dot {\n background: var(--vectis-color-accent);\n border-color: var(--vectis-color-accent);\n }\n\n .v-radio:not([data-readonly])\n .v-choice-row:hover\n .v-radio-input:not(:disabled):is(:checked)\n + .v-radio-dot {\n background: var(--vectis-color-accent-hover);\n border-color: var(--vectis-color-accent-hover);\n }\n\n /* Read-only sinks like a read-only field, and a selected control trades the accent for the\n muted text colour: still plainly on, no longer inviting a click. The mark takes the\n surface colour, which contrasts with that fill in both themes, where white would vanish\n against the light grey of the dark theme. `:where()` keeps both rules at the weight of\n the states they sit between. */\n :where(.v-radio[data-readonly]) .v-radio-input + .v-radio-dot {\n background: var(--vectis-color-surface-sunken);\n border-color: var(--vectis-color-border);\n }\n\n :where(.v-radio[data-readonly]) .v-radio-input:checked + .v-radio-dot {\n background: var(--vectis-color-text-muted);\n border-color: var(--vectis-color-text-muted);\n color: var(--vectis-color-surface);\n }\n\n .v-radio-input:user-invalid + .v-radio-dot,\n .v-radio-input[aria-invalid='true'] + .v-radio-dot {\n border-color: var(--vectis-color-danger);\n }\n\n .v-radio-input:disabled + .v-radio-dot {\n background: var(--vectis-color-surface-muted);\n border-color: var(--vectis-color-border);\n color: var(--vectis-color-text-subtle);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-radio-dot,\n .v-radio-dot::before {\n transition: none;\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"VRadio.js","names":[],"sources":["../../../src/components/VRadio/VRadio.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * A radio button whose dot is drawn by the design system, on the same principle as\n * VCheckbox: the real `<input type=\"radio\">` stays in place and only its own drawing\n * is hidden.\n *\n * The group is native as well. Several VRadio sharing the same `name` and the same\n * v-model form one choice, and it is the browser that then makes the arrow keys move\n * between them, that lets only one be selected, and that gives the group a single\n * stop in the tab order. There is no JavaScript here for any of it; the only piece this\n * component writes is the refusal `readonly` asks for, which a radio has no native form of.\n */\n\nimport { ref } from 'vue'\n\nimport { useFieldIds } from '../../composables/useFieldIds'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport type { ItemValue } from '../../types'\n\n/** Which side of the dot the label sits on. */\nexport type RadioLabelPosition = 'start' | 'end'\n\ninterface RadioProps {\n /**\n * What choosing this button means. The group's v-model holds the value of the\n * selected button, so this is what it becomes when this one is picked.\n */\n value: ItemValue\n /** The text beside the dot, which names it. The default slot replaces it. */\n label?: string\n /**\n * A line of help under the label. It is tied to the radio button for assistive\n * technology, so it is read out after the label rather than as part of it.\n */\n hint?: string\n /** Which side of the dot the label sits on. */\n labelPosition?: RadioLabelPosition\n /**\n * Pushes the label and the dot to opposite ends of the line, the row taking the\n * full width available.\n */\n spread?: boolean\n /**\n * Marks the field as invalid, which colours the dot and tells assistive technology\n * so. It is for a rule the browser cannot check by itself.\n */\n invalid?: boolean\n /** Makes this choice unusable, greyed out through the colour tokens. */\n disabled?: boolean\n /**\n * Shows the selection without allowing it to be changed. The button can still be\n * focused and is still submitted with its form; a click or an arrow key simply selects\n * nothing. Set it on every button of the group.\n */\n readonly?: boolean\n}\n\nconst props = withDefaults(defineProps<RadioProps>(), {\n label: undefined,\n hint: undefined,\n labelPosition: 'end',\n spread: false,\n invalid: false,\n disabled: false,\n readonly: false,\n})\n\n// @a11y — the redirection buys the whole keyboard. Moving between the buttons of a group is\n// the browser's job, but it only groups inputs that share a `name` — so redirecting the\n// attributes is what makes the arrow keys work at all. The root being a layout box, `name`\n// left on it would reach nothing.\ndefineOptions({ inheritAttrs: false })\nconst { attrs, rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\nconst { hintId, describedBy } = useFieldIds(attrs, () => !!props.hint)\n\n/**\n * The value selected in the group, shared by every radio carrying the same `name`. It is\n * empty until one is chosen, and a radio is selected when it matches its own `value`.\n */\nconst model = defineModel<ItemValue>({ default: '' })\n\ndefineSlots<{\n /** The label, when it needs more than the `label` prop's text. It is clickable. */\n default?(): unknown\n}>()\n\nconst inputEl = ref<HTMLInputElement | null>(null)\n\n// @core\n// The native `readonly` attribute does nothing on a radio button. Cancelling the click is\n// what refuses the selection: the browser puts the group's previous selection back and fires\n// no `change`. It covers the arrow keys too, which select the next button of the group\n// through a click the browser dispatches on it — so the focus still moves, the selection\n// does not.\n//\n// No `aria-readonly` goes with it, unlike VCheckbox and VSwitch: ARIA allows it on a\n// `radiogroup` and not on a `radio`, and axe fails the page for it.\nfunction refuseWhenReadonly(event: MouseEvent) {\n if (props.readonly) event.preventDefault()\n}\n\n// The root is a wrapper, so a template ref on the component reaches the layout box and not\n// the control: these two are the way to the real radio button.\ndefineExpose({\n /** Moves the focus to the real radio button. */\n focus: (options?: FocusOptions) => inputEl.value?.focus(options),\n /** The real `<input type=\"radio\">`, for what `focus` does not cover. */\n el: inputEl,\n})\n</script>\n\n<template>\n <span\n class=\"v-radio v-choice\"\n :class=\"rootClass\"\n :style=\"rootStyle\"\n :data-label-position=\"labelPosition\"\n :data-spread=\"spread ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n >\n <label class=\"v-choice-row\">\n <input\n ref=\"inputEl\"\n v-model=\"model\"\n type=\"radio\"\n class=\"v-radio-input v-hidden-input\"\n :aria-invalid=\"invalid || undefined\"\n v-bind=\"forwardedAttrs\"\n :value=\"value\"\n :disabled=\"disabled\"\n :aria-describedby=\"describedBy\"\n @click=\"refuseWhenReadonly\"\n />\n <span class=\"v-radio-dot\" aria-hidden=\"true\" />\n <span v-if=\"$slots.default || label\" class=\"v-radio-label v-choice-label\">\n <slot>{{ label }}</slot>\n </span>\n </label>\n <span v-if=\"hint\" :id=\"hintId\" class=\"v-radio-hint v-choice-hint\">{{ hint }}</span>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The dot works exactly like VCheckbox's box, the accent filling it once the input is\n checked, with the small inner disc drawn as a pseudo-element in currentcolor so it\n follows whatever colour the state gives the ring's content. */\n .v-radio-dot {\n display: inline-grid;\n place-items: center;\n width: var(--vectis-control-size-check);\n height: var(--vectis-control-size-check);\n background: transparent;\n border: var(--vectis-control-border-width) solid var(--vectis-color-border-strong);\n border-radius: var(--vectis-radius-pill);\n color: var(--vectis-color-text-on-accent);\n transition:\n background-color var(--vectis-duration-fast) var(--vectis-ease-default),\n border-color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-radio-dot::before {\n content: '';\n width: var(--vectis-control-size-check-dot);\n height: var(--vectis-control-size-check-dot);\n border-radius: var(--vectis-radius-pill);\n background: currentcolor;\n opacity: 0;\n transition: opacity var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-radio-input:checked + .v-radio-dot::before {\n opacity: 1;\n }\n\n /* The state painting, rule for rule the same as VCheckbox's with its own classes: keep the\n two ALIGNED. The states below weigh (0,3,0), bar the read-only base at (0,2,0), so their\n ORDER arbitrates them: checked, read-only, invalid, then disabled last.\n\n The two hovers sit at (0,7,0) and therefore beat every one of them on specificity, order\n or no order — which is why they have to EXCLUDE by hand each state they must not repaint.\n Forgetting the invalid pair is what once rubbed the danger border out under the pointer,\n on a control whose whole point at that moment is to look wrong. */\n .v-radio:not([data-readonly])\n .v-choice-row:hover\n .v-radio-input:not(:disabled, :checked, :user-invalid, [aria-invalid='true'])\n + .v-radio-dot {\n border-color: color-mix(\n in oklab,\n var(--vectis-color-border-strong),\n var(--vectis-color-text) 15%\n );\n }\n\n .v-radio-input:checked + .v-radio-dot {\n background: var(--vectis-color-accent);\n border-color: var(--vectis-color-accent);\n }\n\n .v-radio:not([data-readonly])\n .v-choice-row:hover\n .v-radio-input:not(:disabled, :user-invalid, [aria-invalid='true']):checked\n + .v-radio-dot {\n background: var(--vectis-color-accent-hover);\n border-color: var(--vectis-color-accent-hover);\n }\n\n /* Read-only sinks like a read-only field, and a selected control trades the accent for the\n muted text colour: still plainly on, no longer inviting a click. The inner disc takes the\n surface colour, which contrasts with that fill in both themes, where white would vanish\n against the light grey of the dark theme. `:where()` keeps both rules at the weight of\n the states they sit between. */\n :where(.v-radio[data-readonly]) .v-radio-input + .v-radio-dot {\n background: var(--vectis-color-surface-sunken);\n border-color: var(--vectis-color-border);\n }\n\n :where(.v-radio[data-readonly]) .v-radio-input:checked + .v-radio-dot {\n background: var(--vectis-color-text-muted);\n border-color: var(--vectis-color-text-muted);\n color: var(--vectis-color-surface);\n }\n\n .v-radio-input:user-invalid + .v-radio-dot,\n .v-radio-input[aria-invalid='true'] + .v-radio-dot {\n border-color: var(--vectis-color-danger);\n }\n\n .v-radio-input:disabled + .v-radio-dot {\n background: var(--vectis-color-surface-muted);\n border-color: var(--vectis-color-border);\n color: var(--vectis-color-text-subtle);\n }\n\n @media (forced-colors: active) {\n /* Windows forced colors erase every author colour: a `background` becomes `Canvas` and a\n `border-color` becomes `CanvasText`, so a selected radio loses its inner disc outright, that disc being\n a `background` on a `background` where a checkbox has a `stroke` that survives. The system\n Highlight pair is what says \"selected\" here, as it does on a pressed VToggleItem, a\n selected VChip and the current VPagination page.\n\n The class is repeated to (0,8,0) so the row's own hover rules, which reach (0,7,0),\n cannot repaint it: `forced-color-adjust: none` takes the forcing off this element, and\n a hover left winning would then paint its REAL grey over the system colour. */\n .v-radio-input.v-radio-input.v-radio-input.v-radio-input.v-radio-input:checked:not(:disabled)\n + .v-radio-dot {\n forced-color-adjust: none;\n background: Highlight;\n border-color: Highlight;\n color: HighlightText;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-radio-dot,\n .v-radio-dot::before {\n transition: none;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -7,9 +7,9 @@ var y = [
7
7
  "data-spread",
8
8
  "data-readonly"
9
9
  ], b = { class: "v-choice-row" }, x = [
10
+ "aria-invalid",
10
11
  "value",
11
12
  "disabled",
12
- "aria-invalid",
13
13
  "aria-describedby"
14
14
  ], S = {
15
15
  key: 0,
@@ -63,11 +63,11 @@ var y = [
63
63
  ref: M,
64
64
  "onUpdate:modelValue": t[0] ||= (e) => j.value = e,
65
65
  type: "radio",
66
- class: "v-radio-input v-hidden-input"
66
+ class: "v-radio-input v-hidden-input",
67
+ "aria-invalid": o.invalid || void 0
67
68
  }, h(O), {
68
69
  value: o.value,
69
70
  disabled: o.disabled,
70
- "aria-invalid": o.invalid || void 0,
71
71
  "aria-describedby": h(A),
72
72
  onClick: N
73
73
  }), null, 16, x), [[_, j.value]]),
@@ -1 +1 @@
1
- {"version":3,"file":"VRadio.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VRadio/VRadio.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * A radio button whose dot is drawn by the design system, on the same principle as\n * VCheckbox: the real `<input type=\"radio\">` stays in place and only its own drawing\n * is hidden.\n *\n * The group is native as well. Several VRadio sharing the same `name` and the same\n * v-model form one choice, and it is the browser that then makes the arrow keys move\n * between them, that lets only one be selected, and that gives the group a single\n * stop in the tab order. There is no JavaScript here for any of it; the only piece this\n * component writes is the refusal `readonly` asks for, which a radio has no native form of.\n */\n\nimport { ref } from 'vue'\n\nimport { useFieldIds } from '../../composables/useFieldIds'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport type { ItemValue } from '../../types'\n\n/** Which side of the dot the label sits on. */\nexport type RadioLabelPosition = 'start' | 'end'\n\ninterface RadioProps {\n /**\n * What choosing this button means. The group's v-model holds the value of the\n * selected button, so this is what it becomes when this one is picked.\n */\n value: ItemValue\n /** The text beside the dot, which names it. The default slot replaces it. */\n label?: string\n /**\n * A line of help under the label. It is tied to the radio button for assistive\n * technology, so it is read out after the label rather than as part of it.\n */\n hint?: string\n /** Which side of the dot the label sits on. */\n labelPosition?: RadioLabelPosition\n /**\n * Pushes the label and the dot to opposite ends of the line, the row taking the\n * full width available.\n */\n spread?: boolean\n /**\n * Marks the field as invalid, which colours the dot and tells assistive technology\n * so. It is for a rule the browser cannot check by itself.\n */\n invalid?: boolean\n /** Makes this choice unusable, greyed out through the colour tokens. */\n disabled?: boolean\n /**\n * Shows the selection without allowing it to be changed. The button can still be\n * focused and is still submitted with its form; a click or an arrow key simply selects\n * nothing. Set it on every button of the group.\n */\n readonly?: boolean\n}\n\nconst props = withDefaults(defineProps<RadioProps>(), {\n label: undefined,\n hint: undefined,\n labelPosition: 'end',\n spread: false,\n invalid: false,\n disabled: false,\n readonly: false,\n})\n\n// @a11y — the redirection buys the whole keyboard. Moving between the buttons of a group is\n// the browser's job, but it only groups inputs that share a `name` — so redirecting the\n// attributes is what makes the arrow keys work at all. The root being a layout box, `name`\n// left on it would reach nothing.\ndefineOptions({ inheritAttrs: false })\nconst { attrs, rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\nconst { hintId, describedBy } = useFieldIds(attrs, () => !!props.hint)\n\n/**\n * The value selected in the group, shared by every radio carrying the same `name`. It is\n * empty until one is chosen, and a radio is selected when it matches its own `value`.\n */\nconst model = defineModel<ItemValue>({ default: '' })\n\ndefineSlots<{\n /** The label, when it needs more than the `label` prop's text. It is clickable. */\n default?(): unknown\n}>()\n\nconst inputEl = ref<HTMLInputElement | null>(null)\n\n// @core\n// The native `readonly` attribute does nothing on a radio button. Cancelling the click is\n// what refuses the selection: the browser puts the group's previous selection back and fires\n// no `change`. It covers the arrow keys too, which select the next button of the group\n// through a click the browser dispatches on it — so the focus still moves, the selection\n// does not.\n//\n// No `aria-readonly` goes with it, unlike VCheckbox and VSwitch: ARIA allows it on a\n// `radiogroup` and not on a `radio`, and axe fails the page for it.\nfunction refuseWhenReadonly(event: MouseEvent) {\n if (props.readonly) event.preventDefault()\n}\n\n// The root is a wrapper, so a template ref on the component reaches the layout box and not\n// the control: these two are the way to the real radio button.\ndefineExpose({\n /** Moves the focus to the real radio button. */\n focus: (options?: FocusOptions) => inputEl.value?.focus(options),\n /** The real `<input type=\"radio\">`, for what `focus` does not cover. */\n el: inputEl,\n})\n</script>\n\n<template>\n <span\n class=\"v-radio v-choice\"\n :class=\"rootClass\"\n :style=\"rootStyle\"\n :data-label-position=\"labelPosition\"\n :data-spread=\"spread ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n >\n <label class=\"v-choice-row\">\n <input\n ref=\"inputEl\"\n v-model=\"model\"\n type=\"radio\"\n class=\"v-radio-input v-hidden-input\"\n v-bind=\"forwardedAttrs\"\n :value=\"value\"\n :disabled=\"disabled\"\n :aria-invalid=\"invalid || undefined\"\n :aria-describedby=\"describedBy\"\n @click=\"refuseWhenReadonly\"\n />\n <span class=\"v-radio-dot\" aria-hidden=\"true\" />\n <span v-if=\"$slots.default || label\" class=\"v-radio-label v-choice-label\">\n <slot>{{ label }}</slot>\n </span>\n </label>\n <span v-if=\"hint\" :id=\"hintId\" class=\"v-radio-hint v-choice-hint\">{{ hint }}</span>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The dot works exactly like VCheckbox's box, the accent filling it once the input is\n checked, with the small inner disc drawn as a pseudo-element in currentcolor so it\n follows whatever colour the state gives the ring's content. */\n .v-radio-dot {\n display: inline-grid;\n place-items: center;\n width: var(--vectis-control-size-check);\n height: var(--vectis-control-size-check);\n background: transparent;\n border: var(--vectis-control-border-width) solid var(--vectis-color-border-strong);\n border-radius: var(--vectis-radius-pill);\n color: var(--vectis-color-text-on-accent);\n transition:\n background-color var(--vectis-duration-fast) var(--vectis-ease-default),\n border-color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-radio-dot::before {\n content: '';\n width: var(--vectis-control-size-check-dot);\n height: var(--vectis-control-size-check-dot);\n border-radius: var(--vectis-radius-pill);\n background: currentcolor;\n opacity: 0;\n transition: opacity var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-radio-input:checked + .v-radio-dot::before {\n opacity: 1;\n }\n\n /* The state painting, rule for rule the same as VCheckbox's with its own classes: keep the\n two ALIGNED. Every state below but the hovers weighs (0,3,0), so their ORDER arbitrates\n them: checked, read-only, invalid, then disabled last. The two hovers exclude every state\n they must not repaint, so no order argument reaches them. */\n .v-radio:not([data-readonly])\n .v-choice-row:hover\n .v-radio-input:not(:disabled, :checked)\n + .v-radio-dot {\n border-color: color-mix(\n in oklab,\n var(--vectis-color-border-strong),\n var(--vectis-color-text) 15%\n );\n }\n\n .v-radio-input:checked + .v-radio-dot {\n background: var(--vectis-color-accent);\n border-color: var(--vectis-color-accent);\n }\n\n .v-radio:not([data-readonly])\n .v-choice-row:hover\n .v-radio-input:not(:disabled):is(:checked)\n + .v-radio-dot {\n background: var(--vectis-color-accent-hover);\n border-color: var(--vectis-color-accent-hover);\n }\n\n /* Read-only sinks like a read-only field, and a selected control trades the accent for the\n muted text colour: still plainly on, no longer inviting a click. The mark takes the\n surface colour, which contrasts with that fill in both themes, where white would vanish\n against the light grey of the dark theme. `:where()` keeps both rules at the weight of\n the states they sit between. */\n :where(.v-radio[data-readonly]) .v-radio-input + .v-radio-dot {\n background: var(--vectis-color-surface-sunken);\n border-color: var(--vectis-color-border);\n }\n\n :where(.v-radio[data-readonly]) .v-radio-input:checked + .v-radio-dot {\n background: var(--vectis-color-text-muted);\n border-color: var(--vectis-color-text-muted);\n color: var(--vectis-color-surface);\n }\n\n .v-radio-input:user-invalid + .v-radio-dot,\n .v-radio-input[aria-invalid='true'] + .v-radio-dot {\n border-color: var(--vectis-color-danger);\n }\n\n .v-radio-input:disabled + .v-radio-dot {\n background: var(--vectis-color-surface-muted);\n border-color: var(--vectis-color-border);\n color: var(--vectis-color-text-subtle);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-radio-dot,\n .v-radio-dot::before {\n transition: none;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyDA,IAAM,IAAQ,GAeR,EAAE,UAAO,cAAW,cAAW,sBAAmB,EAAa,GAC/D,EAAE,WAAQ,mBAAgB,EAAY,SAAa,CAAC,CAAC,EAAM,IAAI,GAM/D,IAAQ,EAAsB,GAAA,YAAgB,GAO9C,IAAU,EAA6B,IAAI;EAWjD,SAAS,EAAmB,GAAmB;GAC7C,AAAI,EAAM,YAAU,EAAM,eAAe;EAC3C;SAIA,EAAa;GAEX,QAAQ,MAA2B,EAAQ,OAAO,MAAM,CAAO;GAE/D,IAAI;EACN,CAAC,mBAIC,EA2BO,QAAA;GA1BL,OAAK,EAAA,CAAC,oBACE,EAAA,CAAA,CAAS,CAAA;GAChB,OAAK,EAAE,EAAA,CAAA,CAAS;GAChB,uBAAqB,EAAA;GACrB,eAAa,EAAA,SAAM,KAAQ,KAAA;GAC3B,iBAAe,EAAA,WAAQ,KAAQ,KAAA;MAEhC,EAiBQ,SAjBR,GAiBQ;KAhBN,EAWE,SAXF,EAWE;aAVI;IAAJ,KAAI;6CACU,QAAA;IACd,MAAK;IACL,OAAM;MACE,EAAA,CAAA,GAAc;IACrB,OAAO,EAAA;IACP,UAAU,EAAA;IACV,gBAAc,EAAA,WAAW,KAAA;IACzB,oBAAkB,EAAA,CAAA;IAClB,SAAO;0BARC,EAAA,KAAK,CAAA,CAAA;YAUhB,EAA+C,QAAA;IAAzC,OAAM;IAAc,eAAY;;GAC1BA,EAAAA,OAAO,WAAW,EAAA,SAAA,EAAA,GAA9B,EAEO,QAFP,GAEO,CADL,EAAwB,EAAA,QAAA,WAAA,CAAA,SAAA,CAAA,EAAA,EAAf,EAAA,KAAK,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;MAGN,EAAA,QAAA,EAAA,GAAZ,EAAmF,QAAA;;GAAhE,IAAI,EAAA,CAAA;GAAQ,OAAM;OAAgC,EAAA,IAAI,GAAA,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,IAAA,CAAA"}
1
+ {"version":3,"file":"VRadio.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VRadio/VRadio.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * A radio button whose dot is drawn by the design system, on the same principle as\n * VCheckbox: the real `<input type=\"radio\">` stays in place and only its own drawing\n * is hidden.\n *\n * The group is native as well. Several VRadio sharing the same `name` and the same\n * v-model form one choice, and it is the browser that then makes the arrow keys move\n * between them, that lets only one be selected, and that gives the group a single\n * stop in the tab order. There is no JavaScript here for any of it; the only piece this\n * component writes is the refusal `readonly` asks for, which a radio has no native form of.\n */\n\nimport { ref } from 'vue'\n\nimport { useFieldIds } from '../../composables/useFieldIds'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport type { ItemValue } from '../../types'\n\n/** Which side of the dot the label sits on. */\nexport type RadioLabelPosition = 'start' | 'end'\n\ninterface RadioProps {\n /**\n * What choosing this button means. The group's v-model holds the value of the\n * selected button, so this is what it becomes when this one is picked.\n */\n value: ItemValue\n /** The text beside the dot, which names it. The default slot replaces it. */\n label?: string\n /**\n * A line of help under the label. It is tied to the radio button for assistive\n * technology, so it is read out after the label rather than as part of it.\n */\n hint?: string\n /** Which side of the dot the label sits on. */\n labelPosition?: RadioLabelPosition\n /**\n * Pushes the label and the dot to opposite ends of the line, the row taking the\n * full width available.\n */\n spread?: boolean\n /**\n * Marks the field as invalid, which colours the dot and tells assistive technology\n * so. It is for a rule the browser cannot check by itself.\n */\n invalid?: boolean\n /** Makes this choice unusable, greyed out through the colour tokens. */\n disabled?: boolean\n /**\n * Shows the selection without allowing it to be changed. The button can still be\n * focused and is still submitted with its form; a click or an arrow key simply selects\n * nothing. Set it on every button of the group.\n */\n readonly?: boolean\n}\n\nconst props = withDefaults(defineProps<RadioProps>(), {\n label: undefined,\n hint: undefined,\n labelPosition: 'end',\n spread: false,\n invalid: false,\n disabled: false,\n readonly: false,\n})\n\n// @a11y — the redirection buys the whole keyboard. Moving between the buttons of a group is\n// the browser's job, but it only groups inputs that share a `name` — so redirecting the\n// attributes is what makes the arrow keys work at all. The root being a layout box, `name`\n// left on it would reach nothing.\ndefineOptions({ inheritAttrs: false })\nconst { attrs, rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\nconst { hintId, describedBy } = useFieldIds(attrs, () => !!props.hint)\n\n/**\n * The value selected in the group, shared by every radio carrying the same `name`. It is\n * empty until one is chosen, and a radio is selected when it matches its own `value`.\n */\nconst model = defineModel<ItemValue>({ default: '' })\n\ndefineSlots<{\n /** The label, when it needs more than the `label` prop's text. It is clickable. */\n default?(): unknown\n}>()\n\nconst inputEl = ref<HTMLInputElement | null>(null)\n\n// @core\n// The native `readonly` attribute does nothing on a radio button. Cancelling the click is\n// what refuses the selection: the browser puts the group's previous selection back and fires\n// no `change`. It covers the arrow keys too, which select the next button of the group\n// through a click the browser dispatches on it — so the focus still moves, the selection\n// does not.\n//\n// No `aria-readonly` goes with it, unlike VCheckbox and VSwitch: ARIA allows it on a\n// `radiogroup` and not on a `radio`, and axe fails the page for it.\nfunction refuseWhenReadonly(event: MouseEvent) {\n if (props.readonly) event.preventDefault()\n}\n\n// The root is a wrapper, so a template ref on the component reaches the layout box and not\n// the control: these two are the way to the real radio button.\ndefineExpose({\n /** Moves the focus to the real radio button. */\n focus: (options?: FocusOptions) => inputEl.value?.focus(options),\n /** The real `<input type=\"radio\">`, for what `focus` does not cover. */\n el: inputEl,\n})\n</script>\n\n<template>\n <span\n class=\"v-radio v-choice\"\n :class=\"rootClass\"\n :style=\"rootStyle\"\n :data-label-position=\"labelPosition\"\n :data-spread=\"spread ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n >\n <label class=\"v-choice-row\">\n <input\n ref=\"inputEl\"\n v-model=\"model\"\n type=\"radio\"\n class=\"v-radio-input v-hidden-input\"\n :aria-invalid=\"invalid || undefined\"\n v-bind=\"forwardedAttrs\"\n :value=\"value\"\n :disabled=\"disabled\"\n :aria-describedby=\"describedBy\"\n @click=\"refuseWhenReadonly\"\n />\n <span class=\"v-radio-dot\" aria-hidden=\"true\" />\n <span v-if=\"$slots.default || label\" class=\"v-radio-label v-choice-label\">\n <slot>{{ label }}</slot>\n </span>\n </label>\n <span v-if=\"hint\" :id=\"hintId\" class=\"v-radio-hint v-choice-hint\">{{ hint }}</span>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The dot works exactly like VCheckbox's box, the accent filling it once the input is\n checked, with the small inner disc drawn as a pseudo-element in currentcolor so it\n follows whatever colour the state gives the ring's content. */\n .v-radio-dot {\n display: inline-grid;\n place-items: center;\n width: var(--vectis-control-size-check);\n height: var(--vectis-control-size-check);\n background: transparent;\n border: var(--vectis-control-border-width) solid var(--vectis-color-border-strong);\n border-radius: var(--vectis-radius-pill);\n color: var(--vectis-color-text-on-accent);\n transition:\n background-color var(--vectis-duration-fast) var(--vectis-ease-default),\n border-color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-radio-dot::before {\n content: '';\n width: var(--vectis-control-size-check-dot);\n height: var(--vectis-control-size-check-dot);\n border-radius: var(--vectis-radius-pill);\n background: currentcolor;\n opacity: 0;\n transition: opacity var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-radio-input:checked + .v-radio-dot::before {\n opacity: 1;\n }\n\n /* The state painting, rule for rule the same as VCheckbox's with its own classes: keep the\n two ALIGNED. The states below weigh (0,3,0), bar the read-only base at (0,2,0), so their\n ORDER arbitrates them: checked, read-only, invalid, then disabled last.\n\n The two hovers sit at (0,7,0) and therefore beat every one of them on specificity, order\n or no order — which is why they have to EXCLUDE by hand each state they must not repaint.\n Forgetting the invalid pair is what once rubbed the danger border out under the pointer,\n on a control whose whole point at that moment is to look wrong. */\n .v-radio:not([data-readonly])\n .v-choice-row:hover\n .v-radio-input:not(:disabled, :checked, :user-invalid, [aria-invalid='true'])\n + .v-radio-dot {\n border-color: color-mix(\n in oklab,\n var(--vectis-color-border-strong),\n var(--vectis-color-text) 15%\n );\n }\n\n .v-radio-input:checked + .v-radio-dot {\n background: var(--vectis-color-accent);\n border-color: var(--vectis-color-accent);\n }\n\n .v-radio:not([data-readonly])\n .v-choice-row:hover\n .v-radio-input:not(:disabled, :user-invalid, [aria-invalid='true']):checked\n + .v-radio-dot {\n background: var(--vectis-color-accent-hover);\n border-color: var(--vectis-color-accent-hover);\n }\n\n /* Read-only sinks like a read-only field, and a selected control trades the accent for the\n muted text colour: still plainly on, no longer inviting a click. The inner disc takes the\n surface colour, which contrasts with that fill in both themes, where white would vanish\n against the light grey of the dark theme. `:where()` keeps both rules at the weight of\n the states they sit between. */\n :where(.v-radio[data-readonly]) .v-radio-input + .v-radio-dot {\n background: var(--vectis-color-surface-sunken);\n border-color: var(--vectis-color-border);\n }\n\n :where(.v-radio[data-readonly]) .v-radio-input:checked + .v-radio-dot {\n background: var(--vectis-color-text-muted);\n border-color: var(--vectis-color-text-muted);\n color: var(--vectis-color-surface);\n }\n\n .v-radio-input:user-invalid + .v-radio-dot,\n .v-radio-input[aria-invalid='true'] + .v-radio-dot {\n border-color: var(--vectis-color-danger);\n }\n\n .v-radio-input:disabled + .v-radio-dot {\n background: var(--vectis-color-surface-muted);\n border-color: var(--vectis-color-border);\n color: var(--vectis-color-text-subtle);\n }\n\n @media (forced-colors: active) {\n /* Windows forced colors erase every author colour: a `background` becomes `Canvas` and a\n `border-color` becomes `CanvasText`, so a selected radio loses its inner disc outright, that disc being\n a `background` on a `background` where a checkbox has a `stroke` that survives. The system\n Highlight pair is what says \"selected\" here, as it does on a pressed VToggleItem, a\n selected VChip and the current VPagination page.\n\n The class is repeated to (0,8,0) so the row's own hover rules, which reach (0,7,0),\n cannot repaint it: `forced-color-adjust: none` takes the forcing off this element, and\n a hover left winning would then paint its REAL grey over the system colour. */\n .v-radio-input.v-radio-input.v-radio-input.v-radio-input.v-radio-input:checked:not(:disabled)\n + .v-radio-dot {\n forced-color-adjust: none;\n background: Highlight;\n border-color: Highlight;\n color: HighlightText;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-radio-dot,\n .v-radio-dot::before {\n transition: none;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyDA,IAAM,IAAQ,GAeR,EAAE,UAAO,cAAW,cAAW,sBAAmB,EAAa,GAC/D,EAAE,WAAQ,mBAAgB,EAAY,SAAa,CAAC,CAAC,EAAM,IAAI,GAM/D,IAAQ,EAAsB,GAAA,YAAgB,GAO9C,IAAU,EAA6B,IAAI;EAWjD,SAAS,EAAmB,GAAmB;GAC7C,AAAI,EAAM,YAAU,EAAM,eAAe;EAC3C;SAIA,EAAa;GAEX,QAAQ,MAA2B,EAAQ,OAAO,MAAM,CAAO;GAE/D,IAAI;EACN,CAAC,mBAIC,EA2BO,QAAA;GA1BL,OAAK,EAAA,CAAC,oBACE,EAAA,CAAA,CAAS,CAAA;GAChB,OAAK,EAAE,EAAA,CAAA,CAAS;GAChB,uBAAqB,EAAA;GACrB,eAAa,EAAA,SAAM,KAAQ,KAAA;GAC3B,iBAAe,EAAA,WAAQ,KAAQ,KAAA;MAEhC,EAiBQ,SAjBR,GAiBQ;KAhBN,EAWE,SAXF,EAWE;aAVI;IAAJ,KAAI;6CACU,QAAA;IACd,MAAK;IACL,OAAM;IACL,gBAAc,EAAA,WAAW,KAAA;MAClB,EAAA,CAAA,GAAc;IACrB,OAAO,EAAA;IACP,UAAU,EAAA;IACV,oBAAkB,EAAA,CAAA;IAClB,SAAO;0BARC,EAAA,KAAK,CAAA,CAAA;YAUhB,EAA+C,QAAA;IAAzC,OAAM;IAAc,eAAY;;GAC1BA,EAAAA,OAAO,WAAW,EAAA,SAAA,EAAA,GAA9B,EAEO,QAFP,GAEO,CADL,EAAwB,EAAA,QAAA,WAAA,CAAA,SAAA,CAAA,EAAA,EAAf,EAAA,KAAK,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;MAGN,EAAA,QAAA,EAAA,GAAZ,EAAmF,QAAA;;GAAhE,IAAI,EAAA,CAAA;GAAQ,OAAM;OAAgC,EAAA,IAAI,GAAA,GAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,IAAA,CAAA"}
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * It carries no content slot and no spacing prop, on purpose. A divider with a label
7
7
  * in the middle is really a heading that happens to have a rule, and the space
8
- * around a rule belongs to the layout placing it — the same rule VTypography
8
+ * around a rule belongs to the layout placing it: the same rule VTypography
9
9
  * follows.
10
10
  */
11
11
  /** Which way the rule runs. */
@@ -1 +1 @@
1
- {"version":3,"file":"VSeparator.js","names":[],"sources":["../../../src/components/VSeparator/VSeparator.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @a11y — no behavioural JS at all. Choosing an `<hr>` as the root IS the\n// accessibility decision: the `separator` role comes with it, and\n// `aria-orientation` is emitted for the vertical case alone.\n/**\n * A one-pixel rule drawn between two blocks. It renders an `<hr>`, so assistive\n * technology already knows it is a separator, and the element takes no focus and\n * appears in no keyboard navigation.\n *\n * It carries no content slot and no spacing prop, on purpose. A divider with a label\n * in the middle is really a heading that happens to have a rule, and the space\n * around a rule belongs to the layout placing it — the same rule VTypography\n * follows.\n */\n/** Which way the rule runs. */\nexport type SeparatorOrientation = 'horizontal' | 'vertical'\n\ninterface SeparatorProps {\n /**\n * The direction the rule runs in: across by default, or down the page under\n * `vertical`. A vertical rule needs a height to show: as a flex or grid item it\n * takes the one of its line, but in ordinary flow the consumer has to set one.\n */\n orientation?: SeparatorOrientation\n}\n\nwithDefaults(defineProps<SeparatorProps>(), {\n orientation: 'horizontal',\n})\n</script>\n\n<template>\n <!-- aria-orientation is emitted only when it CONTRADICTS what the role already\n implies: a separator is horizontal by default, so stating it would merely\n restate the role. This is the same convention the VTabs tablist follows. -->\n <hr\n class=\"v-separator\"\n :data-orientation=\"orientation\"\n :aria-orientation=\"orientation === 'vertical' ? 'vertical' : undefined\"\n />\n</template>\n\n<style>\n@layer vectis.components {\n .v-separator {\n flex: none;\n /* The rule is painted with a BORDER and not a background. Under Windows forced\n colours a background is forced to Canvas, where a rule drawn that way simply\n vanishes, while a border colour is forced to CanvasText and survives — the\n same argument that made the icon registry ship SVG paths. Everywhere else the\n two paints are pixel-identical, `box-sizing: border-box` keeping the box at\n one pixel in total either way.\n\n The user agent gives an <hr> a 0.5em block margin, an automatic inline one and\n an inset border. All three are cancelled here rather than in the reset: the\n reset sits in a weaker layer, so the margin below would win only by accident.\n\n TRAP — `.v-menu-separator` and `.v-combobox-separator` override that margin\n from THEIR OWN sheet, and which of the two sheets the consumer's bundler puts\n last is not ours to decide. Both are therefore written as the compound\n `.v-separator.v-x-separator`, and every declaration added here falls under the\n same obligation. */\n margin: 0;\n border: 0 solid var(--vectis-color-border);\n }\n\n .v-separator[data-orientation='horizontal'] {\n border-block-start-width: 1px;\n }\n\n /* `align-self: stretch` IS the contract of a vertical rule. An <hr> has no height\n of its own, so the rule only appears when it is a flex or grid item, where this\n makes it take the full cross size of its line whatever the container's\n align-items says. In ordinary flow it collapses to nothing, silently and with no\n error — there it is up to the consumer to give it a block-size. */\n .v-separator[data-orientation='vertical'] {\n align-self: stretch;\n border-inline-start-width: 1px;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"VSeparator.js","names":[],"sources":["../../../src/components/VSeparator/VSeparator.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// No behavioural JS at all. Choosing an `<hr>` as the root IS the\n// accessibility decision: the `separator` role comes with it, and\n// `aria-orientation` is emitted for the vertical case alone.\n/**\n * A one-pixel rule drawn between two blocks. It renders an `<hr>`, so assistive\n * technology already knows it is a separator, and the element takes no focus and\n * appears in no keyboard navigation.\n *\n * It carries no content slot and no spacing prop, on purpose. A divider with a label\n * in the middle is really a heading that happens to have a rule, and the space\n * around a rule belongs to the layout placing it: the same rule VTypography\n * follows.\n */\n/** Which way the rule runs. */\nexport type SeparatorOrientation = 'horizontal' | 'vertical'\n\ninterface SeparatorProps {\n /**\n * The direction the rule runs in: across by default, or down the page under\n * `vertical`. A vertical rule needs a height to show: as a flex or grid item it\n * takes the one of its line, but in ordinary flow the consumer has to set one.\n */\n orientation?: SeparatorOrientation\n}\n\nwithDefaults(defineProps<SeparatorProps>(), {\n orientation: 'horizontal',\n})\n</script>\n\n<template>\n <!-- aria-orientation is emitted only when it CONTRADICTS what the role already\n implies: a separator is horizontal by default, so stating it would merely\n restate the role. This is the same convention the VTabs tablist follows. -->\n <hr\n class=\"v-separator\"\n :data-orientation=\"orientation\"\n :aria-orientation=\"orientation === 'vertical' ? 'vertical' : undefined\"\n />\n</template>\n\n<style>\n@layer vectis.components {\n .v-separator {\n flex: none;\n /* The rule is painted with a BORDER and not a background. Under Windows forced\n colours a background is forced to Canvas, where a rule drawn that way simply\n vanishes, while a border colour is forced to CanvasText and survives — the\n same argument that made the icon registry ship SVG paths. Everywhere else the\n two paints are pixel-identical, `box-sizing: border-box` keeping the box at\n one pixel in total either way.\n\n The user agent gives an <hr> a 0.5em block margin, an automatic inline one and\n an inset border. All three are cancelled here rather than in the reset: the\n reset sits in a weaker layer, so the margin below would win only by accident.\n\n TRAP — `.v-menu-separator` and `.v-combobox-separator` override that margin\n from THEIR OWN sheet, and which of the two sheets the consumer's bundler puts\n last is not ours to decide. Both are therefore written as the compound\n `.v-separator.v-x-separator`, and every declaration added here falls under the\n same obligation. */\n margin: 0;\n border: 0 solid var(--vectis-color-border);\n }\n\n .v-separator[data-orientation='horizontal'] {\n border-block-start-width: 1px;\n }\n\n /* `align-self: stretch` IS the contract of a vertical rule. An <hr> has no height\n of its own, so the rule only appears when it is a flex or grid item, where this\n makes it take the full cross size of its line whatever the container's\n align-items says. In ordinary flow it collapses to nothing, silently and with no\n error — there it is up to the consumer to give it a block-size. */\n .v-separator[data-orientation='vertical'] {\n align-self: stretch;\n border-inline-start-width: 1px;\n }\n}\n</style>\n"],"mappings":""}