vectis-ui 0.8.1 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (432) hide show
  1. package/README.md +3 -3
  2. package/dist/components/VAccordion/VAccordionItem.d.ts +4 -6
  3. package/dist/components/VAccordion/VAccordionItem.js.map +1 -1
  4. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js +21 -19
  5. package/dist/components/VAccordion/VAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/VAccordion/context.d.ts +6 -1
  7. package/dist/components/VAccordion/context.js.map +1 -1
  8. package/dist/components/VAvatar/VAvatar.css +1 -1
  9. package/dist/components/VAvatar/VAvatar.d.ts +5 -3
  10. package/dist/components/VAvatar/VAvatar.js.map +1 -1
  11. package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js +53 -39
  12. package/dist/components/VAvatar/VAvatar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  13. package/dist/components/VAvatar/VAvatarGroup.d.ts +12 -3
  14. package/dist/components/VAvatar/VAvatarGroup.js.map +1 -1
  15. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js +27 -20
  16. package/dist/components/VAvatar/VAvatarGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/components/VAvatar/context.d.ts +2 -2
  18. package/dist/components/VAvatar/context.js.map +1 -1
  19. package/dist/components/VBadge/VBadge.css +1 -1
  20. package/dist/components/VBadge/VBadge.d.ts +8 -4
  21. package/dist/components/VBadge/VBadge.js.map +1 -1
  22. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js +6 -3
  23. package/dist/components/VBadge/VBadge.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/VBreadcrumb/VBreadcrumb.d.ts +5 -4
  25. package/dist/components/VBreadcrumb/VBreadcrumb.js.map +1 -1
  26. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js +8 -3
  27. package/dist/components/VBreadcrumb/VBreadcrumb.vue_vue_type_script_setup_true_lang.js.map +1 -1
  28. package/dist/components/VButton/VButton.css +1 -1
  29. package/dist/components/VButton/VButton.d.ts +4 -1
  30. package/dist/components/VButton/VButton.js.map +1 -1
  31. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js +8 -7
  32. package/dist/components/VButton/VButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/VButton/VButtonGroup.js.map +1 -1
  34. package/dist/components/VButton/VButtonGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/components/VCalendar/VCalendar.css +1 -1
  36. package/dist/components/VCalendar/VCalendar.d.ts +15 -6
  37. package/dist/components/VCalendar/VCalendar.js.map +1 -1
  38. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js +144 -126
  39. package/dist/components/VCalendar/VCalendar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  40. package/dist/components/VCalendar/VCalendarEvent.css +1 -1
  41. package/dist/components/VCalendar/VCalendarEvent.d.ts +1 -1
  42. package/dist/components/VCalendar/VCalendarEvent.js.map +1 -1
  43. package/dist/components/VCalendar/VCalendarEvent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  44. package/dist/components/VCalendar/VCalendarMonth.css +1 -1
  45. package/dist/components/VCalendar/VCalendarMonth.d.ts +1 -1
  46. package/dist/components/VCalendar/VCalendarMonth.js.map +1 -1
  47. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js +99 -90
  48. package/dist/components/VCalendar/VCalendarMonth.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/VCalendar/VCalendarTimeGrid.css +1 -1
  50. package/dist/components/VCalendar/VCalendarTimeGrid.d.ts +3 -3
  51. package/dist/components/VCalendar/VCalendarTimeGrid.js.map +1 -1
  52. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js +256 -246
  53. package/dist/components/VCalendar/VCalendarTimeGrid.vue_vue_type_script_setup_true_lang.js.map +1 -1
  54. package/dist/components/VCalendar/VCalendarYear.css +1 -1
  55. package/dist/components/VCalendar/VCalendarYear.d.ts +8 -1
  56. package/dist/components/VCalendar/VCalendarYear.js.map +1 -1
  57. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js +39 -32
  58. package/dist/components/VCalendar/VCalendarYear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  59. package/dist/components/VCalendar/color.d.ts +1 -1
  60. package/dist/components/VCalendar/color.js.map +1 -1
  61. package/dist/components/VCalendar/edgeStep.d.ts +3 -3
  62. package/dist/components/VCalendar/edgeStep.js +5 -0
  63. package/dist/components/VCalendar/edgeStep.js.map +1 -1
  64. package/dist/components/VCalendar/gesture.d.ts +10 -9
  65. package/dist/components/VCalendar/gesture.js +60 -45
  66. package/dist/components/VCalendar/gesture.js.map +1 -1
  67. package/dist/components/VCalendar/keyboard.d.ts +22 -5
  68. package/dist/components/VCalendar/keyboard.js +17 -16
  69. package/dist/components/VCalendar/keyboard.js.map +1 -1
  70. package/dist/components/VCalendar/layout.d.ts +47 -37
  71. package/dist/components/VCalendar/layout.js +47 -37
  72. package/dist/components/VCalendar/layout.js.map +1 -1
  73. package/dist/components/VCalendar/timeGrid.d.ts +4 -4
  74. package/dist/components/VCalendar/timeGrid.js +6 -6
  75. package/dist/components/VCalendar/timeGrid.js.map +1 -1
  76. package/dist/components/VCalendar/types.d.ts +5 -5
  77. package/dist/components/VCarousel/VCarousel.css +1 -1
  78. package/dist/components/VCarousel/VCarousel.d.ts +59 -38
  79. package/dist/components/VCarousel/VCarousel.js.map +1 -1
  80. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js +161 -132
  81. package/dist/components/VCarousel/VCarousel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  82. package/dist/components/VCarousel/VCarouselItem.d.ts +1 -1
  83. package/dist/components/VCarousel/VCarouselItem.js.map +1 -1
  84. package/dist/components/VCarousel/VCarouselItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  85. package/dist/components/VCarousel/context.d.ts +1 -1
  86. package/dist/components/VCarousel/context.js.map +1 -1
  87. package/dist/components/VCheckbox/VCheckbox.css +1 -1
  88. package/dist/components/VCheckbox/VCheckbox.d.ts +2 -2
  89. package/dist/components/VCheckbox/VCheckbox.js.map +1 -1
  90. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js +10 -8
  91. package/dist/components/VCheckbox/VCheckbox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  92. package/dist/components/VChip/VChip.css +1 -1
  93. package/dist/components/VChip/VChip.d.ts +7 -2
  94. package/dist/components/VChip/VChip.js.map +1 -1
  95. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js +69 -55
  96. package/dist/components/VChip/VChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  97. package/dist/components/VCombobox/VCombobox.css +1 -1
  98. package/dist/components/VCombobox/VCombobox.d.ts +50 -36
  99. package/dist/components/VCombobox/VCombobox.js.map +1 -1
  100. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js +167 -161
  101. package/dist/components/VCombobox/VCombobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  102. package/dist/components/VCombobox/VComboboxGroup.css +1 -1
  103. package/dist/components/VCombobox/VComboboxGroup.js.map +1 -1
  104. package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  105. package/dist/components/VCombobox/VComboboxGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  106. package/dist/components/VCombobox/infiniteScroll.d.ts +12 -3
  107. package/dist/components/VCombobox/infiniteScroll.js +18 -12
  108. package/dist/components/VCombobox/infiniteScroll.js.map +1 -1
  109. package/dist/components/VDataTable/VDataTable.css +1 -1
  110. package/dist/components/VDataTable/VDataTable.d.ts +55 -24
  111. package/dist/components/VDataTable/VDataTable.js.map +1 -1
  112. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js +192 -155
  113. package/dist/components/VDataTable/VDataTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  114. package/dist/components/VDateInput/VDateInput.css +1 -1
  115. package/dist/components/VDateInput/VDateInput.d.ts +15 -12
  116. package/dist/components/VDateInput/VDateInput.js.map +1 -1
  117. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js +180 -160
  118. package/dist/components/VDateInput/VDateInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  119. package/dist/components/VDateInput/mask.d.ts +95 -0
  120. package/dist/components/VDateInput/mask.js +118 -0
  121. package/dist/components/VDateInput/mask.js.map +1 -0
  122. package/dist/components/VDatePicker/VDatePicker.css +1 -1
  123. package/dist/components/VDatePicker/VDatePicker.d.ts +6 -5
  124. package/dist/components/VDatePicker/VDatePicker.js.map +1 -1
  125. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js +204 -173
  126. package/dist/components/VDatePicker/VDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  127. package/dist/components/VDatePicker/keyboard.d.ts +3 -3
  128. package/dist/components/VDatePicker/keyboard.js.map +1 -1
  129. package/dist/components/VDatePicker/names.d.ts +34 -0
  130. package/dist/components/VDatePicker/names.js +42 -0
  131. package/dist/components/VDatePicker/names.js.map +1 -0
  132. package/dist/components/VDialog/VDialog.css +1 -1
  133. package/dist/components/VDialog/VDialog.d.ts +2 -2
  134. package/dist/components/VDialog/VDialog.js.map +1 -1
  135. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js +63 -41
  136. package/dist/components/VDialog/VDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  137. package/dist/components/VFileInput/VFileInput.d.ts +38 -25
  138. package/dist/components/VFileInput/VFileInput.js.map +1 -1
  139. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js +74 -71
  140. package/dist/components/VFileInput/VFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  141. package/dist/components/VFileInput/truncate.d.ts +4 -4
  142. package/dist/components/VFileInput/truncate.js.map +1 -1
  143. package/dist/components/VFilePicker/VFilePicker.css +1 -1
  144. package/dist/components/VFilePicker/VFilePicker.d.ts +54 -37
  145. package/dist/components/VFilePicker/VFilePicker.js.map +1 -1
  146. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js +152 -135
  147. package/dist/components/VFilePicker/VFilePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  148. package/dist/components/VFilePicker/fileKind.d.ts +2 -2
  149. package/dist/components/VFilePicker/fileKind.js.map +1 -1
  150. package/dist/components/VHotkeys/VHotkeys.css +1 -1
  151. package/dist/components/VHotkeys/VHotkeys.d.ts +10 -8
  152. package/dist/components/VHotkeys/VHotkeys.js.map +1 -1
  153. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js +22 -20
  154. package/dist/components/VHotkeys/VHotkeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
  155. package/dist/components/VHotkeys/platform.d.ts +9 -7
  156. package/dist/components/VHotkeys/platform.js +41 -30
  157. package/dist/components/VHotkeys/platform.js.map +1 -1
  158. package/dist/components/VIcon/VIcon.css +1 -1
  159. package/dist/components/VIcon/VIcon.d.ts +6 -6
  160. package/dist/components/VIcon/VIcon.js.map +1 -1
  161. package/dist/components/VIcon/VIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  162. package/dist/components/VIcon/iconProps.d.ts +4 -4
  163. package/dist/components/VIcon/iconProps.js.map +1 -1
  164. package/dist/components/VIcon/icons/index.d.ts +1 -1
  165. package/dist/components/VIcon/icons/index.js.map +1 -1
  166. package/dist/components/VIcon/icons/names.d.ts +1 -1
  167. package/dist/components/VIcon/icons/names.js.map +1 -1
  168. package/dist/components/VIcon/resolver.d.ts +3 -3
  169. package/dist/components/VIcon/resolver.js +23 -20
  170. package/dist/components/VIcon/resolver.js.map +1 -1
  171. package/dist/components/VIcon/types.d.ts +4 -4
  172. package/dist/components/VIconButton/VIconButton.d.ts +4 -4
  173. package/dist/components/VIconButton/VIconButton.js.map +1 -1
  174. package/dist/components/VIconButton/VIconButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  175. package/dist/components/VInput/VInput.d.ts +16 -8
  176. package/dist/components/VInput/VInput.js.map +1 -1
  177. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js +22 -16
  178. package/dist/components/VInput/VInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  179. package/dist/components/VInput/VInputGroup.css +1 -1
  180. package/dist/components/VInput/VInputGroup.js.map +1 -1
  181. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js +43 -28
  182. package/dist/components/VInput/VInputGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  183. package/dist/components/VInputOTP/VInputOTP.css +1 -1
  184. package/dist/components/VInputOTP/VInputOTP.d.ts +3 -3
  185. package/dist/components/VInputOTP/VInputOTP.js.map +1 -1
  186. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js +152 -85
  187. package/dist/components/VInputOTP/VInputOTP.vue_vue_type_script_setup_true_lang.js.map +1 -1
  188. package/dist/components/VMenu/VMenu.d.ts +4 -4
  189. package/dist/components/VMenu/VMenu.js.map +1 -1
  190. package/dist/components/VMenu/VMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  191. package/dist/components/VMenu/VMenuGroup.css +1 -1
  192. package/dist/components/VMenu/VMenuGroup.js.map +1 -1
  193. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js +18 -11
  194. package/dist/components/VMenu/VMenuGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  195. package/dist/components/VMenu/VMenuItem.css +1 -1
  196. package/dist/components/VMenu/VMenuItem.d.ts +6 -6
  197. package/dist/components/VMenu/VMenuItem.js.map +1 -1
  198. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js +83 -69
  199. package/dist/components/VMenu/VMenuItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  200. package/dist/components/VMenu/VMenuPanel.css +1 -1
  201. package/dist/components/VMenu/VMenuPanel.d.ts +2 -2
  202. package/dist/components/VMenu/VMenuPanel.js.map +1 -1
  203. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js +56 -55
  204. package/dist/components/VMenu/VMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  205. package/dist/components/VMenu/context.d.ts +2 -2
  206. package/dist/components/VMenu/context.js.map +1 -1
  207. package/dist/components/VPagination/VPagination.css +1 -1
  208. package/dist/components/VPagination/VPagination.d.ts +31 -9
  209. package/dist/components/VPagination/VPagination.js.map +1 -1
  210. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js +82 -52
  211. package/dist/components/VPagination/VPagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  212. package/dist/components/VPopover/VPopover.css +1 -1
  213. package/dist/components/VPopover/VPopover.d.ts +1 -1
  214. package/dist/components/VPopover/VPopover.js.map +1 -1
  215. package/dist/components/VPopover/VPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
  216. package/dist/components/VProgressCircular/VProgressCircular.css +1 -1
  217. package/dist/components/VProgressCircular/VProgressCircular.d.ts +12 -7
  218. package/dist/components/VProgressCircular/VProgressCircular.js.map +1 -1
  219. package/dist/components/VProgressCircular/VProgressCircular.vue_vue_type_script_setup_true_lang.js.map +1 -1
  220. package/dist/components/VProgressLinear/VProgressLinear.css +1 -1
  221. package/dist/components/VProgressLinear/VProgressLinear.d.ts +15 -10
  222. package/dist/components/VProgressLinear/VProgressLinear.js.map +1 -1
  223. package/dist/components/VProgressLinear/VProgressLinear.vue_vue_type_script_setup_true_lang.js.map +1 -1
  224. package/dist/components/VRadio/VRadio.css +1 -1
  225. package/dist/components/VRadio/VRadio.js.map +1 -1
  226. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js +3 -3
  227. package/dist/components/VRadio/VRadio.vue_vue_type_script_setup_true_lang.js.map +1 -1
  228. package/dist/components/VSeparator/VSeparator.d.ts +1 -1
  229. package/dist/components/VSeparator/VSeparator.js.map +1 -1
  230. package/dist/components/VSeparator/VSeparator.vue_vue_type_script_setup_true_lang.js.map +1 -1
  231. package/dist/components/VSideNavigation/VSideNavigation.d.ts +2 -2
  232. package/dist/components/VSideNavigation/VSideNavigation.js.map +1 -1
  233. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js +1 -1
  234. package/dist/components/VSideNavigation/VSideNavigation.vue_vue_type_script_setup_true_lang.js.map +1 -1
  235. package/dist/components/VSideNavigation/VSideNavigationGroup.css +1 -1
  236. package/dist/components/VSideNavigation/VSideNavigationGroup.js.map +1 -1
  237. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js +1 -1
  238. package/dist/components/VSideNavigation/VSideNavigationGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  239. package/dist/components/VSideNavigation/VSideNavigationItem.css +1 -1
  240. package/dist/components/VSideNavigation/VSideNavigationItem.d.ts +12 -13
  241. package/dist/components/VSideNavigation/VSideNavigationItem.js.map +1 -1
  242. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js +87 -68
  243. package/dist/components/VSideNavigation/VSideNavigationItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  244. package/dist/components/VSkeletonLoader/VSkeletonLoader.css +1 -1
  245. package/dist/components/VSkeletonLoader/VSkeletonLoader.d.ts +10 -7
  246. package/dist/components/VSkeletonLoader/VSkeletonLoader.js.map +1 -1
  247. package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js +5 -5
  248. package/dist/components/VSkeletonLoader/VSkeletonLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  249. package/dist/components/VSlider/VSlider.css +1 -1
  250. package/dist/components/VSlider/VSlider.d.ts +21 -7
  251. package/dist/components/VSlider/VSlider.js.map +1 -1
  252. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js +159 -140
  253. package/dist/components/VSlider/VSlider.vue_vue_type_script_setup_true_lang.js.map +1 -1
  254. package/dist/components/VSnackbar/VSnackbar.css +1 -1
  255. package/dist/components/VSnackbar/VSnackbar.d.ts +4 -4
  256. package/dist/components/VSnackbar/VSnackbar.js.map +1 -1
  257. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js +85 -59
  258. package/dist/components/VSnackbar/VSnackbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  259. package/dist/components/VSnackbar/state.d.ts +7 -7
  260. package/dist/components/VSnackbar/state.js +13 -11
  261. package/dist/components/VSnackbar/state.js.map +1 -1
  262. package/dist/components/VSpinner/VSpinner.css +1 -1
  263. package/dist/components/VSpinner/VSpinner.js.map +1 -1
  264. package/dist/components/VSpinner/VSpinner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  265. package/dist/components/VSwitch/VSwitch.css +1 -1
  266. package/dist/components/VSwitch/VSwitch.d.ts +1 -1
  267. package/dist/components/VSwitch/VSwitch.js.map +1 -1
  268. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js +4 -4
  269. package/dist/components/VSwitch/VSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  270. package/dist/components/VTabs/VTab.css +1 -1
  271. package/dist/components/VTabs/VTab.d.ts +4 -0
  272. package/dist/components/VTabs/VTab.js.map +1 -1
  273. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js +9 -8
  274. package/dist/components/VTabs/VTab.vue_vue_type_script_setup_true_lang.js.map +1 -1
  275. package/dist/components/VTabs/VTabs.css +1 -1
  276. package/dist/components/VTabs/VTabs.d.ts +17 -7
  277. package/dist/components/VTabs/VTabs.js.map +1 -1
  278. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js +84 -77
  279. package/dist/components/VTabs/VTabs.vue_vue_type_script_setup_true_lang.js.map +1 -1
  280. package/dist/components/VTextarea/VTextarea.d.ts +8 -8
  281. package/dist/components/VTextarea/VTextarea.js.map +1 -1
  282. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js +71 -69
  283. package/dist/components/VTextarea/VTextarea.vue_vue_type_script_setup_true_lang.js.map +1 -1
  284. package/dist/components/VTimeInput/VTimeInput.css +1 -1
  285. package/dist/components/VTimeInput/VTimeInput.d.ts +21 -12
  286. package/dist/components/VTimeInput/VTimeInput.js.map +1 -1
  287. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js +230 -206
  288. package/dist/components/VTimeInput/VTimeInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  289. package/dist/components/VTimeInput/search.d.ts +17 -2
  290. package/dist/components/VTimeInput/search.js +19 -9
  291. package/dist/components/VTimeInput/search.js.map +1 -1
  292. package/dist/components/VTimePicker/VTimePicker.css +1 -1
  293. package/dist/components/VTimePicker/VTimePicker.d.ts +8 -7
  294. package/dist/components/VTimePicker/VTimePicker.js.map +1 -1
  295. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js +128 -106
  296. package/dist/components/VTimePicker/VTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  297. package/dist/components/VTimePicker/limits.d.ts +11 -4
  298. package/dist/components/VTimePicker/limits.js +3 -2
  299. package/dist/components/VTimePicker/limits.js.map +1 -1
  300. package/dist/components/VToast/VToast.css +1 -1
  301. package/dist/components/VToast/VToast.js.map +1 -1
  302. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js +33 -37
  303. package/dist/components/VToast/VToast.vue_vue_type_script_setup_true_lang.js.map +1 -1
  304. package/dist/components/VToast/VToaster.js.map +1 -1
  305. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js +91 -61
  306. package/dist/components/VToast/VToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
  307. package/dist/components/VToast/state.d.ts +8 -6
  308. package/dist/components/VToast/state.js +15 -13
  309. package/dist/components/VToast/state.js.map +1 -1
  310. package/dist/components/VToggle/VToggle.css +1 -1
  311. package/dist/components/VToggle/VToggle.d.ts +9 -4
  312. package/dist/components/VToggle/VToggle.js.map +1 -1
  313. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js +2 -1
  314. package/dist/components/VToggle/VToggle.vue_vue_type_script_setup_true_lang.js.map +1 -1
  315. package/dist/components/VToggle/VToggleItem.d.ts +4 -0
  316. package/dist/components/VToggle/VToggleItem.js.map +1 -1
  317. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js +5 -5
  318. package/dist/components/VToggle/VToggleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  319. package/dist/components/VTooltip/VTooltip.css +1 -1
  320. package/dist/components/VTooltip/VTooltip.d.ts +17 -10
  321. package/dist/components/VTooltip/VTooltip.js.map +1 -1
  322. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js +46 -26
  323. package/dist/components/VTooltip/VTooltip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  324. package/dist/components/VTypography/VTypography.css +1 -1
  325. package/dist/components/VTypography/VTypography.d.ts +6 -4
  326. package/dist/components/VTypography/VTypography.js.map +1 -1
  327. package/dist/components/VTypography/VTypography.vue_vue_type_script_setup_true_lang.js.map +1 -1
  328. package/dist/composables/useAriaLabel.js +1 -1
  329. package/dist/composables/useAriaLabel.js.map +1 -1
  330. package/dist/composables/useClearable.d.ts +2 -2
  331. package/dist/composables/useClearable.js.map +1 -1
  332. package/dist/composables/useDetailsOpen.d.ts +3 -3
  333. package/dist/composables/useDetailsOpen.js +14 -12
  334. package/dist/composables/useDetailsOpen.js.map +1 -1
  335. package/dist/composables/useFieldIds.d.ts +2 -1
  336. package/dist/composables/useFieldIds.js +6 -5
  337. package/dist/composables/useFieldIds.js.map +1 -1
  338. package/dist/composables/useFieldPanel.d.ts +2 -2
  339. package/dist/composables/useFieldPanel.js +47 -37
  340. package/dist/composables/useFieldPanel.js.map +1 -1
  341. package/dist/composables/useFileDrop.js +3 -3
  342. package/dist/composables/useFileDrop.js.map +1 -1
  343. package/dist/composables/useFileField.d.ts +1 -1
  344. package/dist/composables/useFileField.js +62 -41
  345. package/dist/composables/useFileField.js.map +1 -1
  346. package/dist/composables/useIconClickHandlers.d.ts +3 -3
  347. package/dist/composables/useIconClickHandlers.js +14 -13
  348. package/dist/composables/useIconClickHandlers.js.map +1 -1
  349. package/dist/composables/useInertLink.js +12 -10
  350. package/dist/composables/useInertLink.js.map +1 -1
  351. package/dist/composables/useLiveAnnouncer.d.ts +5 -0
  352. package/dist/composables/useLiveAnnouncer.js +23 -0
  353. package/dist/composables/useLiveAnnouncer.js.map +1 -0
  354. package/dist/composables/useMaskedField.d.ts +5 -5
  355. package/dist/composables/useMaskedField.js.map +1 -1
  356. package/dist/composables/usePopover.d.ts +3 -3
  357. package/dist/composables/usePopover.js +6 -4
  358. package/dist/composables/usePopover.js.map +1 -1
  359. package/dist/composables/useProgressValue.js +11 -2
  360. package/dist/composables/useProgressValue.js.map +1 -1
  361. package/dist/composables/useRootAttrs.d.ts +1 -1
  362. package/dist/composables/useRootAttrs.js.map +1 -1
  363. package/dist/composables/useSlotNodes.d.ts +18 -0
  364. package/dist/composables/useSlotNodes.js +13 -0
  365. package/dist/composables/useSlotNodes.js.map +1 -0
  366. package/dist/composables/useTextLimit.d.ts +2 -1
  367. package/dist/composables/useTextLimit.js +2 -2
  368. package/dist/composables/useTextLimit.js.map +1 -1
  369. package/dist/composables/useTimer.d.ts +5 -0
  370. package/dist/composables/useTimer.js +22 -11
  371. package/dist/composables/useTimer.js.map +1 -1
  372. package/dist/i18n/en.js +1 -1
  373. package/dist/i18n/en.js.map +1 -1
  374. package/dist/i18n/fr.js +14 -14
  375. package/dist/i18n/fr.js.map +1 -1
  376. package/dist/i18n/state.d.ts +7 -7
  377. package/dist/i18n/state.js +37 -28
  378. package/dist/i18n/state.js.map +1 -1
  379. package/dist/i18n/types.d.ts +12 -12
  380. package/dist/icons.d.ts +2 -2
  381. package/dist/index.d.ts +12 -11
  382. package/dist/styles.css +1 -1
  383. package/dist/tokens/css.d.ts +1 -1
  384. package/dist/tokens/css.js.map +1 -1
  385. package/dist/tokens/index.d.ts +6 -0
  386. package/dist/tokens/semantic.d.ts +6 -0
  387. package/dist/tokens/semantic.js +66 -60
  388. package/dist/tokens/semantic.js.map +1 -1
  389. package/dist/tokens/themes/dark.js +3 -3
  390. package/dist/tokens/themes/dark.js.map +1 -1
  391. package/dist/tokens.json +130 -66
  392. package/dist/types.d.ts +1 -1
  393. package/dist/utils/arrowNav.d.ts +4 -1
  394. package/dist/utils/arrowNav.js +7 -7
  395. package/dist/utils/arrowNav.js.map +1 -1
  396. package/dist/utils/chip.d.ts +1 -1
  397. package/dist/utils/chip.js.map +1 -1
  398. package/dist/utils/clock.d.ts +113 -0
  399. package/dist/utils/clock.js +84 -0
  400. package/dist/utils/clock.js.map +1 -0
  401. package/dist/utils/css.d.ts +6 -4
  402. package/dist/utils/css.js +2 -2
  403. package/dist/utils/css.js.map +1 -1
  404. package/dist/utils/date.d.ts +7 -102
  405. package/dist/utils/date.js +33 -160
  406. package/dist/utils/date.js.map +1 -1
  407. package/dist/utils/direction.d.ts +1 -1
  408. package/dist/utils/direction.js.map +1 -1
  409. package/dist/utils/env.d.ts +12 -3
  410. package/dist/utils/env.js +6 -0
  411. package/dist/utils/env.js.map +1 -0
  412. package/dist/utils/file.d.ts +3 -3
  413. package/dist/utils/file.js +1 -1
  414. package/dist/utils/file.js.map +1 -1
  415. package/dist/utils/focus.d.ts +1 -1
  416. package/dist/utils/focus.js.map +1 -1
  417. package/dist/utils/hostWarns.d.ts +1 -1
  418. package/dist/utils/hostWarns.js.map +1 -1
  419. package/dist/utils/ids.d.ts +1 -1
  420. package/dist/utils/ids.js.map +1 -1
  421. package/dist/utils/matcher.d.ts +2 -2
  422. package/dist/utils/matcher.js.map +1 -1
  423. package/dist/utils/memo.d.ts +1 -1
  424. package/dist/utils/memo.js.map +1 -1
  425. package/dist/utils/text.d.ts +3 -3
  426. package/dist/utils/text.js.map +1 -1
  427. package/dist/utils/time.d.ts +2 -101
  428. package/dist/utils/time.js +22 -98
  429. package/dist/utils/time.js.map +1 -1
  430. package/dist/utils/vnode.d.ts +5 -3
  431. package/dist/utils/vnode.js.map +1 -1
  432. package/package.json +2 -2
