vectis-ui 0.1.0 → 0.8.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 (475) hide show
  1. package/README.md +40 -6
  2. package/dist/components/VAccordion/VAccordion.css +1 -1
  3. package/dist/components/VAccordion/VAccordion.d.ts +9 -16
  4. package/dist/components/VAccordion/VAccordion.js.map +1 -1
  5. package/dist/components/VAccordion/VAccordion.vue_vue_type_script_setup_true_lang.js +3 -3
  6. package/dist/components/VAccordion/VAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  7. package/dist/components/VAccordion/VAccordionItem.css +1 -1
  8. package/dist/components/VAccordion/VAccordionItem.d.ts +33 -19
  9. package/dist/components/VAccordion/VAccordionItem.js.map +1 -1
  10. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js +50 -38
  11. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  12. package/dist/components/VAccordion/context.d.ts +1 -8
  13. package/dist/components/VAccordion/context.js.map +1 -1
  14. package/dist/components/VAvatar/VAvatar.css +1 -1
  15. package/dist/components/VAvatar/VAvatar.d.ts +44 -29
  16. package/dist/components/VAvatar/VAvatar.js.map +1 -1
  17. package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js +38 -35
  18. package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/VAvatar/VAvatarGroup.d.ts +5 -16
  20. package/dist/components/VAvatar/VAvatarGroup.js.map +1 -1
  21. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js +7 -7
  22. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  23. package/dist/components/VAvatar/context.d.ts +6 -10
  24. package/dist/components/VAvatar/context.js.map +1 -1
  25. package/dist/components/VBadge/VBadge.css +1 -1
  26. package/dist/components/VBadge/VBadge.d.ts +31 -10
  27. package/dist/components/VBadge/VBadge.js.map +1 -1
  28. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js +39 -24
  29. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
  30. package/dist/components/VBreadcrumb/VBreadcrumb.css +1 -1
  31. package/dist/components/VBreadcrumb/VBreadcrumb.d.ts +4 -17
  32. package/dist/components/VBreadcrumb/VBreadcrumb.js.map +1 -1
  33. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js +23 -25
  34. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/components/VButton/VButton.css +1 -1
  36. package/dist/components/VButton/VButton.d.ts +30 -10
  37. package/dist/components/VButton/VButton.js.map +1 -1
  38. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js +39 -30
  39. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  40. package/dist/components/VButton/VButtonGroup.css +1 -1
  41. package/dist/components/VButton/VButtonGroup.d.ts +76 -13
  42. package/dist/components/VButton/VButtonGroup.js.map +1 -1
  43. package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js +74 -8
  44. package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/VButton/context.d.ts +30 -0
  46. package/dist/components/VButton/context.js +6 -0
  47. package/dist/components/VButton/context.js.map +1 -0
  48. package/dist/components/VCalendar/VCalendar.css +1 -1
  49. package/dist/components/VCalendar/VCalendar.d.ts +50 -36
  50. package/dist/components/VCalendar/VCalendar.js.map +1 -1
  51. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js +99 -85
  52. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  53. package/dist/components/VCalendar/VCalendarEvent.css +1 -1
  54. package/dist/components/VCalendar/VCalendarEvent.d.ts +5 -11
  55. package/dist/components/VCalendar/VCalendarEvent.js.map +1 -1
  56. package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js +7 -1
  57. package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  58. package/dist/components/VCalendar/VCalendarMonth.css +1 -1
  59. package/dist/components/VCalendar/VCalendarMonth.d.ts +10 -13
  60. package/dist/components/VCalendar/VCalendarMonth.js.map +1 -1
  61. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js +183 -244
  62. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/VCalendar/VCalendarTimeGrid.css +1 -1
  64. package/dist/components/VCalendar/VCalendarTimeGrid.d.ts +15 -20
  65. package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -1
  66. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js +385 -448
  67. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/VCalendar/VCalendarYear.css +1 -1
  69. package/dist/components/VCalendar/VCalendarYear.js.map +1 -1
  70. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js +53 -49
  71. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  72. package/dist/components/VCalendar/gesture.d.ts +158 -0
  73. package/dist/components/VCalendar/gesture.js +170 -0
  74. package/dist/components/VCalendar/gesture.js.map +1 -0
  75. package/dist/components/VCalendar/keyboard.d.ts +9 -3
  76. package/dist/components/VCalendar/keyboard.js +2 -6
  77. package/dist/components/VCalendar/keyboard.js.map +1 -1
  78. package/dist/components/VCalendar/layout.d.ts +67 -54
  79. package/dist/components/VCalendar/layout.js +77 -69
  80. package/dist/components/VCalendar/layout.js.map +1 -1
  81. package/dist/components/VCalendar/timeGrid.d.ts +55 -0
  82. package/dist/components/VCalendar/timeGrid.js +71 -0
  83. package/dist/components/VCalendar/timeGrid.js.map +1 -0
  84. package/dist/components/VCalendar/types.d.ts +41 -16
  85. package/dist/components/VCarousel/VCarousel.css +1 -1
  86. package/dist/components/VCarousel/VCarousel.d.ts +21 -41
  87. package/dist/components/VCarousel/VCarousel.js.map +1 -1
  88. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js +157 -129
  89. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  90. package/dist/components/VCarousel/VCarouselItem.d.ts +0 -17
  91. package/dist/components/VCarousel/VCarouselItem.js.map +1 -1
  92. package/dist/components/VCarousel/VCarouselItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  93. package/dist/components/VCarousel/context.d.ts +0 -12
  94. package/dist/components/VCarousel/context.js.map +1 -1
  95. package/dist/components/VCheckbox/VCheckbox.css +1 -1
  96. package/dist/components/VCheckbox/VCheckbox.d.ts +31 -16
  97. package/dist/components/VCheckbox/VCheckbox.js.map +1 -1
  98. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js +62 -29
  99. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  100. package/dist/components/VChip/VChip.css +1 -1
  101. package/dist/components/VChip/VChip.d.ts +36 -26
  102. package/dist/components/VChip/VChip.js.map +1 -1
  103. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js +57 -48
  104. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  105. package/dist/components/VCombobox/VCombobox.css +1 -1
  106. package/dist/components/VCombobox/VCombobox.d.ts +127 -31
  107. package/dist/components/VCombobox/VCombobox.js.map +1 -1
  108. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +336 -247
  109. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  110. package/dist/components/VCombobox/VComboboxGroup.css +1 -1
  111. package/dist/components/VCombobox/VComboboxGroup.d.ts +0 -9
  112. package/dist/components/VCombobox/VComboboxGroup.js.map +1 -1
  113. package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  114. package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  115. package/dist/components/VCombobox/VComboboxOption.css +1 -1
  116. package/dist/components/VCombobox/VComboboxOption.d.ts +0 -15
  117. package/dist/components/VCombobox/VComboboxOption.js.map +1 -1
  118. package/dist/components/VCombobox/VComboboxOption.vue_vue_type_script_setup_true_lang.js +4 -4
  119. package/dist/components/VCombobox/VComboboxOption.vue_vue_type_script_setup_true_lang.js.map +1 -1
  120. package/dist/components/VCombobox/VComboboxSeparator.js.map +1 -1
  121. package/dist/components/VCombobox/VComboboxSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  122. package/dist/components/VCombobox/infiniteScroll.js.map +1 -1
  123. package/dist/components/VDataTable/VDataTable.css +1 -1
  124. package/dist/components/VDataTable/VDataTable.d.ts +50 -28
  125. package/dist/components/VDataTable/VDataTable.js.map +1 -1
  126. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +183 -194
  127. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  128. package/dist/components/VDateInput/VDateInput.css +1 -1
  129. package/dist/components/VDateInput/VDateInput.d.ts +90 -42
  130. package/dist/components/VDateInput/VDateInput.js.map +1 -1
  131. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js +159 -191
  132. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  133. package/dist/components/VDatePicker/VDatePicker.css +1 -1
  134. package/dist/components/VDatePicker/VDatePicker.d.ts +61 -30
  135. package/dist/components/VDatePicker/VDatePicker.js.map +1 -1
  136. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js +243 -221
  137. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  138. package/dist/components/VDialog/VDialog.css +1 -1
  139. package/dist/components/VDialog/VDialog.d.ts +45 -33
  140. package/dist/components/VDialog/VDialog.js.map +1 -1
  141. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js +65 -64
  142. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  143. package/dist/components/VDialog/VDialogAlert.d.ts +24 -20
  144. package/dist/components/VDialog/VDialogAlert.js.map +1 -1
  145. package/dist/components/VDialog/VDialogAlert.vue_vue_type_script_setup_true_lang.js +36 -25
  146. package/dist/components/VDialog/VDialogAlert.vue_vue_type_script_setup_true_lang.js.map +1 -1
  147. package/dist/components/VFileInput/VFileInput.css +1 -1
  148. package/dist/components/VFileInput/VFileInput.d.ts +78 -26
  149. package/dist/components/VFileInput/VFileInput.js.map +1 -1
  150. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js +144 -132
  151. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  152. package/dist/components/VFilePicker/VFilePicker.css +1 -1
  153. package/dist/components/VFilePicker/VFilePicker.d.ts +47 -30
  154. package/dist/components/VFilePicker/VFilePicker.js.map +1 -1
  155. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js +166 -163
  156. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  157. package/dist/components/VFilePicker/fileKind.d.ts +2 -27
  158. package/dist/components/VFilePicker/fileKind.js +9 -8
  159. package/dist/components/VFilePicker/fileKind.js.map +1 -1
  160. package/dist/components/VHotkeys/VHotkeys.css +1 -1
  161. package/dist/components/VHotkeys/VHotkeys.d.ts +8 -30
  162. package/dist/components/VHotkeys/VHotkeys.js.map +1 -1
  163. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js +4 -4
  164. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
  165. package/dist/components/VHotkeys/platform.js.map +1 -1
  166. package/dist/components/VIcon/VIcon.css +1 -1
  167. package/dist/components/VIcon/VIcon.d.ts +15 -6
  168. package/dist/components/VIcon/VIcon.js.map +1 -1
  169. package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js +45 -37
  170. package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  171. package/dist/components/VIcon/iconProps.js.map +1 -1
  172. package/dist/components/VIcon/icons/index.d.ts +1 -1
  173. package/dist/components/VIcon/icons/index.js.map +1 -1
  174. package/dist/components/VIcon/icons/names.d.ts +1 -1
  175. package/dist/components/VIcon/icons/names.js.map +1 -1
  176. package/dist/components/VIcon/resolver.d.ts +3 -3
  177. package/dist/components/VIcon/resolver.js.map +1 -1
  178. package/dist/components/VIcon/types.d.ts +12 -12
  179. package/dist/components/VIconButton/VIconButton.css +1 -1
  180. package/dist/components/VIconButton/VIconButton.d.ts +28 -11
  181. package/dist/components/VIconButton/VIconButton.js.map +1 -1
  182. package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js +26 -20
  183. package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  184. package/dist/components/VInput/VInput.css +1 -1
  185. package/dist/components/VInput/VInput.d.ts +26 -7
  186. package/dist/components/VInput/VInput.js.map +1 -1
  187. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js +86 -75
  188. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  189. package/dist/components/VInput/VInputGroup.css +2 -0
  190. package/dist/components/VInput/VInputGroup.d.ts +47 -0
  191. package/dist/components/VInput/VInputGroup.js +9 -0
  192. package/dist/components/VInput/VInputGroup.js.map +1 -0
  193. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js +80 -0
  194. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -0
  195. package/dist/components/VInput/context.d.ts +11 -0
  196. package/dist/components/VInput/context.js +6 -0
  197. package/dist/components/VInput/context.js.map +1 -0
  198. package/dist/components/VInputOTP/VInputOTP.css +1 -1
  199. package/dist/components/VInputOTP/VInputOTP.d.ts +37 -22
  200. package/dist/components/VInputOTP/VInputOTP.js.map +1 -1
  201. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +98 -61
  202. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -1
  203. package/dist/components/VMenu/VMenu.d.ts +23 -30
  204. package/dist/components/VMenu/VMenu.js.map +1 -1
  205. package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js +31 -27
  206. package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  207. package/dist/components/VMenu/VMenuGroup.css +1 -1
  208. package/dist/components/VMenu/VMenuGroup.d.ts +12 -8
  209. package/dist/components/VMenu/VMenuGroup.js.map +1 -1
  210. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js +11 -11
  211. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  212. package/dist/components/VMenu/VMenuItem.css +1 -1
  213. package/dist/components/VMenu/VMenuItem.d.ts +11 -19
  214. package/dist/components/VMenu/VMenuItem.js.map +1 -1
  215. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js +65 -57
  216. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  217. package/dist/components/VMenu/VMenuPanel.d.ts +14 -30
  218. package/dist/components/VMenu/VMenuPanel.js.map +1 -1
  219. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +43 -44
  220. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  221. package/dist/components/VMenu/context.d.ts +2 -6
  222. package/dist/components/VMenu/context.js.map +1 -1
  223. package/dist/components/VPagination/VPagination.css +1 -1
  224. package/dist/components/VPagination/VPagination.d.ts +60 -22
  225. package/dist/components/VPagination/VPagination.js.map +1 -1
  226. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js +113 -161
  227. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  228. package/dist/components/VPopover/VPopover.css +1 -1
  229. package/dist/components/VPopover/VPopover.d.ts +26 -7
  230. package/dist/components/VPopover/VPopover.js.map +1 -1
  231. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js +43 -37
  232. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
  233. package/dist/components/VProgressCircular/VProgressCircular.css +1 -1
  234. package/dist/components/VProgressCircular/VProgressCircular.d.ts +15 -4
  235. package/dist/components/VProgressCircular/VProgressCircular.js.map +1 -1
  236. package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js +32 -30
  237. package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js.map +1 -1
  238. package/dist/components/VProgressLinear/VProgressLinear.css +1 -1
  239. package/dist/components/VProgressLinear/VProgressLinear.d.ts +23 -8
  240. package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -1
  241. package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js +34 -32
  242. package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  243. package/dist/components/VRadio/VRadio.css +1 -1
  244. package/dist/components/VRadio/VRadio.d.ts +36 -18
  245. package/dist/components/VRadio/VRadio.js.map +1 -1
  246. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js +55 -26
  247. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  248. package/dist/components/VSeparator/VSeparator.d.ts +4 -2
  249. package/dist/components/VSeparator/VSeparator.js.map +1 -1
  250. package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  251. package/dist/components/VSideNavigation/VSideNavigation.css +1 -1
  252. package/dist/components/VSideNavigation/VSideNavigation.d.ts +5 -19
  253. package/dist/components/VSideNavigation/VSideNavigation.js.map +1 -1
  254. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js +5 -5
  255. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js.map +1 -1
  256. package/dist/components/VSideNavigation/VSideNavigationGroup.css +1 -1
  257. package/dist/components/VSideNavigation/VSideNavigationGroup.d.ts +9 -17
  258. package/dist/components/VSideNavigation/VSideNavigationGroup.js.map +1 -1
  259. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js +2 -2
  260. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  261. package/dist/components/VSideNavigation/VSideNavigationItem.css +1 -1
  262. package/dist/components/VSideNavigation/VSideNavigationItem.d.ts +22 -30
  263. package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -1
  264. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +77 -87
  265. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  266. package/dist/components/VSideNavigation/context.d.ts +0 -14
  267. package/dist/components/VSideNavigation/context.js.map +1 -1
  268. package/dist/components/VSkeletonLoader/VSkeletonLoader.css +1 -1
  269. package/dist/components/VSkeletonLoader/VSkeletonLoader.d.ts +9 -9
  270. package/dist/components/VSkeletonLoader/VSkeletonLoader.js.map +1 -1
  271. package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  272. package/dist/components/VSlider/VSlider.css +1 -1
  273. package/dist/components/VSlider/VSlider.d.ts +52 -27
  274. package/dist/components/VSlider/VSlider.js.map +1 -1
  275. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js +202 -118
  276. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  277. package/dist/components/VSnackbar/VSnackbar.css +1 -1
  278. package/dist/components/VSnackbar/VSnackbar.d.ts +0 -23
  279. package/dist/components/VSnackbar/VSnackbar.js.map +1 -1
  280. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js +38 -38
  281. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  282. package/dist/components/VSnackbar/state.d.ts +0 -27
  283. package/dist/components/VSnackbar/state.js.map +1 -1
  284. package/dist/components/VSpinner/VSpinner.css +1 -1
  285. package/dist/components/VSpinner/VSpinner.d.ts +6 -6
  286. package/dist/components/VSpinner/VSpinner.js.map +1 -1
  287. package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js +10 -9
  288. package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  289. package/dist/components/VSwitch/VSwitch.css +1 -1
  290. package/dist/components/VSwitch/VSwitch.d.ts +35 -13
  291. package/dist/components/VSwitch/VSwitch.js.map +1 -1
  292. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js +62 -21
  293. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  294. package/dist/components/VTabs/VTab.css +1 -1
  295. package/dist/components/VTabs/VTab.d.ts +12 -12
  296. package/dist/components/VTabs/VTab.js.map +1 -1
  297. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js +36 -24
  298. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
  299. package/dist/components/VTabs/VTabPanel.d.ts +2 -10
  300. package/dist/components/VTabs/VTabPanel.js.map +1 -1
  301. package/dist/components/VTabs/VTabPanel.vue_vue_type_script_setup_true_lang.js +4 -4
  302. package/dist/components/VTabs/VTabPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  303. package/dist/components/VTabs/VTabs.css +1 -1
  304. package/dist/components/VTabs/VTabs.d.ts +27 -18
  305. package/dist/components/VTabs/VTabs.js.map +1 -1
  306. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js +92 -81
  307. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  308. package/dist/components/VTabs/context.d.ts +9 -19
  309. package/dist/components/VTabs/context.js +1 -1
  310. package/dist/components/VTabs/context.js.map +1 -1
  311. package/dist/components/VTextarea/VTextarea.css +1 -1
  312. package/dist/components/VTextarea/VTextarea.d.ts +34 -6
  313. package/dist/components/VTextarea/VTextarea.js.map +1 -1
  314. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js +91 -74
  315. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  316. package/dist/components/VTimeInput/VTimeInput.css +1 -1
  317. package/dist/components/VTimeInput/VTimeInput.d.ts +123 -33
  318. package/dist/components/VTimeInput/VTimeInput.js.map +1 -1
  319. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js +294 -291
  320. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  321. package/dist/components/VTimeInput/search.d.ts +24 -0
  322. package/dist/components/VTimeInput/search.js +22 -0
  323. package/dist/components/VTimeInput/search.js.map +1 -0
  324. package/dist/components/VTimePicker/VTimePicker.css +1 -1
  325. package/dist/components/VTimePicker/VTimePicker.d.ts +51 -30
  326. package/dist/components/VTimePicker/VTimePicker.js.map +1 -1
  327. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js +216 -151
  328. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  329. package/dist/components/VTimePicker/limits.d.ts +88 -0
  330. package/dist/components/VTimePicker/limits.js +70 -0
  331. package/dist/components/VTimePicker/limits.js.map +1 -0
  332. package/dist/components/VToast/VToast.css +1 -1
  333. package/dist/components/VToast/VToast.d.ts +0 -10
  334. package/dist/components/VToast/VToast.js.map +1 -1
  335. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js +10 -10
  336. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js.map +1 -1
  337. package/dist/components/VToast/VToaster.css +1 -1
  338. package/dist/components/VToast/VToaster.d.ts +0 -17
  339. package/dist/components/VToast/VToaster.js.map +1 -1
  340. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js +29 -28
  341. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
  342. package/dist/components/VToast/state.d.ts +10 -19
  343. package/dist/components/VToast/state.js +1 -1
  344. package/dist/components/VToast/state.js.map +1 -1
  345. package/dist/components/VToggle/VToggle.css +1 -1
  346. package/dist/components/VToggle/VToggle.d.ts +56 -11
  347. package/dist/components/VToggle/VToggle.js.map +1 -1
  348. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js +80 -46
  349. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js.map +1 -1
  350. package/dist/components/VToggle/VToggleItem.d.ts +16 -2
  351. package/dist/components/VToggle/VToggleItem.js +0 -2
  352. package/dist/components/VToggle/VToggleItem.js.map +1 -1
  353. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js +23 -15
  354. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  355. package/dist/components/VToggle/context.d.ts +4 -24
  356. package/dist/components/VToggle/context.js.map +1 -1
  357. package/dist/components/VTooltip/VTooltip.css +1 -1
  358. package/dist/components/VTooltip/VTooltip.d.ts +9 -33
  359. package/dist/components/VTooltip/VTooltip.js.map +1 -1
  360. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js +28 -24
  361. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  362. package/dist/components/VTypography/VTypography.js.map +1 -1
  363. package/dist/components/VTypography/VTypography.vue_vue_type_script_setup_true_lang.js.map +1 -1
  364. package/dist/composables/useAriaLabel.d.ts +0 -17
  365. package/dist/composables/useAriaLabel.js.map +1 -1
  366. package/dist/composables/useClearable.d.ts +42 -0
  367. package/dist/composables/useClearable.js +19 -0
  368. package/dist/composables/useClearable.js.map +1 -0
  369. package/dist/composables/useControlShape.d.ts +22 -0
  370. package/dist/composables/useControlShape.js +13 -0
  371. package/dist/composables/useControlShape.js.map +1 -0
  372. package/dist/composables/useDetailsOpen.d.ts +22 -0
  373. package/dist/composables/useDetailsOpen.js +21 -0
  374. package/dist/composables/useDetailsOpen.js.map +1 -0
  375. package/dist/composables/useFieldIds.d.ts +0 -15
  376. package/dist/composables/useFieldIds.js +8 -7
  377. package/dist/composables/useFieldIds.js.map +1 -1
  378. package/dist/composables/useFieldPanel.d.ts +21 -18
  379. package/dist/composables/useFieldPanel.js +43 -23
  380. package/dist/composables/useFieldPanel.js.map +1 -1
  381. package/dist/composables/useFileDrop.d.ts +0 -22
  382. package/dist/composables/useFileDrop.js.map +1 -1
  383. package/dist/composables/useFileField.d.ts +45 -17
  384. package/dist/composables/useFileField.js +40 -20
  385. package/dist/composables/useFileField.js.map +1 -1
  386. package/dist/composables/useFocusoutDismiss.d.ts +0 -15
  387. package/dist/composables/useFocusoutDismiss.js.map +1 -1
  388. package/dist/composables/useIconClickHandlers.d.ts +29 -14
  389. package/dist/composables/useIconClickHandlers.js +15 -5
  390. package/dist/composables/useIconClickHandlers.js.map +1 -1
  391. package/dist/composables/useInertLink.d.ts +20 -0
  392. package/dist/composables/useInertLink.js +23 -0
  393. package/dist/composables/useInertLink.js.map +1 -0
  394. package/dist/composables/useMaskedField.d.ts +33 -10
  395. package/dist/composables/useMaskedField.js +45 -1
  396. package/dist/composables/useMaskedField.js.map +1 -1
  397. package/dist/composables/usePopover.d.ts +15 -1
  398. package/dist/composables/usePopover.js +23 -8
  399. package/dist/composables/usePopover.js.map +1 -1
  400. package/dist/composables/useProgressValue.d.ts +5 -8
  401. package/dist/composables/useProgressValue.js +6 -3
  402. package/dist/composables/useProgressValue.js.map +1 -1
  403. package/dist/composables/useRootAttrs.d.ts +12 -19
  404. package/dist/composables/useRootAttrs.js.map +1 -1
  405. package/dist/composables/useTimer.d.ts +8 -10
  406. package/dist/composables/useTimer.js.map +1 -1
  407. package/dist/i18n/en.d.ts +2 -10
  408. package/dist/i18n/en.js +18 -19
  409. package/dist/i18n/en.js.map +1 -1
  410. package/dist/i18n/fr.d.ts +2 -18
  411. package/dist/i18n/fr.js +18 -19
  412. package/dist/i18n/fr.js.map +1 -1
  413. package/dist/i18n/state.d.ts +44 -47
  414. package/dist/i18n/state.js +20 -17
  415. package/dist/i18n/state.js.map +1 -1
  416. package/dist/i18n/types.d.ts +53 -44
  417. package/dist/icons.d.ts +3 -3
  418. package/dist/index.d.ts +43 -17
  419. package/dist/index.js +45 -44
  420. package/dist/styles.css +1 -1
  421. package/dist/tokens/css.js.map +1 -1
  422. package/dist/tokens/index.d.ts +5 -1
  423. package/dist/tokens/primitives.js.map +1 -1
  424. package/dist/tokens/semantic.d.ts +5 -1
  425. package/dist/tokens/semantic.js +6 -2
  426. package/dist/tokens/semantic.js.map +1 -1
  427. package/dist/tokens/themes/dark.js.map +1 -1
  428. package/dist/tokens/types.d.ts +7 -15
  429. package/dist/tokens/types.js.map +1 -1
  430. package/dist/tokens.json +25 -5
  431. package/dist/types.d.ts +24 -0
  432. package/dist/utils/array.d.ts +3 -6
  433. package/dist/utils/array.js.map +1 -1
  434. package/dist/utils/arrowNav.d.ts +17 -17
  435. package/dist/utils/arrowNav.js +5 -3
  436. package/dist/utils/arrowNav.js.map +1 -1
  437. package/dist/utils/chip.d.ts +11 -15
  438. package/dist/utils/chip.js.map +1 -1
  439. package/dist/utils/css.d.ts +22 -11
  440. package/dist/utils/css.js +5 -2
  441. package/dist/utils/css.js.map +1 -1
  442. package/dist/utils/date.d.ts +42 -19
  443. package/dist/utils/date.js +97 -98
  444. package/dist/utils/date.js.map +1 -1
  445. package/dist/utils/direction.d.ts +6 -12
  446. package/dist/utils/direction.js.map +1 -1
  447. package/dist/utils/env.d.ts +5 -6
  448. package/dist/utils/file.d.ts +46 -58
  449. package/dist/utils/file.js +43 -36
  450. package/dist/utils/file.js.map +1 -1
  451. package/dist/utils/focus.d.ts +8 -17
  452. package/dist/utils/focus.js.map +1 -1
  453. package/dist/utils/hostWarns.d.ts +12 -0
  454. package/dist/utils/hostWarns.js +6 -0
  455. package/dist/utils/hostWarns.js.map +1 -0
  456. package/dist/utils/ids.d.ts +10 -0
  457. package/dist/utils/ids.js +8 -0
  458. package/dist/utils/ids.js.map +1 -0
  459. package/dist/utils/matcher.d.ts +5 -9
  460. package/dist/utils/matcher.js.map +1 -1
  461. package/dist/utils/memo.d.ts +12 -0
  462. package/dist/utils/memo.js +9 -0
  463. package/dist/utils/memo.js.map +1 -0
  464. package/dist/utils/number.d.ts +3 -4
  465. package/dist/utils/number.js.map +1 -1
  466. package/dist/utils/text.d.ts +20 -9
  467. package/dist/utils/text.js +17 -3
  468. package/dist/utils/text.js.map +1 -1
  469. package/dist/utils/time.d.ts +53 -61
  470. package/dist/utils/time.js +49 -45
  471. package/dist/utils/time.js.map +1 -1
  472. package/dist/utils/vnode.d.ts +8 -15
  473. package/dist/utils/vnode.js.map +1 -1
  474. package/package.json +6 -6
  475. package/dist/components/VToggle/VToggleItem.css +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"VBadge.js","names":[],"sources":["../../../src/components/VBadge/VBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * A small pill carrying one piece of information at a glance: a count of unread\n * items, or a single icon. It is never interactive — there is nothing to click and\n * nothing to focus — and it either stands on its own, sits next to an element, or\n * is pinned to one of that element's corners.\n *\n * It is made of HTML and CSS alone. The only JavaScript decides what to render:\n * whether a target element was given at all, capping the counter at \"99+\", and\n * handing a custom colour to the stylesheet as `--custom-color`.\n */\nimport { computed, useSlots } from 'vue'\n\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport type { IconSource } from '../VIcon/types'\n\nexport type BadgeTone = 'neutral' | 'accent' | 'danger' | 'success' | 'warning'\nexport type BadgeOverlayPosition = 'top' | 'bottom'\n\ninterface BadgeProps {\n /**\n * The meaning the badge carries, expressed as a colour. The pill is filled with\n * it and the text adapts to stay readable; there is a single, fully coloured\n * rendering, so no variant to choose alongside it.\n */\n tone?: BadgeTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. On\n * browsers that support `contrast-color()` the text turns black or white by\n * itself; everywhere else it falls back to white, so with a light colour the\n * contrast is yours to check.\n */\n color?: string\n /**\n * The number to display. Anything above 99 is shown as \"99+\", so that a busy\n * counter cannot stretch the pill indefinitely.\n */\n count?: number\n /**\n * A single icon shown instead of a number: an icon name, or an explicit render\n * (the VIcon contract). It takes precedence over `count`, and is ignored when the\n * badge is a `dot`.\n */\n icon?: IconSource\n /**\n * Reduces the badge to a 10px dot with no content — the discreet way to signal\n * that something is new without saying how much.\n */\n dot?: boolean\n /**\n * Pins the badge to a corner of the target element instead of placing it beside\n * it. It does nothing when the badge has no target.\n */\n overlay?: boolean\n /**\n * Which corner an `overlay` badge is pinned to: the top one by default, the\n * bottom one for a marker that belongs at the foot of its target — a presence dot\n * under an avatar, for instance. The horizontal side follows the reading\n * direction and is not configurable. It does nothing without `overlay`.\n */\n overlayPosition?: BadgeOverlayPosition\n /**\n * Draws a 2px ring in the colour of the surface behind the badge\n * (`--vectis-color-surface`, overridable per subtree), which detaches it from a\n * busy target such as a picture.\n */\n bordered?: boolean\n}\n\nconst props = withDefaults(defineProps<BadgeProps>(), {\n tone: 'accent',\n color: undefined,\n count: undefined,\n icon: undefined,\n overlayPosition: 'top',\n})\n\ndefineSlots<{\n /**\n * The element the badge belongs to. Without it the badge stands on its own; with\n * it, the badge is placed beside the element, or in its corner under `overlay`.\n */\n default?(): unknown\n}>()\n\nconst slots = useSlots()\nconst hasTarget = computed(() => slots.default !== undefined)\n\n/** The counter as it is actually displayed: anything past 99 becomes \"99+\". */\nconst displayCount = computed(() =>\n props.count !== undefined && props.count > 99 ? '99+' : props.count,\n)\n\n/*\n * The attributes of the pill itself. The template has two roots — one wrapping a\n * target, one standing alone — and both render the same badge, so the attributes\n * are computed once here rather than written twice.\n */\nconst badgeAttrs = computed(() => ({\n 'data-tone': props.tone,\n 'data-custom': props.color !== undefined ? '' : undefined,\n 'data-dot': props.dot ? '' : undefined,\n 'data-icon-only': !props.dot && props.icon ? '' : undefined,\n 'data-bordered': props.bordered ? '' : undefined,\n style: props.color !== undefined ? { '--custom-color': props.color } : undefined,\n}))\n</script>\n\n<template>\n <span\n v-if=\"hasTarget\"\n class=\"v-badge-host\"\n :data-overlay=\"overlay ? '' : undefined\"\n :data-overlay-position=\"overlayPosition\"\n >\n <slot />\n <span class=\"v-badge\" v-bind=\"badgeAttrs\">\n <template v-if=\"!dot\">\n <VIcon v-if=\"icon\" v-bind=\"iconProps(icon)\" />\n <template v-else>{{ displayCount }}</template>\n </template>\n </span>\n </span>\n <span v-else class=\"v-badge\" v-bind=\"badgeAttrs\">\n <template v-if=\"!dot\">\n <VIcon v-if=\"icon\" v-bind=\"iconProps(icon)\" />\n <template v-else>{{ displayCount }}</template>\n </template>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n .v-badge-host {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-2); /* the space between the target and the badge, in inline mode */\n }\n\n .v-badge {\n --vectis-icon-size: var(--vectis-icon-size-sm);\n --vectis-icon-opsz: 20;\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: var(--vectis-control-size-badge-h);\n /* A minimum width equal to the height, with a small padding on top, is what\n makes a one- or two-digit counter come out round rather than oval. */\n min-width: var(--vectis-control-size-badge-h);\n padding-inline: var(--vectis-space-1);\n border-radius: var(--vectis-radius-pill);\n background: var(--badge-bg);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n color: var(--tone-text-fallback);\n }\n\n @supports (color: contrast-color(red)) {\n .v-badge {\n color: contrast-color(var(--badge-bg));\n }\n }\n\n .v-badge[data-tone='accent'] {\n --badge-bg: var(--vectis-color-accent);\n --tone-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n .v-badge[data-tone='danger'] {\n --badge-bg: var(--vectis-color-danger);\n --tone-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n .v-badge[data-tone='success'] {\n --badge-bg: var(--vectis-color-success);\n --tone-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n .v-badge[data-tone='warning'] {\n --badge-bg: var(--vectis-color-warning);\n --tone-text-fallback: var(--vectis-color-text-on-warning);\n }\n\n /* The neutral tone inverts text and surface rather than using a grey. A grey of\n the text-muted kind resolves to neutral-400 in the dark theme, where the white\n fallback would no longer contrast with it; with the inversion, the fallback and\n contrast-color() agree in both themes. */\n .v-badge[data-tone='neutral'] {\n --badge-bg: var(--vectis-color-text);\n --tone-text-fallback: var(--vectis-color-surface);\n }\n\n /* Placed after the tones on purpose: the specificity is the same, so it is the\n order that lets a custom colour override the tone it replaces. */\n .v-badge[data-custom] {\n --badge-bg: var(--custom-color);\n --tone-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n .v-badge[data-icon-only] {\n padding: 0;\n }\n\n .v-badge[data-dot] {\n width: var(--vectis-control-size-badge-dot);\n height: var(--vectis-control-size-badge-dot);\n min-width: 0;\n padding: 0;\n }\n\n .v-badge[data-bordered] {\n box-shadow: 0 0 0 2px var(--vectis-color-surface);\n }\n\n /* The tuck-in offset is a ratio of the badge's own size, so it stays proportionate\n across the pill, the dot and the icon. Each half of it is held in its own\n variable: the corner and the reading direction each flip ONE axis, and writing\n the whole `translate` again in each branch would make the two multiply — four\n rules to keep in step by hand for two independent decisions. */\n .v-badge-host[data-overlay] > .v-badge {\n --badge-overlay-x: 25%;\n --badge-overlay-y: -25%;\n\n position: absolute;\n inset-block: 0 auto;\n inset-inline-end: 0;\n translate: var(--badge-overlay-x) var(--badge-overlay-y);\n }\n\n .v-badge-host[data-overlay][data-overlay-position='bottom'] > .v-badge {\n --badge-overlay-y: 25%;\n\n inset-block: auto 0;\n }\n\n /* In a right-to-left direction the logical corner moves to the left, so the\n horizontal half of the translation has to flip with it — `translate` is a\n physical property and knows nothing about direction. */\n .v-badge-host[data-overlay]:dir(rtl) > .v-badge {\n --badge-overlay-x: -25%;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"VBadge.js","names":[],"sources":["../../../src/components/VBadge/VBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * A small pill carrying one piece of information at a glance: a count of unread\n * items, or a single icon. It is never interactive — there is nothing to click and\n * nothing to focus — and it either stands on its own, sits next to an element, or\n * is pinned to one of that element's corners.\n *\n * It is made of HTML and CSS alone. The only JavaScript decides what to render:\n * whether a target element was given at all, capping the counter at \"99+\", and\n * handing the two colours a consumer may choose to the stylesheet as\n * `--custom-color` and `--badge-ring-color`.\n */\nimport { computed, h } from 'vue'\nimport type { FunctionalComponent } from 'vue'\n\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport type { IconSource } from '../VIcon/types'\n\nimport { customColorStyle } from '../../utils/css'\n\nexport type BadgeVariant = 'solid' | 'soft'\nexport type BadgeTone = 'neutral' | 'accent' | 'danger' | 'success' | 'warning'\nexport type BadgeOverlayPosition = 'top' | 'bottom'\n\ninterface BadgeProps {\n /**\n * How strongly the badge is painted: filled with the full colour (`solid`, the\n * default), or a tinted background with the text in the colour (`soft`), for a\n * count that should not draw the eye. A `dot` is always solid: with no content to\n * tint, a soft dot would be a pale disc barely distinguishable from the page.\n */\n variant?: BadgeVariant\n /**\n * The meaning the badge carries, expressed as a colour. A solid badge is filled\n * with it and its text adapts to stay readable; a soft one is tinted with it and\n * writes its text in it.\n */\n tone?: BadgeTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. On a\n * solid badge, browsers that support `contrast-color()` turn the text black or\n * white by themselves; everywhere else it falls back to white, so with a light\n * colour the contrast is yours to check. A soft badge derives its background and\n * text from that colour mixed with the theme's surface and text.\n */\n color?: string\n /**\n * The number to display. Anything above 99 is shown as \"99+\", so that a busy\n * counter cannot stretch the pill indefinitely.\n */\n count?: number\n /**\n * A single icon shown instead of a number: an icon name, or an explicit render\n * (the VIcon contract). It takes precedence over `count`, and is ignored when the\n * badge is a `dot`.\n */\n icon?: IconSource\n /**\n * Reduces the badge to a 10px dot with no content — the discreet way to signal\n * that something is new without saying how much.\n */\n dot?: boolean\n /**\n * Pins the badge to a corner of the target element instead of placing it beside\n * it. It does nothing when the badge has no target.\n */\n overlay?: boolean\n /**\n * Which corner an `overlay` badge is pinned to: the top one by default, the\n * bottom one for a marker that belongs at the foot of its target — a presence dot\n * under an avatar, for instance. The horizontal side follows the reading\n * direction and is not configurable. It does nothing without `overlay`.\n */\n overlayPosition?: BadgeOverlayPosition\n /**\n * Draws a 2px ring around the badge, in the colour of the surface behind it,\n * which detaches it from a busy target such as a picture. That colour defaults to\n * the page background and is named through `ringColor` on any other surface.\n */\n bordered?: boolean\n /**\n * The colour of the ring drawn by `bordered`. It defaults to the page background,\n * which is what makes the ring read as a gap around the badge; on another surface\n * (a card, a coloured banner), pass that surface's colour. It does nothing without\n * `bordered`.\n */\n ringColor?: string\n}\n\nconst props = withDefaults(defineProps<BadgeProps>(), {\n variant: 'solid',\n tone: 'accent',\n color: undefined,\n count: undefined,\n icon: undefined,\n overlayPosition: 'top',\n ringColor: undefined,\n // Written out although Vue casts an absent boolean to `false` on its own: left out,\n // `vue-component-meta` reports no default at all and the docs table's cell goes blank.\n dot: false,\n overlay: false,\n bordered: false,\n})\n\nconst slots = defineSlots<{\n /**\n * The element the badge belongs to. Without it the badge stands on its own; with\n * it, the badge is placed beside the element, or in its corner under `overlay`.\n */\n default?(): unknown\n}>()\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.\nfunction hasTarget() {\n return slots.default !== undefined\n}\n\n/** The counter as it is actually displayed: anything past 99 becomes \"99+\". */\nconst displayCount = computed(() =>\n props.count !== undefined && props.count > 99 ? '99+' : props.count,\n)\n\n/*\n * The pill itself, written once. The template has two roots — one wrapping a target, one\n * standing alone — and both render the same badge; a functional component is the one way\n * to put the same markup in two places of a template without writing it twice.\n */\nconst Pill: FunctionalComponent = () =>\n h(\n 'span',\n {\n class: 'v-badge v-tone',\n 'data-variant': props.variant,\n 'data-tone': props.tone,\n 'data-custom': props.color !== undefined ? '' : undefined,\n 'data-dot': props.dot ? '' : undefined,\n 'data-icon-only': !props.dot && props.icon ? '' : undefined,\n 'data-bordered': props.bordered ? '' : undefined,\n style: [\n customColorStyle(props.color),\n props.ringColor !== undefined ? { '--badge-ring-color': props.ringColor } : undefined,\n ],\n },\n props.dot\n ? undefined\n : props.icon\n ? [h(VIcon, iconProps(props.icon))]\n : displayCount.value === undefined\n ? undefined\n : String(displayCount.value),\n )\n// TRAP — the empty list is not decoration. A functional component that declares no props lets\n// only `class`, `style` and listeners fall through, so a standalone badge, whose root this is,\n// would silently drop every other attribute a consumer set on VBadge (an `id`, a `data-*`).\nPill.props = []\n</script>\n\n<template>\n <span\n v-if=\"hasTarget()\"\n class=\"v-badge-host\"\n :data-overlay=\"overlay ? '' : undefined\"\n :data-overlay-position=\"overlayPosition\"\n >\n <slot />\n <Pill />\n </span>\n <Pill v-else />\n</template>\n\n<style>\n@layer vectis.components {\n .v-badge-host {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-2); /* the space between the target and the badge, in inline mode */\n }\n\n .v-badge {\n --vectis-icon-size: var(--vectis-icon-size-sm);\n --vectis-icon-opsz: 20;\n /* The colour of the `bordered` ring: a bet on the page background, the only one a\n component can make since CSS cannot read what its parent paints. The `ringColor`\n prop overrides it inline for a badge sitting on anything else. */\n --badge-ring-color: var(--vectis-color-surface);\n /* The pill is the tone's solid pair, read from the shared table (`.v-tone`, set in the\n template). Its neutral is the text/surface inversion, which is what lets the\n fallback text and contrast-color() agree in both themes. */\n --badge-bg: var(--tone-bg-solid);\n --badge-text-fallback: var(--tone-text-solid);\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: var(--vectis-control-size-badge-h);\n /* A minimum width equal to the height, with a small padding on top, is what\n makes a one- or two-digit counter come out round rather than oval. */\n min-width: var(--vectis-control-size-badge-h);\n padding-inline: var(--vectis-space-1);\n border-radius: var(--vectis-radius-pill);\n background: var(--badge-bg);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n color: var(--badge-text-fallback);\n }\n\n @supports (color: contrast-color(red)) {\n .v-badge {\n color: contrast-color(var(--badge-bg));\n }\n }\n\n /* A custom colour replaces the tone: at (0,2,0) it beats the base rule's mapping\n whatever the order the two are written in. */\n .v-badge[data-custom] {\n --badge-bg: var(--custom-color);\n --badge-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n /* The soft pair of the same table. The text is the tone's own colour rather than\n contrast-color(): the black or white that function picks reads on a pale tint, but\n says nothing of the tone. At (0,3,0) it beats the `@supports` rule above whatever\n the order. A dot is left out: with no content, a soft dot is a pale disc on the\n page, which a presence marker cannot afford. */\n .v-badge[data-variant='soft']:not([data-dot]) {\n --badge-bg: var(--tone-bg-soft);\n\n color: var(--tone-text-tinted);\n }\n\n /* A custom colour's soft pair, derived as VChip derives its own, so the same value\n gives a soft chip and a soft badge the same tint in both themes. */\n .v-badge[data-variant='soft'][data-custom]:not([data-dot]) {\n --badge-bg: color-mix(in oklab, var(--custom-color), var(--vectis-color-surface) 85%);\n\n color: color-mix(in oklab, var(--custom-color), var(--vectis-color-text) 30%);\n }\n\n .v-badge[data-icon-only] {\n padding: 0;\n }\n\n .v-badge[data-dot] {\n width: var(--vectis-control-size-badge-dot);\n height: var(--vectis-control-size-badge-dot);\n min-width: 0;\n padding: 0;\n }\n\n .v-badge[data-bordered] {\n box-shadow: 0 0 0 var(--vectis-control-size-badge-ring) var(--badge-ring-color);\n }\n\n /* The tuck-in offset is a ratio of the badge's own size, so it stays proportionate\n across the pill, the dot and the icon. Each half of it is held in its own\n variable: the corner and the reading direction each flip ONE axis, and writing\n the whole `translate` again in each branch would make the two multiply — four\n rules to keep in step by hand for two independent decisions. */\n .v-badge-host[data-overlay] > .v-badge {\n --badge-overlay-x: 25%;\n --badge-overlay-y: -25%;\n\n position: absolute;\n inset-block: 0 auto;\n inset-inline-end: 0;\n translate: var(--badge-overlay-x) var(--badge-overlay-y);\n /* TRAP — an overlaid badge deliberately leaves its target's box, so it lands on\n whatever sits beside it, and the host opens no stacking context of its own\n (`position: relative` with `z-index: auto`). Left at `auto` the badge is painted\n with the other positioned boxes in TREE ORDER, which means anything positioned\n after it covers it: inside a VButtonGroup, where every segment is positioned, the\n badge on one segment disappears under the borders of the next. The lift takes it\n past that step, and no further: the segment it leans into comes later in tree\n order, so that segment's focus ring, raised to this same level, is still drawn\n over the badge rather than under it. */\n z-index: 1;\n }\n\n .v-badge-host[data-overlay][data-overlay-position='bottom'] > .v-badge {\n --badge-overlay-y: 25%;\n\n inset-block: auto 0;\n }\n\n /* In a right-to-left direction the logical corner moves to the left, so the\n horizontal half of the translation has to flip with it — `translate` is a\n physical property and knows nothing about direction. */\n .v-badge-host[data-overlay]:dir(rtl) > .v-badge {\n --badge-overlay-x: -25%;\n }\n}\n</style>\n"],"mappings":""}
@@ -1,40 +1,55 @@
1
- import e from "../VIcon/VIcon.js";
2
- import { iconProps as t } from "../VIcon/iconProps.js";
3
- import { Fragment as n, computed as r, createBlock as i, createCommentVNode as a, createElementBlock as o, createElementVNode as s, createTextVNode as c, defineComponent as l, mergeProps as u, normalizeProps as d, openBlock as f, renderSlot as p, toDisplayString as m, unref as h, useSlots as g } from "vue";
1
+ import { iconProps as e } from "../VIcon/iconProps.js";
2
+ import { customColorStyle as t } from "../../utils/css.js";
3
+ import n from "../VIcon/VIcon.js";
4
+ import { computed as r, createBlock as i, createElementBlock as a, createVNode as o, defineComponent as s, h as c, openBlock as l, renderSlot as u, useSlots as d } from "vue";
4
5
  //#region src/components/VBadge/VBadge.vue?vue&type=script&setup=true&lang.ts
5
- var _ = ["data-overlay", "data-overlay-position"], v = /*@__PURE__*/ l({
6
+ var f = ["data-overlay", "data-overlay-position"], p = /*@__PURE__*/ s({
6
7
  __name: "VBadge",
7
8
  props: {
9
+ variant: { default: "solid" },
8
10
  tone: { default: "accent" },
9
11
  color: { default: void 0 },
10
12
  count: { default: void 0 },
11
13
  icon: { default: void 0 },
12
- dot: { type: Boolean },
13
- overlay: { type: Boolean },
14
+ dot: {
15
+ type: Boolean,
16
+ default: !1
17
+ },
18
+ overlay: {
19
+ type: Boolean,
20
+ default: !1
21
+ },
14
22
  overlayPosition: { default: "top" },
15
- bordered: { type: Boolean }
23
+ bordered: {
24
+ type: Boolean,
25
+ default: !1
26
+ },
27
+ ringColor: { default: void 0 }
16
28
  },
17
- setup(l) {
18
- let v = l, y = g(), b = r(() => y.default !== void 0), x = r(() => v.count !== void 0 && v.count > 99 ? "99+" : v.count), S = r(() => ({
19
- "data-tone": v.tone,
20
- "data-custom": v.color === void 0 ? void 0 : "",
21
- "data-dot": v.dot ? "" : void 0,
22
- "data-icon-only": !v.dot && v.icon ? "" : void 0,
23
- "data-bordered": v.bordered ? "" : void 0,
24
- style: v.color === void 0 ? void 0 : { "--custom-color": v.color }
25
- }));
26
- return (r, g) => b.value ? (f(), o("span", {
29
+ setup(s) {
30
+ let p = s, m = d();
31
+ function h() {
32
+ return m.default !== void 0;
33
+ }
34
+ let g = r(() => p.count !== void 0 && p.count > 99 ? "99+" : p.count), _ = () => c("span", {
35
+ class: "v-badge v-tone",
36
+ "data-variant": p.variant,
37
+ "data-tone": p.tone,
38
+ "data-custom": p.color === void 0 ? void 0 : "",
39
+ "data-dot": p.dot ? "" : void 0,
40
+ "data-icon-only": !p.dot && p.icon ? "" : void 0,
41
+ "data-bordered": p.bordered ? "" : void 0,
42
+ style: [t(p.color), p.ringColor === void 0 ? void 0 : { "--badge-ring-color": p.ringColor }]
43
+ }, p.dot ? void 0 : p.icon ? [c(n, e(p.icon))] : g.value === void 0 ? void 0 : String(g.value));
44
+ return _.props = [], (e, t) => h() ? (l(), a("span", {
27
45
  key: 0,
28
46
  class: "v-badge-host",
29
- "data-overlay": l.overlay ? "" : void 0,
30
- "data-overlay-position": l.overlayPosition
31
- }, [p(r.$slots, "default"), s("span", u({ class: "v-badge" }, S.value), [l.dot ? a("", !0) : (f(), o(n, { key: 0 }, [l.icon ? (f(), i(e, d(u({ key: 0 }, h(t)(l.icon))), null, 16)) : (f(), o(n, { key: 1 }, [c(m(x.value), 1)], 64))], 64))], 16)], 8, _)) : (f(), o("span", u({
32
- key: 1,
33
- class: "v-badge"
34
- }, S.value), [l.dot ? a("", !0) : (f(), o(n, { key: 0 }, [l.icon ? (f(), i(e, d(u({ key: 0 }, h(t)(l.icon))), null, 16)) : (f(), o(n, { key: 1 }, [c(m(x.value), 1)], 64))], 64))], 16));
47
+ "data-overlay": s.overlay ? "" : void 0,
48
+ "data-overlay-position": s.overlayPosition
49
+ }, [u(e.$slots, "default"), o(_)], 8, f)) : (l(), i(_, { key: 1 }));
35
50
  }
36
51
  });
37
52
  //#endregion
38
- export { v as default };
53
+ export { p as default };
39
54
 
40
55
  //# sourceMappingURL=VBadge.vue_vue_type_script_setup_true_lang.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VBadge.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VBadge/VBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * A small pill carrying one piece of information at a glance: a count of unread\n * items, or a single icon. It is never interactive — there is nothing to click and\n * nothing to focus — and it either stands on its own, sits next to an element, or\n * is pinned to one of that element's corners.\n *\n * It is made of HTML and CSS alone. The only JavaScript decides what to render:\n * whether a target element was given at all, capping the counter at \"99+\", and\n * handing a custom colour to the stylesheet as `--custom-color`.\n */\nimport { computed, useSlots } from 'vue'\n\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport type { IconSource } from '../VIcon/types'\n\nexport type BadgeTone = 'neutral' | 'accent' | 'danger' | 'success' | 'warning'\nexport type BadgeOverlayPosition = 'top' | 'bottom'\n\ninterface BadgeProps {\n /**\n * The meaning the badge carries, expressed as a colour. The pill is filled with\n * it and the text adapts to stay readable; there is a single, fully coloured\n * rendering, so no variant to choose alongside it.\n */\n tone?: BadgeTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. On\n * browsers that support `contrast-color()` the text turns black or white by\n * itself; everywhere else it falls back to white, so with a light colour the\n * contrast is yours to check.\n */\n color?: string\n /**\n * The number to display. Anything above 99 is shown as \"99+\", so that a busy\n * counter cannot stretch the pill indefinitely.\n */\n count?: number\n /**\n * A single icon shown instead of a number: an icon name, or an explicit render\n * (the VIcon contract). It takes precedence over `count`, and is ignored when the\n * badge is a `dot`.\n */\n icon?: IconSource\n /**\n * Reduces the badge to a 10px dot with no content — the discreet way to signal\n * that something is new without saying how much.\n */\n dot?: boolean\n /**\n * Pins the badge to a corner of the target element instead of placing it beside\n * it. It does nothing when the badge has no target.\n */\n overlay?: boolean\n /**\n * Which corner an `overlay` badge is pinned to: the top one by default, the\n * bottom one for a marker that belongs at the foot of its target — a presence dot\n * under an avatar, for instance. The horizontal side follows the reading\n * direction and is not configurable. It does nothing without `overlay`.\n */\n overlayPosition?: BadgeOverlayPosition\n /**\n * Draws a 2px ring in the colour of the surface behind the badge\n * (`--vectis-color-surface`, overridable per subtree), which detaches it from a\n * busy target such as a picture.\n */\n bordered?: boolean\n}\n\nconst props = withDefaults(defineProps<BadgeProps>(), {\n tone: 'accent',\n color: undefined,\n count: undefined,\n icon: undefined,\n overlayPosition: 'top',\n})\n\ndefineSlots<{\n /**\n * The element the badge belongs to. Without it the badge stands on its own; with\n * it, the badge is placed beside the element, or in its corner under `overlay`.\n */\n default?(): unknown\n}>()\n\nconst slots = useSlots()\nconst hasTarget = computed(() => slots.default !== undefined)\n\n/** The counter as it is actually displayed: anything past 99 becomes \"99+\". */\nconst displayCount = computed(() =>\n props.count !== undefined && props.count > 99 ? '99+' : props.count,\n)\n\n/*\n * The attributes of the pill itself. The template has two roots — one wrapping a\n * target, one standing alone — and both render the same badge, so the attributes\n * are computed once here rather than written twice.\n */\nconst badgeAttrs = computed(() => ({\n 'data-tone': props.tone,\n 'data-custom': props.color !== undefined ? '' : undefined,\n 'data-dot': props.dot ? '' : undefined,\n 'data-icon-only': !props.dot && props.icon ? '' : undefined,\n 'data-bordered': props.bordered ? '' : undefined,\n style: props.color !== undefined ? { '--custom-color': props.color } : undefined,\n}))\n</script>\n\n<template>\n <span\n v-if=\"hasTarget\"\n class=\"v-badge-host\"\n :data-overlay=\"overlay ? '' : undefined\"\n :data-overlay-position=\"overlayPosition\"\n >\n <slot />\n <span class=\"v-badge\" v-bind=\"badgeAttrs\">\n <template v-if=\"!dot\">\n <VIcon v-if=\"icon\" v-bind=\"iconProps(icon)\" />\n <template v-else>{{ displayCount }}</template>\n </template>\n </span>\n </span>\n <span v-else class=\"v-badge\" v-bind=\"badgeAttrs\">\n <template v-if=\"!dot\">\n <VIcon v-if=\"icon\" v-bind=\"iconProps(icon)\" />\n <template v-else>{{ displayCount }}</template>\n </template>\n </span>\n</template>\n\n<style>\n@layer vectis.components {\n .v-badge-host {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-2); /* the space between the target and the badge, in inline mode */\n }\n\n .v-badge {\n --vectis-icon-size: var(--vectis-icon-size-sm);\n --vectis-icon-opsz: 20;\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: var(--vectis-control-size-badge-h);\n /* A minimum width equal to the height, with a small padding on top, is what\n makes a one- or two-digit counter come out round rather than oval. */\n min-width: var(--vectis-control-size-badge-h);\n padding-inline: var(--vectis-space-1);\n border-radius: var(--vectis-radius-pill);\n background: var(--badge-bg);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n color: var(--tone-text-fallback);\n }\n\n @supports (color: contrast-color(red)) {\n .v-badge {\n color: contrast-color(var(--badge-bg));\n }\n }\n\n .v-badge[data-tone='accent'] {\n --badge-bg: var(--vectis-color-accent);\n --tone-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n .v-badge[data-tone='danger'] {\n --badge-bg: var(--vectis-color-danger);\n --tone-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n .v-badge[data-tone='success'] {\n --badge-bg: var(--vectis-color-success);\n --tone-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n .v-badge[data-tone='warning'] {\n --badge-bg: var(--vectis-color-warning);\n --tone-text-fallback: var(--vectis-color-text-on-warning);\n }\n\n /* The neutral tone inverts text and surface rather than using a grey. A grey of\n the text-muted kind resolves to neutral-400 in the dark theme, where the white\n fallback would no longer contrast with it; with the inversion, the fallback and\n contrast-color() agree in both themes. */\n .v-badge[data-tone='neutral'] {\n --badge-bg: var(--vectis-color-text);\n --tone-text-fallback: var(--vectis-color-surface);\n }\n\n /* Placed after the tones on purpose: the specificity is the same, so it is the\n order that lets a custom colour override the tone it replaces. */\n .v-badge[data-custom] {\n --badge-bg: var(--custom-color);\n --tone-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n .v-badge[data-icon-only] {\n padding: 0;\n }\n\n .v-badge[data-dot] {\n width: var(--vectis-control-size-badge-dot);\n height: var(--vectis-control-size-badge-dot);\n min-width: 0;\n padding: 0;\n }\n\n .v-badge[data-bordered] {\n box-shadow: 0 0 0 2px var(--vectis-color-surface);\n }\n\n /* The tuck-in offset is a ratio of the badge's own size, so it stays proportionate\n across the pill, the dot and the icon. Each half of it is held in its own\n variable: the corner and the reading direction each flip ONE axis, and writing\n the whole `translate` again in each branch would make the two multiply — four\n rules to keep in step by hand for two independent decisions. */\n .v-badge-host[data-overlay] > .v-badge {\n --badge-overlay-x: 25%;\n --badge-overlay-y: -25%;\n\n position: absolute;\n inset-block: 0 auto;\n inset-inline-end: 0;\n translate: var(--badge-overlay-x) var(--badge-overlay-y);\n }\n\n .v-badge-host[data-overlay][data-overlay-position='bottom'] > .v-badge {\n --badge-overlay-y: 25%;\n\n inset-block: auto 0;\n }\n\n /* In a right-to-left direction the logical corner moves to the left, so the\n horizontal half of the translation has to flip with it — `translate` is a\n physical property and knows nothing about direction. */\n .v-badge-host[data-overlay]:dir(rtl) > .v-badge {\n --badge-overlay-x: -25%;\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;EAuEA,IAAM,IAAQ,GAgBR,IAAQ,EAAS,GACjB,IAAY,QAAe,EAAM,YAAY,KAAA,CAAS,GAGtD,IAAe,QACnB,EAAM,UAAU,KAAA,KAAa,EAAM,QAAQ,KAAK,QAAQ,EAAM,KAChE,GAOM,IAAa,SAAgB;GACjC,aAAa,EAAM;GACnB,eAAe,EAAM,UAAU,KAAA,IAAiB,KAAA,IAAL;GAC3C,YAAY,EAAM,MAAM,KAAK,KAAA;GAC7B,kBAAkB,CAAC,EAAM,OAAO,EAAM,OAAO,KAAK,KAAA;GAClD,iBAAiB,EAAM,WAAW,KAAK,KAAA;GACvC,OAAO,EAAM,UAAU,KAAA,IAAgD,KAAA,IAApC,EAAE,kBAAkB,EAAM,MAAM;EACrE,EAAE;mBAKQ,EAAA,SAAA,EAAA,GADR,EAaO,QAAA;;GAXL,OAAM;GACL,gBAAc,EAAA,UAAO,KAAQ,KAAA;GAC7B,yBAAuB,EAAA;MAExB,EAAQ,EAAA,QAAA,SAAA,GACR,EAKO,QALP,EAKO,EALD,OAAM,UAAS,GAAS,EAAA,KAAU,GAAA,CACrB,EAAA,MAEiB,EAAA,IAAA,EAAA,KAFjB,EAAA,GAAjB,EAGW,GAAA,EAAA,KAAA,EAAA,GAAA,CAFI,EAAA,QAAA,EAAA,GAAb,EAA8C,GAAA,EAAA,EAAA,EAAA,KAAA,EAAA,GAAnB,EAAA,CAAA,CAAS,CAAC,EAAA,IAAI,CAAA,CAAA,GAAA,MAAA,EAAA,MAAA,EAAA,GACzC,EAA8C,GAAA,EAAA,KAAA,EAAA,GAAA,CAAA,EAAA,EAA1B,EAAA,KAAY,GAAA,CAAA,CAAA,GAAA,EAAA,EAAA,GAAA,EAAA,EAAA,GAAA,EAAA,CAAA,GAAA,GAAA,CAAA,MAAA,EAAA,GAItC,EAKO,QALP,EAKO;;GALM,OAAM;KAAkB,EAAA,KAAU,GAAA,CAC5B,EAAA,MAEiB,EAAA,IAAA,EAAA,KAFjB,EAAA,GAAjB,EAGW,GAAA,EAAA,KAAA,EAAA,GAAA,CAFI,EAAA,QAAA,EAAA,GAAb,EAA8C,GAAA,EAAA,EAAA,EAAA,KAAA,EAAA,GAAnB,EAAA,CAAA,CAAS,CAAC,EAAA,IAAI,CAAA,CAAA,GAAA,MAAA,EAAA,MAAA,EAAA,GACzC,EAA8C,GAAA,EAAA,KAAA,EAAA,GAAA,CAAA,EAAA,EAA1B,EAAA,KAAY,GAAA,CAAA,CAAA,GAAA,EAAA,EAAA,GAAA,EAAA,EAAA,GAAA,EAAA"}
1
+ {"version":3,"file":"VBadge.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VBadge/VBadge.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * A small pill carrying one piece of information at a glance: a count of unread\n * items, or a single icon. It is never interactive — there is nothing to click and\n * nothing to focus — and it either stands on its own, sits next to an element, or\n * is pinned to one of that element's corners.\n *\n * It is made of HTML and CSS alone. The only JavaScript decides what to render:\n * whether a target element was given at all, capping the counter at \"99+\", and\n * handing the two colours a consumer may choose to the stylesheet as\n * `--custom-color` and `--badge-ring-color`.\n */\nimport { computed, h } from 'vue'\nimport type { FunctionalComponent } from 'vue'\n\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport type { IconSource } from '../VIcon/types'\n\nimport { customColorStyle } from '../../utils/css'\n\nexport type BadgeVariant = 'solid' | 'soft'\nexport type BadgeTone = 'neutral' | 'accent' | 'danger' | 'success' | 'warning'\nexport type BadgeOverlayPosition = 'top' | 'bottom'\n\ninterface BadgeProps {\n /**\n * How strongly the badge is painted: filled with the full colour (`solid`, the\n * default), or a tinted background with the text in the colour (`soft`), for a\n * count that should not draw the eye. A `dot` is always solid: with no content to\n * tint, a soft dot would be a pale disc barely distinguishable from the page.\n */\n variant?: BadgeVariant\n /**\n * The meaning the badge carries, expressed as a colour. A solid badge is filled\n * with it and its text adapts to stay readable; a soft one is tinted with it and\n * writes its text in it.\n */\n tone?: BadgeTone\n /**\n * A colour of your own (hex, CSS name or `oklch()`), which replaces the tone. On a\n * solid badge, browsers that support `contrast-color()` turn the text black or\n * white by themselves; everywhere else it falls back to white, so with a light\n * colour the contrast is yours to check. A soft badge derives its background and\n * text from that colour mixed with the theme's surface and text.\n */\n color?: string\n /**\n * The number to display. Anything above 99 is shown as \"99+\", so that a busy\n * counter cannot stretch the pill indefinitely.\n */\n count?: number\n /**\n * A single icon shown instead of a number: an icon name, or an explicit render\n * (the VIcon contract). It takes precedence over `count`, and is ignored when the\n * badge is a `dot`.\n */\n icon?: IconSource\n /**\n * Reduces the badge to a 10px dot with no content — the discreet way to signal\n * that something is new without saying how much.\n */\n dot?: boolean\n /**\n * Pins the badge to a corner of the target element instead of placing it beside\n * it. It does nothing when the badge has no target.\n */\n overlay?: boolean\n /**\n * Which corner an `overlay` badge is pinned to: the top one by default, the\n * bottom one for a marker that belongs at the foot of its target — a presence dot\n * under an avatar, for instance. The horizontal side follows the reading\n * direction and is not configurable. It does nothing without `overlay`.\n */\n overlayPosition?: BadgeOverlayPosition\n /**\n * Draws a 2px ring around the badge, in the colour of the surface behind it,\n * which detaches it from a busy target such as a picture. That colour defaults to\n * the page background and is named through `ringColor` on any other surface.\n */\n bordered?: boolean\n /**\n * The colour of the ring drawn by `bordered`. It defaults to the page background,\n * which is what makes the ring read as a gap around the badge; on another surface\n * (a card, a coloured banner), pass that surface's colour. It does nothing without\n * `bordered`.\n */\n ringColor?: string\n}\n\nconst props = withDefaults(defineProps<BadgeProps>(), {\n variant: 'solid',\n tone: 'accent',\n color: undefined,\n count: undefined,\n icon: undefined,\n overlayPosition: 'top',\n ringColor: undefined,\n // Written out although Vue casts an absent boolean to `false` on its own: left out,\n // `vue-component-meta` reports no default at all and the docs table's cell goes blank.\n dot: false,\n overlay: false,\n bordered: false,\n})\n\nconst slots = defineSlots<{\n /**\n * The element the badge belongs to. Without it the badge stands on its own; with\n * it, the badge is placed beside the element, or in its corner under `overlay`.\n */\n default?(): unknown\n}>()\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.\nfunction hasTarget() {\n return slots.default !== undefined\n}\n\n/** The counter as it is actually displayed: anything past 99 becomes \"99+\". */\nconst displayCount = computed(() =>\n props.count !== undefined && props.count > 99 ? '99+' : props.count,\n)\n\n/*\n * The pill itself, written once. The template has two roots — one wrapping a target, one\n * standing alone — and both render the same badge; a functional component is the one way\n * to put the same markup in two places of a template without writing it twice.\n */\nconst Pill: FunctionalComponent = () =>\n h(\n 'span',\n {\n class: 'v-badge v-tone',\n 'data-variant': props.variant,\n 'data-tone': props.tone,\n 'data-custom': props.color !== undefined ? '' : undefined,\n 'data-dot': props.dot ? '' : undefined,\n 'data-icon-only': !props.dot && props.icon ? '' : undefined,\n 'data-bordered': props.bordered ? '' : undefined,\n style: [\n customColorStyle(props.color),\n props.ringColor !== undefined ? { '--badge-ring-color': props.ringColor } : undefined,\n ],\n },\n props.dot\n ? undefined\n : props.icon\n ? [h(VIcon, iconProps(props.icon))]\n : displayCount.value === undefined\n ? undefined\n : String(displayCount.value),\n )\n// TRAP — the empty list is not decoration. A functional component that declares no props lets\n// only `class`, `style` and listeners fall through, so a standalone badge, whose root this is,\n// would silently drop every other attribute a consumer set on VBadge (an `id`, a `data-*`).\nPill.props = []\n</script>\n\n<template>\n <span\n v-if=\"hasTarget()\"\n class=\"v-badge-host\"\n :data-overlay=\"overlay ? '' : undefined\"\n :data-overlay-position=\"overlayPosition\"\n >\n <slot />\n <Pill />\n </span>\n <Pill v-else />\n</template>\n\n<style>\n@layer vectis.components {\n .v-badge-host {\n position: relative;\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-2); /* the space between the target and the badge, in inline mode */\n }\n\n .v-badge {\n --vectis-icon-size: var(--vectis-icon-size-sm);\n --vectis-icon-opsz: 20;\n /* The colour of the `bordered` ring: a bet on the page background, the only one a\n component can make since CSS cannot read what its parent paints. The `ringColor`\n prop overrides it inline for a badge sitting on anything else. */\n --badge-ring-color: var(--vectis-color-surface);\n /* The pill is the tone's solid pair, read from the shared table (`.v-tone`, set in the\n template). Its neutral is the text/surface inversion, which is what lets the\n fallback text and contrast-color() agree in both themes. */\n --badge-bg: var(--tone-bg-solid);\n --badge-text-fallback: var(--tone-text-solid);\n\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: var(--vectis-control-size-badge-h);\n /* A minimum width equal to the height, with a small padding on top, is what\n makes a one- or two-digit counter come out round rather than oval. */\n min-width: var(--vectis-control-size-badge-h);\n padding-inline: var(--vectis-space-1);\n border-radius: var(--vectis-radius-pill);\n background: var(--badge-bg);\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-caption-size);\n font-weight: var(--vectis-text-control-weight);\n line-height: var(--vectis-text-control-leading);\n color: var(--badge-text-fallback);\n }\n\n @supports (color: contrast-color(red)) {\n .v-badge {\n color: contrast-color(var(--badge-bg));\n }\n }\n\n /* A custom colour replaces the tone: at (0,2,0) it beats the base rule's mapping\n whatever the order the two are written in. */\n .v-badge[data-custom] {\n --badge-bg: var(--custom-color);\n --badge-text-fallback: var(--vectis-color-text-on-accent);\n }\n\n /* The soft pair of the same table. The text is the tone's own colour rather than\n contrast-color(): the black or white that function picks reads on a pale tint, but\n says nothing of the tone. At (0,3,0) it beats the `@supports` rule above whatever\n the order. A dot is left out: with no content, a soft dot is a pale disc on the\n page, which a presence marker cannot afford. */\n .v-badge[data-variant='soft']:not([data-dot]) {\n --badge-bg: var(--tone-bg-soft);\n\n color: var(--tone-text-tinted);\n }\n\n /* A custom colour's soft pair, derived as VChip derives its own, so the same value\n gives a soft chip and a soft badge the same tint in both themes. */\n .v-badge[data-variant='soft'][data-custom]:not([data-dot]) {\n --badge-bg: color-mix(in oklab, var(--custom-color), var(--vectis-color-surface) 85%);\n\n color: color-mix(in oklab, var(--custom-color), var(--vectis-color-text) 30%);\n }\n\n .v-badge[data-icon-only] {\n padding: 0;\n }\n\n .v-badge[data-dot] {\n width: var(--vectis-control-size-badge-dot);\n height: var(--vectis-control-size-badge-dot);\n min-width: 0;\n padding: 0;\n }\n\n .v-badge[data-bordered] {\n box-shadow: 0 0 0 var(--vectis-control-size-badge-ring) var(--badge-ring-color);\n }\n\n /* The tuck-in offset is a ratio of the badge's own size, so it stays proportionate\n across the pill, the dot and the icon. Each half of it is held in its own\n variable: the corner and the reading direction each flip ONE axis, and writing\n the whole `translate` again in each branch would make the two multiply — four\n rules to keep in step by hand for two independent decisions. */\n .v-badge-host[data-overlay] > .v-badge {\n --badge-overlay-x: 25%;\n --badge-overlay-y: -25%;\n\n position: absolute;\n inset-block: 0 auto;\n inset-inline-end: 0;\n translate: var(--badge-overlay-x) var(--badge-overlay-y);\n /* TRAP — an overlaid badge deliberately leaves its target's box, so it lands on\n whatever sits beside it, and the host opens no stacking context of its own\n (`position: relative` with `z-index: auto`). Left at `auto` the badge is painted\n with the other positioned boxes in TREE ORDER, which means anything positioned\n after it covers it: inside a VButtonGroup, where every segment is positioned, the\n badge on one segment disappears under the borders of the next. The lift takes it\n past that step, and no further: the segment it leans into comes later in tree\n order, so that segment's focus ring, raised to this same level, is still drawn\n over the badge rather than under it. */\n z-index: 1;\n }\n\n .v-badge-host[data-overlay][data-overlay-position='bottom'] > .v-badge {\n --badge-overlay-y: 25%;\n\n inset-block: auto 0;\n }\n\n /* In a right-to-left direction the logical corner moves to the left, so the\n horizontal half of the translation has to flip with it — `translate` is a\n physical property and knows nothing about direction. */\n .v-badge-host[data-overlay]:dir(rtl) > .v-badge {\n --badge-overlay-x: -25%;\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2FA,IAAM,IAAQ,GAeR,IAAQ,EAAA;EAUd,SAAS,IAAY;GACnB,OAAO,EAAM,YAAY,KAAA;EAC3B;EAGA,IAAM,IAAe,QACnB,EAAM,UAAU,KAAA,KAAa,EAAM,QAAQ,KAAK,QAAQ,EAAM,KAChE,GAOM,UACJ,EACE,QACA;GACE,OAAO;GACP,gBAAgB,EAAM;GACtB,aAAa,EAAM;GACnB,eAAe,EAAM,UAAU,KAAA,IAAiB,KAAA,IAAL;GAC3C,YAAY,EAAM,MAAM,KAAK,KAAA;GAC7B,kBAAkB,CAAC,EAAM,OAAO,EAAM,OAAO,KAAK,KAAA;GAClD,iBAAiB,EAAM,WAAW,KAAK,KAAA;GACvC,OAAO,CACL,EAAiB,EAAM,KAAK,GAC5B,EAAM,cAAc,KAAA,IAAwD,KAAA,IAA5C,EAAE,sBAAsB,EAAM,UAAU,CAC1E;EACF,GACA,EAAM,MACF,KAAA,IACA,EAAM,OACJ,CAAC,EAAE,GAAO,EAAU,EAAM,IAAI,CAAC,CAAC,IAChC,EAAa,UAAU,KAAA,IACrB,KAAA,IACA,OAAO,EAAa,KAAK,CACnC;SAIF,EAAK,QAAQ,CAAC,aAKJ,EAAS,KAAA,EAAA,GADjB,EAQO,QAAA;;GANL,OAAM;GACL,gBAAc,EAAA,UAAO,KAAQ,KAAA;GAC7B,yBAAuB,EAAA;MAExB,EAAQ,EAAA,QAAA,SAAA,GACR,EAAQ,CAAA,CAAA,GAAA,GAAA,CAAA,MAAA,EAAA,GAEV,EAAe,GAAA,EAAA,KAAA,EAAA,CAAA"}
@@ -1,2 +1,2 @@
1
1
  @layer vectis.reset, vectis.tokens, vectis.components, vectis.utilities;
2
- @layer vectis.components{.v-breadcrumb{--vectis-icon-size:var(--vectis-icon-size-sm);--vectis-icon-opsz:20}.v-breadcrumb-list{align-items:center;gap:var(--vectis-space-2);font-family:var(--vectis-text-family);font-size:var(--vectis-text-body-md-size);flex-wrap:wrap;margin:0;padding:0;list-style:none;display:flex}.v-breadcrumb-item{align-items:center;gap:var(--vectis-space-2);color:var(--vectis-color-text-muted);display:inline-flex}.v-breadcrumb-list>.v-breadcrumb-item:first-child>.v-breadcrumb-separator{display:none}.v-breadcrumb-separator{color:var(--vectis-color-text-subtle)}.v-breadcrumb-link{align-items:center;gap:var(--vectis-space-1);color:var(--vectis-color-text-muted);border-radius:var(--vectis-radius-xs);transition:color var(--vectis-duration-fast) var(--vectis-ease-default);text-decoration:none;display:inline-flex}.v-breadcrumb-link:hover{color:var(--vectis-color-text);text-decoration:underline}.v-breadcrumb-link:focus-visible{outline:var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);outline-offset:var(--vectis-focus-ring-offset)}.v-breadcrumb-link[aria-current=page]{color:var(--vectis-color-text);font-weight:var(--vectis-text-label-weight)}@media (prefers-reduced-motion:reduce){.v-breadcrumb-link{transition:none}}}
2
+ @layer vectis.components{.v-breadcrumb{--vectis-icon-size:var(--vectis-icon-size-sm);--vectis-icon-opsz:20}.v-breadcrumb-list{align-items:center;gap:var(--vectis-space-2);font-family:var(--vectis-text-family);font-size:var(--vectis-text-body-md-size);flex-wrap:wrap;margin:0;padding:0;list-style:none;display:flex}.v-breadcrumb-item{align-items:center;gap:var(--vectis-space-2);color:var(--vectis-color-text-muted);display:inline-flex}.v-breadcrumb-list>.v-breadcrumb-item:first-child>.v-breadcrumb-separator{display:none}.v-breadcrumb-separator{color:var(--vectis-color-text-subtle)}.v-breadcrumb-link{align-items:center;gap:var(--vectis-space-1);color:var(--vectis-color-text-muted);border-radius:min(var(--vectis-radius-interactive), .5lh);transition:color var(--vectis-duration-fast) var(--vectis-ease-default);text-decoration:none;display:inline-flex}.v-breadcrumb-link:hover{color:var(--vectis-color-text);text-decoration:underline}.v-breadcrumb-link:focus-visible{outline:var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);outline-offset:var(--vectis-focus-ring-offset)}.v-breadcrumb-link[aria-current=page]{color:var(--vectis-color-text);font-weight:var(--vectis-text-label-weight)}@media (prefers-reduced-motion:reduce){.v-breadcrumb-link{transition:none}}}
@@ -1,17 +1,4 @@
1
1
  import { IconSource } from '../VIcon/types.js';
2
- /**
3
- * A breadcrumb trail: the path that leads to the page being read, from the most
4
- * general section down to the current one. It is a `<nav>` holding an ordered list,
5
- * built entirely from the `items` prop — nothing is read from the browser, so the
6
- * server and the client render exactly the same thing.
7
- *
8
- * The separators between the segments are decorative icons, hidden from screen
9
- * readers, and the very first one is removed in CSS rather than by a condition in
10
- * the markup. The current page is found by comparing each segment's address with
11
- * `currentPath`: it is marked with `aria-current="page"` and stays a working link,
12
- * as the ARIA authoring practices recommend. When the trail grows past `maxItems`,
13
- * the middle segments are folded into a menu opened by an "…" button.
14
- */
15
2
  export interface BreadcrumbItem {
16
3
  /** The text shown for this segment. */
17
4
  label: string;
@@ -24,7 +11,7 @@ export interface BreadcrumbItem {
24
11
  * An icon placed before the label: a Material Symbols Rounded name, an icon URL,
25
12
  * or an explicit render (`{ src: '/logo.svg' }`, `{ component }`…).
26
13
  */
27
- iconStart?: IconSource;
14
+ icon?: IconSource;
28
15
  }
29
16
  interface BreadcrumbProps {
30
17
  /** The segments of the trail, ordered from the most general down to the deepest. */
@@ -41,9 +28,9 @@ interface BreadcrumbProps {
41
28
  currentPath?: string;
42
29
  /**
43
30
  * The icon drawn between two segments: an icon name, or an explicit render,
44
- * exactly like `iconStart`.
31
+ * exactly like an item's `icon`.
45
32
  */
46
- separator?: IconSource;
33
+ separatorIcon?: IconSource;
47
34
  /**
48
35
  * The length past which the trail folds: only the first segment, an "…" button and
49
36
  * the last two remain, the button opening a menu that lists the hidden segments
@@ -59,8 +46,8 @@ interface BreadcrumbProps {
59
46
  }
60
47
  declare const __VLS_export: import('vue').DefineComponent<BreadcrumbProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<BreadcrumbProps> & Readonly<{}>, {
61
48
  label: string;
62
- separator: IconSource;
63
49
  currentPath: string;
50
+ separatorIcon: IconSource;
64
51
  maxItems: number;
65
52
  ellipsisLabel: string;
66
53
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
@@ -1 +1 @@
1
- {"version":3,"file":"VBreadcrumb.js","names":[],"sources":["../../../src/components/VBreadcrumb/VBreadcrumb.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport { chevron_right as chevronRightIcon } from '../VIcon/icons/chevron_right'\nimport { more_horiz as moreHorizIcon } from '../VIcon/icons/more_horiz'\nimport type { IconSource } from '../VIcon/types'\nimport VIconButton from '../VIconButton/VIconButton.vue'\nimport VMenu from '../VMenu/VMenu.vue'\nimport VMenuItem from '../VMenu/VMenuItem.vue'\n\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useMessages } from '../../i18n/state'\n\n// @ssr @core\n/**\n * A breadcrumb trail: the path that leads to the page being read, from the most\n * general section down to the current one. It is a `<nav>` holding an ordered list,\n * built entirely from the `items` prop — nothing is read from the browser, so the\n * server and the client render exactly the same thing.\n *\n * The separators between the segments are decorative icons, hidden from screen\n * readers, and the very first one is removed in CSS rather than by a condition in\n * the markup. The current page is found by comparing each segment's address with\n * `currentPath`: it is marked with `aria-current=\"page\"` and stays a working link,\n * as the ARIA authoring practices recommend. When the trail grows past `maxItems`,\n * the middle segments are folded into a menu opened by an \"…\" button.\n */\nexport interface BreadcrumbItem {\n /** The text shown for this segment. */\n label: string\n /**\n * Where the segment leads. It is also the value compared with `currentPath` to\n * decide which segment is the current page.\n */\n href: string\n /**\n * An icon placed before the label: a Material Symbols Rounded name, an icon URL,\n * or an explicit render (`{ src: '/logo.svg' }`, `{ component }`…).\n */\n iconStart?: IconSource\n}\n\ninterface BreadcrumbProps {\n /** The segments of the trail, ordered from the most general down to the deepest. */\n items: BreadcrumbItem[]\n /**\n * The name screen readers announce for this navigation. It falls back to the\n * wording of the DS dictionary, in the current language.\n */\n label?: string\n /**\n * The address of the page being displayed. The segment whose `href` matches it is\n * the current one; a trailing slash on either side makes no difference.\n */\n currentPath?: string\n /**\n * The icon drawn between two segments: an icon name, or an explicit render,\n * exactly like `iconStart`.\n */\n separator?: IconSource\n /**\n * The length past which the trail folds: only the first segment, an \"…\" button and\n * the last two remain, the button opening a menu that lists the hidden segments\n * alone. Below 3 there would be nothing left to fold, so 3 is the effective\n * minimum.\n */\n maxItems?: number\n /**\n * The name screen readers announce for the \"…\" button. It falls back to the\n * wording of the DS dictionary.\n */\n ellipsisLabel?: string\n}\n\nconst props = withDefaults(defineProps<BreadcrumbProps>(), {\n label: undefined,\n currentPath: undefined,\n separator: () => chevronRightIcon,\n maxItems: undefined,\n ellipsisLabel: undefined,\n})\n\nconst m = useMessages()\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.breadcrumb.label)\nconst resolvedEllipsisLabel = computed(() => props.ellipsisLabel ?? m.value.breadcrumb.ellipsis)\n\n/**\n * Drops a trailing slash so that `/docs` and `/docs/` compare as the same page; the\n * root `/` is left alone. Pure string handling, hence safe to run on the server.\n */\nfunction normalize(path: string): string {\n return path.length > 1 && path.endsWith('/') ? path.slice(0, -1) : path\n}\n\n// @a11y — this is what feeds `aria-current=\"page\"`, the only marker telling\n// assistive technology where the trail ends.\nfunction isCurrent(item: BreadcrumbItem): boolean {\n if (props.currentPath === undefined) return false\n return normalize(item.href) === normalize(props.currentPath)\n}\n\nconst truncated = computed(\n () => props.maxItems !== undefined && props.items.length > Math.max(props.maxItems, 3),\n)\n/** The segments folded into the menu: everything between the first and the last two. */\nconst hiddenItems = computed(() => (truncated.value ? props.items.slice(1, -2) : []))\n/**\n * The segments actually rendered in the list — when the trail is folded, the first\n * one followed by the last two.\n */\nconst visibleItems = computed(() =>\n truncated.value ? [props.items[0] as BreadcrumbItem, ...props.items.slice(-2)] : props.items,\n)\n</script>\n\n<template>\n <nav class=\"v-breadcrumb\" :aria-label=\"ariaLabel\">\n <ol class=\"v-breadcrumb-list\">\n <template v-for=\"(item, index) in visibleItems\" :key=\"item.href\">\n <li v-if=\"truncated && index === 1\" class=\"v-breadcrumb-item v-breadcrumb-ellipsis\">\n <VIcon class=\"v-breadcrumb-separator\" v-bind=\"iconProps(separator)\" />\n <VMenu compact>\n <template #trigger=\"{ triggerProps }\">\n <VIconButton size=\"sm\" compact :label=\"resolvedEllipsisLabel\" v-bind=\"triggerProps\">\n <VIcon :name=\"moreHorizIcon\" />\n </VIconButton>\n </template>\n <VMenuItem\n v-for=\"hidden in hiddenItems\"\n :key=\"hidden.href\"\n :href=\"hidden.href\"\n :label=\"hidden.label\"\n :icon-start=\"hidden.iconStart\"\n />\n </VMenu>\n </li>\n <li class=\"v-breadcrumb-item\">\n <VIcon class=\"v-breadcrumb-separator\" v-bind=\"iconProps(separator)\" />\n <a\n class=\"v-breadcrumb-link\"\n :href=\"item.href\"\n :aria-current=\"isCurrent(item) ? 'page' : undefined\"\n >\n <VIcon v-if=\"item.iconStart\" v-bind=\"iconProps(item.iconStart)\" />\n {{ item.label }}\n </a>\n </li>\n </template>\n </ol>\n </nav>\n</template>\n\n<style>\n@layer vectis.components {\n .v-breadcrumb {\n --vectis-icon-size: var(--vectis-icon-size-sm);\n --vectis-icon-opsz: 20;\n }\n\n .v-breadcrumb-list {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--vectis-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-body-md-size);\n }\n\n .v-breadcrumb-item {\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-2);\n color: var(--vectis-color-text-muted);\n }\n\n .v-breadcrumb-list > .v-breadcrumb-item:first-child > .v-breadcrumb-separator {\n display: none;\n }\n\n .v-breadcrumb-separator {\n color: var(--vectis-color-text-subtle);\n }\n\n .v-breadcrumb-link {\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-1);\n color: var(--vectis-color-text-muted);\n text-decoration: none;\n border-radius: var(--vectis-radius-xs);\n transition: color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-breadcrumb-link:hover {\n color: var(--vectis-color-text);\n text-decoration: underline;\n }\n\n .v-breadcrumb-link:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n }\n\n .v-breadcrumb-link[aria-current='page'] {\n color: var(--vectis-color-text);\n font-weight: var(--vectis-text-label-weight);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-breadcrumb-link {\n transition: none;\n }\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"VBreadcrumb.js","names":[],"sources":["../../../src/components/VBreadcrumb/VBreadcrumb.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @ssr @core\n/**\n * The path leading to the page being read, from the broadest section down to the current\n * one: a `<nav>` holding an `<ol>`, built entirely from the `items` prop. Nothing is read\n * from the browser, so the server and the client render the same thing.\n *\n * The separators are decorative `aria-hidden` icons, and the first is removed in CSS rather\n * than by a condition in the markup. The current page is found by comparing each address\n * with `currentPath`, carries `aria-current=\"page\"` and stays a working link, as the ARIA\n * practices recommend. Past `maxItems`, the middle segments fold into a VMenu behind an \"…\".\n */\n\nimport { computed } from 'vue'\n\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport { chevron_right as chevronRightIcon } from '../VIcon/icons/chevron_right'\nimport { more_horiz as moreHorizIcon } from '../VIcon/icons/more_horiz'\nimport type { IconSource } from '../VIcon/types'\nimport VIconButton from '../VIconButton/VIconButton.vue'\nimport VMenu from '../VMenu/VMenu.vue'\nimport VMenuItem from '../VMenu/VMenuItem.vue'\n\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useMessages } from '../../i18n/state'\n\nexport interface BreadcrumbItem {\n /** The text shown for this segment. */\n label: string\n /**\n * Where the segment leads. It is also the value compared with `currentPath` to\n * decide which segment is the current page.\n */\n href: string\n /**\n * An icon placed before the label: a Material Symbols Rounded name, an icon URL,\n * or an explicit render (`{ src: '/logo.svg' }`, `{ component }`…).\n */\n icon?: IconSource\n}\n\ninterface BreadcrumbProps {\n /** The segments of the trail, ordered from the most general down to the deepest. */\n items: BreadcrumbItem[]\n /**\n * The name screen readers announce for this navigation. It falls back to the\n * wording of the DS dictionary, in the current language.\n */\n label?: string\n /**\n * The address of the page being displayed. The segment whose `href` matches it is\n * the current one; a trailing slash on either side makes no difference.\n */\n currentPath?: string\n /**\n * The icon drawn between two segments: an icon name, or an explicit render,\n * exactly like an item's `icon`.\n */\n separatorIcon?: IconSource\n /**\n * The length past which the trail folds: only the first segment, an \"…\" button and\n * the last two remain, the button opening a menu that lists the hidden segments\n * alone. Below 3 there would be nothing left to fold, so 3 is the effective\n * minimum.\n */\n maxItems?: number\n /**\n * The name screen readers announce for the \"…\" button. It falls back to the\n * wording of the DS dictionary.\n */\n ellipsisLabel?: string\n}\n\nconst props = withDefaults(defineProps<BreadcrumbProps>(), {\n label: undefined,\n currentPath: undefined,\n separatorIcon: () => chevronRightIcon,\n maxItems: undefined,\n ellipsisLabel: undefined,\n})\n\nconst m = useMessages()\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.breadcrumb.label)\nconst resolvedEllipsisLabel = computed(() => props.ellipsisLabel ?? m.value.breadcrumb.ellipsis)\n\n/**\n * Drops a trailing slash so that `/docs` and `/docs/` compare as the same page; the\n * root `/` is left alone. Pure string handling, hence safe to run on the server.\n */\nfunction normalize(path: string): string {\n return path.length > 1 && path.endsWith('/') ? path.slice(0, -1) : path\n}\n\n// Normalized once per change of the prop rather than once per segment on every render.\nconst normalizedCurrent = computed(() =>\n props.currentPath === undefined ? undefined : normalize(props.currentPath),\n)\n\n// @a11y — this is what feeds `aria-current=\"page\"`, the only marker telling\n// assistive technology where the trail ends.\nfunction isCurrent(item: BreadcrumbItem): boolean {\n return normalizedCurrent.value !== undefined && normalize(item.href) === normalizedCurrent.value\n}\n\nconst truncated = computed(\n () => props.maxItems !== undefined && props.items.length > Math.max(props.maxItems, 3),\n)\n/** The segments folded into the menu: everything between the first and the last two. */\nconst hiddenItems = computed(() => (truncated.value ? props.items.slice(1, -2) : []))\n/**\n * The segments actually rendered in the list — when the trail is folded, the first\n * one followed by the last two.\n */\nconst visibleItems = computed(() =>\n truncated.value ? [props.items[0] as BreadcrumbItem, ...props.items.slice(-2)] : props.items,\n)\n</script>\n\n<template>\n <nav class=\"v-breadcrumb\" :aria-label=\"ariaLabel\">\n <ol class=\"v-breadcrumb-list\">\n <template v-for=\"(item, index) in visibleItems\" :key=\"item.href\">\n <li v-if=\"truncated && index === 1\" class=\"v-breadcrumb-item v-breadcrumb-ellipsis\">\n <VIcon class=\"v-breadcrumb-separator\" v-bind=\"iconProps(separatorIcon)\" mirrored />\n <VMenu>\n <template #trigger=\"{ triggerProps }\">\n <VIconButton\n size=\"sm\"\n :label=\"resolvedEllipsisLabel\"\n :icon=\"moreHorizIcon\"\n v-bind=\"triggerProps\"\n />\n </template>\n <VMenuItem\n v-for=\"hidden in hiddenItems\"\n :key=\"hidden.href\"\n :href=\"hidden.href\"\n :label=\"hidden.label\"\n :icon-start=\"hidden.icon\"\n />\n </VMenu>\n </li>\n <li class=\"v-breadcrumb-item\">\n <VIcon class=\"v-breadcrumb-separator\" v-bind=\"iconProps(separatorIcon)\" mirrored />\n <a\n class=\"v-breadcrumb-link\"\n :href=\"item.href\"\n :aria-current=\"isCurrent(item) ? 'page' : undefined\"\n >\n <VIcon v-if=\"item.icon\" v-bind=\"iconProps(item.icon)\" />\n {{ item.label }}\n </a>\n </li>\n </template>\n </ol>\n </nav>\n</template>\n\n<style>\n@layer vectis.components {\n /* The icon context is set here rather than through `.v-control`, which is the usual\n route: a trail has no `size` prop and no height to speak of, so the size scale would\n bring a table of five steps to pick one value from. */\n .v-breadcrumb {\n --vectis-icon-size: var(--vectis-icon-size-sm);\n --vectis-icon-opsz: 20;\n }\n\n .v-breadcrumb-list {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--vectis-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-body-md-size);\n }\n\n .v-breadcrumb-item {\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-2);\n color: var(--vectis-color-text-muted);\n }\n\n /* TRAP — every item renders its own leading separator and the first one is hidden HERE,\n which is what keeps the template free of an index test. Delete this rule and the trail\n opens on a stray chevron; both child combinators are load-bearing too, so wrapping an\n item or the list in anything puts that chevron straight back. */\n .v-breadcrumb-list > .v-breadcrumb-item:first-child > .v-breadcrumb-separator {\n display: none;\n }\n\n .v-breadcrumb-separator {\n color: var(--vectis-color-text-subtle);\n }\n\n /* The corner is only ever seen on the focus ring, which follows it. It is the control\n radius capped at half a line, the row recipe of VSideNavigationItem with the line\n standing in for a control height the link does not have: a label that wraps keeps\n the corner of a one-line one under a pill override. */\n .v-breadcrumb-link {\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-1);\n color: var(--vectis-color-text-muted);\n text-decoration: none;\n border-radius: min(var(--vectis-radius-interactive), 0.5lh);\n transition: color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-breadcrumb-link:hover {\n color: var(--vectis-color-text);\n text-decoration: underline;\n }\n\n .v-breadcrumb-link:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n }\n\n .v-breadcrumb-link[aria-current='page'] {\n color: var(--vectis-color-text);\n font-weight: var(--vectis-text-label-weight);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-breadcrumb-link {\n transition: none;\n }\n }\n}\n</style>\n"],"mappings":""}
@@ -1,10 +1,10 @@
1
1
  import { useMessages as e } from "../../i18n/state.js";
2
- import t from "../VIcon/VIcon.js";
3
- import { iconProps as n } from "../VIcon/iconProps.js";
2
+ import { iconProps as t } from "../VIcon/iconProps.js";
3
+ import n from "../VIcon/VIcon.js";
4
4
  import r from "../VIconButton/VIconButton.js";
5
- import { chevron_right as i } from "../VIcon/icons/chevron_right.js";
6
- import { more_horiz as a } from "../VIcon/icons/more_horiz.js";
7
- import { useAriaLabel as o } from "../../composables/useAriaLabel.js";
5
+ import { useAriaLabel as i } from "../../composables/useAriaLabel.js";
6
+ import { chevron_right as a } from "../VIcon/icons/chevron_right.js";
7
+ import { more_horiz as o } from "../VIcon/icons/more_horiz.js";
8
8
  import s from "../VMenu/VMenu.js";
9
9
  import c from "../VMenu/VMenuItem.js";
10
10
  import { Fragment as l, computed as u, createBlock as d, createCommentVNode as f, createElementBlock as p, createElementVNode as m, createTextVNode as h, createVNode as g, defineComponent as _, mergeProps as v, openBlock as y, renderList as b, toDisplayString as x, unref as S, withCtx as C } from "vue";
@@ -18,50 +18,48 @@ var w = ["aria-label"], T = { class: "v-breadcrumb-list" }, E = {
18
18
  items: {},
19
19
  label: { default: void 0 },
20
20
  currentPath: { default: void 0 },
21
- separator: { default: () => i },
21
+ separatorIcon: { default: () => a },
22
22
  maxItems: { default: void 0 },
23
23
  ellipsisLabel: { default: void 0 }
24
24
  },
25
- setup(i) {
26
- let _ = i, k = e(), A = o(() => _.label ?? k.value.breadcrumb.label), j = u(() => _.ellipsisLabel ?? k.value.breadcrumb.ellipsis);
25
+ setup(a) {
26
+ let _ = a, k = e(), A = i(() => _.label ?? k.value.breadcrumb.label), j = u(() => _.ellipsisLabel ?? k.value.breadcrumb.ellipsis);
27
27
  function M(e) {
28
28
  return e.length > 1 && e.endsWith("/") ? e.slice(0, -1) : e;
29
29
  }
30
- function N(e) {
31
- return _.currentPath !== void 0 && M(e.href) === M(_.currentPath);
30
+ let N = u(() => _.currentPath === void 0 ? void 0 : M(_.currentPath));
31
+ function P(e) {
32
+ return N.value !== void 0 && M(e.href) === N.value;
32
33
  }
33
- let P = u(() => _.maxItems !== void 0 && _.items.length > Math.max(_.maxItems, 3)), F = u(() => P.value ? _.items.slice(1, -2) : []), I = u(() => P.value ? [_.items[0], ..._.items.slice(-2)] : _.items);
34
- return (e, o) => (y(), p("nav", {
34
+ let F = u(() => _.maxItems !== void 0 && _.items.length > Math.max(_.maxItems, 3)), I = u(() => F.value ? _.items.slice(1, -2) : []), L = u(() => F.value ? [_.items[0], ..._.items.slice(-2)] : _.items);
35
+ return (e, i) => (y(), p("nav", {
35
36
  class: "v-breadcrumb",
36
37
  "aria-label": S(A)
37
- }, [m("ol", T, [(y(!0), p(l, null, b(I.value, (e, o) => (y(), p(l, { key: e.href }, [P.value && o === 1 ? (y(), p("li", E, [g(t, v({ class: "v-breadcrumb-separator" }, { ref_for: !0 }, S(n)(i.separator)), null, 16), g(s, { compact: "" }, {
38
+ }, [m("ol", T, [(y(!0), p(l, null, b(L.value, (e, i) => (y(), p(l, { key: e.href }, [F.value && i === 1 ? (y(), p("li", E, [g(n, v({ class: "v-breadcrumb-separator" }, { ref_for: !0 }, S(t)(a.separatorIcon), { mirrored: "" }), null, 16), g(s, null, {
38
39
  trigger: C(({ triggerProps: e }) => [g(r, v({
39
40
  size: "sm",
40
- compact: "",
41
- label: j.value
42
- }, { ref_for: !0 }, e), {
43
- default: C(() => [g(t, { name: S(a) }, null, 8, ["name"])]),
44
- _: 1
45
- }, 16, ["label"])]),
46
- default: C(() => [(y(!0), p(l, null, b(F.value, (e) => (y(), d(c, {
41
+ label: j.value,
42
+ icon: S(o)
43
+ }, { ref_for: !0 }, e), null, 16, ["label", "icon"])]),
44
+ default: C(() => [(y(!0), p(l, null, b(I.value, (e) => (y(), d(c, {
47
45
  key: e.href,
48
46
  href: e.href,
49
47
  label: e.label,
50
- "icon-start": e.iconStart
48
+ "icon-start": e.icon
51
49
  }, null, 8, [
52
50
  "href",
53
51
  "label",
54
52
  "icon-start"
55
53
  ]))), 128))]),
56
54
  _: 1
57
- })])) : f("", !0), m("li", D, [g(t, v({ class: "v-breadcrumb-separator" }, { ref_for: !0 }, S(n)(i.separator)), null, 16), m("a", {
55
+ })])) : f("", !0), m("li", D, [g(n, v({ class: "v-breadcrumb-separator" }, { ref_for: !0 }, S(t)(a.separatorIcon), { mirrored: "" }), null, 16), m("a", {
58
56
  class: "v-breadcrumb-link",
59
57
  href: e.href,
60
- "aria-current": N(e) ? "page" : void 0
61
- }, [e.iconStart ? (y(), d(t, v({
58
+ "aria-current": P(e) ? "page" : void 0
59
+ }, [e.icon ? (y(), d(n, v({
62
60
  key: 0,
63
61
  ref_for: !0
64
- }, S(n)(e.iconStart)), null, 16)) : f("", !0), h(" " + x(e.label), 1)], 8, O)])], 64))), 128))])], 8, w));
62
+ }, S(t)(e.icon)), null, 16)) : f("", !0), h(" " + x(e.label), 1)], 8, O)])], 64))), 128))])], 8, w));
65
63
  }
66
64
  });
67
65
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"VBreadcrumb.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VBreadcrumb/VBreadcrumb.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport { chevron_right as chevronRightIcon } from '../VIcon/icons/chevron_right'\nimport { more_horiz as moreHorizIcon } from '../VIcon/icons/more_horiz'\nimport type { IconSource } from '../VIcon/types'\nimport VIconButton from '../VIconButton/VIconButton.vue'\nimport VMenu from '../VMenu/VMenu.vue'\nimport VMenuItem from '../VMenu/VMenuItem.vue'\n\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useMessages } from '../../i18n/state'\n\n// @ssr @core\n/**\n * A breadcrumb trail: the path that leads to the page being read, from the most\n * general section down to the current one. It is a `<nav>` holding an ordered list,\n * built entirely from the `items` prop — nothing is read from the browser, so the\n * server and the client render exactly the same thing.\n *\n * The separators between the segments are decorative icons, hidden from screen\n * readers, and the very first one is removed in CSS rather than by a condition in\n * the markup. The current page is found by comparing each segment's address with\n * `currentPath`: it is marked with `aria-current=\"page\"` and stays a working link,\n * as the ARIA authoring practices recommend. When the trail grows past `maxItems`,\n * the middle segments are folded into a menu opened by an \"…\" button.\n */\nexport interface BreadcrumbItem {\n /** The text shown for this segment. */\n label: string\n /**\n * Where the segment leads. It is also the value compared with `currentPath` to\n * decide which segment is the current page.\n */\n href: string\n /**\n * An icon placed before the label: a Material Symbols Rounded name, an icon URL,\n * or an explicit render (`{ src: '/logo.svg' }`, `{ component }`…).\n */\n iconStart?: IconSource\n}\n\ninterface BreadcrumbProps {\n /** The segments of the trail, ordered from the most general down to the deepest. */\n items: BreadcrumbItem[]\n /**\n * The name screen readers announce for this navigation. It falls back to the\n * wording of the DS dictionary, in the current language.\n */\n label?: string\n /**\n * The address of the page being displayed. The segment whose `href` matches it is\n * the current one; a trailing slash on either side makes no difference.\n */\n currentPath?: string\n /**\n * The icon drawn between two segments: an icon name, or an explicit render,\n * exactly like `iconStart`.\n */\n separator?: IconSource\n /**\n * The length past which the trail folds: only the first segment, an \"…\" button and\n * the last two remain, the button opening a menu that lists the hidden segments\n * alone. Below 3 there would be nothing left to fold, so 3 is the effective\n * minimum.\n */\n maxItems?: number\n /**\n * The name screen readers announce for the \"…\" button. It falls back to the\n * wording of the DS dictionary.\n */\n ellipsisLabel?: string\n}\n\nconst props = withDefaults(defineProps<BreadcrumbProps>(), {\n label: undefined,\n currentPath: undefined,\n separator: () => chevronRightIcon,\n maxItems: undefined,\n ellipsisLabel: undefined,\n})\n\nconst m = useMessages()\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.breadcrumb.label)\nconst resolvedEllipsisLabel = computed(() => props.ellipsisLabel ?? m.value.breadcrumb.ellipsis)\n\n/**\n * Drops a trailing slash so that `/docs` and `/docs/` compare as the same page; the\n * root `/` is left alone. Pure string handling, hence safe to run on the server.\n */\nfunction normalize(path: string): string {\n return path.length > 1 && path.endsWith('/') ? path.slice(0, -1) : path\n}\n\n// @a11y — this is what feeds `aria-current=\"page\"`, the only marker telling\n// assistive technology where the trail ends.\nfunction isCurrent(item: BreadcrumbItem): boolean {\n if (props.currentPath === undefined) return false\n return normalize(item.href) === normalize(props.currentPath)\n}\n\nconst truncated = computed(\n () => props.maxItems !== undefined && props.items.length > Math.max(props.maxItems, 3),\n)\n/** The segments folded into the menu: everything between the first and the last two. */\nconst hiddenItems = computed(() => (truncated.value ? props.items.slice(1, -2) : []))\n/**\n * The segments actually rendered in the list — when the trail is folded, the first\n * one followed by the last two.\n */\nconst visibleItems = computed(() =>\n truncated.value ? [props.items[0] as BreadcrumbItem, ...props.items.slice(-2)] : props.items,\n)\n</script>\n\n<template>\n <nav class=\"v-breadcrumb\" :aria-label=\"ariaLabel\">\n <ol class=\"v-breadcrumb-list\">\n <template v-for=\"(item, index) in visibleItems\" :key=\"item.href\">\n <li v-if=\"truncated && index === 1\" class=\"v-breadcrumb-item v-breadcrumb-ellipsis\">\n <VIcon class=\"v-breadcrumb-separator\" v-bind=\"iconProps(separator)\" />\n <VMenu compact>\n <template #trigger=\"{ triggerProps }\">\n <VIconButton size=\"sm\" compact :label=\"resolvedEllipsisLabel\" v-bind=\"triggerProps\">\n <VIcon :name=\"moreHorizIcon\" />\n </VIconButton>\n </template>\n <VMenuItem\n v-for=\"hidden in hiddenItems\"\n :key=\"hidden.href\"\n :href=\"hidden.href\"\n :label=\"hidden.label\"\n :icon-start=\"hidden.iconStart\"\n />\n </VMenu>\n </li>\n <li class=\"v-breadcrumb-item\">\n <VIcon class=\"v-breadcrumb-separator\" v-bind=\"iconProps(separator)\" />\n <a\n class=\"v-breadcrumb-link\"\n :href=\"item.href\"\n :aria-current=\"isCurrent(item) ? 'page' : undefined\"\n >\n <VIcon v-if=\"item.iconStart\" v-bind=\"iconProps(item.iconStart)\" />\n {{ item.label }}\n </a>\n </li>\n </template>\n </ol>\n </nav>\n</template>\n\n<style>\n@layer vectis.components {\n .v-breadcrumb {\n --vectis-icon-size: var(--vectis-icon-size-sm);\n --vectis-icon-opsz: 20;\n }\n\n .v-breadcrumb-list {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--vectis-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-body-md-size);\n }\n\n .v-breadcrumb-item {\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-2);\n color: var(--vectis-color-text-muted);\n }\n\n .v-breadcrumb-list > .v-breadcrumb-item:first-child > .v-breadcrumb-separator {\n display: none;\n }\n\n .v-breadcrumb-separator {\n color: var(--vectis-color-text-subtle);\n }\n\n .v-breadcrumb-link {\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-1);\n color: var(--vectis-color-text-muted);\n text-decoration: none;\n border-radius: var(--vectis-radius-xs);\n transition: color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-breadcrumb-link:hover {\n color: var(--vectis-color-text);\n text-decoration: underline;\n }\n\n .v-breadcrumb-link:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n }\n\n .v-breadcrumb-link[aria-current='page'] {\n color: var(--vectis-color-text);\n font-weight: var(--vectis-text-label-weight);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-breadcrumb-link {\n transition: none;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;EA4EA,IAAM,IAAQ,GAQR,IAAI,EAAY,GAChB,IAAY,QAAmB,EAAM,SAAS,EAAE,MAAM,WAAW,KAAK,GACtE,IAAwB,QAAe,EAAM,iBAAiB,EAAE,MAAM,WAAW,QAAQ;EAM/F,SAAS,EAAU,GAAsB;GACvC,OAAO,EAAK,SAAS,KAAK,EAAK,SAAS,GAAG,IAAI,EAAK,MAAM,GAAG,EAAE,IAAI;EACrE;EAIA,SAAS,EAAU,GAA+B;GAEhD,OADI,EAAM,gBAAgB,KAAA,KACnB,EAAU,EAAK,IAAI,MAAM,EAAU,EAAM,WAAW;EAC7D;EAEA,IAAM,IAAY,QACV,EAAM,aAAa,KAAA,KAAa,EAAM,MAAM,SAAS,KAAK,IAAI,EAAM,UAAU,CAAC,CACvF,GAEM,IAAc,QAAgB,EAAU,QAAQ,EAAM,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,CAAE,GAK9E,IAAe,QACnB,EAAU,QAAQ,CAAC,EAAM,MAAM,IAAsB,GAAG,EAAM,MAAM,MAAM,EAAE,CAAC,IAAI,EAAM,KACzF;yBAIE,EAiCM,OAAA;GAjCD,OAAM;GAAgB,cAAY,EAAA,CAAA;MACrC,EA+BK,MA/BL,GA+BK,EAAA,EAAA,EAAA,GA9BH,EA6BW,GAAA,MAAA,EA7BuB,EAAA,QAAhB,GAAM,wBAA8B,EAAK,KAAA,GAAA,CAC/C,EAAA,SAAa,MAAK,KAAA,EAAA,GAA5B,EAgBK,MAhBL,GAgBK,CAfH,EAAsE,GAAtE,EAAsE,EAA/D,OAAM,yBAAwB,GAAA,EAAA,SAAA,GAAA,GAAS,EAAA,CAAA,CAAS,CAAC,EAAA,SAAS,CAAA,GAAA,MAAA,EAAA,GACjE,EAaQ,GAAA,EAbD,SAAA,GAAO,GAAA;GACD,SAAO,GAGF,EAHM,sBAAY,CAChC,EAEc,GAFd,EAEc;IAFD,MAAK;IAAK,SAAA;IAAS,OAAO,EAAA;uBAA+B,CAAY,GAAA;qBACjD,CAA/B,EAA+B,GAAA,EAAvB,MAAM,EAAA,CAAA,EAAa,GAAA,MAAA,GAAA,CAAA,MAAA,CAAA,CAAA,CAAA;;;oBAIA,EAAA,EAAA,EAAA,GAD/B,EAME,GAAA,MAAA,EALiB,EAAA,QAAV,YADT,EAME,GAAA;IAJC,KAAK,EAAO;IACZ,MAAM,EAAO;IACb,OAAO,EAAO;IACd,cAAY,EAAO;;;;;;;qBAI1B,EAUK,MAVL,GAUK,CATH,EAAsE,GAAtE,EAAsE,EAA/D,OAAM,yBAAwB,GAAA,EAAA,SAAA,GAAA,GAAS,EAAA,CAAA,CAAS,CAAC,EAAA,SAAS,CAAA,GAAA,MAAA,EAAA,GACjE,EAOI,KAAA;GANF,OAAM;GACL,MAAM,EAAK;GACX,gBAAc,EAAU,CAAI,IAAA,SAAa,KAAA;MAE7B,EAAK,aAAA,EAAA,GAAlB,EAAkE,GAAlE,EAAkE;;;KAA7B,EAAA,CAAA,CAAS,CAAC,EAAK,SAAS,CAAA,GAAA,MAAA,EAAA,KAAA,EAAA,IAAA,EAAA,GAAA,EAAK,MAClE,EAAG,EAAK,KAAK,GAAA,CAAA,CAAA,GAAA,GAAA,CAAA,CAAA,CAAA,CAAA,GAAA,EAAA"}
1
+ {"version":3,"file":"VBreadcrumb.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/VBreadcrumb/VBreadcrumb.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @ssr @core\n/**\n * The path leading to the page being read, from the broadest section down to the current\n * one: a `<nav>` holding an `<ol>`, built entirely from the `items` prop. Nothing is read\n * from the browser, so the server and the client render the same thing.\n *\n * The separators are decorative `aria-hidden` icons, and the first is removed in CSS rather\n * than by a condition in the markup. The current page is found by comparing each address\n * with `currentPath`, carries `aria-current=\"page\"` and stays a working link, as the ARIA\n * practices recommend. Past `maxItems`, the middle segments fold into a VMenu behind an \"…\".\n */\n\nimport { computed } from 'vue'\n\nimport VIcon from '../VIcon/VIcon.vue'\nimport { iconProps } from '../VIcon/iconProps'\nimport { chevron_right as chevronRightIcon } from '../VIcon/icons/chevron_right'\nimport { more_horiz as moreHorizIcon } from '../VIcon/icons/more_horiz'\nimport type { IconSource } from '../VIcon/types'\nimport VIconButton from '../VIconButton/VIconButton.vue'\nimport VMenu from '../VMenu/VMenu.vue'\nimport VMenuItem from '../VMenu/VMenuItem.vue'\n\nimport { useAriaLabel } from '../../composables/useAriaLabel'\nimport { useMessages } from '../../i18n/state'\n\nexport interface BreadcrumbItem {\n /** The text shown for this segment. */\n label: string\n /**\n * Where the segment leads. It is also the value compared with `currentPath` to\n * decide which segment is the current page.\n */\n href: string\n /**\n * An icon placed before the label: a Material Symbols Rounded name, an icon URL,\n * or an explicit render (`{ src: '/logo.svg' }`, `{ component }`…).\n */\n icon?: IconSource\n}\n\ninterface BreadcrumbProps {\n /** The segments of the trail, ordered from the most general down to the deepest. */\n items: BreadcrumbItem[]\n /**\n * The name screen readers announce for this navigation. It falls back to the\n * wording of the DS dictionary, in the current language.\n */\n label?: string\n /**\n * The address of the page being displayed. The segment whose `href` matches it is\n * the current one; a trailing slash on either side makes no difference.\n */\n currentPath?: string\n /**\n * The icon drawn between two segments: an icon name, or an explicit render,\n * exactly like an item's `icon`.\n */\n separatorIcon?: IconSource\n /**\n * The length past which the trail folds: only the first segment, an \"…\" button and\n * the last two remain, the button opening a menu that lists the hidden segments\n * alone. Below 3 there would be nothing left to fold, so 3 is the effective\n * minimum.\n */\n maxItems?: number\n /**\n * The name screen readers announce for the \"…\" button. It falls back to the\n * wording of the DS dictionary.\n */\n ellipsisLabel?: string\n}\n\nconst props = withDefaults(defineProps<BreadcrumbProps>(), {\n label: undefined,\n currentPath: undefined,\n separatorIcon: () => chevronRightIcon,\n maxItems: undefined,\n ellipsisLabel: undefined,\n})\n\nconst m = useMessages()\nconst ariaLabel = useAriaLabel(() => props.label ?? m.value.breadcrumb.label)\nconst resolvedEllipsisLabel = computed(() => props.ellipsisLabel ?? m.value.breadcrumb.ellipsis)\n\n/**\n * Drops a trailing slash so that `/docs` and `/docs/` compare as the same page; the\n * root `/` is left alone. Pure string handling, hence safe to run on the server.\n */\nfunction normalize(path: string): string {\n return path.length > 1 && path.endsWith('/') ? path.slice(0, -1) : path\n}\n\n// Normalized once per change of the prop rather than once per segment on every render.\nconst normalizedCurrent = computed(() =>\n props.currentPath === undefined ? undefined : normalize(props.currentPath),\n)\n\n// @a11y — this is what feeds `aria-current=\"page\"`, the only marker telling\n// assistive technology where the trail ends.\nfunction isCurrent(item: BreadcrumbItem): boolean {\n return normalizedCurrent.value !== undefined && normalize(item.href) === normalizedCurrent.value\n}\n\nconst truncated = computed(\n () => props.maxItems !== undefined && props.items.length > Math.max(props.maxItems, 3),\n)\n/** The segments folded into the menu: everything between the first and the last two. */\nconst hiddenItems = computed(() => (truncated.value ? props.items.slice(1, -2) : []))\n/**\n * The segments actually rendered in the list — when the trail is folded, the first\n * one followed by the last two.\n */\nconst visibleItems = computed(() =>\n truncated.value ? [props.items[0] as BreadcrumbItem, ...props.items.slice(-2)] : props.items,\n)\n</script>\n\n<template>\n <nav class=\"v-breadcrumb\" :aria-label=\"ariaLabel\">\n <ol class=\"v-breadcrumb-list\">\n <template v-for=\"(item, index) in visibleItems\" :key=\"item.href\">\n <li v-if=\"truncated && index === 1\" class=\"v-breadcrumb-item v-breadcrumb-ellipsis\">\n <VIcon class=\"v-breadcrumb-separator\" v-bind=\"iconProps(separatorIcon)\" mirrored />\n <VMenu>\n <template #trigger=\"{ triggerProps }\">\n <VIconButton\n size=\"sm\"\n :label=\"resolvedEllipsisLabel\"\n :icon=\"moreHorizIcon\"\n v-bind=\"triggerProps\"\n />\n </template>\n <VMenuItem\n v-for=\"hidden in hiddenItems\"\n :key=\"hidden.href\"\n :href=\"hidden.href\"\n :label=\"hidden.label\"\n :icon-start=\"hidden.icon\"\n />\n </VMenu>\n </li>\n <li class=\"v-breadcrumb-item\">\n <VIcon class=\"v-breadcrumb-separator\" v-bind=\"iconProps(separatorIcon)\" mirrored />\n <a\n class=\"v-breadcrumb-link\"\n :href=\"item.href\"\n :aria-current=\"isCurrent(item) ? 'page' : undefined\"\n >\n <VIcon v-if=\"item.icon\" v-bind=\"iconProps(item.icon)\" />\n {{ item.label }}\n </a>\n </li>\n </template>\n </ol>\n </nav>\n</template>\n\n<style>\n@layer vectis.components {\n /* The icon context is set here rather than through `.v-control`, which is the usual\n route: a trail has no `size` prop and no height to speak of, so the size scale would\n bring a table of five steps to pick one value from. */\n .v-breadcrumb {\n --vectis-icon-size: var(--vectis-icon-size-sm);\n --vectis-icon-opsz: 20;\n }\n\n .v-breadcrumb-list {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--vectis-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n font-family: var(--vectis-text-family);\n font-size: var(--vectis-text-body-md-size);\n }\n\n .v-breadcrumb-item {\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-2);\n color: var(--vectis-color-text-muted);\n }\n\n /* TRAP — every item renders its own leading separator and the first one is hidden HERE,\n which is what keeps the template free of an index test. Delete this rule and the trail\n opens on a stray chevron; both child combinators are load-bearing too, so wrapping an\n item or the list in anything puts that chevron straight back. */\n .v-breadcrumb-list > .v-breadcrumb-item:first-child > .v-breadcrumb-separator {\n display: none;\n }\n\n .v-breadcrumb-separator {\n color: var(--vectis-color-text-subtle);\n }\n\n /* The corner is only ever seen on the focus ring, which follows it. It is the control\n radius capped at half a line, the row recipe of VSideNavigationItem with the line\n standing in for a control height the link does not have: a label that wraps keeps\n the corner of a one-line one under a pill override. */\n .v-breadcrumb-link {\n display: inline-flex;\n align-items: center;\n gap: var(--vectis-space-1);\n color: var(--vectis-color-text-muted);\n text-decoration: none;\n border-radius: min(var(--vectis-radius-interactive), 0.5lh);\n transition: color var(--vectis-duration-fast) var(--vectis-ease-default);\n }\n\n .v-breadcrumb-link:hover {\n color: var(--vectis-color-text);\n text-decoration: underline;\n }\n\n .v-breadcrumb-link:focus-visible {\n outline: var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);\n outline-offset: var(--vectis-focus-ring-offset);\n }\n\n .v-breadcrumb-link[aria-current='page'] {\n color: var(--vectis-color-text);\n font-weight: var(--vectis-text-label-weight);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .v-breadcrumb-link {\n transition: none;\n }\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;EA0EA,IAAM,IAAQ,GAQR,IAAI,EAAY,GAChB,IAAY,QAAmB,EAAM,SAAS,EAAE,MAAM,WAAW,KAAK,GACtE,IAAwB,QAAe,EAAM,iBAAiB,EAAE,MAAM,WAAW,QAAQ;EAM/F,SAAS,EAAU,GAAsB;GACvC,OAAO,EAAK,SAAS,KAAK,EAAK,SAAS,GAAG,IAAI,EAAK,MAAM,GAAG,EAAE,IAAI;EACrE;EAGA,IAAM,IAAoB,QACxB,EAAM,gBAAgB,KAAA,IAAY,KAAA,IAAY,EAAU,EAAM,WAAW,CAC3E;EAIA,SAAS,EAAU,GAA+B;GAChD,OAAO,EAAkB,UAAU,KAAA,KAAa,EAAU,EAAK,IAAI,MAAM,EAAkB;EAC7F;EAEA,IAAM,IAAY,QACV,EAAM,aAAa,KAAA,KAAa,EAAM,MAAM,SAAS,KAAK,IAAI,EAAM,UAAU,CAAC,CACvF,GAEM,IAAc,QAAgB,EAAU,QAAQ,EAAM,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,CAAE,GAK9E,IAAe,QACnB,EAAU,QAAQ,CAAC,EAAM,MAAM,IAAsB,GAAG,EAAM,MAAM,MAAM,EAAE,CAAC,IAAI,EAAM,KACzF;yBAIE,EAoCM,OAAA;GApCD,OAAM;GAAgB,cAAY,EAAA,CAAA;MACrC,EAkCK,MAlCL,GAkCK,EAAA,EAAA,EAAA,GAjCH,EAgCW,GAAA,MAAA,EAhCuB,EAAA,QAAhB,GAAM,wBAA8B,EAAK,KAAA,GAAA,CAC/C,EAAA,SAAa,MAAK,KAAA,EAAA,GAA5B,EAmBK,MAnBL,GAmBK,CAlBH,EAAmF,GAAnF,EAAmF,EAA5E,OAAM,yBAAwB,GAAA,EAAA,SAAA,GAAA,GAAS,EAAA,CAAA,CAAS,CAAC,EAAA,aAAa,GAAA,EAAG,UAAA,GAAQ,CAAA,GAAA,MAAA,EAAA,GAChF,EAgBQ,GAAA,MAAA;GAfK,SAAO,GAMd,EANkB,sBAAY,CAChC,EAKE,GALF,EAKE;IAJA,MAAK;IACJ,OAAO,EAAA;IACP,MAAM,EAAA,CAAA;uBACC,CAAY,GAAA,MAAA,IAAA,CAAA,SAAA,MAAA,CAAA,CAAA,CAAA;oBAIO,EAAA,EAAA,EAAA,GAD/B,EAME,GAAA,MAAA,EALiB,EAAA,QAAV,YADT,EAME,GAAA;IAJC,KAAK,EAAO;IACZ,MAAM,EAAO;IACb,OAAO,EAAO;IACd,cAAY,EAAO;;;;;;;qBAI1B,EAUK,MAVL,GAUK,CATH,EAAmF,GAAnF,EAAmF,EAA5E,OAAM,yBAAwB,GAAA,EAAA,SAAA,GAAA,GAAS,EAAA,CAAA,CAAS,CAAC,EAAA,aAAa,GAAA,EAAG,UAAA,GAAQ,CAAA,GAAA,MAAA,EAAA,GAChF,EAOI,KAAA;GANF,OAAM;GACL,MAAM,EAAK;GACX,gBAAc,EAAU,CAAI,IAAA,SAAa,KAAA;MAE7B,EAAK,QAAA,EAAA,GAAlB,EAAwD,GAAxD,EAAwD;;;KAAxB,EAAA,CAAA,CAAS,CAAC,EAAK,IAAI,CAAA,GAAA,MAAA,EAAA,KAAA,EAAA,IAAA,EAAA,GAAA,EAAK,MACxD,EAAG,EAAK,KAAK,GAAA,CAAA,CAAA,GAAA,GAAA,CAAA,CAAA,CAAA,CAAA,GAAA,EAAA"}
@@ -1,2 +1,2 @@
1
1
  @layer vectis.reset, vectis.tokens, vectis.components, vectis.utilities;
2
- @layer vectis.components{.v-button{justify-content:center;align-items:center;gap:var(--control-gap);height:var(--control-height);padding-inline:var(--control-padding-inline);border-radius:var(--vectis-radius-interactive);font-family:var(--vectis-text-family);font-size:var(--control-font-size);font-weight:var(--vectis-text-control-weight);line-height:var(--vectis-text-control-leading);cursor:pointer;transition:background-color var(--vectis-duration-fast) var(--vectis-ease-default), border-color var(--vectis-duration-fast) var(--vectis-ease-default), color var(--vectis-duration-fast) var(--vectis-ease-default), box-shadow var(--vectis-duration-fast) var(--vectis-ease-default);border:1px solid #0000;text-decoration:none;display:inline-flex}.v-button:focus-visible{outline:var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);outline-offset:var(--vectis-focus-ring-offset)}.v-button[data-variant=solid]{background:var(--tone-bg-solid);color:var(--tone-text-solid)}.v-button[data-variant=solid]:hover:not(:disabled,[aria-disabled=true]){background:var(--tone-bg-solid-hover)}.v-button[data-variant=solid]:active:not(:disabled,[aria-disabled=true]){background:var(--tone-bg-solid-active)}.v-button[data-variant=outline]{color:var(--tone-text-tinted);border-color:var(--tone-border-soft);background:0 0}.v-button[data-variant=ghost]{color:var(--tone-text-tinted);background:0 0}.v-button[data-variant=outline]:not([data-elevated]):hover:not(:disabled,[aria-disabled=true]),.v-button[data-variant=ghost]:not([data-elevated]):hover:not(:disabled,[aria-disabled=true]){background:var(--tone-bg-soft)}.v-button[data-variant=outline]:not([data-elevated]):active:not(:disabled,[aria-disabled=true]),.v-button[data-variant=ghost]:not([data-elevated]):active:not(:disabled,[aria-disabled=true]){background:color-mix(in oklab, var(--tone-bg-soft), var(--tone-text-tinted) 8%)}.v-button[data-variant=soft]{background:var(--tone-bg-soft);color:var(--tone-text-tinted)}.v-button[data-variant=soft]:hover:not(:disabled,[aria-disabled=true]){background:color-mix(in oklab, var(--tone-bg-soft), var(--tone-text-tinted) 8%)}.v-button[data-variant=soft]:active:not(:disabled,[aria-disabled=true]){background:color-mix(in oklab, var(--tone-bg-soft), var(--tone-text-tinted) 14%)}.v-button[data-elevated]{box-shadow:var(--vectis-shadow-sm)}.v-button[data-elevated]:is([data-variant=ghost],[data-variant=outline]){background:var(--vectis-color-surface-raised)}.v-button[data-elevated]:hover:not(:disabled,[aria-disabled=true]){box-shadow:var(--vectis-shadow-md)}.v-button[data-elevated]:is([data-variant=ghost],[data-variant=outline]):hover:not(:disabled,[aria-disabled=true]){background:color-mix(in oklab, var(--vectis-color-surface-raised), var(--tone-text-tinted) 8%)}.v-button[data-elevated]:active:not(:disabled,[aria-disabled=true]){box-shadow:var(--vectis-shadow-sm)}.v-button[data-elevated]:is([data-variant=ghost],[data-variant=outline]):active:not(:disabled,[aria-disabled=true]){background:color-mix(in oklab, var(--vectis-color-surface-raised), var(--tone-text-tinted) 12%)}.v-button:is(:disabled,[aria-disabled=true]){cursor:not-allowed}.v-button[data-loading]{opacity:.5}.v-button:is(:disabled,[aria-disabled=true]):not([data-loading]):is([data-variant=solid],[data-variant=soft]){background:var(--vectis-color-surface-muted);color:var(--vectis-color-text-subtle)}.v-button:is(:disabled,[aria-disabled=true]):not([data-loading])[data-variant=outline]{color:var(--vectis-color-text-subtle);border-color:var(--vectis-color-border);background:0 0}.v-button:is(:disabled,[aria-disabled=true]):not([data-loading])[data-variant=ghost]{color:var(--vectis-color-text-subtle);background:0 0}.v-button:is(:disabled,[aria-disabled=true]):not([data-loading])[data-elevated]{box-shadow:none}.v-button-spinner{width:var(--vectis-icon-size);height:var(--vectis-icon-size);font-size:var(--vectis-icon-size);flex:none;justify-content:center;align-items:center;display:inline-flex}@media (prefers-reduced-motion:reduce){.v-button{transition:none}}}
2
+ @layer vectis.components{.v-button{justify-content:center;align-items:center;gap:var(--control-gap);height:var(--control-height);padding-inline:var(--control-padding-inline);border-radius:var(--vectis-radius-interactive);font-family:var(--vectis-text-family);font-size:var(--control-font-size);font-weight:var(--vectis-text-control-weight);line-height:var(--vectis-text-control-leading);cursor:pointer;transition:background-color var(--vectis-duration-fast) var(--vectis-ease-default), border-color var(--vectis-duration-fast) var(--vectis-ease-default), color var(--vectis-duration-fast) var(--vectis-ease-default), box-shadow var(--vectis-duration-fast) var(--vectis-ease-default);border:1px solid #0000;text-decoration:none;display:inline-flex}.v-button[data-full-width]{inline-size:100%;display:flex}.v-button[data-icon-only]{min-inline-size:var(--control-height);padding-inline:0}.v-button:focus-visible{outline:var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);outline-offset:var(--vectis-focus-ring-offset)}.v-button[data-variant=solid]:hover:not(:disabled,[aria-disabled=true]){background:var(--tone-bg-solid-hover)}.v-button[data-variant=solid]:active:not(:disabled,[aria-disabled=true]){background:var(--tone-bg-solid-active)}.v-button:is([data-variant=outline],[data-variant=ghost]):not([data-elevated]):hover:not(:disabled,[aria-disabled=true]){background:var(--tone-bg-soft)}.v-button:is([data-variant=outline],[data-variant=ghost]):not([data-elevated]):active:not(:disabled,[aria-disabled=true]),.v-button[data-variant=soft]:hover:not(:disabled,[aria-disabled=true]){background:color-mix(in oklab, var(--tone-bg-soft), var(--tone-text-tinted) 8%)}.v-button[data-variant=soft]:active:not(:disabled,[aria-disabled=true]){background:color-mix(in oklab, var(--tone-bg-soft), var(--tone-text-tinted) 14%)}.v-button[data-elevated]{box-shadow:var(--vectis-shadow-sm)}.v-button[data-elevated]:is([data-variant=ghost],[data-variant=outline]){background:var(--vectis-color-surface-raised)}.v-button[data-elevated]:hover:not(:disabled,[aria-disabled=true]){box-shadow:var(--vectis-shadow-md)}.v-button[data-elevated]:is([data-variant=ghost],[data-variant=outline]):hover:not(:disabled,[aria-disabled=true]){background:color-mix(in oklab, var(--vectis-color-surface-raised), var(--tone-text-tinted) 8%)}.v-button[data-elevated]:active:not(:disabled,[aria-disabled=true]){box-shadow:var(--vectis-shadow-sm)}.v-button[data-elevated]:is([data-variant=ghost],[data-variant=outline]):active:not(:disabled,[aria-disabled=true]){background:color-mix(in oklab, var(--vectis-color-surface-raised), var(--tone-text-tinted) 12%)}.v-button:is(:disabled,[aria-disabled=true]){cursor:not-allowed}.v-button[data-loading]{opacity:.5}.v-button:is(:disabled,[aria-disabled=true]):not([data-loading]):is([data-variant=solid],[data-variant=soft]){background:var(--vectis-color-surface-muted);color:var(--vectis-color-text-subtle)}.v-button:is(:disabled,[aria-disabled=true]):not([data-loading])[data-variant=outline]{color:var(--vectis-color-text-subtle);border-color:var(--vectis-color-border);background:0 0}.v-button:is(:disabled,[aria-disabled=true]):not([data-loading])[data-variant=ghost]{color:var(--vectis-color-text-subtle);background:0 0}.v-button:is(:disabled,[aria-disabled=true]):not([data-loading])[data-elevated]{box-shadow:none}.v-button-spinner{width:var(--vectis-icon-size);height:var(--vectis-icon-size);font-size:var(--vectis-icon-size);flex:none;justify-content:center;align-items:center;display:inline-flex}@media (prefers-reduced-motion:reduce){.v-button{transition:none}}}
@@ -1,29 +1,48 @@
1
1
  import { ButtonHTMLAttributes } from 'vue';
2
2
  import { IconSource } from '../VIcon/types.js';
3
+ export type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'soft';
4
+ export type ButtonTone = 'accent' | 'neutral' | 'danger';
5
+ export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
3
6
  interface ButtonProps {
4
7
  /**
5
8
  * How much visual weight the button carries: `solid` is filled with the tone,
6
9
  * `soft` uses a tinted background, `outline` keeps only a border, and `ghost`
7
- * shows nothing until it is hovered.
10
+ * shows nothing until it is hovered. Inside a VButtonGroup the group's own variant
11
+ * wins over this one.
8
12
  */
9
- variant?: 'solid' | 'outline' | 'ghost' | 'soft';
13
+ variant?: ButtonVariant;
10
14
  /**
11
15
  * What the action means: `accent` for the ordinary one, `neutral` for a secondary
12
16
  * one, `danger` for one that destroys something. On a button a tone is an
13
17
  * intention, which is why states such as success or warning are not offered here.
18
+ * Left out inside a VButtonGroup it takes the group's tone, which is the point of
19
+ * not defaulting it here; on its own it is `accent`.
14
20
  */
15
- tone?: 'accent' | 'neutral' | 'danger';
21
+ tone?: ButtonTone;
16
22
  /**
17
23
  * Raises the button off the page: a shadow that grows on hover and settles back
18
24
  * when pressed, whatever the variant. On `ghost` and `outline`, which have no
19
25
  * background of their own, it also paints the raised surface — in the dark theme
20
- * a shadow lying straight on the page background has nothing casting it.
26
+ * a shadow lying straight on the page background has nothing casting it. Inside a
27
+ * VButtonGroup the group's own value wins over this one.
21
28
  */
22
29
  elevated?: boolean;
23
- /** The height of the button, taken from the size scale shared by every control. */
24
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
25
- /** Takes 4px off the height, leaving the padding, the text and the icons as they are. */
30
+ /**
31
+ * The height of the button, taken from the size scale shared by every control.
32
+ * Inside a VButtonGroup the group's own size wins over this one.
33
+ */
34
+ size?: ButtonSize;
35
+ /**
36
+ * Takes 4px off the height, leaving the padding, the text and the icons as they
37
+ * are. Inside a VButtonGroup the group's own value wins over this one.
38
+ */
26
39
  compact?: boolean;
40
+ /**
41
+ * Stretches the button to the whole inline size of its parent, instead of leaving
42
+ * it only as wide as its content. The label stays centred, and the button becomes
43
+ * block-level, so it no longer sits on a line of text.
44
+ */
45
+ fullWidth?: boolean;
27
46
  /**
28
47
  * Turns the button into an `<a>` pointing at this address. A disabled or loading
29
48
  * link becomes inert: the address is dropped, so it can be neither focused nor
@@ -66,12 +85,13 @@ type __VLS_Slots = {
66
85
  };
67
86
  declare const __VLS_base: import('vue').DefineComponent<ButtonProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<ButtonProps> & Readonly<{}>, {
68
87
  loading: boolean;
69
- size: "xs" | "sm" | "md" | "lg" | "xl";
88
+ size: ButtonSize;
70
89
  type: "button" | "submit" | "reset";
71
- variant: "solid" | "outline" | "ghost" | "soft";
72
- tone: "accent" | "neutral" | "danger";
90
+ variant: ButtonVariant;
91
+ tone: ButtonTone;
73
92
  elevated: boolean;
74
93
  compact: boolean;
94
+ fullWidth: boolean;
75
95
  href: string;
76
96
  disabled: boolean;
77
97
  iconStart: IconSource;