vectis-ui 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +22 -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 +67 -57
  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
@@ -62,7 +62,7 @@ var h = /*@__PURE__*/ s({
62
62
  function v(e) {
63
63
  if (h.multiple) {
64
64
  let t = Array.isArray(g.value) ? g.value : [];
65
- if (h.mandatory && t.length === 1 && t.includes(e)) return;
65
+ if (h.mandatory && t.length > 0 && t.every((t) => t === e)) return;
66
66
  g.value = i(t, e);
67
67
  return;
68
68
  }
@@ -89,6 +89,7 @@ var h = /*@__PURE__*/ s({
89
89
  }
90
90
  });
91
91
  function y(e) {
92
+ if (!e.target.matches(".v-toggle-item")) return;
92
93
  let r = e.currentTarget;
93
94
  t(e, r, () => n(r, ".v-toggle-item:not(:disabled)"), { vertical: h.orientation === "vertical" });
94
95
  }
@@ -1 +1 @@
1
- {"version":3,"file":"VToggle.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VToggle/VToggle.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @keyboard @core\n/**\n * A row of buttons where one — or several — stay pressed: choosing a text alignment,\n * a view, a set of filters. A single v-model holds what is chosen.\n *\n * Every item is a VButton, the selected one drawn in the group's tone and the others\n * quiet. The row itself is a VButtonGroup, which is where the drawing lives: joining the\n * items or leaving them apart, the lines between them, the shared size and the shared\n * elevation are that component's, and the props for them are handed straight over.\n * Nothing about hovering, focusing or disabling is written here either: it all comes\n * from VButton.\n *\n * The JavaScript covers the two things HTML has no answer for: what a click does to\n * the selection — toggling it off, or refusing to when the last choice may not be\n * given up — and moving between the items with the arrow keys.\n */\nimport { computed, provide, ref } from 'vue'\n\nimport VButtonGroup from '../VButton/VButtonGroup.vue'\nimport { toggleKey } from './context'\n\nimport { toggleValue } from '../../utils/array'\nimport { arrowNavigate, navigableItems } from '../../utils/arrowNav'\n\nimport type { ItemValue } from '../../types'\n\n/**\n * What identifies an item. It is the design system's own `ItemValue`, re-exported\n * under the family's name so a consumer typing a toggle need not reach for another module.\n */\nexport type ToggleValue = ItemValue\n/**\n * What the v-model holds, which follows `multiple`: one value or nothing when a single\n * choice is allowed, and a list of them when several are.\n */\nexport type ToggleModelValue = ToggleValue | ToggleValue[] | null\nexport type ToggleItemVariant = 'ghost' | 'outline'\nexport type ToggleSelectedVariant = 'solid' | 'soft' | 'ghost'\nexport type ToggleTone = 'accent' | 'neutral' | 'danger'\nexport type ToggleSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\nexport type ToggleOrientation = 'horizontal' | 'vertical'\n\ninterface ToggleProps {\n /** Allows several items to be chosen at once, which makes the v-model a list. */\n multiple?: boolean\n /**\n * Refuses to let the last chosen item be given up, so that something is always\n * selected once something has been. It is a guard and nothing more: it selects\n * nothing on its own at the start.\n */\n mandatory?: boolean\n /**\n * Leaves the items as separate buttons with a gap between them. Left out, they are\n * joined into one segmented control.\n */\n detached?: boolean\n /**\n * Takes the lines out from between the joined items, so the row reads as one frame\n * rather than as segments. It has no effect under `detached`, where the items are\n * separate buttons already.\n */\n seamless?: boolean\n /** Whether the items run across the page or down it. */\n orientation?: ToggleOrientation\n /**\n * Stretches the row across the whole inline size of its parent, every item taking an equal\n * share of it, on the terms of VButtonGroup's own `fullWidth`.\n */\n fullWidth?: boolean\n /**\n * How the UNSELECTED items are drawn. What the selected one takes is `selectedVariant`.\n * It is named for the ITEMS because that is what it paints: on VTabs and VDataTable\n * `variant` names the decoration of the frame instead.\n */\n itemVariant?: ToggleItemVariant\n /**\n * How the SELECTED item is drawn, in the group's tone: filled, tinted, or the colour\n * of its text alone.\n */\n selectedVariant?: ToggleSelectedVariant\n /** The colour a selected item takes. The others stay neutral. */\n tone?: ToggleTone\n /** The height of the items, from the scale shared by every control. */\n size?: ToggleSize\n /** Takes 4px off the height of every item. */\n compact?: boolean\n /** Raises the row off the page, on the terms of VButtonGroup's own `elevated`. */\n elevated?: boolean\n /** Makes the whole group unusable. */\n disabled?: boolean\n /**\n * Draws the selected item's icon in its filled form, a common way of reinforcing\n * that it is the one in effect.\n */\n selectedIconFilled?: boolean\n /**\n * What screen readers announce for the group — \"Text alignment\", \"Filters\". It is\n * strongly recommended: no default could say what a group of buttons is for.\n */\n label?: string\n}\n\nconst props = withDefaults(defineProps<ToggleProps>(), {\n multiple: false,\n mandatory: false,\n detached: false,\n seamless: false,\n orientation: 'horizontal',\n fullWidth: false,\n itemVariant: 'ghost',\n selectedVariant: 'solid',\n tone: 'accent',\n size: 'md',\n compact: false,\n elevated: false,\n disabled: false,\n selectedIconFilled: false,\n label: undefined,\n})\n\ndefineSlots<{\n /** The items of the group. */\n default(): unknown\n}>()\n\n/**\n * What is selected, and its SHAPE follows `multiple`: a single value — or `null`, which is\n * where it starts — when one item may be chosen, and an array when several may. A null or\n * scalar value passed in `multiple` mode is read as an empty selection.\n *\n * The array is never mutated in place; each change is a new one, which is what wakes the\n * consumer's binding. Re-clicking the selected item deselects it unless `mandatory` is set.\n */\nconst model = defineModel<ToggleModelValue>({ default: null })\n\nfunction isSelected(value: ToggleValue): boolean {\n return props.multiple\n ? Array.isArray(model.value) && model.value.includes(value)\n : model.value === value\n}\n\n/*\n * What a click does to the selection.\n *\n * With several choices allowed, the list is NEVER changed in place: each write\n * produces a new one. That is what makes a consumer's own watchers and computed values\n * notice; mutating the existing list would leave some of them silent. A model still\n * holding a single value, or nothing, is treated as an empty list rather than\n * refused.\n *\n * There is no check for the disabled state here, and none is needed: a disabled button\n * emits no click at all.\n */\nfunction select(value: ToggleValue) {\n if (props.multiple) {\n const current = Array.isArray(model.value) ? model.value : []\n if (props.mandatory && current.length === 1 && current.includes(value)) return\n model.value = toggleValue(current, value)\n return\n }\n if (model.value === value) {\n if (!props.mandatory) model.value = null\n return\n }\n model.value = value\n}\n\nprovide(toggleKey, {\n isSelected,\n select,\n get itemVariant() {\n return props.itemVariant\n },\n get selectedVariant() {\n return props.selectedVariant\n },\n get tone() {\n return props.tone\n },\n get selectedIconFilled() {\n return props.selectedIconFilled\n },\n})\n\n// @keyboard @a11y\n/*\n * The arrow keys, through the shared implementation in `utils/arrowNav`.\n *\n * Every visible item stays a stop in the tab order here — the VPagination model. The\n * single-stop treatment is reserved for the patterns that require it, a row of tabs or\n * a radio group, and a group of buttons is neither. Disabled items are really disabled\n * buttons, which the selector leaves out.\n *\n * The container is read from the event rather than kept as a reference: the root is a\n * VButtonGroup, so a template ref would hand back its component instance rather than the\n * element the items are navigated inside.\n */\nfunction onKeydown(event: KeyboardEvent) {\n const group = event.currentTarget as HTMLElement\n arrowNavigate(event, group, () => navigableItems(group, '.v-toggle-item:not(:disabled)'), {\n vertical: props.orientation === 'vertical',\n })\n}\n\nconst groupRef = ref<InstanceType<typeof VButtonGroup> | null>(null)\nconst groupEl = computed(() => groupRef.value?.el ?? null)\n\n// The root is a VButtonGroup and the items come from the consumer's slot, so a template ref\n// on the toggle reaches no button. `focus` goes to the item that stands for the current\n// choice, the one a keyboard user would expect to resume from.\ndefineExpose({\n /**\n * Moves the focus to the selected item (the first of them when several are), or to the\n * first item that can take it when nothing is selected.\n */\n focus: (options?: FocusOptions) => {\n const group = groupEl.value\n const enabled = '.v-toggle-item:not(:disabled, [aria-disabled=\"true\"])'\n const item =\n group?.querySelector<HTMLElement>(`${enabled}[aria-pressed=\"true\"]`) ??\n group?.querySelector<HTMLElement>(enabled)\n item?.focus(options)\n },\n /** The `role=\"group\"` row, which is also where the consumer's attributes land. */\n el: groupEl,\n})\n</script>\n\n<template>\n <!-- The row is a VButtonGroup, which merges the borders of the buttons among its\n children — which is why an item renders the button as its own root, and why what\n may stand between the two is the wrappers a VTooltip, a VPopover or a VBadge put\n there, and nothing else. It brings the role, its accessible name and the orientation\n attribute with it, and of the props handed to it here it forwards the size, the density,\n the elevation and the disabled state to the buttons itself.\n\n The three booleans go down as `|| undefined`, the VPagination idiom: `undefined` is\n what means \"no opinion\" to a group, where `false` is an order every item would obey,\n and a toggle left at its defaults has no opinion to give. The size is always one, the\n toggle having a default of its own.\n\n The name is resolved by the group, which sees a consumer's `aria-label` or\n `aria-labelledby` too: they fall through this component onto it.\n\n `variant` is deliberately NOT among them, and neither is the tone: the group wins\n over a button that names its own variant, which would erase the one the selected\n item carries. Both stay with the items, through the context.\n\n `data-variant` is a plain attribute, and it is what tells the sheet an outline row\n from a ghost one — something the items cannot say for themselves, since the\n selected one carries its own variant rather than the row's. -->\n <VButtonGroup\n ref=\"groupRef\"\n class=\"v-toggle\"\n :orientation=\"orientation\"\n :detached=\"detached\"\n :seamless=\"seamless\"\n :full-width=\"fullWidth\"\n :size=\"size\"\n :compact=\"compact || undefined\"\n :elevated=\"elevated || undefined\"\n :disabled=\"disabled || undefined\"\n :label=\"label\"\n :data-item-variant=\"itemVariant\"\n @keydown=\"onKeydown\"\n >\n <slot />\n </VButtonGroup>\n</template>\n\n<style>\n@layer vectis.components {\n /*\n * Both rules below are written for the two shapes an item can take, exactly as\n * VButtonGroup's own sheet is and for the same reason: a VTooltip, a VPopover or a\n * VBadge puts a wrapper between the row and the item, and a rule reaching for a direct\n * child alone would leave a gap in the frame around whichever item carries one. The\n * `:not(:where(.v-overlay))` guard weighs nothing and keeps a panel from passing for an\n * item; the pair is one specificity, so the arbitration with the group's seamless rules\n * holds on both shapes.\n *\n * The frame of an `outline` row, which only that row has: the colour its unselected\n * items already paint. They are drawn in the NEUTRAL tone, so this is what their\n * `--tone-border-soft` resolves to — naming that variable here instead would read the\n * SELECTED item's tone and tint one segment of the frame accent or red.\n *\n * It is a variable on the root rather than a value in the rule below because a\n * disabled segment greys, and VButton greys an outline border to a different token.\n * Nothing else declares it, so the two rules never arbitrate a border-color between\n * them.\n */\n .v-toggle[data-item-variant='outline'] {\n --toggle-frame: var(--vectis-color-border-strong);\n }\n\n .v-toggle[data-item-variant='outline'] > .v-toggle-item:is(:disabled, [aria-disabled='true']),\n .v-toggle[data-item-variant='outline']\n > :not(:where(.v-overlay, .v-button-group))\n .v-toggle-item:is(:disabled, [aria-disabled='true']):not(:where(.v-overlay *)) {\n --toggle-frame: var(--vectis-color-border);\n }\n\n /*\n * `soft` and `ghost` leave VButton's border transparent, which in an outline row\n * opens a gap in the frame for the whole width of the selected segment. Restoring it\n * on all four sides is what keeps the frame closed wherever the selection sits, in\n * either orientation and in RTL. It is not conditioned on `seamless`, and deliberately\n * so: the border is transparent whether the internal lines are drawn or not. Seamless,\n * the shared edges are cleared again by VButtonGroup's own (0,6,0) rules, which is why\n * they are written at that weight — a middle segment then keeps its top and bottom\n * alone.\n */\n .v-toggle[data-item-variant='outline']\n > .v-toggle-item[aria-pressed='true']:is([data-variant='soft'], [data-variant='ghost']),\n .v-toggle[data-item-variant='outline']\n > :not(:where(.v-overlay, .v-button-group))\n .v-toggle-item[aria-pressed='true']:is([data-variant='soft'], [data-variant='ghost']):not(\n :where(.v-overlay *)\n ) {\n border-color: var(--toggle-frame);\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuGA,IAAM,IAAQ,GA+BR,IAAQ,EAA6B,GAAA,YAAkB;EAE7D,SAAS,EAAW,GAA6B;GAC/C,OAAO,EAAM,WACT,MAAM,QAAQ,EAAM,KAAK,KAAK,EAAM,MAAM,SAAS,CAAK,IACxD,EAAM,UAAU;EACtB;EAcA,SAAS,EAAO,GAAoB;GAClC,IAAI,EAAM,UAAU;IAClB,IAAM,IAAU,MAAM,QAAQ,EAAM,KAAK,IAAI,EAAM,QAAQ,CAAC;IAC5D,IAAI,EAAM,aAAa,EAAQ,WAAW,KAAK,EAAQ,SAAS,CAAK,GAAG;IACxE,EAAM,QAAQ,EAAY,GAAS,CAAK;IACxC;GACF;GACA,IAAI,EAAM,UAAU,GAAO;IACzB,AAAK,EAAM,cAAW,EAAM,QAAQ;IACpC;GACF;GACA,EAAM,QAAQ;EAChB;EAEA,EAAQ,GAAW;GACjB;GACA;GACA,IAAI,cAAc;IAChB,OAAO,EAAM;GACf;GACA,IAAI,kBAAkB;IACpB,OAAO,EAAM;GACf;GACA,IAAI,OAAO;IACT,OAAO,EAAM;GACf;GACA,IAAI,qBAAqB;IACvB,OAAO,EAAM;GACf;EACF,CAAC;EAeD,SAAS,EAAU,GAAsB;GACvC,IAAM,IAAQ,EAAM;GACpB,EAAc,GAAO,SAAa,EAAe,GAAO,+BAA+B,GAAG,EACxF,UAAU,EAAM,gBAAgB,WAClC,CAAC;EACH;EAEA,IAAM,IAAW,EAA8C,IAAI,GAC7D,IAAU,QAAe,EAAS,OAAO,MAAM,IAAI;SAKzD,EAAa;GAKX,QAAQ,MAA2B;IACjC,IAAM,IAAQ,EAAQ,OAChB,IAAU;IAIhB,CAFE,GAAO,cAA2B,GAAG,EAAQ,sBAAsB,KACnE,GAAO,cAA2B,CAAO,EAAA,EACrC,MAAM,CAAO;GACrB;GAEA,IAAI;EACN,CAAC,mBA0BC,EAgBe,GAAA;YAfT;GAAJ,KAAI;GACJ,OAAM;GACL,aAAa,EAAA;GACb,UAAU,EAAA;GACV,UAAU,EAAA;GACV,cAAY,EAAA;GACZ,MAAM,EAAA;GACN,SAAS,EAAA,WAAW,KAAA;GACpB,UAAU,EAAA,YAAY,KAAA;GACtB,UAAU,EAAA,YAAY,KAAA;GACtB,OAAO,EAAA;GACP,qBAAmB,EAAA;GACV;;oBAEF,CAAR,EAAQ,EAAA,QAAA,SAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"VToggle.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VToggle/VToggle.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @keyboard @core\n/**\n * A row of buttons where one — or several — stay pressed: choosing a text alignment,\n * a view, a set of filters. A single v-model holds what is chosen.\n *\n * Every item is a VButton, the selected one drawn in the group's tone and the others\n * quiet. The row itself is a VButtonGroup, which is where the drawing lives: joining the\n * items or leaving them apart, the lines between them, the shared size and the shared\n * elevation are that component's, and the props for them are handed straight over.\n * Nothing about hovering, focusing or disabling is written here either: it all comes\n * from VButton.\n *\n * The JavaScript covers the two things HTML has no answer for: what a click does to\n * the selection — toggling it off, or refusing to when the last choice may not be\n * given up — and moving between the items with the arrow keys.\n */\nimport { computed, provide, ref } from 'vue'\n\nimport VButtonGroup from '../VButton/VButtonGroup.vue'\nimport { toggleKey } from './context'\n\nimport { toggleValue } from '../../utils/array'\nimport { arrowNavigate, navigableItems } from '../../utils/arrowNav'\n\nimport type { ItemValue } from '../../types'\n\n/**\n * What identifies an item. It is the design system's own `ItemValue`, re-exported\n * under the family's name so a consumer typing a toggle need not reach for another module.\n */\nexport type ToggleValue = ItemValue\n/**\n * What the v-model holds, which follows `multiple`: one value or nothing when a single\n * choice is allowed, and a list of them when several are.\n */\nexport type ToggleModelValue = ToggleValue | ToggleValue[] | null\n/** How the items that are not selected are drawn. */\nexport type ToggleItemVariant = 'ghost' | 'outline'\n/** How a selected item is drawn. */\nexport type ToggleSelectedVariant = 'solid' | 'soft' | 'ghost'\n/** The colour of a selected item. */\nexport type ToggleTone = 'accent' | 'neutral' | 'danger'\n/** The height of the items, from the scale every control shares. */\nexport type ToggleSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n/** Whether the items run across the page or down it. */\nexport type ToggleOrientation = 'horizontal' | 'vertical'\n\ninterface ToggleProps {\n /** Allows several items to be chosen at once, which makes the v-model a list. */\n multiple?: boolean\n /**\n * Refuses to let the last chosen item be given up, so that something is always\n * selected once something has been. It is a guard and nothing more: it selects\n * nothing on its own at the start.\n */\n mandatory?: boolean\n /**\n * Leaves the items as separate buttons with a gap between them. Left out, they are\n * joined into one segmented control.\n */\n detached?: boolean\n /**\n * Takes the lines out from between the joined items, so the row reads as one frame\n * rather than as segments. It has no effect under `detached`, where the items are\n * separate buttons already.\n */\n seamless?: boolean\n /** Whether the items run across the page or down it. */\n orientation?: ToggleOrientation\n /**\n * Stretches the row across the whole inline size of its parent, every item taking an equal\n * share of it, on the terms of VButtonGroup's own `fullWidth`.\n */\n fullWidth?: boolean\n /**\n * How the UNSELECTED items are drawn. What the selected one takes is `selectedVariant`.\n * It is named for the ITEMS because that is what it paints: on VTabs and VDataTable\n * `variant` names the decoration of the frame instead.\n */\n itemVariant?: ToggleItemVariant\n /**\n * How the SELECTED item is drawn, in the group's tone: filled, tinted, or the colour\n * of its text alone.\n */\n selectedVariant?: ToggleSelectedVariant\n /** The colour a selected item takes. The others stay neutral. */\n tone?: ToggleTone\n /** The height of the items, from the scale shared by every control. */\n size?: ToggleSize\n /** Takes 4px off the height of every item. */\n compact?: boolean\n /** Raises the row off the page, on the terms of VButtonGroup's own `elevated`. */\n elevated?: boolean\n /** Makes the whole group unusable. */\n disabled?: boolean\n /**\n * Draws the selected item's icon in its filled form, a common way of reinforcing\n * that it is the one in effect.\n */\n selectedIconFilled?: boolean\n /**\n * What screen readers announce for the group, such as \"Text alignment\" or \"Filters\". It is\n * strongly recommended: no default could say what a group of buttons is for.\n */\n label?: string\n}\n\nconst props = withDefaults(defineProps<ToggleProps>(), {\n multiple: false,\n mandatory: false,\n detached: false,\n seamless: false,\n orientation: 'horizontal',\n fullWidth: false,\n itemVariant: 'ghost',\n selectedVariant: 'solid',\n tone: 'accent',\n size: 'md',\n compact: false,\n elevated: false,\n disabled: false,\n selectedIconFilled: false,\n label: undefined,\n})\n\ndefineSlots<{\n /** The items of the group. */\n default(): unknown\n}>()\n\n/**\n * What is selected, and its SHAPE follows `multiple`: a single value (or `null`, which is\n * where it starts) when one item may be chosen, and an array when several may. A null or\n * scalar value passed in `multiple` mode is read as an empty selection.\n *\n * The array is never mutated in place; each change is a new one, which is what wakes the\n * consumer's binding. Re-clicking the selected item deselects it unless `mandatory` is set.\n */\nconst model = defineModel<ToggleModelValue>({ default: null })\n\nfunction isSelected(value: ToggleValue): boolean {\n return props.multiple\n ? Array.isArray(model.value) && model.value.includes(value)\n : model.value === value\n}\n\n/*\n * What a click does to the selection.\n *\n * With several choices allowed, the list is NEVER changed in place: each write\n * produces a new one. That is what makes a consumer's own watchers and computed values\n * notice; mutating the existing list would leave some of them silent. A model still\n * holding a single value, or nothing, is treated as an empty list rather than\n * refused.\n *\n * There is no check for the disabled state here, and none is needed: a disabled button\n * emits no click at all.\n */\nfunction select(value: ToggleValue) {\n if (props.multiple) {\n const current = Array.isArray(model.value) ? model.value : []\n // `every` rather than a length of one: the removal takes out every copy of the value, so\n // a list holding it twice would otherwise be emptied past the guard.\n if (props.mandatory && current.length > 0 && current.every((v) => v === value)) return\n model.value = toggleValue(current, value)\n return\n }\n if (model.value === value) {\n if (!props.mandatory) model.value = null\n return\n }\n model.value = value\n}\n\nprovide(toggleKey, {\n isSelected,\n select,\n get itemVariant() {\n return props.itemVariant\n },\n get selectedVariant() {\n return props.selectedVariant\n },\n get tone() {\n return props.tone\n },\n get selectedIconFilled() {\n return props.selectedIconFilled\n },\n})\n\n// @keyboard @a11y\n/*\n * The arrow keys, through the shared implementation in `utils/arrowNav`.\n *\n * Every visible item stays a stop in the tab order here — the VPagination model. The\n * single-stop treatment is reserved for the patterns that require it, a row of tabs or\n * a radio group, and a group of buttons is neither. Disabled items are really disabled\n * buttons, which the selector leaves out.\n *\n * The container is read from the event rather than kept as a reference: the root is a\n * VButtonGroup, so a template ref would hand back its component instance rather than the\n * element the items are navigated inside.\n *\n * Only a key pressed ON an item is taken. An item may carry a companion whose content sits\n * inside the group (a VPopover's panel stays a DOM descendant of its trigger), and an arrow\n * typed in a field there must move the caret, not the focus.\n */\nfunction onKeydown(event: KeyboardEvent) {\n if (!(event.target as Element).matches('.v-toggle-item')) return\n const group = event.currentTarget as HTMLElement\n arrowNavigate(event, group, () => navigableItems(group, '.v-toggle-item:not(:disabled)'), {\n vertical: props.orientation === 'vertical',\n })\n}\n\nconst groupRef = ref<InstanceType<typeof VButtonGroup> | null>(null)\nconst groupEl = computed(() => groupRef.value?.el ?? null)\n\n// The root is a VButtonGroup and the items come from the consumer's slot, so a template ref\n// on the toggle reaches no button. `focus` goes to the item that stands for the current\n// choice, the one a keyboard user would expect to resume from.\ndefineExpose({\n /**\n * Moves the focus to the selected item (the first of them when several are), or to the\n * first item that can take it when nothing is selected.\n */\n focus: (options?: FocusOptions) => {\n const group = groupEl.value\n const enabled = '.v-toggle-item:not(:disabled, [aria-disabled=\"true\"])'\n const item =\n group?.querySelector<HTMLElement>(`${enabled}[aria-pressed=\"true\"]`) ??\n group?.querySelector<HTMLElement>(enabled)\n item?.focus(options)\n },\n /** The `role=\"group\"` row, which is also where the consumer's attributes land. */\n el: groupEl,\n})\n</script>\n\n<template>\n <!-- The row is a VButtonGroup, which merges the borders of the buttons among its\n children — which is why an item renders the button as its own root, and why what\n may stand between the two is the wrappers a VTooltip, a VPopover or a VBadge put\n there, and nothing else. It brings the role, its accessible name and the orientation\n attribute with it, and of the props handed to it here it forwards the size, the density,\n the elevation and the disabled state to the buttons itself.\n\n The three booleans go down as `|| undefined`, the VPagination idiom: `undefined` is\n what means \"no opinion\" to a group, where `false` is an order every item would obey,\n and a toggle left at its defaults has no opinion to give. The size is always one, the\n toggle having a default of its own.\n\n The name is resolved by the group, which sees a consumer's `aria-label` or\n `aria-labelledby` too: they fall through this component onto it.\n\n `variant` is deliberately NOT among them, and neither is the tone: the group wins\n over a button that names its own variant, which would erase the one the selected\n item carries. Both stay with the items, through the context.\n\n `data-item-variant` is a plain attribute, and it is what tells the sheet an outline row\n from a ghost one — something the items cannot say for themselves, since the\n selected one carries its own variant rather than the row's. -->\n <VButtonGroup\n ref=\"groupRef\"\n class=\"v-toggle\"\n :orientation=\"orientation\"\n :detached=\"detached\"\n :seamless=\"seamless\"\n :full-width=\"fullWidth\"\n :size=\"size\"\n :compact=\"compact || undefined\"\n :elevated=\"elevated || undefined\"\n :disabled=\"disabled || undefined\"\n :label=\"label\"\n :data-item-variant=\"itemVariant\"\n @keydown=\"onKeydown\"\n >\n <slot />\n </VButtonGroup>\n</template>\n\n<style>\n@layer vectis.components {\n /*\n * Both rules below are written for the two shapes an item can take, exactly as\n * VButtonGroup's own sheet is and for the same reason: a VTooltip, a VPopover or a\n * VBadge puts a wrapper between the row and the item, and a rule reaching for a direct\n * child alone would leave a gap in the frame around whichever item carries one. The\n * `:not(:where(.v-overlay))` guard weighs nothing and keeps a panel from passing for an\n * item; the pair is one specificity, so the arbitration with the group's seamless rules\n * holds on both shapes.\n *\n * The frame of an `outline` row, which only that row has: the colour its unselected\n * items already paint. They are drawn in the NEUTRAL tone, so this is what their\n * `--tone-border-soft` resolves to — naming that variable here instead would read the\n * SELECTED item's tone and tint one segment of the frame accent or red.\n *\n * It is a variable on the root rather than a value in the rule below because a\n * disabled segment greys, and VButton greys an outline border to a different token.\n * Nothing else declares it, so the two rules never arbitrate a border-color between\n * them.\n */\n .v-toggle[data-item-variant='outline'] {\n --toggle-frame: var(--vectis-color-border-strong);\n }\n\n .v-toggle[data-item-variant='outline'] > .v-toggle-item:is(:disabled, [aria-disabled='true']),\n .v-toggle[data-item-variant='outline']\n > :not(:where(.v-overlay, .v-button-group))\n .v-toggle-item:is(:disabled, [aria-disabled='true']):not(:where(.v-overlay *)) {\n --toggle-frame: var(--vectis-color-border);\n }\n\n /*\n * `soft` and `ghost` leave VButton's border transparent, which in an outline row\n * opens a gap in the frame for the whole width of the selected segment. Restoring it\n * on all four sides is what keeps the frame closed wherever the selection sits, in\n * either orientation and in RTL. It is not conditioned on `seamless`, and deliberately\n * so: the border is transparent whether the internal lines are drawn or not. Seamless,\n * the shared edges are cleared again by VButtonGroup's own (0,6,0) rules, which is why\n * they are written at that weight — a middle segment then keeps its top and bottom\n * alone.\n */\n .v-toggle[data-item-variant='outline']\n > .v-toggle-item[aria-pressed='true']:is([data-variant='soft'], [data-variant='ghost']),\n .v-toggle[data-item-variant='outline']\n > :not(:where(.v-overlay, .v-button-group))\n .v-toggle-item[aria-pressed='true']:is([data-variant='soft'], [data-variant='ghost']):not(\n :where(.v-overlay *)\n ) {\n border-color: var(--toggle-frame);\n }\n\n /*\n * Windows forced colors replace every background with the page's, so the pressed item would look\n * exactly like the others there: the fill is its only cue, the state being in an ARIA\n * attribute a sighted reader never sees. It takes the system's own selection pair\n * instead, and opts out of the forcing for that element alone so the pair is painted.\n *\n * TRAP — the class is repeated to reach (0,6,0). The variant, hover and active rules\n * reach (0,5,0), and with the forcing turned off any of them that still won would paint\n * its tone over the selection, with HighlightText on top of it.\n */\n @media (forced-colors: active) {\n .v-toggle-item.v-toggle-item.v-toggle-item.v-toggle-item[aria-pressed='true']:not(:disabled) {\n forced-color-adjust: none;\n background-color: Highlight;\n color: HighlightText;\n border-color: Highlight;\n outline-color: CanvasText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4GA,IAAM,IAAQ,GA+BR,IAAQ,EAA6B,GAAA,YAAkB;EAE7D,SAAS,EAAW,GAA6B;GAC/C,OAAO,EAAM,WACT,MAAM,QAAQ,EAAM,KAAK,KAAK,EAAM,MAAM,SAAS,CAAK,IACxD,EAAM,UAAU;EACtB;EAcA,SAAS,EAAO,GAAoB;GAClC,IAAI,EAAM,UAAU;IAClB,IAAM,IAAU,MAAM,QAAQ,EAAM,KAAK,IAAI,EAAM,QAAQ,CAAC;IAG5D,IAAI,EAAM,aAAa,EAAQ,SAAS,KAAK,EAAQ,OAAO,MAAM,MAAM,CAAK,GAAG;IAChF,EAAM,QAAQ,EAAY,GAAS,CAAK;IACxC;GACF;GACA,IAAI,EAAM,UAAU,GAAO;IACzB,AAAK,EAAM,cAAW,EAAM,QAAQ;IACpC;GACF;GACA,EAAM,QAAQ;EAChB;EAEA,EAAQ,GAAW;GACjB;GACA;GACA,IAAI,cAAc;IAChB,OAAO,EAAM;GACf;GACA,IAAI,kBAAkB;IACpB,OAAO,EAAM;GACf;GACA,IAAI,OAAO;IACT,OAAO,EAAM;GACf;GACA,IAAI,qBAAqB;IACvB,OAAO,EAAM;GACf;EACF,CAAC;EAmBD,SAAS,EAAU,GAAsB;GACvC,IAAI,CAAE,EAAM,OAAmB,QAAQ,gBAAgB,GAAG;GAC1D,IAAM,IAAQ,EAAM;GACpB,EAAc,GAAO,SAAa,EAAe,GAAO,+BAA+B,GAAG,EACxF,UAAU,EAAM,gBAAgB,WAClC,CAAC;EACH;EAEA,IAAM,IAAW,EAA8C,IAAI,GAC7D,IAAU,QAAe,EAAS,OAAO,MAAM,IAAI;SAKzD,EAAa;GAKX,QAAQ,MAA2B;IACjC,IAAM,IAAQ,EAAQ,OAChB,IAAU;IAIhB,CAFE,GAAO,cAA2B,GAAG,EAAQ,sBAAsB,KACnE,GAAO,cAA2B,CAAO,EAAA,EACrC,MAAM,CAAO;GACrB;GAEA,IAAI;EACN,CAAC,mBA0BC,EAgBe,GAAA;YAfT;GAAJ,KAAI;GACJ,OAAM;GACL,aAAa,EAAA;GACb,UAAU,EAAA;GACV,UAAU,EAAA;GACV,cAAY,EAAA;GACZ,MAAM,EAAA;GACN,SAAS,EAAA,WAAW,KAAA;GACpB,UAAU,EAAA,YAAY,KAAA;GACtB,UAAU,EAAA,YAAY,KAAA;GACtB,OAAO,EAAA;GACP,qBAAmB,EAAA;GACV;;oBAEF,CAAR,EAAQ,EAAA,QAAA,SAAA,CAAA,CAAA"}
@@ -31,6 +31,10 @@ interface ToggleItemProps {
31
31
  type __VLS_Slots = {
32
32
  /** The content of the item, replacing the `label` prop. */
33
33
  default?(): unknown;
34
+ /** Content before the label, which takes the place of `iconStart`. */
35
+ start?(): unknown;
36
+ /** Content after the label, which takes the place of `iconEnd`. */
37
+ end?(): unknown;
34
38
  };
35
39
  declare const __VLS_base: import('vue').DefineComponent<ToggleItemProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<ToggleItemProps> & Readonly<{}>, {
36
40
  label: string;
@@ -1 +1 @@
1
- {"version":3,"file":"VToggleItem.js","names":[],"sources":["../../../src/components/VToggle/VToggleItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * One item of a VToggle. It IS a VButton — the colour, the size, the focus ring and\n * the disabled state all come from there — and what this component adds is the one\n * attribute saying whether the button is currently pressed.\n *\n * That button is also this component's own root element, with nothing wrapped around\n * it, which is what lets the group merge the borders of neighbouring items: it only\n * joins its DIRECT children. It is also what brings the size, the density, the elevation\n * and a row-wide disabled state here with nothing asked for: the VButtonGroup the VToggle\n * renders hands them to every button it contains, this one included.\n *\n * Used outside a VToggle it renders as a plain neutral VButton that is never pressed: the\n * way it is drawn is the group's decision, and there is no group to take it.\n */\nimport { computed, inject } from 'vue'\n\nimport VButton from '../VButton/VButton.vue'\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport type { IconSource } from '../VIcon/types'\nimport { toggleKey } from './context'\nimport type { ToggleValue } from './VToggle.vue'\n\ninterface ToggleItemProps {\n /**\n * What choosing this item means. It is what the group's v-model holds when the item\n * is selected, and it must be unique within the group.\n */\n value: ToggleValue\n /** The visible label. The default slot replaces it. */\n label?: string\n /** An icon before the label: an icon name, or an explicit render. */\n iconStart?: IconSource\n /**\n * An icon after the label. It is NOT switched to its filled form by the group's\n * `selectedIconFilled`, which names the icon standing for the item rather than one\n * trailing it; `iconFilled` fills it for good.\n */\n iconEnd?: IconSource\n /**\n * Renders `iconStart` and `iconEnd` in their filled form (the font's `FILL` axis), whether\n * the item is selected or not. The group's `selectedIconFilled` still fills the start icon\n * of the selected item when this is left out.\n */\n iconFilled?: boolean\n /**\n * Makes this item unusable: it no longer responds, the arrow keys skip over it, and\n * it greys out through the colour tokens.\n */\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<ToggleItemProps>(), {\n label: undefined,\n iconStart: undefined,\n iconEnd: undefined,\n iconFilled: false,\n disabled: false,\n})\n\nconst slots = defineSlots<{\n /** The content of the item, replacing the `label` prop. */\n default?(): unknown\n}>()\n\nconst toggle = inject(toggleKey, null)\n\nconst selected = computed(() => toggle != null && toggle.isSelected(props.value))\n\n// TRAP — a function read by the template, never a `computed`: `slots` is not reactive, so a\n// computed would keep its first answer while a slot behind a `v-if` comes and goes.\n/**\n * An icon, on either side, and no label at all: the item becomes a square, like a VIconButton.\n * The same definition as VChip's, and the square itself is VButton's `[data-icon-only]` rule.\n */\nfunction iconOnly() {\n return !props.label && !slots.default && Boolean(props.iconStart || props.iconEnd)\n}\n</script>\n\n<template>\n <!-- The pressed state is always rendered, false included: it is its PRESENCE that\n makes a screen reader announce the button as one that stays pressed, and an\n attribute appearing only when true would leave the unselected items announced\n as ordinary buttons.\n\n The filled form is asked of the icon directly, because VButton's own icon\n options have no effect on an icon handed to it through a slot. -->\n <VButton\n class=\"v-toggle-item\"\n :aria-pressed=\"selected ? 'true' : 'false'\"\n :variant=\"selected && toggle ? toggle.selectedVariant : toggle?.itemVariant\"\n :tone=\"selected && toggle ? toggle.tone : 'neutral'\"\n :disabled=\"disabled\"\n :data-icon-only=\"iconOnly() ? '' : undefined\"\n @click=\"toggle?.select(value)\"\n >\n <template v-if=\"iconStart\" #start>\n <VIcon\n v-bind=\"iconProps(iconStart)\"\n :filled=\"iconFilled || (selected && toggle?.selectedIconFilled)\"\n />\n </template>\n <template v-if=\"iconEnd\" #end>\n <VIcon v-bind=\"iconProps(iconEnd)\" :filled=\"iconFilled\" />\n </template>\n <slot v-if=\"!iconOnly()\">{{ label }}</slot>\n </VButton>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"VToggleItem.js","names":[],"sources":["../../../src/components/VToggle/VToggleItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * One item of a VToggle. It IS a VButton — the colour, the size, the focus ring and\n * the disabled state all come from there — and what this component adds is the one\n * attribute saying whether the button is currently pressed.\n *\n * That button is also this component's own root element, with nothing wrapped around\n * it, which is what lets the group merge the borders of neighbouring items: it only\n * joins its DIRECT children. It is also what brings the size, the density, the elevation\n * and a row-wide disabled state here with nothing asked for: the VButtonGroup the VToggle\n * renders hands them to every button it contains, this one included.\n *\n * Used outside a VToggle it renders as a plain neutral VButton that is never pressed: the\n * way it is drawn is the group's decision, and there is no group to take it.\n */\nimport { computed, inject } from 'vue'\n\nimport VButton from '../VButton/VButton.vue'\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport type { IconSource } from '../VIcon/types'\nimport { toggleKey } from './context'\nimport type { ToggleValue } from './VToggle.vue'\n\ninterface ToggleItemProps {\n /**\n * What choosing this item means. It is what the group's v-model holds when the item\n * is selected, and it must be unique within the group.\n */\n value: ToggleValue\n /** The visible label. The default slot replaces it. */\n label?: string\n /** An icon before the label: an icon name, or an explicit render. */\n iconStart?: IconSource\n /**\n * An icon after the label. It is NOT switched to its filled form by the group's\n * `selectedIconFilled`, which names the icon standing for the item rather than one\n * trailing it; `iconFilled` fills it for good.\n */\n iconEnd?: IconSource\n /**\n * Renders `iconStart` and `iconEnd` in their filled form (the font's `FILL` axis), whether\n * the item is selected or not. The group's `selectedIconFilled` still fills the start icon\n * of the selected item when this is left out.\n */\n iconFilled?: boolean\n /**\n * Makes this item unusable: it no longer responds, the arrow keys skip over it, and\n * it greys out through the colour tokens.\n */\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<ToggleItemProps>(), {\n label: undefined,\n iconStart: undefined,\n iconEnd: undefined,\n iconFilled: false,\n disabled: false,\n})\n\nconst slots = defineSlots<{\n /** The content of the item, replacing the `label` prop. */\n default?(): unknown\n /** Content before the label, which takes the place of `iconStart`. */\n start?(): unknown\n /** Content after the label, which takes the place of `iconEnd`. */\n end?(): unknown\n}>()\n\nconst toggle = inject(toggleKey, null)\n\nconst selected = computed(() => toggle != null && toggle.isSelected(props.value))\n\n// TRAP — a function read by the template, never a `computed`: `slots` is not reactive, so a\n// computed would keep its first answer while a slot behind a `v-if` comes and goes.\n/**\n * An icon, on either side, and no label at all: the item becomes a square, like a VIconButton.\n * The same definition as VChip's, and the square itself is VButton's `[data-icon-only]` rule.\n */\nfunction iconOnly() {\n return (\n !props.label &&\n !slots.default &&\n Boolean(slots.start || slots.end || props.iconStart || props.iconEnd)\n )\n}\n</script>\n\n<template>\n <!-- The pressed state is always rendered, false included: it is its PRESENCE that\n makes a screen reader announce the button as one that stays pressed, and an\n attribute appearing only when true would leave the unselected items announced\n as ordinary buttons.\n\n The filled form is asked of the icon directly, because VButton's own icon\n options have no effect on an icon handed to it through a slot. -->\n <VButton\n class=\"v-toggle-item\"\n :aria-pressed=\"selected ? 'true' : 'false'\"\n :variant=\"selected && toggle ? toggle.selectedVariant : toggle?.itemVariant\"\n :tone=\"selected && toggle ? toggle.tone : 'neutral'\"\n :disabled=\"disabled\"\n :data-icon-only=\"iconOnly() ? '' : undefined\"\n @click=\"toggle?.select(value)\"\n >\n <template v-if=\"iconStart || $slots.start\" #start>\n <slot name=\"start\">\n <VIcon\n v-bind=\"iconProps(iconStart!)\"\n :filled=\"iconFilled || (selected && toggle?.selectedIconFilled)\"\n />\n </slot>\n </template>\n <template v-if=\"iconEnd || $slots.end\" #end>\n <slot name=\"end\"><VIcon v-bind=\"iconProps(iconEnd!)\" :filled=\"iconFilled\" /></slot>\n </template>\n <slot v-if=\"!iconOnly()\">{{ label }}</slot>\n </VButton>\n</template>\n"],"mappings":""}
@@ -23,7 +23,7 @@ var y = /*@__PURE__*/ u({
23
23
  setup(u) {
24
24
  let y = u, b = _(), x = d(r, null), S = i(() => x != null && x.isSelected(y.value));
25
25
  function C() {
26
- return !y.label && !b.default && !!(y.iconStart || y.iconEnd);
26
+ return !y.label && !b.default && !!(b.start || b.end || y.iconStart || y.iconEnd);
27
27
  }
28
28
  return (r, i) => (p(), a(n, {
29
29
  class: "v-toggle-item",
@@ -36,13 +36,13 @@ var y = /*@__PURE__*/ u({
36
36
  }, s({
37
37
  default: v(() => [C() ? o("", !0) : m(r.$slots, "default", {}, () => [c(h(u.label), 1)], void 0, 0)]),
38
38
  _: 2
39
- }, [u.iconStart ? {
39
+ }, [u.iconStart || r.$slots.start ? {
40
40
  name: "start",
41
- fn: v(() => [l(t, f(g(e)(u.iconStart), { filled: u.iconFilled || S.value && g(x)?.selectedIconFilled }), null, 16, ["filled"])]),
41
+ fn: v(() => [m(r.$slots, "start", {}, () => [l(t, f(g(e)(u.iconStart), { filled: u.iconFilled || S.value && g(x)?.selectedIconFilled }), null, 16, ["filled"])])]),
42
42
  key: "0"
43
- } : void 0, u.iconEnd ? {
43
+ } : void 0, u.iconEnd || r.$slots.end ? {
44
44
  name: "end",
45
- fn: v(() => [l(t, f(g(e)(u.iconEnd), { filled: u.iconFilled }), null, 16, ["filled"])]),
45
+ fn: v(() => [m(r.$slots, "end", {}, () => [l(t, f(g(e)(u.iconEnd), { filled: u.iconFilled }), null, 16, ["filled"])])]),
46
46
  key: "1"
47
47
  } : void 0]), 1032, [
48
48
  "aria-pressed",
@@ -1 +1 @@
1
- {"version":3,"file":"VToggleItem.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VToggle/VToggleItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * One item of a VToggle. It IS a VButton — the colour, the size, the focus ring and\n * the disabled state all come from there — and what this component adds is the one\n * attribute saying whether the button is currently pressed.\n *\n * That button is also this component's own root element, with nothing wrapped around\n * it, which is what lets the group merge the borders of neighbouring items: it only\n * joins its DIRECT children. It is also what brings the size, the density, the elevation\n * and a row-wide disabled state here with nothing asked for: the VButtonGroup the VToggle\n * renders hands them to every button it contains, this one included.\n *\n * Used outside a VToggle it renders as a plain neutral VButton that is never pressed: the\n * way it is drawn is the group's decision, and there is no group to take it.\n */\nimport { computed, inject } from 'vue'\n\nimport VButton from '../VButton/VButton.vue'\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport type { IconSource } from '../VIcon/types'\nimport { toggleKey } from './context'\nimport type { ToggleValue } from './VToggle.vue'\n\ninterface ToggleItemProps {\n /**\n * What choosing this item means. It is what the group's v-model holds when the item\n * is selected, and it must be unique within the group.\n */\n value: ToggleValue\n /** The visible label. The default slot replaces it. */\n label?: string\n /** An icon before the label: an icon name, or an explicit render. */\n iconStart?: IconSource\n /**\n * An icon after the label. It is NOT switched to its filled form by the group's\n * `selectedIconFilled`, which names the icon standing for the item rather than one\n * trailing it; `iconFilled` fills it for good.\n */\n iconEnd?: IconSource\n /**\n * Renders `iconStart` and `iconEnd` in their filled form (the font's `FILL` axis), whether\n * the item is selected or not. The group's `selectedIconFilled` still fills the start icon\n * of the selected item when this is left out.\n */\n iconFilled?: boolean\n /**\n * Makes this item unusable: it no longer responds, the arrow keys skip over it, and\n * it greys out through the colour tokens.\n */\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<ToggleItemProps>(), {\n label: undefined,\n iconStart: undefined,\n iconEnd: undefined,\n iconFilled: false,\n disabled: false,\n})\n\nconst slots = defineSlots<{\n /** The content of the item, replacing the `label` prop. */\n default?(): unknown\n}>()\n\nconst toggle = inject(toggleKey, null)\n\nconst selected = computed(() => toggle != null && toggle.isSelected(props.value))\n\n// TRAP — a function read by the template, never a `computed`: `slots` is not reactive, so a\n// computed would keep its first answer while a slot behind a `v-if` comes and goes.\n/**\n * An icon, on either side, and no label at all: the item becomes a square, like a VIconButton.\n * The same definition as VChip's, and the square itself is VButton's `[data-icon-only]` rule.\n */\nfunction iconOnly() {\n return !props.label && !slots.default && Boolean(props.iconStart || props.iconEnd)\n}\n</script>\n\n<template>\n <!-- The pressed state is always rendered, false included: it is its PRESENCE that\n makes a screen reader announce the button as one that stays pressed, and an\n attribute appearing only when true would leave the unselected items announced\n as ordinary buttons.\n\n The filled form is asked of the icon directly, because VButton's own icon\n options have no effect on an icon handed to it through a slot. -->\n <VButton\n class=\"v-toggle-item\"\n :aria-pressed=\"selected ? 'true' : 'false'\"\n :variant=\"selected && toggle ? toggle.selectedVariant : toggle?.itemVariant\"\n :tone=\"selected && toggle ? toggle.tone : 'neutral'\"\n :disabled=\"disabled\"\n :data-icon-only=\"iconOnly() ? '' : undefined\"\n @click=\"toggle?.select(value)\"\n >\n <template v-if=\"iconStart\" #start>\n <VIcon\n v-bind=\"iconProps(iconStart)\"\n :filled=\"iconFilled || (selected && toggle?.selectedIconFilled)\"\n />\n </template>\n <template v-if=\"iconEnd\" #end>\n <VIcon v-bind=\"iconProps(iconEnd)\" :filled=\"iconFilled\" />\n </template>\n <slot v-if=\"!iconOnly()\">{{ label }}</slot>\n </VButton>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAqDA,IAAM,IAAQ,GAQR,IAAQ,EAAA,GAKR,IAAS,EAAO,GAAW,IAAI,GAE/B,IAAW,QAAe,KAAU,QAAQ,EAAO,WAAW,EAAM,KAAK,CAAC;EAQhF,SAAS,IAAW;GAClB,OAAO,CAAC,EAAM,SAAS,CAAC,EAAM,WAAW,GAAQ,EAAM,aAAa,EAAM;EAC5E;yBAWE,EAmBU,GAAA;GAlBR,OAAM;GACL,gBAAc,EAAA,QAAQ,SAAA;GACtB,SAAS,EAAA,SAAY,EAAA,CAAA,IAAS,EAAA,CAAA,CAAM,CAAC,kBAAkB,EAAA,CAAA,CAAM,EAAE;GAC/D,MAAM,EAAA,SAAY,EAAA,CAAA,IAAS,EAAA,CAAA,CAAM,CAAC,OAAI;GACtC,UAAU,EAAA;GACV,kBAAgB,EAAQ,IAAA,KAAU,KAAA;GAClC,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAM,EAAE,OAAO,EAAA,KAAK;;oBAStB,CAEO,EAAQ,IAAY,EAAA,IAAA,EAAA,IAAjC,EAA2C,EAAA,QAAA,WAAA,CAAA,SAAA,CAAA,EAAA,EAAf,EAAA,KAAK,GAAA,CAAA,CAAA,GAAA,KAAA,GAAA,CAAA,CAAA,CAAA;;MATjB,EAAA,YAAA;SAAY;eAIxB,CAHF,EAGE,GAHF,EACU,EAER,CAAA,CAFiB,CAAC,EAAA,SAAS,GAAA,EAC1B,QAAQ,EAAA,cAAe,EAAA,SAAY,EAAA,CAAA,CAAM,EAAE,mBAAA,CAAA,GAAA,MAAA,IAAA,CAAA,QAAA,CAAA,CAAA,CAAA;;cAGhC,EAAA,UAAA;SAAU;eACkC,CAA1D,EAA0D,GAA1D,EAAe,EAA2C,CAAA,CAAlC,CAAC,EAAA,OAAO,GAAA,EAAI,QAAQ,EAAA,WAAU,CAAA,GAAA,MAAA,IAAA,CAAA,QAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"VToggleItem.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VToggle/VToggleItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * One item of a VToggle. It IS a VButton — the colour, the size, the focus ring and\n * the disabled state all come from there — and what this component adds is the one\n * attribute saying whether the button is currently pressed.\n *\n * That button is also this component's own root element, with nothing wrapped around\n * it, which is what lets the group merge the borders of neighbouring items: it only\n * joins its DIRECT children. It is also what brings the size, the density, the elevation\n * and a row-wide disabled state here with nothing asked for: the VButtonGroup the VToggle\n * renders hands them to every button it contains, this one included.\n *\n * Used outside a VToggle it renders as a plain neutral VButton that is never pressed: the\n * way it is drawn is the group's decision, and there is no group to take it.\n */\nimport { computed, inject } from 'vue'\n\nimport VButton from '../VButton/VButton.vue'\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport type { IconSource } from '../VIcon/types'\nimport { toggleKey } from './context'\nimport type { ToggleValue } from './VToggle.vue'\n\ninterface ToggleItemProps {\n /**\n * What choosing this item means. It is what the group's v-model holds when the item\n * is selected, and it must be unique within the group.\n */\n value: ToggleValue\n /** The visible label. The default slot replaces it. */\n label?: string\n /** An icon before the label: an icon name, or an explicit render. */\n iconStart?: IconSource\n /**\n * An icon after the label. It is NOT switched to its filled form by the group's\n * `selectedIconFilled`, which names the icon standing for the item rather than one\n * trailing it; `iconFilled` fills it for good.\n */\n iconEnd?: IconSource\n /**\n * Renders `iconStart` and `iconEnd` in their filled form (the font's `FILL` axis), whether\n * the item is selected or not. The group's `selectedIconFilled` still fills the start icon\n * of the selected item when this is left out.\n */\n iconFilled?: boolean\n /**\n * Makes this item unusable: it no longer responds, the arrow keys skip over it, and\n * it greys out through the colour tokens.\n */\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<ToggleItemProps>(), {\n label: undefined,\n iconStart: undefined,\n iconEnd: undefined,\n iconFilled: false,\n disabled: false,\n})\n\nconst slots = defineSlots<{\n /** The content of the item, replacing the `label` prop. */\n default?(): unknown\n /** Content before the label, which takes the place of `iconStart`. */\n start?(): unknown\n /** Content after the label, which takes the place of `iconEnd`. */\n end?(): unknown\n}>()\n\nconst toggle = inject(toggleKey, null)\n\nconst selected = computed(() => toggle != null && toggle.isSelected(props.value))\n\n// TRAP — a function read by the template, never a `computed`: `slots` is not reactive, so a\n// computed would keep its first answer while a slot behind a `v-if` comes and goes.\n/**\n * An icon, on either side, and no label at all: the item becomes a square, like a VIconButton.\n * The same definition as VChip's, and the square itself is VButton's `[data-icon-only]` rule.\n */\nfunction iconOnly() {\n return (\n !props.label &&\n !slots.default &&\n Boolean(slots.start || slots.end || props.iconStart || props.iconEnd)\n )\n}\n</script>\n\n<template>\n <!-- The pressed state is always rendered, false included: it is its PRESENCE that\n makes a screen reader announce the button as one that stays pressed, and an\n attribute appearing only when true would leave the unselected items announced\n as ordinary buttons.\n\n The filled form is asked of the icon directly, because VButton's own icon\n options have no effect on an icon handed to it through a slot. -->\n <VButton\n class=\"v-toggle-item\"\n :aria-pressed=\"selected ? 'true' : 'false'\"\n :variant=\"selected && toggle ? toggle.selectedVariant : toggle?.itemVariant\"\n :tone=\"selected && toggle ? toggle.tone : 'neutral'\"\n :disabled=\"disabled\"\n :data-icon-only=\"iconOnly() ? '' : undefined\"\n @click=\"toggle?.select(value)\"\n >\n <template v-if=\"iconStart || $slots.start\" #start>\n <slot name=\"start\">\n <VIcon\n v-bind=\"iconProps(iconStart!)\"\n :filled=\"iconFilled || (selected && toggle?.selectedIconFilled)\"\n />\n </slot>\n </template>\n <template v-if=\"iconEnd || $slots.end\" #end>\n <slot name=\"end\"><VIcon v-bind=\"iconProps(iconEnd!)\" :filled=\"iconFilled\" /></slot>\n </template>\n <slot v-if=\"!iconOnly()\">{{ label }}</slot>\n </VButton>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAqDA,IAAM,IAAQ,GAQR,IAAQ,EAAA,GASR,IAAS,EAAO,GAAW,IAAI,GAE/B,IAAW,QAAe,KAAU,QAAQ,EAAO,WAAW,EAAM,KAAK,CAAC;EAQhF,SAAS,IAAW;GAClB,OACE,CAAC,EAAM,SACP,CAAC,EAAM,WACP,GAAQ,EAAM,SAAS,EAAM,OAAO,EAAM,aAAa,EAAM;EAEjE;yBAWE,EAqBU,GAAA;GApBR,OAAM;GACL,gBAAc,EAAA,QAAQ,SAAA;GACtB,SAAS,EAAA,SAAY,EAAA,CAAA,IAAS,EAAA,CAAA,CAAM,CAAC,kBAAkB,EAAA,CAAA,CAAM,EAAE;GAC/D,MAAM,EAAA,SAAY,EAAA,CAAA,IAAS,EAAA,CAAA,CAAM,CAAC,OAAI;GACtC,UAAU,EAAA;GACV,kBAAgB,EAAQ,IAAA,KAAU,KAAA;GAClC,SAAK,AAAA,EAAA,QAAA,MAAE,EAAA,CAAA,CAAM,EAAE,OAAO,EAAA,KAAK;;oBASb,CAIF,EAAQ,IAAY,EAAA,IAAA,EAAA,IAAjC,EAA2C,EAAA,QAAA,WAAA,CAAA,SAAA,CAAA,EAAA,EAAf,EAAA,KAAK,GAAA,CAAA,CAAA,GAAA,KAAA,GAAA,CAAA,CAAA,CAAA;;MAXjB,EAAA,aAAaA,EAAAA,OAAO,QAAA;SAAQ;eAMnC,CALP,EAKO,EAAA,QAAA,SAAA,CAAA,SAAA,CAJL,EAGE,GAHF,EACU,EAER,CAAA,CAFiB,CAAC,EAAA,SAAS,GAAA,EAC1B,QAAQ,EAAA,cAAe,EAAA,SAAY,EAAA,CAAA,CAAM,EAAE,mBAAA,CAAA,GAAA,MAAA,IAAA,CAAA,QAAA,CAAA,CAAA,CAAA,CAAA,CAAA;;cAIlC,EAAA,WAAWA,EAAAA,OAAO,MAAA;SAAM;eAC6C,CAAnF,EAAmF,EAAA,QAAA,OAAA,CAAA,SAAA,CAAlE,EAA2D,GAA3D,EAAe,EAA4C,CAAA,CAAnC,CAAC,EAAA,OAAO,GAAA,EAAK,QAAQ,EAAA,WAAU,CAAA,GAAA,MAAA,IAAA,CAAA,QAAA,CAAA,CAAA,CAAA,CAAA,CAAA"}
@@ -1,2 +1,2 @@
1
1
  @layer vectis.reset, vectis.tokens, vectis.components, vectis.utilities;
2
- @layer vectis.components{.v-tooltip{anchor-name:--tooltip-anchor;anchor-scope:--tooltip-anchor;align-items:center;display:inline-flex}.v-popover-panel.v-tooltip-panel{width:max-content;max-width:min(18rem, calc(100vw - var(--vectis-space-8)));padding:var(--vectis-space-1) var(--vectis-space-2);background:var(--vectis-color-surface-inverse);color:var(--vectis-color-text-on-inverse);border-radius:min(var(--vectis-radius-interactive), calc(.5lh + var(--vectis-space-1)));box-shadow:var(--vectis-shadow-sm);font-family:var(--vectis-text-family);font-size:var(--vectis-text-caption-size);line-height:var(--vectis-text-caption-leading);border:none}}
2
+ @layer vectis.components{.v-tooltip{anchor-name:--tooltip-anchor;anchor-scope:--tooltip-anchor;align-items:center;display:inline-flex}.v-popover-panel.v-tooltip-panel{inline-size:max-content;max-inline-size:min(var(--vectis-control-size-tooltip-max), calc(100dvi - var(--vectis-space-8)));padding:var(--vectis-space-1) var(--vectis-space-2);background:var(--vectis-color-surface-inverse);color:var(--vectis-color-text-on-inverse);border-radius:min(var(--vectis-radius-interactive), calc(.5lh + var(--vectis-space-1)));box-shadow:var(--vectis-shadow-sm);font-family:var(--vectis-text-family);font-size:var(--vectis-text-caption-size);line-height:var(--vectis-text-caption-leading);border:none}@media (forced-colors:active){.v-popover-panel.v-tooltip-panel{outline:1px solid canvastext}}}
@@ -1,5 +1,5 @@
1
1
  /** Which side of the element the tooltip appears on. */
2
- export type TooltipPlacement = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'right';
2
+ export type TooltipPlacement = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end';
3
3
  /** What the described element has to carry: the link to the tooltip that describes it. */
4
4
  export type TooltipTriggerProps = {
5
5
  'aria-describedby': string;
@@ -14,30 +14,37 @@ interface TooltipProps {
14
14
  placement?: TooltipPlacement;
15
15
  /**
16
16
  * How long the pointer must rest on the element before the tooltip appears, in
17
- * milliseconds. Keyboard focus opens it at once — the intent is not in doubt there
18
- * — and a delay of 0 disables the wait entirely.
17
+ * milliseconds. Keyboard focus opens it at once, the intent being in no doubt there,
18
+ * and a delay of 0 disables the wait entirely.
19
19
  */
20
20
  delay?: number;
21
21
  }
22
22
  type __VLS_Slots = {
23
23
  /**
24
- * The element the tooltip describes. Bind the `triggerProps` it receives onto it —
25
- * that is what ties the two together for assistive technology — and make sure it is
26
- * something that can take focus, or keyboard users will never see the tooltip.
24
+ * The element the tooltip describes. Bind the `triggerProps` it receives onto it, which
25
+ * is what ties the two together for assistive technology, and make sure it is something
26
+ * that can take focus, or keyboard users will never see the tooltip.
27
27
  */
28
28
  default(props: {
29
29
  triggerProps: TooltipTriggerProps;
30
30
  }): unknown;
31
31
  /**
32
32
  * Content richer than a plain string: formatting, a keyboard shortcut, an icon. It
33
- * must stay NON-interactive. The tooltip closes as soon as the pointer leaves the
34
- * element, so a link or a button inside could never be reached, and the description
35
- * is flattened to plain text for screen readers anyway. Content one can interact
33
+ * must stay NON-interactive: the description is flattened to plain text for screen
34
+ * readers, and nothing inside can be reached from the keyboard. Content one can interact
36
35
  * with belongs in a panel that stays open, such as VMenu.
37
36
  */
38
37
  content?(): unknown;
39
38
  };
40
- declare const __VLS_base: import('vue').DefineComponent<TooltipProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<TooltipProps> & Readonly<{}>, {
39
+ declare function hide(): void;
40
+ declare const __VLS_base: import('vue').DefineComponent<TooltipProps, {
41
+ /** Shows the tooltip at once, without the hover delay. */
42
+ show: () => void;
43
+ /** Hides the tooltip. */
44
+ close: typeof hide;
45
+ /** The tooltip bubble. */
46
+ el: import('vue').ComputedRef<HTMLElement | null>;
47
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<TooltipProps> & Readonly<{}>, {
41
48
  text: string;
42
49
  placement: TooltipPlacement;
43
50
  delay: number;
@@ -1 +1 @@
1
- {"version":3,"file":"VTooltip.js","names":[],"sources":["../../../src/components/VTooltip/VTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * A short explanation appearing beside an element on hover or keyboard focus. A VPopover in\n * `mode=\"manual\"`, a tooltip having its own rules about when to appear and when to go.\n *\n * Those rules are why there is JS here at all: HTML has no stable way to say \"show this\n * after a delay on hover or focus\", so the component handles the delay, the pointer, the\n * focus, a press on the trigger, and Escape — which must dismiss without moving the focus\n * (WCAG 1.4.13).\n *\n * Four ways out, each covering what the others do not: the pointer leaves, the focus leaves,\n * Escape, or the trigger is PRESSED — that last for a trigger opening a panel, where the\n * tooltip would otherwise stand over what it just opened.\n *\n * Positioning is pure CSS with no generated id: the wrapper names itself as the anchor and\n * confines that name to its own subtree. The confinement is essential — a shown panel moves\n * to the top layer, which anchor resolution treats as coming after the whole document, so\n * without it every tooltip would attach to the last wrapper named on the page.\n *\n * The wrapper stays HERE rather than going through VPopover's `#trigger`: a tooltip trigger\n * is not a `popovertarget` invoker, which would toggle on click, but an element the panel\n * DESCRIBES.\n */\n\nimport { ref, useId } from 'vue'\n\nimport VPopover from '../VPopover/VPopover.vue'\n\nimport { useTimer } from '../../composables/useTimer'\nimport { isKeyboardFocus } from '../../utils/focus'\n\n/** Which side of the element the tooltip appears on. */\nexport type TooltipPlacement =\n 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'right'\n\n/** What the described element has to carry: the link to the tooltip that describes it. */\nexport type TooltipTriggerProps = {\n 'aria-describedby': string\n}\n\ninterface TooltipProps {\n /** What the tooltip says. The `#content` slot replaces it when both are given. */\n text?: string\n /**\n * Which side of the element the tooltip appears on. The browser flips it to the\n * opposite side by itself when there is not enough room.\n */\n placement?: TooltipPlacement\n /**\n * How long the pointer must rest on the element before the tooltip appears, in\n * milliseconds. Keyboard focus opens it at once — the intent is not in doubt there\n * — and a delay of 0 disables the wait entirely.\n */\n delay?: number\n}\n\nconst props = withDefaults(defineProps<TooltipProps>(), {\n text: undefined,\n placement: 'top',\n delay: 300,\n})\n\ndefineSlots<{\n /**\n * The element the tooltip describes. Bind the `triggerProps` it receives onto it —\n * that is what ties the two together for assistive technology — and make sure it is\n * something that can take focus, or keyboard users will never see the tooltip.\n */\n default(props: { triggerProps: TooltipTriggerProps }): unknown\n /**\n * Content richer than a plain string: formatting, a keyboard shortcut, an icon. It\n * must stay NON-interactive. The tooltip closes as soon as the pointer leaves the\n * element, so a link or a button inside could never be reached, and the description\n * is flattened to plain text for screen readers anyway. Content one can interact\n * with belongs in a panel that stays open, such as VMenu.\n */\n content?(): unknown\n}>()\n\nconst tooltipId = useId()\n// @a11y\n/*\n * The panel is opened and closed by calling it directly rather than through\n * `v-model:open`. Keyboard focus has to open it SYNCHRONOUSLY, and a model would go\n * through VPopover's watcher, hence through a tick. There is nothing lost either way:\n * a tooltip publishes no open state anyone needs to read.\n *\n * Calling twice is harmless — the guards for that live upstream in usePopover.\n */\nconst popoverRef = ref<InstanceType<typeof VPopover> | null>(null)\n\n// The delay before appearing. useTimer is what makes it re-armable and cancels it\n// when the component goes away.\nconst timer = useTimer()\n\n// @core\nfunction show(immediate = false) {\n // A delay of 0 runs the callback synchronously — the design system's convention,\n // and what lets keyboard focus share this code path without waiting a tick.\n timer.start(() => popoverRef.value?.show(), immediate ? 0 : props.delay)\n}\n\nfunction hide() {\n timer.cancel()\n popoverRef.value?.close()\n}\n\n// @a11y\n/*\n * The tooltip belongs to the KEYBOARD focus, and a `focusin` says the focus arrived, never\n * how it got there. Three ways in are not a Tab: a click, which the pointer already covers\n * and which the `pointerdown` above has just closed the tooltip for; a tap, which no browser\n * agrees on; and a `focus()` from code — the one a closing panel hands back to the button\n * that opened it, which would raise a tooltip over a page the reader is no longer pointing\n * at. `:focus-visible` is the browser's own answer to the question, the same one VMenu asks\n * to decide where a menu's focus lands.\n *\n * The consequence to know: a tooltip never opens on a tap. Content a touch reader needs\n * cannot live here alone.\n */\nfunction onFocusIn(event: FocusEvent) {\n if (isKeyboardFocus(event.target)) show(true)\n}\n\n// @keyboard @a11y — Escape must dismiss a tooltip opened by hover or focus without\n// moving the focus anywhere (WCAG 1.4.13): content appearing on hover has to be\n// dismissible, for a magnifier user whose view it may be covering.\nfunction onKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape') hide()\n}\n</script>\n\n<template>\n <!--\n TRAP — `pointerdown` is what stops a tooltip from surviving the click that acted on its\n trigger, and the case it really covers is a trigger that OPENS something: a menu, a\n dialog, a popover of any kind. The tooltip would then stand over what it opened, and\n none of the other three exits applies — the pointer has not left, the focus has not\n moved out on its own, and nobody pressed Escape.\n\n It looks redundant on Chromium and Firefox, where a click focuses the button and the\n panel then takes the focus, which fires this wrapper's `focusout`. Safari on macOS does\n NOT focus a button on click, so nothing leaves the wrapper and the tooltip stays up,\n behind the panel, until the pointer moves. Delete this line and that is the bug that\n comes back, on one browser only.\n\n It is `pointerdown` and not `click`, so the tooltip is gone BEFORE the panel appears\n rather than overlapping it for a frame. Keyboard activation sends no `pointerdown` at\n all, and needs none: focus moving into the panel closes the tooltip everywhere.\n -->\n <span\n class=\"v-tooltip\"\n @pointerenter=\"show()\"\n @pointerleave=\"hide\"\n @pointerdown=\"hide\"\n @focusin=\"onFocusIn\"\n @focusout=\"hide\"\n @keydown=\"onKeydown\"\n >\n <slot :trigger-props=\"{ 'aria-describedby': tooltipId }\" />\n <VPopover\n :id=\"tooltipId\"\n ref=\"popoverRef\"\n mode=\"manual\"\n anchor=\"--tooltip-anchor\"\n :placement=\"placement\"\n bare\n role=\"tooltip\"\n class=\"v-tooltip-panel\"\n >\n <slot name=\"content\">{{ text }}</slot>\n </VPopover>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The wrapper is FLEX and not inline-block, for the same reason as `.v-badge-host`:\n both are inline-level atomic boxes, so the surrounding text flows identically, but\n an inline-block establishes an inline formatting context for the trigger — which\n then sits on a line box and adds the strut's descender to the wrapper's height.\n That is not only a couple of pixels in a flex row: this wrapper is also the ANCHOR,\n so the panel is offset by them too.\n\n `align-items: center` covers what is left. A wrapper stretched by a parent in\n `align-items: stretch` would otherwise stretch the trigger with it, where the\n inline-block form left it at its natural height. */\n .v-tooltip {\n display: inline-flex;\n align-items: center;\n anchor-name: --tooltip-anchor;\n /* Confining the name to this subtree is indispensable: a visible panel moves to\n the top layer, where anchor resolution treats it as coming after the whole\n document, so without it every tooltip would attach to the LAST wrapper carrying\n this name. */\n anchor-scope: --tooltip-anchor;\n }\n\n /* The anchoring itself comes from VPopover, through the `anchor` prop.\n\n The selector is written as a compound of two classes that both land on this same\n element, even though the panel class it guards against — `.v-panel` — is never\n present here, VTooltip asking for a `bare` panel. It is written that way so it cannot\n break the day that prop changes: at equal specificity the winner between two\n component sheets is decided by the order the consumer's bundler happens to\n produce, which is nobody's decision. */\n .v-popover-panel.v-tooltip-panel {\n width: max-content;\n max-width: min(18rem, calc(100vw - var(--vectis-space-8)));\n padding: var(--vectis-space-1) var(--vectis-space-2);\n /* The tooltip is painted against the page rather than with it: a dark surface in\n both themes, darker still in the dark one, so it reads as an overlay whatever\n it happens to cover. */\n background: var(--vectis-color-surface-inverse);\n color: var(--vectis-color-text-on-inverse);\n border: none;\n /* The control radius capped at half the height of a ONE-line bubble, the row recipe\n of VSideNavigationItem: a tooltip wraps past its max-width, and under a pill\n override a two-line bubble would otherwise round to half of its own height. */\n border-radius: min(var(--vectis-radius-interactive), calc(0.5lh + var(--vectis-space-1)));\n box-shadow: var(--vectis-shadow-sm);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n line-height: var(--vectis-text-caption-leading);\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"VTooltip.js","names":[],"sources":["../../../src/components/VTooltip/VTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * A short explanation appearing beside an element on hover or keyboard focus. A VPopover in\n * `mode=\"manual\"`, a tooltip having its own rules about when to appear and when to go.\n *\n * Those rules are why there is JS here at all: HTML has no stable way to say \"show this\n * after a delay on hover or focus\", so the component handles the delay, the pointer, the\n * focus, a press on the trigger, and Escape — which must dismiss without moving the focus\n * (WCAG 1.4.13).\n *\n * It stays as long as EITHER the pointer rests on it (the trigger or the bubble) or the\n * keyboard focus is on the trigger, and goes when both have left, after a short grace the\n * pointer needs to cross the gap onto the bubble (WCAG 1.4.13: hoverable, persistent).\n * Two more ways out: Escape, heard from anywhere on the page while it shows and spent on\n * it, and the trigger being PRESSED, for a trigger opening a panel, where the tooltip would\n * otherwise stand over what it just opened.\n *\n * Positioning is pure CSS with no generated id: the wrapper names itself as the anchor and\n * confines that name to its own subtree. The confinement is essential — a shown panel moves\n * to the top layer, which anchor resolution treats as coming after the whole document, so\n * without it every tooltip would attach to the last wrapper named on the page.\n *\n * The wrapper stays HERE rather than going through VPopover's `#trigger`: a tooltip trigger\n * is not a `popovertarget` invoker, which would toggle on click, but an element the panel\n * DESCRIBES.\n */\n\nimport { computed, onBeforeUnmount, ref, useId } from 'vue'\n\nimport VPopover from '../VPopover/VPopover.vue'\n\nimport { useTimer } from '../../composables/useTimer'\nimport { isKeyboardFocus } from '../../utils/focus'\n\n/** Which side of the element the tooltip appears on. */\nexport type TooltipPlacement =\n | 'top'\n | 'top-start'\n | 'top-end'\n | 'bottom'\n | 'bottom-start'\n | 'bottom-end'\n | 'left'\n | 'left-start'\n | 'left-end'\n | 'right'\n | 'right-start'\n | 'right-end'\n\n/** What the described element has to carry: the link to the tooltip that describes it. */\nexport type TooltipTriggerProps = {\n 'aria-describedby': string\n}\n\ninterface TooltipProps {\n /** What the tooltip says. The `#content` slot replaces it when both are given. */\n text?: string\n /**\n * Which side of the element the tooltip appears on. The browser flips it to the\n * opposite side by itself when there is not enough room.\n */\n placement?: TooltipPlacement\n /**\n * How long the pointer must rest on the element before the tooltip appears, in\n * milliseconds. Keyboard focus opens it at once, the intent being in no doubt there,\n * and a delay of 0 disables the wait entirely.\n */\n delay?: number\n}\n\nconst props = withDefaults(defineProps<TooltipProps>(), {\n text: undefined,\n placement: 'top',\n delay: 300,\n})\n\ndefineSlots<{\n /**\n * The element the tooltip describes. Bind the `triggerProps` it receives onto it, which\n * is what ties the two together for assistive technology, and make sure it is something\n * that can take focus, or keyboard users will never see the tooltip.\n */\n default(props: { triggerProps: TooltipTriggerProps }): unknown\n /**\n * Content richer than a plain string: formatting, a keyboard shortcut, an icon. It\n * must stay NON-interactive: the description is flattened to plain text for screen\n * readers, and nothing inside can be reached from the keyboard. Content one can interact\n * with belongs in a panel that stays open, such as VMenu.\n */\n content?(): unknown\n}>()\n\nconst tooltipId = useId()\n// @a11y\n/*\n * The panel is opened and closed by calling it directly rather than through\n * `v-model:open`. Keyboard focus has to open it SYNCHRONOUSLY, and a model would go\n * through VPopover's watcher, hence through a tick. There is nothing lost either way:\n * a tooltip publishes no open state anyone needs to read.\n *\n * Calling twice is harmless — the guards for that live upstream in usePopover.\n */\nconst popoverRef = ref<InstanceType<typeof VPopover> | null>(null)\n\n// The delay before appearing. useTimer is what makes it re-armable and cancels it\n// when the component goes away.\nconst timer = useTimer()\n\n/**\n * How long a tooltip the pointer has left waits before going: the time to cross the gap\n * between the trigger and the bubble, which the margin leaves empty and which no pointer\n * event covers. The bubble is a DOM descendant of the wrapper, so reaching it counts as\n * coming back and cancels the close.\n */\nconst LEAVE_GRACE = 100\n\n// The two reasons it is showing. It goes only once neither holds.\nlet hovered = false\nlet focused = false\n\n// @core\nfunction show(immediate = false) {\n // A delay of 0 runs the callback synchronously — the design system's convention,\n // and what lets keyboard focus share this code path without waiting a tick.\n timer.start(() => popoverRef.value?.show(), immediate ? 0 : props.delay)\n}\n\nfunction hide() {\n timer.cancel()\n popoverRef.value?.close()\n}\n\nfunction onPointerEnter() {\n hovered = true\n show()\n}\n\nfunction onPointerLeave() {\n hovered = false\n if (focused) return\n timer.start(() => popoverRef.value?.close(), LEAVE_GRACE)\n}\n\nfunction onPointerDown() {\n hovered = false\n focused = false\n hide()\n}\n\nfunction onFocusOut() {\n focused = false\n if (!hovered) hide()\n}\n\n// @a11y\n/*\n * The tooltip belongs to the KEYBOARD focus, and a `focusin` says the focus arrived, never\n * how it got there. Three ways in are not a Tab: a click, which the pointer already covers\n * and which the `pointerdown` above has just closed the tooltip for; a tap, which no browser\n * agrees on; and a `focus()` from code — the one a closing panel hands back to the button\n * that opened it, which would raise a tooltip over a page the reader is no longer pointing\n * at. `:focus-visible` is the browser's own answer to the question, the same one VMenu asks\n * to decide where a menu's focus lands.\n *\n * The consequence to know: a tooltip never opens on a tap. Content a touch reader needs\n * cannot live here alone.\n */\nfunction onFocusIn(event: FocusEvent) {\n if (!isKeyboardFocus(event.target)) return\n focused = true\n show(true)\n}\n\n// @keyboard @a11y\n// Escape must dismiss a tooltip opened by hover or focus without moving the focus anywhere\n// (WCAG 1.4.13), for a magnifier user whose view it may be covering. It is heard on the\n// DOCUMENT while the tooltip shows, since a hovered tooltip rarely holds the focus, and it\n// is SPENT on it: inside a VDialog the same key would otherwise also be the dialog's close\n// request.\nfunction onDocumentKeydown(event: KeyboardEvent) {\n if (event.key !== 'Escape' || event.defaultPrevented) return\n event.preventDefault()\n hovered = false\n focused = false\n hide()\n}\n\nconst listening = ref(false)\nfunction onOpenChange(open: boolean) {\n if (open === listening.value) return\n listening.value = open\n if (open) document.addEventListener('keydown', onDocumentKeydown)\n else document.removeEventListener('keydown', onDocumentKeydown)\n}\nonBeforeUnmount(() => onOpenChange(false))\n\ndefineExpose({\n /** Shows the tooltip at once, without the hover delay. */\n show: () => show(true),\n /** Hides the tooltip. */\n close: hide,\n /** The tooltip bubble. */\n el: computed(() => popoverRef.value?.el ?? null),\n})\n</script>\n\n<template>\n <!--\n TRAP — `pointerdown` is what stops a tooltip from surviving the click that acted on its\n trigger, and the case it really covers is a trigger that OPENS something: a menu, a\n dialog, a popover of any kind. The tooltip would then stand over what it opened, and\n none of the other three exits applies — the pointer has not left, the focus has not\n moved out on its own, and nobody pressed Escape.\n\n It looks redundant on Chromium and Firefox, where a click focuses the button and the\n panel then takes the focus, which fires this wrapper's `focusout`. Safari on macOS does\n NOT focus a button on click, so nothing leaves the wrapper and the tooltip stays up,\n behind the panel, until the pointer moves. Delete this line and that is the bug that\n comes back, on one browser only.\n\n It is `pointerdown` and not `click`, so the tooltip is gone BEFORE the panel appears\n rather than overlapping it for a frame. Keyboard activation sends no `pointerdown` at\n all, and needs none: focus moving into the panel closes the tooltip everywhere.\n -->\n <span\n class=\"v-tooltip\"\n @pointerenter=\"onPointerEnter\"\n @pointerleave=\"onPointerLeave\"\n @pointerdown=\"onPointerDown\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <slot :trigger-props=\"{ 'aria-describedby': tooltipId }\" />\n <VPopover\n :id=\"tooltipId\"\n ref=\"popoverRef\"\n mode=\"manual\"\n anchor=\"--tooltip-anchor\"\n :placement=\"placement\"\n bare\n role=\"tooltip\"\n class=\"v-tooltip-panel\"\n @update:open=\"onOpenChange\"\n >\n <slot name=\"content\">{{ text }}</slot>\n </VPopover>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The wrapper is FLEX and not inline-block, for the same reason as `.v-badge-host`:\n both are inline-level atomic boxes, so the surrounding text flows identically, but\n an inline-block establishes an inline formatting context for the trigger — which\n then sits on a line box and adds the strut's descender to the wrapper's height.\n That is not only a couple of pixels in a flex row: this wrapper is also the ANCHOR,\n so the panel is offset by them too.\n\n `align-items: center` covers what is left. A wrapper stretched by a parent in\n `align-items: stretch` would otherwise stretch the trigger with it, where the\n inline-block form left it at its natural height. */\n .v-tooltip {\n display: inline-flex;\n align-items: center;\n anchor-name: --tooltip-anchor;\n /* Confining the name to this subtree is indispensable: a visible panel moves to\n the top layer, where anchor resolution treats it as coming after the whole\n document, so without it every tooltip would attach to the LAST wrapper carrying\n this name. */\n anchor-scope: --tooltip-anchor;\n }\n\n /* The anchoring itself comes from VPopover, through the `anchor` prop.\n\n The selector is written as a compound of two classes that both land on this same\n element, even though the panel class it guards against — `.v-panel` — is never\n present here, VTooltip asking for a `bare` panel. It is written that way so it cannot\n break the day that prop changes: at equal specificity the winner between two\n component sheets is decided by the order the consumer's bundler happens to\n produce, which is nobody's decision. */\n .v-popover-panel.v-tooltip-panel {\n inline-size: max-content;\n max-inline-size: min(\n var(--vectis-control-size-tooltip-max),\n calc(100dvi - var(--vectis-space-8))\n );\n padding: var(--vectis-space-1) var(--vectis-space-2);\n /* The tooltip is painted against the page rather than with it: a dark surface in\n both themes, darker still in the dark one, so it reads as an overlay whatever\n it happens to cover. */\n background: var(--vectis-color-surface-inverse);\n color: var(--vectis-color-text-on-inverse);\n border: none;\n /* The control radius capped at half the height of a ONE-line bubble, the row recipe\n of VSideNavigationItem: a tooltip wraps past its max-inline-size, and under a pill\n override a two-line bubble would otherwise round to half of its own height. */\n border-radius: min(var(--vectis-radius-interactive), calc(0.5lh + var(--vectis-space-1)));\n box-shadow: var(--vectis-shadow-sm);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n line-height: var(--vectis-text-caption-leading);\n }\n\n /* Windows forced colors flattens the bubble's background to Canvas and drops its shadow,\n which were its only edge: it would float over the page with no boundary at all. An\n outline draws one without moving the layout by a pixel. */\n @media (forced-colors: active) {\n .v-popover-panel.v-tooltip-panel {\n outline: 1px solid CanvasText;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -1,54 +1,74 @@
1
1
  import e from "../VPopover/VPopover.js";
2
2
  import { useTimer as t } from "../../composables/useTimer.js";
3
3
  import { isKeyboardFocus as n } from "../../utils/focus.js";
4
- import { createElementBlock as r, createTextVNode as i, createVNode as a, defineComponent as o, openBlock as s, ref as c, renderSlot as l, toDisplayString as u, unref as d, useId as f, withCtx as p } from "vue";
4
+ import { computed as r, createElementBlock as i, createTextVNode as a, createVNode as o, defineComponent as s, onBeforeUnmount as c, openBlock as l, ref as u, renderSlot as d, toDisplayString as f, unref as p, useId as m, withCtx as h } from "vue";
5
5
  //#region src/components/VTooltip/VTooltip.vue?vue&type=script&setup=true&lang.ts
6
- var m = /*@__PURE__*/ o({
6
+ var g = 100, _ = /*@__PURE__*/ s({
7
7
  __name: "VTooltip",
8
8
  props: {
9
9
  text: { default: void 0 },
10
10
  placement: { default: "top" },
11
11
  delay: { default: 300 }
12
12
  },
13
- setup(o) {
14
- let m = o, h = f(), g = c(null), _ = t();
15
- function v(e = !1) {
16
- _.start(() => g.value?.show(), e ? 0 : m.delay);
13
+ setup(s, { expose: _ }) {
14
+ let v = s, y = m(), b = u(null), x = t(), S = !1, C = !1;
15
+ function w(e = !1) {
16
+ x.start(() => b.value?.show(), e ? 0 : v.delay);
17
17
  }
18
- function y() {
19
- _.cancel(), g.value?.close();
18
+ function T() {
19
+ x.cancel(), b.value?.close();
20
20
  }
21
- function b(e) {
22
- n(e.target) && v(!0);
21
+ function E() {
22
+ S = !0, w();
23
23
  }
24
- function x(e) {
25
- e.key === "Escape" && y();
24
+ function D() {
25
+ S = !1, !C && x.start(() => b.value?.close(), g);
26
26
  }
27
- return (t, n) => (s(), r("span", {
27
+ function O() {
28
+ S = !1, C = !1, T();
29
+ }
30
+ function k() {
31
+ C = !1, S || T();
32
+ }
33
+ function A(e) {
34
+ n(e.target) && (C = !0, w(!0));
35
+ }
36
+ function j(e) {
37
+ e.key !== "Escape" || e.defaultPrevented || (e.preventDefault(), S = !1, C = !1, T());
38
+ }
39
+ let M = u(!1);
40
+ function N(e) {
41
+ e !== M.value && (M.value = e, e ? document.addEventListener("keydown", j) : document.removeEventListener("keydown", j));
42
+ }
43
+ return c(() => N(!1)), _({
44
+ show: () => w(!0),
45
+ close: T,
46
+ el: r(() => b.value?.el ?? null)
47
+ }), (t, n) => (l(), i("span", {
28
48
  class: "v-tooltip",
29
- onPointerenter: n[0] ||= (e) => v(),
30
- onPointerleave: y,
31
- onPointerdown: y,
32
- onFocusin: b,
33
- onFocusout: y,
34
- onKeydown: x
35
- }, [l(t.$slots, "default", { triggerProps: { "aria-describedby": d(h) } }), a(e, {
36
- id: d(h),
49
+ onPointerenter: E,
50
+ onPointerleave: D,
51
+ onPointerdown: O,
52
+ onFocusin: A,
53
+ onFocusout: k
54
+ }, [d(t.$slots, "default", { triggerProps: { "aria-describedby": p(y) } }), o(e, {
55
+ id: p(y),
37
56
  ref_key: "popoverRef",
38
- ref: g,
57
+ ref: b,
39
58
  mode: "manual",
40
59
  anchor: "--tooltip-anchor",
41
- placement: o.placement,
60
+ placement: s.placement,
42
61
  bare: "",
43
62
  role: "tooltip",
44
- class: "v-tooltip-panel"
63
+ class: "v-tooltip-panel",
64
+ "onUpdate:open": N
45
65
  }, {
46
- default: p(() => [l(t.$slots, "content", {}, () => [i(u(o.text), 1)])]),
66
+ default: h(() => [d(t.$slots, "content", {}, () => [a(f(s.text), 1)])]),
47
67
  _: 3
48
68
  }, 8, ["id", "placement"])], 32));
49
69
  }
50
70
  });
51
71
  //#endregion
52
- export { m as default };
72
+ export { _ as default };
53
73
 
54
74
  //# sourceMappingURL=VTooltip.vue_vue_type_script_setup_true_lang.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VTooltip.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VTooltip/VTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * A short explanation appearing beside an element on hover or keyboard focus. A VPopover in\n * `mode=\"manual\"`, a tooltip having its own rules about when to appear and when to go.\n *\n * Those rules are why there is JS here at all: HTML has no stable way to say \"show this\n * after a delay on hover or focus\", so the component handles the delay, the pointer, the\n * focus, a press on the trigger, and Escape — which must dismiss without moving the focus\n * (WCAG 1.4.13).\n *\n * Four ways out, each covering what the others do not: the pointer leaves, the focus leaves,\n * Escape, or the trigger is PRESSED — that last for a trigger opening a panel, where the\n * tooltip would otherwise stand over what it just opened.\n *\n * Positioning is pure CSS with no generated id: the wrapper names itself as the anchor and\n * confines that name to its own subtree. The confinement is essential — a shown panel moves\n * to the top layer, which anchor resolution treats as coming after the whole document, so\n * without it every tooltip would attach to the last wrapper named on the page.\n *\n * The wrapper stays HERE rather than going through VPopover's `#trigger`: a tooltip trigger\n * is not a `popovertarget` invoker, which would toggle on click, but an element the panel\n * DESCRIBES.\n */\n\nimport { ref, useId } from 'vue'\n\nimport VPopover from '../VPopover/VPopover.vue'\n\nimport { useTimer } from '../../composables/useTimer'\nimport { isKeyboardFocus } from '../../utils/focus'\n\n/** Which side of the element the tooltip appears on. */\nexport type TooltipPlacement =\n 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'right'\n\n/** What the described element has to carry: the link to the tooltip that describes it. */\nexport type TooltipTriggerProps = {\n 'aria-describedby': string\n}\n\ninterface TooltipProps {\n /** What the tooltip says. The `#content` slot replaces it when both are given. */\n text?: string\n /**\n * Which side of the element the tooltip appears on. The browser flips it to the\n * opposite side by itself when there is not enough room.\n */\n placement?: TooltipPlacement\n /**\n * How long the pointer must rest on the element before the tooltip appears, in\n * milliseconds. Keyboard focus opens it at once — the intent is not in doubt there\n * — and a delay of 0 disables the wait entirely.\n */\n delay?: number\n}\n\nconst props = withDefaults(defineProps<TooltipProps>(), {\n text: undefined,\n placement: 'top',\n delay: 300,\n})\n\ndefineSlots<{\n /**\n * The element the tooltip describes. Bind the `triggerProps` it receives onto it —\n * that is what ties the two together for assistive technology — and make sure it is\n * something that can take focus, or keyboard users will never see the tooltip.\n */\n default(props: { triggerProps: TooltipTriggerProps }): unknown\n /**\n * Content richer than a plain string: formatting, a keyboard shortcut, an icon. It\n * must stay NON-interactive. The tooltip closes as soon as the pointer leaves the\n * element, so a link or a button inside could never be reached, and the description\n * is flattened to plain text for screen readers anyway. Content one can interact\n * with belongs in a panel that stays open, such as VMenu.\n */\n content?(): unknown\n}>()\n\nconst tooltipId = useId()\n// @a11y\n/*\n * The panel is opened and closed by calling it directly rather than through\n * `v-model:open`. Keyboard focus has to open it SYNCHRONOUSLY, and a model would go\n * through VPopover's watcher, hence through a tick. There is nothing lost either way:\n * a tooltip publishes no open state anyone needs to read.\n *\n * Calling twice is harmless — the guards for that live upstream in usePopover.\n */\nconst popoverRef = ref<InstanceType<typeof VPopover> | null>(null)\n\n// The delay before appearing. useTimer is what makes it re-armable and cancels it\n// when the component goes away.\nconst timer = useTimer()\n\n// @core\nfunction show(immediate = false) {\n // A delay of 0 runs the callback synchronously — the design system's convention,\n // and what lets keyboard focus share this code path without waiting a tick.\n timer.start(() => popoverRef.value?.show(), immediate ? 0 : props.delay)\n}\n\nfunction hide() {\n timer.cancel()\n popoverRef.value?.close()\n}\n\n// @a11y\n/*\n * The tooltip belongs to the KEYBOARD focus, and a `focusin` says the focus arrived, never\n * how it got there. Three ways in are not a Tab: a click, which the pointer already covers\n * and which the `pointerdown` above has just closed the tooltip for; a tap, which no browser\n * agrees on; and a `focus()` from code — the one a closing panel hands back to the button\n * that opened it, which would raise a tooltip over a page the reader is no longer pointing\n * at. `:focus-visible` is the browser's own answer to the question, the same one VMenu asks\n * to decide where a menu's focus lands.\n *\n * The consequence to know: a tooltip never opens on a tap. Content a touch reader needs\n * cannot live here alone.\n */\nfunction onFocusIn(event: FocusEvent) {\n if (isKeyboardFocus(event.target)) show(true)\n}\n\n// @keyboard @a11y — Escape must dismiss a tooltip opened by hover or focus without\n// moving the focus anywhere (WCAG 1.4.13): content appearing on hover has to be\n// dismissible, for a magnifier user whose view it may be covering.\nfunction onKeydown(event: KeyboardEvent) {\n if (event.key === 'Escape') hide()\n}\n</script>\n\n<template>\n <!--\n TRAP — `pointerdown` is what stops a tooltip from surviving the click that acted on its\n trigger, and the case it really covers is a trigger that OPENS something: a menu, a\n dialog, a popover of any kind. The tooltip would then stand over what it opened, and\n none of the other three exits applies — the pointer has not left, the focus has not\n moved out on its own, and nobody pressed Escape.\n\n It looks redundant on Chromium and Firefox, where a click focuses the button and the\n panel then takes the focus, which fires this wrapper's `focusout`. Safari on macOS does\n NOT focus a button on click, so nothing leaves the wrapper and the tooltip stays up,\n behind the panel, until the pointer moves. Delete this line and that is the bug that\n comes back, on one browser only.\n\n It is `pointerdown` and not `click`, so the tooltip is gone BEFORE the panel appears\n rather than overlapping it for a frame. Keyboard activation sends no `pointerdown` at\n all, and needs none: focus moving into the panel closes the tooltip everywhere.\n -->\n <span\n class=\"v-tooltip\"\n @pointerenter=\"show()\"\n @pointerleave=\"hide\"\n @pointerdown=\"hide\"\n @focusin=\"onFocusIn\"\n @focusout=\"hide\"\n @keydown=\"onKeydown\"\n >\n <slot :trigger-props=\"{ 'aria-describedby': tooltipId }\" />\n <VPopover\n :id=\"tooltipId\"\n ref=\"popoverRef\"\n mode=\"manual\"\n anchor=\"--tooltip-anchor\"\n :placement=\"placement\"\n bare\n role=\"tooltip\"\n class=\"v-tooltip-panel\"\n >\n <slot name=\"content\">{{ text }}</slot>\n </VPopover>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The wrapper is FLEX and not inline-block, for the same reason as `.v-badge-host`:\n both are inline-level atomic boxes, so the surrounding text flows identically, but\n an inline-block establishes an inline formatting context for the trigger — which\n then sits on a line box and adds the strut's descender to the wrapper's height.\n That is not only a couple of pixels in a flex row: this wrapper is also the ANCHOR,\n so the panel is offset by them too.\n\n `align-items: center` covers what is left. A wrapper stretched by a parent in\n `align-items: stretch` would otherwise stretch the trigger with it, where the\n inline-block form left it at its natural height. */\n .v-tooltip {\n display: inline-flex;\n align-items: center;\n anchor-name: --tooltip-anchor;\n /* Confining the name to this subtree is indispensable: a visible panel moves to\n the top layer, where anchor resolution treats it as coming after the whole\n document, so without it every tooltip would attach to the LAST wrapper carrying\n this name. */\n anchor-scope: --tooltip-anchor;\n }\n\n /* The anchoring itself comes from VPopover, through the `anchor` prop.\n\n The selector is written as a compound of two classes that both land on this same\n element, even though the panel class it guards against — `.v-panel` — is never\n present here, VTooltip asking for a `bare` panel. It is written that way so it cannot\n break the day that prop changes: at equal specificity the winner between two\n component sheets is decided by the order the consumer's bundler happens to\n produce, which is nobody's decision. */\n .v-popover-panel.v-tooltip-panel {\n width: max-content;\n max-width: min(18rem, calc(100vw - var(--vectis-space-8)));\n padding: var(--vectis-space-1) var(--vectis-space-2);\n /* The tooltip is painted against the page rather than with it: a dark surface in\n both themes, darker still in the dark one, so it reads as an overlay whatever\n it happens to cover. */\n background: var(--vectis-color-surface-inverse);\n color: var(--vectis-color-text-on-inverse);\n border: none;\n /* The control radius capped at half the height of a ONE-line bubble, the row recipe\n of VSideNavigationItem: a tooltip wraps past its max-width, and under a pill\n override a two-line bubble would otherwise round to half of its own height. */\n border-radius: min(var(--vectis-radius-interactive), calc(0.5lh + var(--vectis-space-1)));\n box-shadow: var(--vectis-shadow-sm);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n line-height: var(--vectis-text-caption-leading);\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;EAwDA,IAAM,IAAQ,GAuBR,IAAY,EAAM,GAUlB,IAAa,EAA0C,IAAI,GAI3D,IAAQ,EAAS;EAGvB,SAAS,EAAK,IAAY,IAAO;GAG/B,EAAM,YAAY,EAAW,OAAO,KAAK,GAAG,IAAY,IAAI,EAAM,KAAK;EACzE;EAEA,SAAS,IAAO;GAEd,AADA,EAAM,OAAO,GACb,EAAW,OAAO,MAAM;EAC1B;EAeA,SAAS,EAAU,GAAmB;GACpC,AAAI,EAAgB,EAAM,MAAM,KAAG,EAAK,EAAI;EAC9C;EAKA,SAAS,EAAU,GAAsB;GACvC,AAAI,EAAM,QAAQ,YAAU,EAAK;EACnC;yBAqBE,EAsBO,QAAA;GArBL,OAAM;GACL,gBAAY,AAAA,EAAA,QAAA,MAAE,EAAI;GAClB,gBAAc;GACd,eAAa;GACb,WAAS;GACT,YAAU;GACD;MAEV,EAA2D,EAAA,QAAA,WAAA,EAApD,cAAa,EAAA,oBAAwB,EAAA,CAAA,EAAS,EAAA,CAAA,GACrD,EAWW,GAAA;GAVR,IAAI,EAAA,CAAA;YACD;GAAJ,KAAI;GACJ,MAAK;GACL,QAAO;GACN,WAAW,EAAA;GACZ,MAAA;GACA,MAAK;GACL,OAAM;;oBAEgC,CAAtC,EAAsC,EAAA,QAAA,WAAA,CAAA,SAAA,CAAA,EAAA,EAAd,EAAA,IAAI,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"VTooltip.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VTooltip/VTooltip.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * A short explanation appearing beside an element on hover or keyboard focus. A VPopover in\n * `mode=\"manual\"`, a tooltip having its own rules about when to appear and when to go.\n *\n * Those rules are why there is JS here at all: HTML has no stable way to say \"show this\n * after a delay on hover or focus\", so the component handles the delay, the pointer, the\n * focus, a press on the trigger, and Escape — which must dismiss without moving the focus\n * (WCAG 1.4.13).\n *\n * It stays as long as EITHER the pointer rests on it (the trigger or the bubble) or the\n * keyboard focus is on the trigger, and goes when both have left, after a short grace the\n * pointer needs to cross the gap onto the bubble (WCAG 1.4.13: hoverable, persistent).\n * Two more ways out: Escape, heard from anywhere on the page while it shows and spent on\n * it, and the trigger being PRESSED, for a trigger opening a panel, where the tooltip would\n * otherwise stand over what it just opened.\n *\n * Positioning is pure CSS with no generated id: the wrapper names itself as the anchor and\n * confines that name to its own subtree. The confinement is essential — a shown panel moves\n * to the top layer, which anchor resolution treats as coming after the whole document, so\n * without it every tooltip would attach to the last wrapper named on the page.\n *\n * The wrapper stays HERE rather than going through VPopover's `#trigger`: a tooltip trigger\n * is not a `popovertarget` invoker, which would toggle on click, but an element the panel\n * DESCRIBES.\n */\n\nimport { computed, onBeforeUnmount, ref, useId } from 'vue'\n\nimport VPopover from '../VPopover/VPopover.vue'\n\nimport { useTimer } from '../../composables/useTimer'\nimport { isKeyboardFocus } from '../../utils/focus'\n\n/** Which side of the element the tooltip appears on. */\nexport type TooltipPlacement =\n | 'top'\n | 'top-start'\n | 'top-end'\n | 'bottom'\n | 'bottom-start'\n | 'bottom-end'\n | 'left'\n | 'left-start'\n | 'left-end'\n | 'right'\n | 'right-start'\n | 'right-end'\n\n/** What the described element has to carry: the link to the tooltip that describes it. */\nexport type TooltipTriggerProps = {\n 'aria-describedby': string\n}\n\ninterface TooltipProps {\n /** What the tooltip says. The `#content` slot replaces it when both are given. */\n text?: string\n /**\n * Which side of the element the tooltip appears on. The browser flips it to the\n * opposite side by itself when there is not enough room.\n */\n placement?: TooltipPlacement\n /**\n * How long the pointer must rest on the element before the tooltip appears, in\n * milliseconds. Keyboard focus opens it at once, the intent being in no doubt there,\n * and a delay of 0 disables the wait entirely.\n */\n delay?: number\n}\n\nconst props = withDefaults(defineProps<TooltipProps>(), {\n text: undefined,\n placement: 'top',\n delay: 300,\n})\n\ndefineSlots<{\n /**\n * The element the tooltip describes. Bind the `triggerProps` it receives onto it, which\n * is what ties the two together for assistive technology, and make sure it is something\n * that can take focus, or keyboard users will never see the tooltip.\n */\n default(props: { triggerProps: TooltipTriggerProps }): unknown\n /**\n * Content richer than a plain string: formatting, a keyboard shortcut, an icon. It\n * must stay NON-interactive: the description is flattened to plain text for screen\n * readers, and nothing inside can be reached from the keyboard. Content one can interact\n * with belongs in a panel that stays open, such as VMenu.\n */\n content?(): unknown\n}>()\n\nconst tooltipId = useId()\n// @a11y\n/*\n * The panel is opened and closed by calling it directly rather than through\n * `v-model:open`. Keyboard focus has to open it SYNCHRONOUSLY, and a model would go\n * through VPopover's watcher, hence through a tick. There is nothing lost either way:\n * a tooltip publishes no open state anyone needs to read.\n *\n * Calling twice is harmless — the guards for that live upstream in usePopover.\n */\nconst popoverRef = ref<InstanceType<typeof VPopover> | null>(null)\n\n// The delay before appearing. useTimer is what makes it re-armable and cancels it\n// when the component goes away.\nconst timer = useTimer()\n\n/**\n * How long a tooltip the pointer has left waits before going: the time to cross the gap\n * between the trigger and the bubble, which the margin leaves empty and which no pointer\n * event covers. The bubble is a DOM descendant of the wrapper, so reaching it counts as\n * coming back and cancels the close.\n */\nconst LEAVE_GRACE = 100\n\n// The two reasons it is showing. It goes only once neither holds.\nlet hovered = false\nlet focused = false\n\n// @core\nfunction show(immediate = false) {\n // A delay of 0 runs the callback synchronously — the design system's convention,\n // and what lets keyboard focus share this code path without waiting a tick.\n timer.start(() => popoverRef.value?.show(), immediate ? 0 : props.delay)\n}\n\nfunction hide() {\n timer.cancel()\n popoverRef.value?.close()\n}\n\nfunction onPointerEnter() {\n hovered = true\n show()\n}\n\nfunction onPointerLeave() {\n hovered = false\n if (focused) return\n timer.start(() => popoverRef.value?.close(), LEAVE_GRACE)\n}\n\nfunction onPointerDown() {\n hovered = false\n focused = false\n hide()\n}\n\nfunction onFocusOut() {\n focused = false\n if (!hovered) hide()\n}\n\n// @a11y\n/*\n * The tooltip belongs to the KEYBOARD focus, and a `focusin` says the focus arrived, never\n * how it got there. Three ways in are not a Tab: a click, which the pointer already covers\n * and which the `pointerdown` above has just closed the tooltip for; a tap, which no browser\n * agrees on; and a `focus()` from code — the one a closing panel hands back to the button\n * that opened it, which would raise a tooltip over a page the reader is no longer pointing\n * at. `:focus-visible` is the browser's own answer to the question, the same one VMenu asks\n * to decide where a menu's focus lands.\n *\n * The consequence to know: a tooltip never opens on a tap. Content a touch reader needs\n * cannot live here alone.\n */\nfunction onFocusIn(event: FocusEvent) {\n if (!isKeyboardFocus(event.target)) return\n focused = true\n show(true)\n}\n\n// @keyboard @a11y\n// Escape must dismiss a tooltip opened by hover or focus without moving the focus anywhere\n// (WCAG 1.4.13), for a magnifier user whose view it may be covering. It is heard on the\n// DOCUMENT while the tooltip shows, since a hovered tooltip rarely holds the focus, and it\n// is SPENT on it: inside a VDialog the same key would otherwise also be the dialog's close\n// request.\nfunction onDocumentKeydown(event: KeyboardEvent) {\n if (event.key !== 'Escape' || event.defaultPrevented) return\n event.preventDefault()\n hovered = false\n focused = false\n hide()\n}\n\nconst listening = ref(false)\nfunction onOpenChange(open: boolean) {\n if (open === listening.value) return\n listening.value = open\n if (open) document.addEventListener('keydown', onDocumentKeydown)\n else document.removeEventListener('keydown', onDocumentKeydown)\n}\nonBeforeUnmount(() => onOpenChange(false))\n\ndefineExpose({\n /** Shows the tooltip at once, without the hover delay. */\n show: () => show(true),\n /** Hides the tooltip. */\n close: hide,\n /** The tooltip bubble. */\n el: computed(() => popoverRef.value?.el ?? null),\n})\n</script>\n\n<template>\n <!--\n TRAP — `pointerdown` is what stops a tooltip from surviving the click that acted on its\n trigger, and the case it really covers is a trigger that OPENS something: a menu, a\n dialog, a popover of any kind. The tooltip would then stand over what it opened, and\n none of the other three exits applies — the pointer has not left, the focus has not\n moved out on its own, and nobody pressed Escape.\n\n It looks redundant on Chromium and Firefox, where a click focuses the button and the\n panel then takes the focus, which fires this wrapper's `focusout`. Safari on macOS does\n NOT focus a button on click, so nothing leaves the wrapper and the tooltip stays up,\n behind the panel, until the pointer moves. Delete this line and that is the bug that\n comes back, on one browser only.\n\n It is `pointerdown` and not `click`, so the tooltip is gone BEFORE the panel appears\n rather than overlapping it for a frame. Keyboard activation sends no `pointerdown` at\n all, and needs none: focus moving into the panel closes the tooltip everywhere.\n -->\n <span\n class=\"v-tooltip\"\n @pointerenter=\"onPointerEnter\"\n @pointerleave=\"onPointerLeave\"\n @pointerdown=\"onPointerDown\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <slot :trigger-props=\"{ 'aria-describedby': tooltipId }\" />\n <VPopover\n :id=\"tooltipId\"\n ref=\"popoverRef\"\n mode=\"manual\"\n anchor=\"--tooltip-anchor\"\n :placement=\"placement\"\n bare\n role=\"tooltip\"\n class=\"v-tooltip-panel\"\n @update:open=\"onOpenChange\"\n >\n <slot name=\"content\">{{ text }}</slot>\n </VPopover>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n /* The wrapper is FLEX and not inline-block, for the same reason as `.v-badge-host`:\n both are inline-level atomic boxes, so the surrounding text flows identically, but\n an inline-block establishes an inline formatting context for the trigger — which\n then sits on a line box and adds the strut's descender to the wrapper's height.\n That is not only a couple of pixels in a flex row: this wrapper is also the ANCHOR,\n so the panel is offset by them too.\n\n `align-items: center` covers what is left. A wrapper stretched by a parent in\n `align-items: stretch` would otherwise stretch the trigger with it, where the\n inline-block form left it at its natural height. */\n .v-tooltip {\n display: inline-flex;\n align-items: center;\n anchor-name: --tooltip-anchor;\n /* Confining the name to this subtree is indispensable: a visible panel moves to\n the top layer, where anchor resolution treats it as coming after the whole\n document, so without it every tooltip would attach to the LAST wrapper carrying\n this name. */\n anchor-scope: --tooltip-anchor;\n }\n\n /* The anchoring itself comes from VPopover, through the `anchor` prop.\n\n The selector is written as a compound of two classes that both land on this same\n element, even though the panel class it guards against — `.v-panel` — is never\n present here, VTooltip asking for a `bare` panel. It is written that way so it cannot\n break the day that prop changes: at equal specificity the winner between two\n component sheets is decided by the order the consumer's bundler happens to\n produce, which is nobody's decision. */\n .v-popover-panel.v-tooltip-panel {\n inline-size: max-content;\n max-inline-size: min(\n var(--vectis-control-size-tooltip-max),\n calc(100dvi - var(--vectis-space-8))\n );\n padding: var(--vectis-space-1) var(--vectis-space-2);\n /* The tooltip is painted against the page rather than with it: a dark surface in\n both themes, darker still in the dark one, so it reads as an overlay whatever\n it happens to cover. */\n background: var(--vectis-color-surface-inverse);\n color: var(--vectis-color-text-on-inverse);\n border: none;\n /* The control radius capped at half the height of a ONE-line bubble, the row recipe\n of VSideNavigationItem: a tooltip wraps past its max-inline-size, and under a pill\n override a two-line bubble would otherwise round to half of its own height. */\n border-radius: min(var(--vectis-radius-interactive), calc(0.5lh + var(--vectis-space-1)));\n box-shadow: var(--vectis-shadow-sm);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n line-height: var(--vectis-text-caption-leading);\n }\n\n /* Windows forced colors flattens the bubble's background to Canvas and drops its shadow,\n which were its only edge: it would float over the page with no boundary at all. An\n outline draws one without moving the layout by a pixel. */\n @media (forced-colors: active) {\n .v-popover-panel.v-tooltip-panel {\n outline: 1px solid CanvasText;\n }\n }\n}\n</style>\n"],"mappings":";;;;;AAkHA,IAAM,IAAc;;;;;;;;EA5CpB,IAAM,IAAQ,GAsBR,IAAY,EAAM,GAUlB,IAAa,EAA0C,IAAI,GAI3D,IAAQ,EAAS,GAWnB,IAAU,IACV,IAAU;EAGd,SAAS,EAAK,IAAY,IAAO;GAG/B,EAAM,YAAY,EAAW,OAAO,KAAK,GAAG,IAAY,IAAI,EAAM,KAAK;EACzE;EAEA,SAAS,IAAO;GAEd,AADA,EAAM,OAAO,GACb,EAAW,OAAO,MAAM;EAC1B;EAEA,SAAS,IAAiB;GAExB,AADA,IAAU,IACV,EAAK;EACP;EAEA,SAAS,IAAiB;GACxB,IAAU,IACN,MACJ,EAAM,YAAY,EAAW,OAAO,MAAM,GAAG,CAAW;EAC1D;EAEA,SAAS,IAAgB;GAGvB,AAFA,IAAU,IACV,IAAU,IACV,EAAK;EACP;EAEA,SAAS,IAAa;GAEpB,AADA,IAAU,IACL,KAAS,EAAK;EACrB;EAeA,SAAS,EAAU,GAAmB;GAC/B,EAAgB,EAAM,MAAM,MACjC,IAAU,IACV,EAAK,EAAI;EACX;EAQA,SAAS,EAAkB,GAAsB;GAC3C,EAAM,QAAQ,YAAY,EAAM,qBACpC,EAAM,eAAe,GACrB,IAAU,IACV,IAAU,IACV,EAAK;EACP;EAEA,IAAM,IAAY,EAAI,EAAK;EAC3B,SAAS,EAAa,GAAe;GAC/B,MAAS,EAAU,UACvB,EAAU,QAAQ,GACd,IAAM,SAAS,iBAAiB,WAAW,CAAiB,IAC3D,SAAS,oBAAoB,WAAW,CAAiB;EAChE;SACA,QAAsB,EAAa,EAAK,CAAC,GAEzC,EAAa;GAEX,YAAY,EAAK,EAAI;GAErB,OAAO;GAEP,IAAI,QAAe,EAAW,OAAO,MAAM,IAAI;EACjD,CAAC,mBAqBC,EAsBO,QAAA;GArBL,OAAM;GACL,gBAAc;GACd,gBAAc;GACd,eAAa;GACb,WAAS;GACT,YAAU;MAEX,EAA2D,EAAA,QAAA,WAAA,EAApD,cAAa,EAAA,oBAAwB,EAAA,CAAA,EAAS,EAAA,CAAA,GACrD,EAYW,GAAA;GAXR,IAAI,EAAA,CAAA;YACD;GAAJ,KAAI;GACJ,MAAK;GACL,QAAO;GACN,WAAW,EAAA;GACZ,MAAA;GACA,MAAK;GACL,OAAM;GACL,iBAAa;;oBAEwB,CAAtC,EAAsC,EAAA,QAAA,WAAA,CAAA,SAAA,CAAA,EAAA,EAAd,EAAA,IAAI,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA"}
@@ -1,2 +1,2 @@
1
1
  @layer vectis.reset, vectis.tokens, vectis.components, vectis.utilities;
2
- @layer vectis.components{.v-typography{--typography-family:var(--vectis-text-family);--typography-tracking:normal;font-family:var(--typography-family);font-size:var(--typography-size);font-weight:var(--typography-weight);line-height:var(--typography-leading);letter-spacing:var(--typography-tracking);color:var(--typography-color,inherit);overflow-wrap:break-word;margin:0}.v-typography[data-variant=display]{--typography-family:var(--vectis-text-family-heading);--typography-size:var(--vectis-text-display-size);--typography-weight:var(--vectis-text-display-weight);--typography-leading:var(--vectis-text-display-leading);--typography-tracking:var(--vectis-text-display-tracking)}.v-typography[data-variant=heading-1]{--typography-family:var(--vectis-text-family-heading);--typography-size:var(--vectis-text-heading-1-size);--typography-weight:var(--vectis-text-heading-1-weight);--typography-leading:var(--vectis-text-heading-1-leading);--typography-tracking:var(--vectis-text-heading-1-tracking)}.v-typography[data-variant=heading-2]{--typography-family:var(--vectis-text-family-heading);--typography-size:var(--vectis-text-heading-2-size);--typography-weight:var(--vectis-text-heading-2-weight);--typography-leading:var(--vectis-text-heading-2-leading);--typography-tracking:var(--vectis-text-heading-2-tracking)}.v-typography[data-variant=heading-3]{--typography-family:var(--vectis-text-family-heading);--typography-size:var(--vectis-text-heading-3-size);--typography-weight:var(--vectis-text-heading-3-weight);--typography-leading:var(--vectis-text-heading-3-leading)}.v-typography[data-variant=heading-4]{--typography-family:var(--vectis-text-family-heading);--typography-size:var(--vectis-text-heading-4-size);--typography-weight:var(--vectis-text-heading-4-weight);--typography-leading:var(--vectis-text-heading-4-leading)}.v-typography[data-variant=subtitle]{--typography-size:var(--vectis-text-subtitle-size);--typography-weight:var(--vectis-text-subtitle-weight);--typography-leading:var(--vectis-text-subtitle-leading)}.v-typography[data-variant=body-xl]{--typography-size:var(--vectis-text-body-xl-size);--typography-weight:var(--vectis-text-body-xl-weight);--typography-leading:var(--vectis-text-body-xl-leading)}.v-typography[data-variant=body-lg]{--typography-size:var(--vectis-text-body-lg-size);--typography-weight:var(--vectis-text-body-lg-weight);--typography-leading:var(--vectis-text-body-lg-leading)}.v-typography[data-variant=body-md]{--typography-size:var(--vectis-text-body-md-size);--typography-weight:var(--vectis-text-body-md-weight);--typography-leading:var(--vectis-text-body-md-leading)}.v-typography[data-variant=body-sm]{--typography-size:var(--vectis-text-body-sm-size);--typography-weight:var(--vectis-text-body-sm-weight);--typography-leading:var(--vectis-text-body-sm-leading)}.v-typography[data-variant=label]{--typography-size:var(--vectis-text-label-size);--typography-weight:var(--vectis-text-label-weight);--typography-leading:var(--vectis-text-label-leading)}.v-typography[data-variant=caption]{--typography-size:var(--vectis-text-caption-size);--typography-weight:var(--vectis-text-caption-weight);--typography-leading:var(--vectis-text-caption-leading)}.v-typography[data-variant=overline]{--typography-size:var(--vectis-text-overline-size);--typography-weight:var(--vectis-text-overline-weight);--typography-leading:var(--vectis-text-overline-leading);--typography-tracking:var(--vectis-text-overline-tracking);text-transform:uppercase}.v-typography[data-variant=code]{--typography-family:var(--vectis-text-family-code);--typography-size:var(--vectis-text-code-size);--typography-weight:var(--vectis-text-code-weight);--typography-leading:var(--vectis-text-code-leading)}.v-typography[data-tone=muted]{--typography-color:var(--vectis-color-text-muted)}.v-typography[data-tone=subtle]{--typography-color:var(--vectis-color-text-subtle)}.v-typography[data-tone=accent]{--typography-color:var(--vectis-color-accent-text)}.v-typography[data-tone=danger]{--typography-color:var(--vectis-color-danger-text)}.v-typography[data-tone=success]{--typography-color:var(--vectis-color-success-text)}.v-typography[data-tone=warning]{--typography-color:var(--vectis-color-warning-text)}.v-typography[data-tone=on-inverse]{--typography-color:var(--vectis-color-text-on-inverse)}.v-typography[data-truncate]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}}
2
+ @layer vectis.components{.v-typography{--typography-family:var(--vectis-text-family);--typography-tracking:normal;font-family:var(--typography-family);font-size:var(--typography-size);font-weight:var(--typography-weight);line-height:var(--typography-leading);letter-spacing:var(--typography-tracking);color:var(--typography-color,inherit);overflow-wrap:break-word;margin:0}:where(.v-typography){--typography-color:initial}.v-typography[data-variant=display]{--typography-family:var(--vectis-text-family-heading);--typography-size:var(--vectis-text-display-size);--typography-weight:var(--vectis-text-display-weight);--typography-leading:var(--vectis-text-display-leading);--typography-tracking:var(--vectis-text-display-tracking)}.v-typography[data-variant=heading-1]{--typography-family:var(--vectis-text-family-heading);--typography-size:var(--vectis-text-heading-1-size);--typography-weight:var(--vectis-text-heading-1-weight);--typography-leading:var(--vectis-text-heading-1-leading);--typography-tracking:var(--vectis-text-heading-1-tracking)}.v-typography[data-variant=heading-2]{--typography-family:var(--vectis-text-family-heading);--typography-size:var(--vectis-text-heading-2-size);--typography-weight:var(--vectis-text-heading-2-weight);--typography-leading:var(--vectis-text-heading-2-leading);--typography-tracking:var(--vectis-text-heading-2-tracking)}.v-typography[data-variant=heading-3]{--typography-family:var(--vectis-text-family-heading);--typography-size:var(--vectis-text-heading-3-size);--typography-weight:var(--vectis-text-heading-3-weight);--typography-leading:var(--vectis-text-heading-3-leading)}.v-typography[data-variant=heading-4]{--typography-family:var(--vectis-text-family-heading);--typography-size:var(--vectis-text-heading-4-size);--typography-weight:var(--vectis-text-heading-4-weight);--typography-leading:var(--vectis-text-heading-4-leading)}.v-typography[data-variant=subtitle]{--typography-size:var(--vectis-text-subtitle-size);--typography-weight:var(--vectis-text-subtitle-weight);--typography-leading:var(--vectis-text-subtitle-leading)}.v-typography[data-variant=body-xl]{--typography-size:var(--vectis-text-body-xl-size);--typography-weight:var(--vectis-text-body-xl-weight);--typography-leading:var(--vectis-text-body-xl-leading)}.v-typography[data-variant=body-lg]{--typography-size:var(--vectis-text-body-lg-size);--typography-weight:var(--vectis-text-body-lg-weight);--typography-leading:var(--vectis-text-body-lg-leading)}.v-typography[data-variant=body-md]{--typography-size:var(--vectis-text-body-md-size);--typography-weight:var(--vectis-text-body-md-weight);--typography-leading:var(--vectis-text-body-md-leading)}.v-typography[data-variant=body-sm]{--typography-size:var(--vectis-text-body-sm-size);--typography-weight:var(--vectis-text-body-sm-weight);--typography-leading:var(--vectis-text-body-sm-leading)}.v-typography[data-variant=label]{--typography-size:var(--vectis-text-label-size);--typography-weight:var(--vectis-text-label-weight);--typography-leading:var(--vectis-text-label-leading)}.v-typography[data-variant=caption]{--typography-size:var(--vectis-text-caption-size);--typography-weight:var(--vectis-text-caption-weight);--typography-leading:var(--vectis-text-caption-leading)}.v-typography[data-variant=overline]{--typography-size:var(--vectis-text-overline-size);--typography-weight:var(--vectis-text-overline-weight);--typography-leading:var(--vectis-text-overline-leading);--typography-tracking:var(--vectis-text-overline-tracking);text-transform:uppercase}.v-typography[data-variant=code]{--typography-family:var(--vectis-text-family-code);--typography-size:var(--vectis-text-code-size);--typography-weight:var(--vectis-text-code-weight);--typography-leading:var(--vectis-text-code-leading)}.v-typography[data-tone=muted]{--typography-color:var(--vectis-color-text-muted)}.v-typography[data-tone=subtle]{--typography-color:var(--vectis-color-text-subtle)}.v-typography[data-tone=accent]{--typography-color:var(--vectis-color-accent-text)}.v-typography[data-tone=danger]{--typography-color:var(--vectis-color-danger-text)}.v-typography[data-tone=success]{--typography-color:var(--vectis-color-success-text)}.v-typography[data-tone=warning]{--typography-color:var(--vectis-color-warning-text)}.v-typography[data-tone=on-inverse]{--typography-color:var(--vectis-color-text-on-inverse)}.v-typography[data-truncate]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}}
@@ -1,27 +1,29 @@
1
+ /** The role a text plays, each with its complete typographic recipe. */
1
2
  export type TypographyVariant = 'display' | 'heading-1' | 'heading-2' | 'heading-3' | 'heading-4' | 'subtitle' | 'body-xl' | 'body-lg' | 'body-md' | 'body-sm' | 'label' | 'caption' | 'overline' | 'code';
3
+ /** The colour of a text; `default` sets none and inherits. */
2
4
  export type TypographyTone = 'default' | 'muted' | 'subtle' | 'accent' | 'danger' | 'success' | 'warning' | 'on-inverse';
3
5
  interface TypographyProps {
4
6
  /**
5
7
  * The role this text plays, which selects a complete recipe of typographic
6
- * tokens — size, weight, line height and, where the role calls for it, letter
8
+ * tokens: size, weight, line height and, where the role calls for it, letter
7
9
  * spacing and a monospaced family.
8
10
  */
9
11
  variant?: TypographyVariant;
10
12
  /**
11
13
  * The HTML tag to render. Each variant already has a sensible default (h1 to h4,
12
- * p, span, code), so this is for the cases where the meaning and the look differ —
14
+ * p, span, code), so this is for the cases where the meaning and the look differ:
13
15
  * a subtitle that is really an `h2`, or a label attached to a field.
14
16
  */
15
17
  as?: string;
16
18
  /**
17
19
  * The colour of the text. `default` sets none at all, so the text inherits from
18
- * whatever surrounds it — which is what lets the same component be used on an
20
+ * whatever surrounds it, which is what lets the same component be used on an
19
21
  * inverted surface or inside a coloured toast.
20
22
  */
21
23
  tone?: TypographyTone;
22
24
  /**
23
25
  * Cuts the text to one line and ends it with an ellipsis. The element needs a
24
- * width to be cut against — being a block, or a flex item — otherwise there is
26
+ * width to be cut against (being a block, or a flex item), otherwise there is
25
27
  * nothing to overflow and the text simply stays whole.
26
28
  */
27
29
  truncate?: boolean;