@@ -1,32 +1,33 @@
1
- import { useLocale as e, useMessages as t } from "../../i18n/state.js";
2
- import n from "../VTypography/VTypography.js";
3
- import { useControlShape as ee } from "../../composables/useControlShape.js";
4
- import { useRootAttrs as te } from "../../composables/useRootAttrs.js";
5
- import { joinIds as r } from "../../utils/ids.js";
6
- import { iconStartListener as i } from "../../composables/useIconClickHandlers.js";
7
- import { canClear as a } from "../../composables/useClearable.js";
1
+ import { isDev as e } from "../../utils/env.js";
2
+ import { useLocale as t, useMessages as n } from "../../i18n/state.js";
3
+ import ee from "../VTypography/VTypography.js";
4
+ import { useControlShape as r } from "../../composables/useControlShape.js";
5
+ import { useRootAttrs as i } from "../../composables/useRootAttrs.js";
6
+ import { joinIds as a } from "../../utils/ids.js";
7
+ import { iconStartListener as o } from "../../composables/useIconClickHandlers.js";
8
+ import { canClear as te } from "../../composables/useClearable.js";
8
9
  import { inputGroupKey as ne } from "../VInput/context.js";
9
10
  import re from "../VInput/VInput.js";
10
11
  import ie from "../VChip/VChip.js";
11
12
  import { chipScaleFor as ae } from "../../utils/chip.js";
12
- import { attach_file as o } from "../VIcon/icons/attach_file.js";
13
+ import { attach_file as s } from "../VIcon/icons/attach_file.js";
13
14
  import { useFileDrop as oe } from "../../composables/useFileDrop.js";
14
15
  import { fileKey as se, formatBytes as ce } from "../../utils/file.js";
15
16
  import { useFileField as le } from "../../composables/useFileField.js";
16
17
  import { truncateMiddle as ue } from "./truncate.js";
17
- import { Fragment as de, computed as s, createBlock as c, createCommentVNode as l, createElementBlock as u, createElementVNode as d, createSlots as f, createTextVNode as p, createVNode as m, defineComponent as h, inject as fe, mergeModels as g, mergeProps as _, normalizeClass as pe, normalizeStyle as me, openBlock as v, ref as y, renderList as he, renderSlot as b, toDisplayString as x, unref as S, useId as C, useModel as ge, withCtx as w } from "vue";
18
+ import { Fragment as de, computed as c, createBlock as l, createCommentVNode as u, createElementBlock as d, createElementVNode as f, createSlots as fe, createTextVNode as p, createVNode as m, defineComponent as h, inject as pe, mergeModels as g, mergeProps as _, normalizeClass as me, normalizeStyle as he, openBlock as v, ref as y, renderList as ge, renderSlot as b, toDisplayString as x, unref as S, useId as C, useModel as _e, withCtx as w } from "vue";
18
19
  //#region src/components/VFileInput/VFileInput.vue?vue&type=script&setup=true&lang.ts
19
- var _e = [
20
+ var ve = [
20
21
  "data-size",
21
22
  "data-compact",
22
23
  "data-display",
23
24
  "data-disabled",
24
25
  "data-readonly",
25
26
  "data-dragging"
26
- ], ve = {
27
+ ], ye = {
27
28
  key: 0,
28
29
  class: "v-file-input-meta v-field-meta"
29
- }, ye = ["id"], T = /*@__PURE__*/ h({
30
+ }, T = ["id"], E = /*@__PURE__*/ h({
30
31
  inheritAttrs: !1,
31
32
  __name: "VFileInput",
32
33
  props: /*@__PURE__*/ g({
@@ -43,7 +44,7 @@ var _e = [
43
44
  type: Boolean,
44
45
  default: !1
45
46
  },
46
- pickerIcon: { default: () => o },
47
+ pickerIcon: { default: () => s },
47
48
  noDrop: {
48
49
  type: Boolean,
49
50
  default: !1
@@ -75,7 +76,7 @@ var _e = [
75
76
  type: Boolean,
76
77
  default: !1
77
78
  },
78
- loadingLabel: { default: void 0 },
79
+ loadingText: { default: void 0 },
79
80
  clearable: {
80
81
  type: Boolean,
81
82
  default: !1
@@ -92,89 +93,90 @@ var _e = [
92
93
  "clear",
93
94
  "click:icon-start"
94
95
  ], ["update:modelValue"]),
95
- setup(o, { expose: h, emit: g }) {
96
- let T = o, E = g, D = ge(o, "modelValue"), { attrs: O, rootClass: k, rootStyle: A, forwardedAttrs: j } = te(), M = i((e) => E("click:icon-start", e)), N = t(), P = e(), { size: F, compact: I, disabled: L } = ee(T, fe(ne, null)), { fileEl: be, enabled: R, nativeInputAttrs: xe, controlAttrs: Se, acceptFiles: Ce, openPicker: z, removeAt: we, clear: Te } = le({
97
- model: D,
98
- props: T,
99
- emit: E,
100
- forwardedAttrs: j,
96
+ setup(s, { expose: h, emit: g }) {
97
+ let E = s, D = g, O = _e(s, "modelValue", { get: (e) => e ?? [] }), { attrs: k, rootClass: A, rootStyle: j, forwardedAttrs: M } = i(), N = o((e) => D("click:icon-start", e)), P = n(), be = t(), { size: F, compact: I, disabled: L } = r(E, pe(ne, null)), { fileEl: xe, enabled: R, nativeInputAttrs: Se, controlAttrs: Ce, acceptFiles: we, openPicker: z, removeAt: Te, clear: Ee } = le({
98
+ model: O,
99
+ props: E,
100
+ emit: D,
101
+ forwardedAttrs: M,
101
102
  disabled: L,
102
103
  excludeFromControl: ["aria-describedby"],
103
- onClear: () => E("clear"),
104
- warnings: void 0
105
- }), Ee = s(() => ({
106
- ...Se.value,
107
- ...M
108
- })), B = y(null), V = y(null), H = s(() => T.multiple ? T.display : "text"), De = s(() => H.value === "chip" ? "" : D.value.map((e) => e.name).join(", ")), Oe = s(() => D.value.length > 0 ? void 0 : T.placeholder ?? N.value.fileInput.placeholder), ke = s(() => a(T, L.value, D.value.length > 0)), Ae = s(() => T.readonly ? void 0 : T.pickerIcon), je = s(() => T.pickerIconLabel ?? N.value.fileInput.openPicker), Me = s(() => T.clearLabel ?? N.value.fileInput.clear), U = s(() => D.value.reduce((e, t) => e + t.size, 0)), W = s(() => {
109
- let e = N.value.fileInput.files(D.value.length);
110
- return D.value.length === 0 ? e : `${e} (${ce(U.value, P.value)})`;
111
- }), G = C(), K = C(), Ne = s(() => r(O["aria-describedby"], !!T.hint && G, T.counter && K)), q = s(() => ae(F.value, I.value)), J = s(() => D.value.map((e) => ue(e.name)));
112
- function Pe(e) {
104
+ onClear: () => D("clear"),
105
+ warnings: e ? () => [E.display === "chip" && !E.multiple && "display=\"chip\" ignored without `multiple`: a single file shows as text."] : void 0
106
+ }), De = c(() => ({
107
+ ...Ce.value,
108
+ ...N
109
+ })), B = y(null), V = y(null), H = c(() => E.multiple ? E.display : "text"), Oe = c(() => H.value === "chip" ? "" : O.value.map((e) => e.name).join(", ")), ke = c(() => O.value.length > 0 ? void 0 : E.placeholder ?? P.value.fileInput.placeholder), Ae = c(() => te(E, L.value, O.value.length > 0)), je = c(() => E.readonly ? void 0 : E.pickerIcon), Me = c(() => E.pickerIconLabel ?? P.value.fileInput.openPicker), Ne = c(() => E.clearLabel ?? P.value.fileInput.clear), U = c(() => O.value.reduce((e, t) => e + t.size, 0)), W = c(() => {
110
+ let e = P.value.fileInput.files(O.value.length);
111
+ return O.value.length === 0 ? e : `${e} (${ce(U.value, be.value)})`;
112
+ }), G = C(), K = C(), Pe = c(() => a(k["aria-describedby"], !!E.hint && G, E.counter && K)), q = c(() => ae(F.value, I.value)), J = c(() => O.value.map((e) => ue(e.name)));
113
+ function Fe(e) {
113
114
  e.target.closest("button") || z();
114
115
  }
115
- function Fe(e) {
116
+ function Ie(e) {
116
117
  e.key !== "Enter" && e.key !== " " || (e.preventDefault(), z());
117
118
  }
118
119
  function Y(e) {
119
- we(e) && B.value?.focus();
120
+ Te(e) && B.value?.focus();
120
121
  }
121
- let { dragging: Ie, onDragEnter: X, onDragOver: Z, onDragLeave: Q, onDrop: $ } = oe(() => !T.noDrop && R.value, Ce);
122
+ let { dragging: Le, onDragEnter: X, onDragOver: Z, onDragLeave: Q, onDrop: $ } = oe(() => !E.noDrop && R.value, we);
122
123
  return h({
123
124
  focus: (e) => B.value?.focus(e),
124
125
  open: z,
125
126
  el: V
126
- }), (e, t) => (v(), u("div", {
127
+ }), (e, t) => (v(), d("div", {
127
128
  ref_key: "rootEl",
128
129
  ref: V,
129
- class: pe(["v-file-input", S(k)]),
130
- style: me([{ "--chip-height": q.value.height }, S(A)]),
130
+ class: me(["v-file-input", S(A)]),
131
+ style: he([{ "--chip-height": q.value.height }, S(j)]),
131
132
  "data-size": S(F),
132
133
  "data-compact": S(I) ? "" : void 0,
133
134
  "data-display": H.value,
134
135
  "data-disabled": S(L) ? "" : void 0,
135
- "data-readonly": o.readonly ? "" : void 0,
136
- "data-dragging": S(Ie) ? "" : void 0,
136
+ "data-readonly": s.readonly ? "" : void 0,
137
+ "data-dragging": S(Le) ? "" : void 0,
137
138
  onDragenter: t[0] ||= (...e) => S(X) && S(X)(...e),
138
139
  onDragover: t[1] ||= (...e) => S(Z) && S(Z)(...e),
139
140
  onDragleave: t[2] ||= (...e) => S(Q) && S(Q)(...e),
140
141
  onDrop: t[3] ||= (...e) => S($) && S($)(...e)
141
142
  }, [
142
- d("input", _(S(xe), {
143
+ f("input", _(S(Se), {
143
144
  ref_key: "fileEl",
144
- ref: be,
145
+ ref: xe,
145
146
  class: "v-file-input-native v-hidden-input"
146
147
  }), null, 16),
147
- d("div", {
148
+ f("div", {
148
149
  class: "v-file-input-control",
149
- onClick: Pe
150
- }, [m(re, _(Ee.value, {
150
+ onClick: Fe
151
+ }, [m(re, _(De.value, {
151
152
  ref_key: "inputRef",
152
153
  ref: B,
153
154
  class: { "v-input-end-pinned v-input-chips": H.value === "chip" },
154
- "model-value": De.value,
155
- readonly: "",
156
- label: o.label,
157
- placeholder: Oe.value,
155
+ "model-value": Oe.value,
156
+ "no-typing": "",
157
+ readonly: s.readonly,
158
+ label: s.label,
159
+ placeholder: ke.value,
158
160
  size: S(F),
159
161
  compact: S(I),
160
162
  disabled: S(L),
161
- invalid: o.invalid,
162
- clearable: o.clearable,
163
- "clear-visible": ke.value,
164
- "clear-label": Me.value,
165
- "icon-start": o.iconStart,
166
- "icon-start-label": o.iconStartLabel,
167
- loading: o.loading,
168
- "loading-label": o.loadingLabel,
169
- "icon-end": Ae.value,
170
- "icon-end-label": je.value,
171
- "aria-describedby": Ne.value,
163
+ invalid: s.invalid,
164
+ clearable: s.clearable,
165
+ "clear-visible": Ae.value,
166
+ "clear-label": Ne.value,
167
+ "icon-start": s.iconStart,
168
+ "icon-start-label": s.iconStartLabel,
169
+ loading: s.loading,
170
+ "loading-text": s.loadingText,
171
+ "icon-end": je.value,
172
+ "icon-end-label": Me.value,
173
+ "aria-describedby": Pe.value,
172
174
  "onClick:iconEnd": S(z),
173
- onClear: S(Te),
174
- onKeydown: Fe
175
- }), f({ _: 2 }, [H.value === "chip" || e.$slots.start ? {
175
+ onClear: S(Ee),
176
+ onKeydown: Ie
177
+ }), fe({ _: 2 }, [H.value === "chip" || e.$slots.start ? {
176
178
  name: "start",
177
- fn: w(() => [(v(!0), u(de, null, he(H.value === "chip" ? D.value : [], (t, n) => b(e.$slots, "chip", {
179
+ fn: w(() => [(v(!0), d(de, null, ge(H.value === "chip" ? O.value : [], (t, n) => b(e.$slots, "chip", {
178
180
  file: t,
179
181
  index: n,
180
182
  label: J.value[n],
@@ -186,7 +188,7 @@ var _e = [
186
188
  size: q.value.size,
187
189
  compact: q.value.compact,
188
190
  dismissible: S(R),
189
- "dismiss-label": S(N).common.remove(t.name),
191
+ "dismiss-label": S(P).common.remove(t.name),
190
192
  disabled: S(L),
191
193
  title: J.value[n] === t.name ? void 0 : t.name,
192
194
  onDismiss: (e) => Y(n)
@@ -210,6 +212,7 @@ var _e = [
210
212
  } : void 0]), 1040, [
211
213
  "class",
212
214
  "model-value",
215
+ "readonly",
213
216
  "label",
214
217
  "placeholder",
215
218
  "size",
@@ -222,35 +225,35 @@ var _e = [
222
225
  "icon-start",
223
226
  "icon-start-label",
224
227
  "loading",
225
- "loading-label",
228
+ "loading-text",
226
229
  "icon-end",
227
230
  "icon-end-label",
228
231
  "aria-describedby",
229
232
  "onClick:iconEnd",
230
233
  "onClear"
231
234
  ])]),
232
- o.hint || o.counter ? (v(), u("div", ve, [o.hint ? (v(), c(n, {
235
+ s.hint || s.counter ? (v(), d("div", ye, [s.hint ? (v(), l(ee, {
233
236
  key: 0,
234
237
  id: S(G),
235
238
  variant: "caption",
236
239
  tone: "muted",
237
240
  class: "v-file-input-hint"
238
241
  }, {
239
- default: w(() => [p(x(o.hint), 1)]),
242
+ default: w(() => [p(x(s.hint), 1)]),
240
243
  _: 1
241
- }, 8, ["id"])) : l("", !0), o.counter ? (v(), u("span", {
244
+ }, 8, ["id"])) : u("", !0), s.counter ? (v(), d("span", {
242
245
  key: 1,
243
246
  id: S(K),
244
247
  class: "v-file-input-counter v-field-counter"
245
248
  }, [b(e.$slots, "counter", {
246
- count: D.value.length,
249
+ count: O.value.length,
247
250
  bytes: U.value,
248
251
  text: W.value
249
- }, () => [p(x(W.value), 1)])], 8, ye)) : l("", !0)])) : l("", !0)
250
- ], 46, _e));
252
+ }, () => [p(x(W.value), 1)])], 8, T)) : u("", !0)])) : u("", !0)
253
+ ], 46, ve));
251
254
  }
252
255
  });
253
256
  //#endregion
254
- export { T as default };
257
+ export { E as default };
255
258
 
256
259
  //# sourceMappingURL=VFileInput.vue_vue_type_script_setup_true_lang.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"VFileInput.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VFileInput/VFileInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * File selection presented as an ordinary form field: a read-only VInput showing what was\n * picked, with the real file input hidden behind it — VDateInput's `readonly` shape, minus\n * the panel. The v-model is always a `File[]`, `multiple` or not, so a consumer never has to\n * narrow a union TypeScript cannot discriminate.\n *\n * The JS is imposed by the platform, not chosen. A dialog opens ONLY from a real click on a\n * file input, and a `FileList` cannot be written from a template — so the visible field can\n * never BE the native control, and that control is only ever a SOURCE of files.\n *\n * The rest follows: the relayed click, the reset after every change (without which the same\n * file cannot be picked twice running), and screening in code, `accept` having no say over\n * a drop.\n */\nimport { computed, inject, ref, useId } from 'vue'\n\nimport VChip from '../VChip/VChip.vue'\nimport type { ChipSize } from '../VChip/VChip.vue'\nimport { attach_file as attachFileIcon } from '../VIcon/icons/attach_file'\nimport type { IconSource } from '../VIcon/types'\nimport VInput from '../VInput/VInput.vue'\nimport { inputGroupKey } from '../VInput/context'\nimport VTypography from '../VTypography/VTypography.vue'\n\nimport { canClear } from '../../composables/useClearable'\nimport { useControlShape } from '../../composables/useControlShape'\nimport { useFileDrop } from '../../composables/useFileDrop'\nimport { useFileField } from '../../composables/useFileField'\nimport { iconStartListener } from '../../composables/useIconClickHandlers'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport { useLocale, useMessages } from '../../i18n/state'\nimport { chipScaleFor } from '../../utils/chip'\nimport { isDev } from '../../utils/env'\nimport { fileKey, formatBytes, type FileRejection } from '../../utils/file'\nimport { joinIds } from '../../utils/ids'\nimport { truncateMiddle } from './truncate'\n\n/** How the chosen files are shown inside the field when several are allowed. */\nexport type FileInputDisplay = 'text' | 'chip'\n\n/** The height of the field: 32, 40 or 48 pixels. */\nexport type FileInputSize = 'sm' | 'md' | 'lg'\n\ninterface FileInputProps {\n /** Allows several files to be chosen. With one only, every extra file is turned away. */\n multiple?: boolean\n /**\n * Which kinds of file are accepted, in the browser's own syntax (`image/*,.pdf`).\n *\n * It is applied TWICE, and it has to be: as an attribute, which is what filters the\n * system's file dialog, and again in code, which is the only thing that can filter a\n * file DROPPED on the component — the attribute has no say over a drop.\n */\n accept?: string\n /**\n * How the chosen files are shown: their names joined by commas, or one dismissible\n * chip each. It only means something when several files are allowed; a single name is\n * always text.\n */\n display?: FileInputDisplay\n /** The largest ONE file may be, in bytes. */\n maxSize?: number\n /** The largest the whole selection may be, in bytes. */\n maxTotalSize?: number\n /** How many files may be chosen at most. */\n maxFiles?: number\n /** Shows how much has been chosen under the field: \"3 files (1.2 MB)\". */\n counter?: boolean\n /** The icon at the end of the field, which opens the file dialog. */\n pickerIcon?: IconSource\n /** Refuses files dropped onto the component: only the dialog then adds any. */\n noDrop?: boolean\n /** The height of the field: 32, 40 or 48 pixels. */\n size?: FileInputSize\n /** Takes 4px off the height, leaving the padding, the text and the icons as they are. */\n compact?: boolean\n /** Makes the field unusable, greyed out through the colour tokens. */\n disabled?: boolean\n /**\n * Shows what was chosen without allowing it to change: no dialog, no drop, no removal.\n */\n readonly?: boolean\n /**\n * Marks the field as invalid — for a rule of your own, since nothing here is checked\n * by the browser.\n */\n invalid?: boolean\n /** The label above the field, tied to it so that clicking it focuses the field. */\n label?: string\n /**\n * A line of help under the field, to the left of the counter. It is tied to the field\n * for assistive technology.\n */\n hint?: string\n /**\n * What the field says while nothing is chosen. It falls back to the design system\n * dictionary.\n */\n placeholder?: string\n /**\n * An icon inside the field, at the start. It is rendered before the chips rather than\n * in their place, so it survives a chip display. Decorative by default, it becomes a\n * real button as soon as a `@click:icon-start` listener is attached, in which case it\n * needs `iconStartLabel`.\n */\n iconStart?: IconSource\n /** What the start icon does, in words, once it is clickable. */\n iconStartLabel?: string\n /**\n * What the button at the end of the field does, in words. It names the button\n * `pickerIcon` renders, and falls back to the design system dictionary.\n */\n pickerIconLabel?: string\n /**\n * Shows a spinner at the end of the field, in place of the attach icon — while an\n * upload is under way, typically. It says that something is happening and changes\n * nothing else: files can still be dropped and the dialog still opens.\n */\n loading?: boolean\n /**\n * What screen readers announce while the spinner turns. It falls back to the design\n * system dictionary.\n */\n loadingLabel?: string\n /**\n * Offers a cross that empties the selection. Worth turning on here more than on an\n * ordinary field: what a picker holds cannot be erased by typing, so the cross is the\n * only way back out of a wrong choice.\n */\n clearable?: boolean\n /** What that cross does, in words. It falls back to the design system dictionary. */\n clearLabel?: string\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FileInputProps>(), {\n multiple: false,\n accept: undefined,\n display: 'text',\n maxSize: undefined,\n maxTotalSize: undefined,\n maxFiles: undefined,\n counter: false,\n pickerIcon: () => attachFileIcon,\n noDrop: false,\n size: 'md',\n compact: false,\n disabled: false,\n readonly: false,\n invalid: false,\n label: undefined,\n hint: undefined,\n placeholder: undefined,\n iconStart: undefined,\n iconStartLabel: undefined,\n pickerIconLabel: undefined,\n loading: false,\n loadingLabel: undefined,\n clearable: false,\n clearLabel: undefined,\n})\n\nconst emit = defineEmits<{\n /** The reader changed the selection — added something, removed something, cleared it. */\n change: [files: File[]]\n /**\n * A file was turned away and never joined the selection. It is emitted once PER file,\n * so a batch drop can be reported precisely.\n */\n reject: [rejection: FileRejection]\n /**\n * ONE file was taken out through its chip, with the file and the position it held.\n * `change` follows it with the whole list, as it does after every other change.\n */\n remove: [file: File, index: number]\n /** The clear cross emptied the selection. */\n clear: []\n /** The start icon was clicked. Attaching this listener is what makes it a button. */\n 'click:icon-start': [event: MouseEvent]\n}>()\n\ndefineSlots<{\n /**\n * Content at the start of the field, rendered after the chips standing for the chosen\n * files rather than in their place.\n */\n start?(): unknown\n /**\n * Controls of your own inside the field, placed before the ones the field owns — the\n * clear cross and the icon that opens the file dialog. Those two are this component's\n * own affordance, which is why there is no `#end` here: it would replace them.\n */\n 'value-end'?(): unknown\n /**\n * Replaces the chip standing for one file.\n *\n * Three of the values it receives are what make it usable without regressions:\n * `label` is the name already shortened in the MIDDLE so that its extension survives,\n * `remove` is what takes the file out — without it the file could no longer be removed\n * at all — and the size and density are the ones worked out to sit inside the field,\n * which cannot be guessed from outside.\n */\n chip?(props: {\n file: File\n index: number\n label: string\n remove: () => void\n size: ChipSize\n compact: boolean\n }): unknown\n /**\n * Replaces the counter under the field. `text` is the sentence already built and\n * translated; the count and the total size in `bytes` are there for a wording of your own.\n */\n counter?(props: { count: number; bytes: number; text: string }): unknown\n}>()\n\n/**\n * Always a LIST of files, whether or not several are allowed — never a file on its own.\n * The shape of the value does not depend on a prop, so a consumer never has to narrow a\n * union TypeScript has no way of discriminating. With a single file it is simply a list\n * of at most one.\n */\nconst model = defineModel<File[]>({ default: () => [] })\n\nconst { attrs, rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\n\n// Declared as this component's own event, `click:icon-start` is out of `$attrs`, so the\n// listener is relayed to the field by hand — and only when the consumer wrote one.\nconst iconStartClick = iconStartListener((event) => emit('click:icon-start', event))\n\nconst m = useMessages()\nconst locale = useLocale()\n\n// A VInputGroup joins several controls into one object, so the shape of this field is the\n// row's decision rather than its own (VInput/context.ts). The chips read the resolved pair\n// too, or they would come out one step off the field they sit in.\nconst group = inject(inputGroupKey, null)\nconst {\n size: resolvedSize,\n compact: resolvedCompact,\n disabled: resolvedDisabled,\n} = useControlShape(props, group)\n\n/*\n * The hidden input, the sorting of the consumer's attributes, the single entry point into\n * the value, the removal of a file and the emptying of all of them live in `useFileField`,\n * shared with VFilePicker.\n *\n * Here, the bucket meant for \"the control the user deals with\" goes to the visible\n * field: that is what they see, focus and click, so a consumer's own `<label for>` has\n * to point at it. The description attribute is pulled out of that bucket, because this\n * component re-assembles it further down.\n */\nconst {\n fileEl,\n enabled,\n nativeInputAttrs,\n controlAttrs,\n acceptFiles,\n openPicker,\n removeAt,\n clear,\n} = useFileField({\n model,\n props,\n emit,\n forwardedAttrs,\n disabled: resolvedDisabled,\n excludeFromControl: ['aria-describedby'],\n onClear: () => emit('clear'),\n // Behind `isDev`, which a production build folds to false, so the message is dropped.\n warnings: isDev\n ? () => [\n props.display === 'chip' &&\n !props.multiple &&\n 'display=\"chip\" ignored without `multiple`: a single file shows as text.',\n ]\n : undefined,\n})\n\n/** What reaches the visible field: the consumer's own attributes, plus that listener. */\nconst fieldAttrs = computed(() => ({ ...controlAttrs.value, ...iconStartClick }))\n\nconst inputRef = ref<InstanceType<typeof VInput> | null>(null)\nconst rootEl = ref<HTMLElement | null>(null)\n\n// Chips only mean something for a list: a single file always shows as plain text.\nconst resolvedDisplay = computed<FileInputDisplay>(() => (props.multiple ? props.display : 'text'))\n\nconst displayText = computed(() =>\n resolvedDisplay.value === 'chip' ? '' : model.value.map((file) => file.name).join(', '),\n)\n\nconst placeholderText = computed(() =>\n model.value.length > 0 ? undefined : (props.placeholder ?? m.value.fileInput.placeholder),\n)\n\n/*\n * Whether the clear cross is shown has to be answered EXPLICITLY here. The visible field\n * is read-only, and a read-only field hides its cross by default — rightly so, since its\n * text cannot be edited. Here the value comes from the file dialog rather than from\n * typing, so there is something to clear all the same.\n */\nconst clearVisible = computed(() => canClear(props, resolvedDisabled.value, model.value.length > 0))\n\n// @a11y @devwarn\n/*\n * The icon disappears along with what it offers: a read-only field opens no dialog, so\n * an icon inviting one would be a lie — the same rule VDateInput follows for its\n * calendar.\n *\n * TRAP — its LABEL stays defined at all times, even when no icon is rendered. The helper\n * that detects a click handler on an icon warns AT SETUP if one is attached without a\n * label, and it has no way of knowing whether an icon exists.\n */\nconst endIcon = computed<IconSource | undefined>(() =>\n props.readonly ? undefined : props.pickerIcon,\n)\nconst endIconLabel = computed(() => props.pickerIconLabel ?? m.value.fileInput.openPicker)\nconst resolvedClearLabel = computed(() => props.clearLabel ?? m.value.fileInput.clear)\n\nconst totalSize = computed(() => model.value.reduce((sum, file) => sum + file.size, 0))\n\n/*\n * The counter is assembled from three sources: the WORD comes from the dictionary, since\n * it is language; the SIZE is formatted by the platform, which knows the local\n * conventions; and the parentheses come from neither, being punctuation every language\n * shares — the same boundary VBadge's \"99+\" falls on.\n *\n * With nothing chosen it states the count alone: \"0 files ()\" would be noise.\n */\nconst counterText = computed(() => {\n const word = m.value.fileInput.files(model.value.length)\n return model.value.length === 0 ? word : `${word} (${formatBytes(totalSize.value, locale.value)})`\n})\n\nconst hintId = useId()\nconst counterId = useId()\n\n// @a11y\n/*\n * What describes the field for a screen reader is a LIST of references, assembled here\n * rather than by VInput: the hint belongs to OUR row under the field, VInput having no\n * such row — its own counter sits inside the field.\n *\n * The counter is deliberately part of that list, unlike in VTextarea. When the files are\n * shown as chips the field's own text is EMPTY, and the counter is then the only spoken\n * summary of what has been chosen.\n */\nconst describedBy = computed(() =>\n joinIds(\n attrs['aria-describedby'] as string | undefined,\n !!props.hint && hintId,\n props.counter && counterId,\n ),\n)\n\n// The size, the density and the HEIGHT of the chips sitting inside the field, worked out\n// once in `utils/chip.ts` and shared with VCombobox. The height is set inline rather than\n// restated as a table of CSS rules: it belongs to the chips' own subtree, out of the\n// field's reach, and the field has to force its input to that same height or it grows\n// when focused.\nconst chipScale = computed(() => chipScaleFor(resolvedSize.value, resolvedCompact.value))\n\n/**\n * What each chip shows for its file, worked out once per change of the selection rather\n * than on every render, which reads it three times per chip. The name is shortened in the\n * MIDDLE rather than cut off at the end, for two reasons.\n *\n * The chips WRAP, so there is no line for a long name to overflow: left whole it would\n * simply push the field onto two or three rows. And cutting the middle preserves the\n * extension, which is what tells the reader what kind of file it is — an ellipsis at the\n * end drops it first.\n *\n * The full name is never lost: the removal button is named with it, and the chip carries\n * it as a tooltip whenever the label was actually shortened.\n */\n// Computed lazily, so a text display, which never reads it, never pays for it.\nconst chipLabels = computed(() => model.value.map((file) => truncateMiddle(file.name)))\n\nfunction onControlClick(event: MouseEvent) {\n // The field's own buttons already handle their clicks, and the click also reaches the\n // field itself. Without this guard the attach icon would open the dialog TWICE, and\n // the clear cross would reopen it immediately after emptying the selection.\n if ((event.target as HTMLElement).closest('button')) return\n openPicker()\n}\n\nfunction onFieldKeydown(event: KeyboardEvent) {\n if (event.key !== 'Enter' && event.key !== ' ') return\n // Cancelling the default on Enter also stops the form from being submitted: a\n // read-only text field is still a field, and Enter in one submits the form around it.\n event.preventDefault()\n openPicker()\n}\n\nfunction removeFile(index: number) {\n // The removal button disappears along with its chip, so the focus would fall back to\n // the page body. Unlike the date and time pickers, nothing here opens on focus, so\n // this needs no guard against re-entering.\n if (removeAt(index)) inputRef.value?.focus()\n}\n\n/* Files may be dropped on the component itself; there is no separate drop area here —\n that is what VFilePicker is for. */\nconst { dragging, onDragEnter, onDragOver, onDragLeave, onDrop } = useFileDrop(\n () => !props.noDrop && enabled.value,\n acceptFiles,\n)\n\ndefineExpose({\n /** Moves the focus to the visible field. */\n focus: (options?: FocusOptions) => inputRef.value?.focus(options),\n /**\n * Opens the file dialog. It only works when called from something the reader did — a\n * click, a key press: browsers refuse to open a file dialog by themselves.\n */\n open: openPicker,\n /**\n * The component's own box, for what neither of the two above covers. It is the wrapper\n * and not the hidden file input: that one is the FORM's element, this is the reader's.\n */\n el: rootEl,\n})\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n class=\"v-file-input\"\n :class=\"rootClass\"\n :style=\"[{ '--chip-height': chipScale.height }, rootStyle]\"\n :data-size=\"resolvedSize\"\n :data-compact=\"resolvedCompact ? '' : undefined\"\n :data-display=\"resolvedDisplay\"\n :data-disabled=\"resolvedDisabled ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n :data-dragging=\"dragging ? '' : undefined\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <input v-bind=\"nativeInputAttrs\" ref=\"fileEl\" class=\"v-file-input-native v-hidden-input\" />\n\n <div class=\"v-file-input-control\" @click=\"onControlClick\">\n <!-- Shown as chips, the field takes VInput's two arrangements for chips: its end\n controls lifted out of the flow, and the chips wrapping onto several rows. -->\n <VInput\n v-bind=\"fieldAttrs\"\n ref=\"inputRef\"\n :class=\"{ 'v-input-end-pinned v-input-chips': resolvedDisplay === 'chip' }\"\n :model-value=\"displayText\"\n readonly\n :label=\"label\"\n :placeholder=\"placeholderText\"\n :size=\"resolvedSize\"\n :compact=\"resolvedCompact\"\n :disabled=\"resolvedDisabled\"\n :invalid=\"invalid\"\n :clearable=\"clearable\"\n :clear-visible=\"clearVisible\"\n :clear-label=\"resolvedClearLabel\"\n :icon-start=\"iconStart\"\n :icon-start-label=\"iconStartLabel\"\n :loading=\"loading\"\n :loading-label=\"loadingLabel\"\n :icon-end=\"endIcon\"\n :icon-end-label=\"endIconLabel\"\n :aria-describedby=\"describedBy\"\n @click:icon-end=\"openPicker\"\n @clear=\"clear\"\n @keydown=\"onFieldKeydown\"\n >\n <template v-if=\"resolvedDisplay === 'chip' || $slots.start\" #start>\n <template\n v-for=\"(file, index) in resolvedDisplay === 'chip' ? model : []\"\n :key=\"fileKey(file)\"\n >\n <slot\n name=\"chip\"\n :file=\"file\"\n :index=\"index\"\n :label=\"chipLabels[index]!\"\n :remove=\"() => removeFile(index)\"\n :size=\"chipScale.size\"\n :compact=\"chipScale.compact\"\n >\n <VChip\n tone=\"accent\"\n :size=\"chipScale.size\"\n :compact=\"chipScale.compact\"\n :dismissible=\"enabled\"\n :dismiss-label=\"m.common.remove(file.name)\"\n :disabled=\"resolvedDisabled\"\n :title=\"chipLabels[index] === file.name ? undefined : file.name\"\n @dismiss=\"removeFile(index)\"\n >{{ chipLabels[index] }}</VChip\n >\n </slot>\n </template>\n <slot name=\"start\" />\n </template>\n\n <template v-if=\"$slots['value-end']\" #value-end><slot name=\"value-end\" /></template>\n </VInput>\n </div>\n\n <div v-if=\"hint || counter\" class=\"v-file-input-meta v-field-meta\">\n <VTypography\n v-if=\"hint\"\n :id=\"hintId\"\n variant=\"caption\"\n tone=\"muted\"\n class=\"v-file-input-hint\"\n >\n {{ hint }}\n </VTypography>\n <span v-if=\"counter\" :id=\"counterId\" class=\"v-file-input-counter v-field-counter\">\n <slot name=\"counter\" :count=\"model.length\" :bytes=\"totalSize\" :text=\"counterText\">\n {{ counterText }}\n </slot>\n </span>\n </div>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n /* Positioned so the hidden file input, which has no size at all, has something to be\n placed against. */\n .v-file-input {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: var(--vectis-space-1);\n width: 100%;\n font-family: var(--vectis-text-family);\n }\n\n /* The real file input is a SOURCE of files and not a control anyone deals with: it\n wears `.v-hidden-input`, and taking it out of the tab order and hiding it from screen\n readers, in `useFileField`, is what leaves the visible field as the single stop and the\n single announcement. */\n .v-file-input:not([data-disabled]):not([data-readonly]) .v-file-input-control,\n .v-file-input:not([data-disabled]):not([data-readonly])[data-display='text'] .v-input-control {\n cursor: pointer;\n }\n\n /* An ellipsis DOES work on an input, and a read-only one never scrolls by itself, so a\n long list of names is simply cut short. No tooltip is added for the rest: it would be\n announced as a description repeating the value the field already shows, and the\n complete list is what the model is for. */\n .v-file-input[data-display='text'] .v-input-control {\n text-overflow: ellipsis;\n }\n\n /* While a file is being dragged over it, the field is highlighted by redefining the\n very variable VInput uses for its own border colour — so the two can never disagree.\n\n TRAP — the selector weighs (0,4,0), one step above VInput's states, and it has to. The\n field inside is ALWAYS read-only, and VInput's read-only background weighs (0,3,0): at\n that weight the winner would be whichever of the two sheets a bundler put last. */\n .v-file-input[data-dragging] .v-input .v-input-field {\n --field-border-color: var(--vectis-color-accent);\n\n background: var(--vectis-color-accent-surface);\n }\n\n .v-file-input[data-disabled] .v-file-input-hint,\n .v-file-input[data-disabled] .v-file-input-counter {\n color: var(--vectis-color-text-subtle);\n }\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"VFileInput.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/VFileInput/VFileInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\n// @core\n/**\n * File selection presented as an ordinary form field: a read-only VInput showing what was\n * picked, with the real file input hidden behind it — VDateInput's `readonly` shape, minus\n * the panel. The v-model is always a `File[]`, `multiple` or not, so a consumer never has to\n * narrow a union TypeScript cannot discriminate.\n *\n * The JS is imposed by the platform, not chosen. A dialog opens ONLY from a real click on a\n * file input, and a `FileList` cannot be written from a template — so the visible field can\n * never BE the native control, and that control is only ever a SOURCE of files.\n *\n * The rest follows: the relayed click, the reset after every change (without which the same\n * file cannot be picked twice running), and screening in code, `accept` having no say over\n * a drop.\n */\nimport { computed, inject, ref, useId } from 'vue'\n\nimport VChip from '../VChip/VChip.vue'\nimport type { ChipSize } from '../VChip/VChip.vue'\nimport { attach_file as attachFileIcon } from '../VIcon/icons/attach_file'\nimport type { IconSource } from '../VIcon/types'\nimport VInput from '../VInput/VInput.vue'\nimport { inputGroupKey } from '../VInput/context'\nimport VTypography from '../VTypography/VTypography.vue'\n\nimport { canClear } from '../../composables/useClearable'\nimport { useControlShape } from '../../composables/useControlShape'\nimport { useFileDrop } from '../../composables/useFileDrop'\nimport { useFileField } from '../../composables/useFileField'\nimport { iconStartListener } from '../../composables/useIconClickHandlers'\nimport { useRootAttrs } from '../../composables/useRootAttrs'\nimport { useLocale, useMessages } from '../../i18n/state'\nimport { chipScaleFor } from '../../utils/chip'\nimport { isDev } from '../../utils/env'\nimport { fileKey, formatBytes, type FileRejection } from '../../utils/file'\nimport { joinIds } from '../../utils/ids'\nimport { truncateMiddle } from './truncate'\n\n/** How the chosen files are shown inside the field when several are allowed. */\nexport type FileInputDisplay = 'chip' | 'text'\n\n/** What the `#chip` slot receives. */\nexport interface FileInputChipSlotProps {\n /** The file the chip stands for. */\n file: File\n /** Its position in the selection. */\n index: number\n /** Its name, already shortened in the middle so the extension survives. */\n label: string\n /** Takes the file out of the selection, the only way to. */\n remove: () => void\n /** The chip size worked out to sit inside the field, one step below it. */\n size: ChipSize\n /** Whether the chip takes its compact height, to catch up below the smallest step. */\n compact: boolean\n}\n\n/** What the `#counter` slot receives. */\nexport interface FileInputCounterSlotProps {\n /** How many files are selected. */\n count: number\n /** Their total size, in bytes. */\n bytes: number\n /** The sentence the counter shows by default, already translated. */\n text: string\n}\n\n/** The height of the field: 32, 40 or 48 pixels. */\nexport type FileInputSize = 'sm' | 'md' | 'lg'\n\ninterface FileInputProps {\n /** Allows several files to be chosen. With one only, every extra file is turned away. */\n multiple?: boolean\n /**\n * Which kinds of file are accepted, in the browser's own syntax (`image/*,.pdf`).\n *\n * It is applied TWICE, and it has to be: as an attribute, which is what filters the\n * system's file dialog, and again in code, which is the only thing that can filter a\n * file DROPPED on the component, the attribute having no say over a drop.\n */\n accept?: string\n /**\n * How the chosen files are shown: their names joined by commas, or one dismissible\n * chip each. It only means something when several files are allowed; a single name is\n * always text.\n */\n display?: FileInputDisplay\n /** The largest ONE file may be, in bytes. */\n maxSize?: number\n /** The largest the whole selection may be, in bytes. */\n maxTotalSize?: number\n /** How many files may be chosen at most. */\n maxFiles?: number\n /** Shows how much has been chosen under the field: \"3 files (1.2 MB)\". */\n counter?: boolean\n /** The icon at the end of the field, which opens the file dialog. */\n pickerIcon?: IconSource\n /** Refuses files dropped onto the component: only the dialog then adds any. */\n noDrop?: boolean\n /** The height of the field: 32, 40 or 48 pixels. */\n size?: FileInputSize\n /** Takes 4px off the height, leaving the padding, the text and the icons as they are. */\n compact?: boolean\n /** Makes the field unusable, greyed out through the colour tokens. */\n disabled?: boolean\n /**\n * Shows what was chosen without allowing it to change: no dialog, no drop, no removal.\n */\n readonly?: boolean\n /**\n * Marks the field as invalid, for a rule of your own, since nothing here is checked\n * by the browser.\n */\n invalid?: boolean\n /** The label above the field, tied to it so that clicking it focuses the field. */\n label?: string\n /**\n * A line of help under the field, to the left of the counter. It is tied to the field\n * for assistive technology.\n */\n hint?: string\n /**\n * What the field says while nothing is chosen. It falls back to the design system\n * dictionary.\n */\n placeholder?: string\n /**\n * An icon inside the field, at the start. It is rendered before the chips rather than\n * in their place, so it survives a chip display. Decorative by default, it becomes a\n * real button as soon as a `@click:icon-start` listener is attached, in which case it\n * needs `iconStartLabel`.\n */\n iconStart?: IconSource\n /** What the start icon does, in words, once it is clickable. */\n iconStartLabel?: string\n /**\n * What the button at the end of the field does, in words. It names the button\n * `pickerIcon` renders, and falls back to the design system dictionary.\n */\n pickerIconLabel?: string\n /**\n * Shows a spinner at the end of the field, in place of the attach icon, while an\n * upload is under way, typically. It says that something is happening and changes\n * nothing else: files can still be dropped and the dialog still opens.\n */\n loading?: boolean\n /**\n * What screen readers announce while the spinner turns. It falls back to the design\n * system dictionary.\n */\n loadingText?: string\n /**\n * Offers a cross that empties the selection. Worth turning on here more than on an\n * ordinary field: what a picker holds cannot be erased by typing, so the cross is the\n * only way back out of a wrong choice.\n */\n clearable?: boolean\n /** What that cross does, in words. It falls back to the design system dictionary. */\n clearLabel?: string\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<FileInputProps>(), {\n multiple: false,\n accept: undefined,\n display: 'text',\n maxSize: undefined,\n maxTotalSize: undefined,\n maxFiles: undefined,\n counter: false,\n pickerIcon: () => attachFileIcon,\n noDrop: false,\n size: 'md',\n compact: false,\n disabled: false,\n readonly: false,\n invalid: false,\n label: undefined,\n hint: undefined,\n placeholder: undefined,\n iconStart: undefined,\n iconStartLabel: undefined,\n pickerIconLabel: undefined,\n loading: false,\n loadingText: undefined,\n clearable: false,\n clearLabel: undefined,\n})\n\nconst emit = defineEmits<{\n /** The reader changed the selection: added something, removed something, cleared it. */\n change: [files: File[]]\n /**\n * A file was turned away and never joined the selection. It is emitted once PER file,\n * so a batch drop can be reported precisely.\n */\n reject: [rejection: FileRejection]\n /**\n * ONE file was taken out through its chip, with the file and the position it held.\n * `change` follows it with the whole list, as it does after every other change.\n */\n remove: [file: File, index: number]\n /** The clear cross emptied the selection. */\n clear: []\n /** The start icon was clicked. Attaching this listener is what makes it a button. */\n 'click:icon-start': [event: MouseEvent]\n}>()\n\ndefineSlots<{\n /**\n * Content at the start of the field, rendered after the chips standing for the chosen\n * files rather than in their place.\n */\n start?(): unknown\n /**\n * Controls of your own inside the field, placed before the ones the field owns: the\n * clear cross and the icon that opens the file dialog. Those two are this component's\n * own affordance, which is why there is no `#end` here: it would replace them.\n */\n 'value-end'?(): unknown\n /**\n * Replaces the chip standing for one file.\n *\n * Three of the values it receives are what make it usable without regressions:\n * `label` is the name already shortened in the MIDDLE so that its extension survives,\n * `remove` is what takes the file out (without it the file could no longer be removed\n * at all), and the size and density are the ones worked out to sit inside the field,\n * which cannot be guessed from outside.\n */\n chip?(props: FileInputChipSlotProps): unknown\n /**\n * Replaces the counter under the field. `text` is the sentence already built and\n * translated; the count and the total size in `bytes` are there for a wording of your own.\n */\n counter?(props: FileInputCounterSlotProps): unknown\n}>()\n\n// `get` reads an explicit `null` as the empty list: the default applies only to a model\n// that was never given, and `files = ref(null)` is a common start in untyped code.\n/**\n * Always a LIST of files, whether or not several are allowed, and never a file on its own.\n * The shape of the value does not depend on a prop, so a consumer never has to narrow a\n * union TypeScript has no way of discriminating. With a single file it is simply a list\n * of at most one.\n */\nconst model = defineModel<File[]>({ default: () => [], get: (files) => files ?? [] })\n\nconst { attrs, rootClass, rootStyle, forwardedAttrs } = useRootAttrs()\n\n// Declared as this component's own event, `click:icon-start` is out of `$attrs`, so the\n// listener is relayed to the field by hand — and only when the consumer wrote one.\nconst iconStartClick = iconStartListener((event) => emit('click:icon-start', event))\n\nconst m = useMessages()\nconst locale = useLocale()\n\n// A VInputGroup joins several controls into one object, so the shape of this field is the\n// row's decision rather than its own (VInput/context.ts). The chips read the resolved pair\n// too, or they would come out one step off the field they sit in.\nconst group = inject(inputGroupKey, null)\nconst {\n size: resolvedSize,\n compact: resolvedCompact,\n disabled: resolvedDisabled,\n} = useControlShape(props, group)\n\n/*\n * The hidden input, the sorting of the consumer's attributes, the single entry point into\n * the value, the removal of a file and the emptying of all of them live in `useFileField`,\n * shared with VFilePicker.\n *\n * Here, the bucket meant for \"the control the user deals with\" goes to the visible\n * field: that is what they see, focus and click, so a consumer's own `<label for>` has\n * to point at it. The description attribute is pulled out of that bucket, because this\n * component re-assembles it further down.\n */\nconst {\n fileEl,\n enabled,\n nativeInputAttrs,\n controlAttrs,\n acceptFiles,\n openPicker,\n removeAt,\n clear,\n} = useFileField({\n model,\n props,\n emit,\n forwardedAttrs,\n disabled: resolvedDisabled,\n excludeFromControl: ['aria-describedby'],\n onClear: () => emit('clear'),\n // Behind `isDev`, which a production build folds to false, so the message is dropped.\n warnings: isDev\n ? () => [\n props.display === 'chip' &&\n !props.multiple &&\n 'display=\"chip\" ignored without `multiple`: a single file shows as text.',\n ]\n : undefined,\n})\n\n/** What reaches the visible field: the consumer's own attributes, plus that listener. */\nconst fieldAttrs = computed(() => ({ ...controlAttrs.value, ...iconStartClick }))\n\nconst inputRef = ref<InstanceType<typeof VInput> | null>(null)\nconst rootEl = ref<HTMLElement | null>(null)\n\n// Chips only mean something for a list: a single file always shows as plain text.\nconst resolvedDisplay = computed<FileInputDisplay>(() => (props.multiple ? props.display : 'text'))\n\nconst displayText = computed(() =>\n resolvedDisplay.value === 'chip' ? '' : model.value.map((file) => file.name).join(', '),\n)\n\nconst placeholderText = computed(() =>\n model.value.length > 0 ? undefined : (props.placeholder ?? m.value.fileInput.placeholder),\n)\n\n/*\n * Whether the clear cross is shown has to be answered EXPLICITLY here. The visible field\n * is read-only, and a read-only field hides its cross by default — rightly so, since its\n * text cannot be edited. Here the value comes from the file dialog rather than from\n * typing, so there is something to clear all the same.\n */\nconst clearVisible = computed(() => canClear(props, resolvedDisabled.value, model.value.length > 0))\n\n// @a11y @devwarn\n/*\n * The icon disappears along with what it offers: a read-only field opens no dialog, so\n * an icon inviting one would be a lie — the same rule VDateInput follows for its\n * calendar.\n *\n * TRAP — its LABEL stays defined at all times, even when no icon is rendered. The helper\n * that detects a click handler on an icon warns AT SETUP if one is attached without a\n * label, and it has no way of knowing whether an icon exists.\n */\nconst endIcon = computed<IconSource | undefined>(() =>\n props.readonly ? undefined : props.pickerIcon,\n)\nconst endIconLabel = computed(() => props.pickerIconLabel ?? m.value.fileInput.openPicker)\nconst resolvedClearLabel = computed(() => props.clearLabel ?? m.value.fileInput.clear)\n\nconst totalSize = computed(() => model.value.reduce((sum, file) => sum + file.size, 0))\n\n/*\n * The counter is assembled from three sources: the WORD comes from the dictionary, since\n * it is language; the SIZE is formatted by the platform, which knows the local\n * conventions; and the parentheses come from neither, being punctuation every language\n * shares — the same boundary VBadge's \"99+\" falls on.\n *\n * With nothing chosen it states the count alone: \"0 files ()\" would be noise.\n */\nconst counterText = computed(() => {\n const word = m.value.fileInput.files(model.value.length)\n return model.value.length === 0 ? word : `${word} (${formatBytes(totalSize.value, locale.value)})`\n})\n\nconst hintId = useId()\nconst counterId = useId()\n\n// @a11y\n/*\n * What describes the field for a screen reader is a LIST of references, assembled here\n * rather than by VInput: the hint belongs to OUR row under the field, VInput having no\n * such row — its own counter sits inside the field.\n *\n * The counter is deliberately part of that list, unlike in VTextarea. When the files are\n * shown as chips the field's own text is EMPTY, and the counter is then the only spoken\n * summary of what has been chosen.\n */\nconst describedBy = computed(() =>\n joinIds(\n attrs['aria-describedby'] as string | undefined,\n !!props.hint && hintId,\n props.counter && counterId,\n ),\n)\n\n// The size, the density and the HEIGHT of the chips sitting inside the field, worked out\n// once in `utils/chip.ts` and shared with VCombobox. The height is set inline rather than\n// restated as a table of CSS rules: it belongs to the chips' own subtree, out of the\n// field's reach, and the field has to force its input to that same height or it grows\n// when focused.\nconst chipScale = computed(() => chipScaleFor(resolvedSize.value, resolvedCompact.value))\n\n/**\n * What each chip shows for its file, worked out once per change of the selection rather\n * than on every render, which reads it three times per chip. The name is shortened in the\n * MIDDLE rather than cut off at the end, for two reasons.\n *\n * The chips WRAP, so there is no line for a long name to overflow: left whole it would\n * simply push the field onto two or three rows. And cutting the middle preserves the\n * extension, which is what tells the reader what kind of file it is — an ellipsis at the\n * end drops it first.\n *\n * The full name is never lost: the removal button is named with it, and the chip carries\n * it as a tooltip whenever the label was actually shortened.\n */\n// Computed lazily, so a text display, which never reads it, never pays for it.\nconst chipLabels = computed(() => model.value.map((file) => truncateMiddle(file.name)))\n\nfunction onControlClick(event: MouseEvent) {\n // The field's own buttons already handle their clicks, and the click also reaches the\n // field itself. Without this guard the attach icon would open the dialog TWICE, and\n // the clear cross would reopen it immediately after emptying the selection.\n if ((event.target as HTMLElement).closest('button')) return\n openPicker()\n}\n\nfunction onFieldKeydown(event: KeyboardEvent) {\n if (event.key !== 'Enter' && event.key !== ' ') return\n // Cancelling the default on Enter also stops the form from being submitted: a\n // read-only text field is still a field, and Enter in one submits the form around it.\n event.preventDefault()\n openPicker()\n}\n\nfunction removeFile(index: number) {\n // The removal button disappears along with its chip, so the focus would fall back to\n // the page body. Unlike the date and time pickers, nothing here opens on focus, so\n // this needs no guard against re-entering.\n if (removeAt(index)) inputRef.value?.focus()\n}\n\n/* Files may be dropped on the component itself; there is no separate drop area here —\n that is what VFilePicker is for. */\nconst { dragging, onDragEnter, onDragOver, onDragLeave, onDrop } = useFileDrop(\n () => !props.noDrop && enabled.value,\n acceptFiles,\n)\n\ndefineExpose({\n /** Moves the focus to the visible field. */\n focus: (options?: FocusOptions) => inputRef.value?.focus(options),\n /**\n * Opens the file dialog. It only works when called from something the reader did (a\n * click, a key press): browsers refuse to open a file dialog by themselves.\n */\n open: openPicker,\n /**\n * The component's own box, for what neither of the two above covers. It is the wrapper\n * and not the hidden file input: that one is the FORM's element, this is the reader's.\n */\n el: rootEl,\n})\n</script>\n\n<template>\n <div\n ref=\"rootEl\"\n class=\"v-file-input\"\n :class=\"rootClass\"\n :style=\"[{ '--chip-height': chipScale.height }, rootStyle]\"\n :data-size=\"resolvedSize\"\n :data-compact=\"resolvedCompact ? '' : undefined\"\n :data-display=\"resolvedDisplay\"\n :data-disabled=\"resolvedDisabled ? '' : undefined\"\n :data-readonly=\"readonly ? '' : undefined\"\n :data-dragging=\"dragging ? '' : undefined\"\n @dragenter=\"onDragEnter\"\n @dragover=\"onDragOver\"\n @dragleave=\"onDragLeave\"\n @drop=\"onDrop\"\n >\n <input v-bind=\"nativeInputAttrs\" ref=\"fileEl\" class=\"v-file-input-native v-hidden-input\" />\n\n <div class=\"v-file-input-control\" @click=\"onControlClick\">\n <!-- Shown as chips, the field takes VInput's two arrangements for chips: its end\n controls lifted out of the flow, and the chips wrapping onto several rows. -->\n <VInput\n v-bind=\"fieldAttrs\"\n ref=\"inputRef\"\n :class=\"{ 'v-input-end-pinned v-input-chips': resolvedDisplay === 'chip' }\"\n :model-value=\"displayText\"\n no-typing\n :readonly=\"readonly\"\n :label=\"label\"\n :placeholder=\"placeholderText\"\n :size=\"resolvedSize\"\n :compact=\"resolvedCompact\"\n :disabled=\"resolvedDisabled\"\n :invalid=\"invalid\"\n :clearable=\"clearable\"\n :clear-visible=\"clearVisible\"\n :clear-label=\"resolvedClearLabel\"\n :icon-start=\"iconStart\"\n :icon-start-label=\"iconStartLabel\"\n :loading=\"loading\"\n :loading-text=\"loadingText\"\n :icon-end=\"endIcon\"\n :icon-end-label=\"endIconLabel\"\n :aria-describedby=\"describedBy\"\n @click:icon-end=\"openPicker\"\n @clear=\"clear\"\n @keydown=\"onFieldKeydown\"\n >\n <template v-if=\"resolvedDisplay === 'chip' || $slots.start\" #start>\n <template\n v-for=\"(file, index) in resolvedDisplay === 'chip' ? model : []\"\n :key=\"fileKey(file)\"\n >\n <slot\n name=\"chip\"\n :file=\"file\"\n :index=\"index\"\n :label=\"chipLabels[index]!\"\n :remove=\"() => removeFile(index)\"\n :size=\"chipScale.size\"\n :compact=\"chipScale.compact\"\n >\n <VChip\n tone=\"accent\"\n :size=\"chipScale.size\"\n :compact=\"chipScale.compact\"\n :dismissible=\"enabled\"\n :dismiss-label=\"m.common.remove(file.name)\"\n :disabled=\"resolvedDisabled\"\n :title=\"chipLabels[index] === file.name ? undefined : file.name\"\n @dismiss=\"removeFile(index)\"\n >{{ chipLabels[index] }}</VChip\n >\n </slot>\n </template>\n <slot name=\"start\" />\n </template>\n\n <template v-if=\"$slots['value-end']\" #value-end><slot name=\"value-end\" /></template>\n </VInput>\n </div>\n\n <div v-if=\"hint || counter\" class=\"v-file-input-meta v-field-meta\">\n <VTypography\n v-if=\"hint\"\n :id=\"hintId\"\n variant=\"caption\"\n tone=\"muted\"\n class=\"v-file-input-hint\"\n >\n {{ hint }}\n </VTypography>\n <span v-if=\"counter\" :id=\"counterId\" class=\"v-file-input-counter v-field-counter\">\n <slot name=\"counter\" :count=\"model.length\" :bytes=\"totalSize\" :text=\"counterText\">\n {{ counterText }}\n </slot>\n </span>\n </div>\n </div>\n</template>\n\n<style>\n@layer vectis.components {\n /* Positioned so the hidden file input, which has no size at all, has something to be\n placed against. */\n .v-file-input {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: var(--vectis-space-1);\n width: 100%;\n font-family: var(--vectis-text-family);\n }\n\n /* The real file input is a SOURCE of files and not a control anyone deals with: it\n wears `.v-hidden-input`, and taking it out of the tab order and hiding it from screen\n readers, in `useFileField`, is what leaves the visible field as the single stop and the\n single announcement. */\n .v-file-input:not([data-disabled]):not([data-readonly]) .v-file-input-control,\n .v-file-input:not([data-disabled]):not([data-readonly])[data-display='text'] .v-input-control {\n cursor: pointer;\n }\n\n /* An ellipsis DOES work on an input, and a read-only one never scrolls by itself, so a\n long list of names is simply cut short. No tooltip is added for the rest: it would be\n announced as a description repeating the value the field already shows, and the\n complete list is what the model is for. */\n .v-file-input[data-display='text'] .v-input-control {\n text-overflow: ellipsis;\n }\n\n /* While a file is being dragged over it, the field is highlighted by redefining the\n very variable VInput uses for its own border colour — so the two can never disagree.\n\n TRAP — the selector weighs (0,4,0), one step above VInput's states, and it has to. The\n field inside is ALWAYS read-only, and VInput's read-only background weighs (0,3,0): at\n that weight the winner would be whichever of the two sheets a bundler put last. */\n .v-file-input[data-dragging] .v-input .v-input-field {\n --field-border-color: var(--vectis-color-accent);\n\n background: var(--vectis-color-accent-surface);\n }\n\n .v-file-input[data-disabled] .v-file-input-hint,\n .v-file-input[data-disabled] .v-file-input-counter {\n color: var(--vectis-color-text-subtle);\n }\n}\n</style>\n"],"mappings":"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"}
@@ -5,10 +5,10 @@
5
5
  * (`invoice.pdf` and `invoice.png`), and the tail is also where the version or
6
6
  * date suffixes live.
7
7
  *
8
- * Pure, no Vue — the `VHotkeys/platform.ts` precedent: a single consumer, so it
8
+ * Pure, no Vue: the `VHotkeys/platform.ts` precedent: a single consumer, so it
9
9
  * stays in the component's folder. Deliberately NOT promoted alongside the file
10
10
  * helpers of `utils/file.ts`: cutting a string is a lexical operation, not
11
- * something the FILE domain decides — `utils/text.ts` is where it would go the
11
+ * something the FILE domain decides: `utils/text.ts` is where it would go the
12
12
  * day a second consumer appears.
13
13
  */
14
14
  /** Ceiling of a chip's label, ellipsis included. Chips wrap, so the point is not
@@ -18,12 +18,12 @@ export declare const CHIP_NAME_MAX = 20;
18
18
  * `truncateMiddle('annual_report_2026_final.pdf')` → `annual_rep…_final.pdf`.
19
19
  *
20
20
  * The result is EXACTLY `max` characters long: the ellipsis takes one of them,
21
- * and the odd one goes to the head — the start of a name is what makes it
21
+ * and the odd one goes to the head: the start of a name is what makes it
22
22
  * recognizable, the end is what disambiguates it.
23
23
  *
24
24
  * Counted in CODE POINTS (`[...text]`) and not in UTF-16 units: an emoji in a
25
25
  * name would otherwise be cut between its two halves and render as a
26
- * replacement character. Combining marks stay out of scope — a grapheme
26
+ * replacement character. Combining marks stay out of scope: a grapheme
27
27
  * segmenter for a chip label would be a lot of machinery for a rounding error.
28
28
  */
29
29
  export declare function truncateMiddle(text: string, max?: number): string;
@@ -1 +1 @@
1
- {"version":3,"file":"truncate.js","names":[],"sources":["../../../src/components/VFileInput/truncate.ts"],"sourcesContent":["/**\n * Middle truncation, for text whose END carries as much meaning as its start.\n * A file name is the canonical case: `text-overflow: ellipsis` would drop the\n * extension, which is often the only thing distinguishing two entries\n * (`invoice.pdf` and `invoice.png`), and the tail is also where the version or\n * date suffixes live.\n *\n * Pure, no Vue — the `VHotkeys/platform.ts` precedent: a single consumer, so it\n * stays in the component's folder. Deliberately NOT promoted alongside the file\n * helpers of `utils/file.ts`: cutting a string is a lexical operation, not\n * something the FILE domain decides — `utils/text.ts` is where it would go the\n * day a second consumer appears.\n */\n\n/** Ceiling of a chip's label, ellipsis included. Chips wrap, so the point is not\n the field's width but keeping a row readable at a glance. */\nexport const CHIP_NAME_MAX = 20\n\n/**\n * `truncateMiddle('annual_report_2026_final.pdf')` → `annual_rep…_final.pdf`.\n *\n * The result is EXACTLY `max` characters long: the ellipsis takes one of them,\n * and the odd one goes to the head — the start of a name is what makes it\n * recognizable, the end is what disambiguates it.\n *\n * Counted in CODE POINTS (`[...text]`) and not in UTF-16 units: an emoji in a\n * name would otherwise be cut between its two halves and render as a\n * replacement character. Combining marks stay out of scope — a grapheme\n * segmenter for a chip label would be a lot of machinery for a rounding error.\n */\nexport function truncateMiddle(text: string, max: number = CHIP_NAME_MAX): string {\n const chars = [...text]\n if (chars.length <= max) return text\n\n const budget = Math.max(0, max - 1)\n const head = Math.ceil(budget / 2)\n const tail = budget - head\n\n return `${chars.slice(0, head).join('')}…${chars.slice(chars.length - tail).join('')}`\n}\n"],"mappings":"AA8BA,SAAgB,EAAe,GAAc,IAAA,IAAqC;CAChF,IAAM,IAAQ,CAAC,GAAG,CAAI;CACtB,IAAI,EAAM,UAAU,GAAK,OAAO;CAEhC,IAAM,IAAS,KAAK,IAAI,GAAG,IAAM,CAAC,GAC5B,IAAO,KAAK,KAAK,IAAS,CAAC,GAC3B,IAAO,IAAS;CAEtB,OAAO,GAAG,EAAM,MAAM,GAAG,CAAI,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,EAAM,MAAM,EAAM,SAAS,CAAI,CAAC,CAAC,KAAK,EAAE;AACrF"}
1
+ {"version":3,"file":"truncate.js","names":[],"sources":["../../../src/components/VFileInput/truncate.ts"],"sourcesContent":["/**\n * Middle truncation, for text whose END carries as much meaning as its start.\n * A file name is the canonical case: `text-overflow: ellipsis` would drop the\n * extension, which is often the only thing distinguishing two entries\n * (`invoice.pdf` and `invoice.png`), and the tail is also where the version or\n * date suffixes live.\n *\n * Pure, no Vue: the `VHotkeys/platform.ts` precedent: a single consumer, so it\n * stays in the component's folder. Deliberately NOT promoted alongside the file\n * helpers of `utils/file.ts`: cutting a string is a lexical operation, not\n * something the FILE domain decides: `utils/text.ts` is where it would go the\n * day a second consumer appears.\n */\n\n/** Ceiling of a chip's label, ellipsis included. Chips wrap, so the point is not\n the field's width but keeping a row readable at a glance. */\nexport const CHIP_NAME_MAX = 20\n\n/**\n * `truncateMiddle('annual_report_2026_final.pdf')` → `annual_rep…_final.pdf`.\n *\n * The result is EXACTLY `max` characters long: the ellipsis takes one of them,\n * and the odd one goes to the head: the start of a name is what makes it\n * recognizable, the end is what disambiguates it.\n *\n * Counted in CODE POINTS (`[...text]`) and not in UTF-16 units: an emoji in a\n * name would otherwise be cut between its two halves and render as a\n * replacement character. Combining marks stay out of scope: a grapheme\n * segmenter for a chip label would be a lot of machinery for a rounding error.\n */\nexport function truncateMiddle(text: string, max: number = CHIP_NAME_MAX): string {\n const chars = [...text]\n if (chars.length <= max) return text\n\n const budget = Math.max(0, max - 1)\n const head = Math.ceil(budget / 2)\n const tail = budget - head\n\n return `${chars.slice(0, head).join('')}…${chars.slice(chars.length - tail).join('')}`\n}\n"],"mappings":"AA8BA,SAAgB,EAAe,GAAc,IAAA,IAAqC;CAChF,IAAM,IAAQ,CAAC,GAAG,CAAI;CACtB,IAAI,EAAM,UAAU,GAAK,OAAO;CAEhC,IAAM,IAAS,KAAK,IAAI,GAAG,IAAM,CAAC,GAC5B,IAAO,KAAK,KAAK,IAAS,CAAC,GAC3B,IAAO,IAAS;CAEtB,OAAO,GAAG,EAAM,MAAM,GAAG,CAAI,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,EAAM,MAAM,EAAM,SAAS,CAAI,CAAC,CAAC,KAAK,EAAE;AACrF"}
@@ -1,2 +1,2 @@
1
1
  @layer vectis.reset, vectis.tokens, vectis.components, vectis.utilities;
2
- @layer vectis.components{.v-file-picker{--file-picker-border-color:var(--vectis-color-border-strong);--file-picker-bg:var(--vectis-color-surface-sunken);--file-picker-text:var(--vectis-color-text);--file-picker-text-muted:var(--vectis-color-text-muted);--file-picker-row-bg:var(--vectis-color-surface-raised);--file-picker-thumb-bg:var(--vectis-color-surface-muted);inline-size:100%;font-family:var(--vectis-text-family);display:block;position:relative}.v-file-picker-body{gap:var(--vectis-space-4);flex-direction:column;display:flex}.v-file-picker-zone{justify-content:center;align-items:center;gap:var(--vectis-space-2);inline-size:100%;min-block-size:var(--vectis-control-size-file-picker-min-block);padding:var(--vectis-space-6) var(--vectis-space-4);appearance:none;border:1px dashed var(--file-picker-border-color);border-radius:var(--vectis-radius-surface);background:var(--file-picker-bg);color:var(--file-picker-text);font:inherit;text-align:center;transition:border-color var(--vectis-duration-fast) var(--vectis-ease-default), background-color var(--vectis-duration-fast) var(--vectis-ease-default);flex-direction:column;margin:0;display:flex}.v-file-picker:not([data-disabled]):not([data-readonly]) .v-file-picker-zone{cursor:pointer}.v-file-picker:not([data-disabled]):not([data-readonly]) .v-file-picker-zone:hover{--file-picker-border-color:var(--vectis-color-accent)}.v-file-picker[data-invalid] .v-file-picker-zone{--file-picker-border-color:var(--vectis-color-danger)}.v-file-picker-zone:focus-visible{outline:var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);outline-offset:var(--vectis-focus-ring-offset)}.v-file-picker[data-dragging]{--file-picker-border-color:var(--vectis-color-accent);--file-picker-bg:var(--vectis-color-accent-surface)}.v-file-picker-icon{--vectis-icon-size:var(--vectis-control-size-file-picker-icon);min-inline-size:var(--vectis-control-size-file-picker-icon);min-block-size:var(--vectis-control-size-file-picker-icon);color:var(--file-picker-text-muted);justify-content:center;align-items:center;display:inline-flex}.v-file-picker-icon>.v-spinner{font-size:var(--vectis-icon-size)}.v-file-picker-subtitle{--typography-color:var(--file-picker-text-muted)}.v-file-picker-separator{align-items:center;gap:var(--vectis-space-3);inline-size:100%;color:var(--file-picker-text-muted);font-size:var(--vectis-text-caption-size);margin-block-start:var(--vectis-space-2);display:flex}.v-file-picker-separator:before,.v-file-picker-separator:after{content:"";border-block-start:1px solid var(--vectis-color-border);flex:1 1 0}.v-file-picker-list{gap:var(--vectis-space-2);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}.v-file-picker-item{align-items:center;gap:var(--vectis-space-3);padding:var(--vectis-space-2);border:1px solid var(--vectis-color-border);border-radius:var(--vectis-radius-interactive);background:var(--file-picker-row-bg);display:flex}.v-file-picker-thumb{inline-size:var(--vectis-control-size-file-picker-thumb);block-size:var(--vectis-control-size-file-picker-thumb);border-radius:var(--vectis-radius-interactive);background:var(--file-picker-thumb-bg);color:var(--file-picker-text-muted);flex:none;justify-content:center;align-items:center;display:inline-flex;overflow:hidden}.v-file-picker-image{object-fit:cover;block-size:100%;inline-size:100%;display:block}.v-file-picker-info{min-inline-size:0;color:var(--file-picker-text);flex-direction:column;flex:auto;display:flex}.v-file-picker-name{font-size:var(--vectis-text-body-sm-size);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.v-file-picker-size{color:var(--file-picker-text-muted);font-size:var(--vectis-text-caption-size);font-variant-numeric:tabular-nums}.v-file-picker[data-preview=end]{container:v-file-picker/inline-size}.v-file-picker[data-preview=end] .v-file-picker-body{flex-direction:row;align-items:flex-start}.v-file-picker[data-preview=end] .v-file-picker-zone,.v-file-picker[data-preview=end] .v-file-picker-list{flex:1 1 0;min-inline-size:0}@container v-file-picker (width<=34rem){.v-file-picker[data-preview=end] .v-file-picker-body{flex-direction:column}}.v-file-picker[data-disabled]{--file-picker-border-color:var(--vectis-color-border);--file-picker-bg:var(--vectis-color-surface-muted);--file-picker-text:var(--vectis-color-text-muted);--file-picker-text-muted:var(--vectis-color-text-muted);--file-picker-row-bg:var(--vectis-color-surface-muted)}.v-file-picker[data-readonly]{--file-picker-border-color:var(--vectis-color-border)}@media (prefers-reduced-motion:reduce){.v-file-picker-zone{transition:none}}@media (forced-colors:active){.v-file-picker[data-dragging] .v-file-picker-zone{border-style:solid}.v-file-picker-thumb{border:1px solid}}}
2
+ @layer vectis.components{.v-file-picker{--file-picker-border-color:var(--vectis-color-border-strong);--file-picker-bg:var(--vectis-color-surface-sunken);--file-picker-text:var(--vectis-color-text);--file-picker-text-muted:var(--vectis-color-text-muted);--file-picker-row-bg:var(--vectis-color-surface-raised);--file-picker-thumb-bg:var(--vectis-color-surface-muted);inline-size:100%;font-family:var(--vectis-text-family);display:block;position:relative}.v-file-picker-body{gap:var(--vectis-space-4);flex-direction:column;display:flex}.v-file-picker-zone{justify-content:center;align-items:center;gap:var(--vectis-space-2);inline-size:100%;min-block-size:var(--vectis-control-size-file-picker-min-block);padding:var(--vectis-space-6) var(--vectis-space-4);appearance:none;border:1px dashed var(--file-picker-border-color);border-radius:var(--vectis-radius-surface);background:var(--file-picker-bg);color:var(--file-picker-text);font:inherit;text-align:center;transition:border-color var(--vectis-duration-fast) var(--vectis-ease-default), background-color var(--vectis-duration-fast) var(--vectis-ease-default);flex-direction:column;margin:0;display:flex}.v-file-picker:not([data-disabled]):not([data-readonly]) .v-file-picker-zone{cursor:pointer}.v-file-picker:not([data-disabled]):not([data-readonly]):not([data-invalid]) .v-file-picker-zone:hover{--file-picker-border-color:var(--vectis-color-accent)}.v-file-picker[data-invalid] .v-file-picker-zone{--file-picker-border-color:var(--vectis-color-danger)}.v-file-picker-zone:focus-visible{outline:var(--vectis-focus-ring-width) solid var(--vectis-focus-ring-color);outline-offset:var(--vectis-focus-ring-offset)}.v-file-picker[data-dragging]{--file-picker-border-color:var(--vectis-color-accent);--file-picker-bg:var(--vectis-color-accent-surface)}.v-file-picker-icon{--vectis-icon-size:var(--vectis-control-size-file-picker-icon);min-inline-size:var(--vectis-control-size-file-picker-icon);min-block-size:var(--vectis-control-size-file-picker-icon);color:var(--file-picker-text-muted);justify-content:center;align-items:center;display:inline-flex}.v-file-picker-icon>.v-spinner{font-size:var(--vectis-icon-size)}.v-file-picker-subtitle{--typography-color:var(--file-picker-text-muted)}.v-file-picker-separator{align-items:center;gap:var(--vectis-space-3);inline-size:100%;color:var(--file-picker-text-muted);font-size:var(--vectis-text-caption-size);margin-block-start:var(--vectis-space-2);display:flex}.v-file-picker-separator:before,.v-file-picker-separator:after{content:"";border-block-start:1px solid var(--vectis-color-border);flex:1 1 0}.v-file-picker-list{gap:var(--vectis-space-2);flex-direction:column;margin:0;padding:0;list-style:none;display:flex}.v-file-picker-item{align-items:center;gap:var(--vectis-space-3);padding:var(--vectis-space-2);border:1px solid var(--vectis-color-border);border-radius:var(--vectis-radius-interactive);background:var(--file-picker-row-bg);display:flex}.v-file-picker-thumb{inline-size:var(--vectis-control-size-file-picker-thumb);block-size:var(--vectis-control-size-file-picker-thumb);border-radius:var(--vectis-radius-interactive);background:var(--file-picker-thumb-bg);color:var(--file-picker-text-muted);flex:none;justify-content:center;align-items:center;display:inline-flex;overflow:hidden}.v-file-picker-image{object-fit:cover;block-size:100%;inline-size:100%;display:block}.v-file-picker-info{min-inline-size:0;color:var(--file-picker-text);flex-direction:column;flex:auto;display:flex}.v-file-picker-name{font-size:var(--vectis-text-body-sm-size);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.v-file-picker-size{color:var(--file-picker-text-muted);font-size:var(--vectis-text-caption-size);font-variant-numeric:tabular-nums}.v-file-picker[data-preview=end]{container:v-file-picker/inline-size}.v-file-picker[data-preview=end] .v-file-picker-body{flex-direction:row;align-items:flex-start}.v-file-picker[data-preview=end] .v-file-picker-zone,.v-file-picker[data-preview=end] .v-file-picker-list{flex:1 1 0;min-inline-size:0}@container v-file-picker (width<=34rem){.v-file-picker[data-preview=end] .v-file-picker-body{flex-direction:column}}.v-file-picker[data-disabled]{--file-picker-border-color:var(--vectis-color-border);--file-picker-bg:var(--vectis-color-surface-muted);--file-picker-text:var(--vectis-color-text-muted);--file-picker-text-muted:var(--vectis-color-text-muted);--file-picker-row-bg:var(--vectis-color-surface-muted)}.v-file-picker[data-readonly]{--file-picker-border-color:var(--vectis-color-border)}@media (prefers-reduced-motion:reduce){.v-file-picker-zone{transition:none}}@media (forced-colors:active){.v-file-picker[data-dragging] .v-file-picker-zone{border-style:solid}.v-file-picker-thumb{border:1px solid}}}