@vuetify/nightly 3.8.9-master.2025-06-14 → 3.8.10-dev.2025-06-18

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 (231) hide show
  1. package/CHANGELOG.md +46 -14
  2. package/dist/json/attributes.json +3541 -3137
  3. package/dist/json/importMap-labs.json +30 -26
  4. package/dist/json/importMap.json +174 -174
  5. package/dist/json/tags.json +108 -2
  6. package/dist/json/web-types.json +7295 -5648
  7. package/dist/vuetify-labs.cjs +795 -198
  8. package/dist/vuetify-labs.css +4855 -4806
  9. package/dist/vuetify-labs.d.ts +10430 -3099
  10. package/dist/vuetify-labs.esm.js +796 -199
  11. package/dist/vuetify-labs.esm.js.map +1 -1
  12. package/dist/vuetify-labs.js +795 -198
  13. package/dist/vuetify-labs.min.css +2 -2
  14. package/dist/vuetify.cjs +520 -183
  15. package/dist/vuetify.cjs.map +1 -1
  16. package/dist/vuetify.css +2398 -2349
  17. package/dist/vuetify.d.ts +2798 -2091
  18. package/dist/vuetify.esm.js +521 -184
  19. package/dist/vuetify.esm.js.map +1 -1
  20. package/dist/vuetify.js +520 -183
  21. package/dist/vuetify.js.map +1 -1
  22. package/dist/vuetify.min.css +2 -2
  23. package/dist/vuetify.min.js +1257 -1234
  24. package/dist/vuetify.min.js.map +1 -1
  25. package/lib/components/VAlert/VAlert.css +6 -1
  26. package/lib/components/VAlert/VAlert.d.ts +35 -0
  27. package/lib/components/VAlert/VAlert.js +15 -10
  28. package/lib/components/VAlert/VAlert.js.map +1 -1
  29. package/lib/components/VAlert/VAlert.sass +7 -1
  30. package/lib/components/VAppBar/VAppBar.d.ts +15 -3
  31. package/lib/components/VAppBar/VAppBarNavIcon.d.ts +20 -10
  32. package/lib/components/VAutocomplete/VAutocomplete.d.ts +175 -110
  33. package/lib/components/VAutocomplete/VAutocomplete.js +21 -3
  34. package/lib/components/VAutocomplete/VAutocomplete.js.map +1 -1
  35. package/lib/components/VBadge/VBadge.d.ts +60 -0
  36. package/lib/components/VBadge/VBadge.js +7 -2
  37. package/lib/components/VBadge/VBadge.js.map +1 -1
  38. package/lib/components/VBtn/VBtn.css +3 -0
  39. package/lib/components/VBtn/VBtn.d.ts +20 -10
  40. package/lib/components/VBtn/VBtn.sass +3 -0
  41. package/lib/components/VBtnGroup/VBtnGroup.css +32 -8
  42. package/lib/components/VBtnGroup/VBtnGroup.d.ts +58 -32
  43. package/lib/components/VBtnGroup/VBtnGroup.js +7 -3
  44. package/lib/components/VBtnGroup/VBtnGroup.js.map +1 -1
  45. package/lib/components/VBtnGroup/VBtnGroup.sass +46 -18
  46. package/lib/components/VBtnToggle/VBtnToggle.d.ts +25 -0
  47. package/lib/components/VCard/VCard.d.ts +20 -10
  48. package/lib/components/VCheckbox/VCheckbox.d.ts +23 -13
  49. package/lib/components/VCheckbox/VCheckboxBtn.d.ts +20 -10
  50. package/lib/components/VChip/VChip.d.ts +20 -10
  51. package/lib/components/VChipGroup/VChipGroup.d.ts +10 -0
  52. package/lib/components/VCombobox/VCombobox.d.ts +175 -110
  53. package/lib/components/VCombobox/VCombobox.js +22 -3
  54. package/lib/components/VCombobox/VCombobox.js.map +1 -1
  55. package/lib/components/VDataTable/VDataTable.d.ts +60 -0
  56. package/lib/components/VDataTable/VDataTableHeaders.d.ts +13 -0
  57. package/lib/components/VDataTable/VDataTableHeaders.js +4 -2
  58. package/lib/components/VDataTable/VDataTableHeaders.js.map +1 -1
  59. package/lib/components/VDataTable/VDataTableServer.d.ts +42 -0
  60. package/lib/components/VDataTable/VDataTableVirtual.d.ts +42 -0
  61. package/lib/components/VDatePicker/VDatePicker.d.ts +80 -5
  62. package/lib/components/VDatePicker/VDatePicker.js +10 -4
  63. package/lib/components/VDatePicker/VDatePicker.js.map +1 -1
  64. package/lib/components/VDatePicker/VDatePickerMonth.d.ts +10 -0
  65. package/lib/components/VDatePicker/VDatePickerMonth.js +1 -1
  66. package/lib/components/VDatePicker/VDatePickerMonth.js.map +1 -1
  67. package/lib/components/VExpansionPanel/VExpansionPanel.d.ts +20 -10
  68. package/lib/components/VExpansionPanel/VExpansionPanelTitle.d.ts +20 -10
  69. package/lib/components/VExpansionPanel/VExpansionPanels.d.ts +20 -10
  70. package/lib/components/VFab/VFab.d.ts +20 -10
  71. package/lib/components/VField/VField.d.ts +3 -3
  72. package/lib/components/VFileInput/VFileInput.d.ts +15 -15
  73. package/lib/components/VInfiniteScroll/VInfiniteScroll.d.ts +9 -3
  74. package/lib/components/VInfiniteScroll/VInfiniteScroll.js +29 -0
  75. package/lib/components/VInfiniteScroll/VInfiniteScroll.js.map +1 -1
  76. package/lib/components/VInput/VInput.d.ts +4 -4
  77. package/lib/components/VKbd/VKbd.css +13 -2
  78. package/lib/components/VKbd/VKbd.d.ts +221 -0
  79. package/lib/components/VKbd/VKbd.js +55 -0
  80. package/lib/components/VKbd/VKbd.js.map +1 -0
  81. package/lib/components/VKbd/VKbd.sass +2 -1
  82. package/lib/components/VKbd/_variables.scss +12 -1
  83. package/lib/components/VKbd/index.d.ts +1 -95
  84. package/lib/components/VKbd/index.js +1 -4
  85. package/lib/components/VKbd/index.js.map +1 -1
  86. package/lib/components/VList/VList.d.ts +13 -0
  87. package/lib/components/VList/VList.js +4 -1
  88. package/lib/components/VList/VList.js.map +1 -1
  89. package/lib/components/VList/VListChildren.js +4 -3
  90. package/lib/components/VList/VListChildren.js.map +1 -1
  91. package/lib/components/VList/VListGroup.d.ts +10 -0
  92. package/lib/components/VList/VListGroup.js +2 -2
  93. package/lib/components/VList/VListGroup.js.map +1 -1
  94. package/lib/components/VList/VListItem.d.ts +28 -10
  95. package/lib/components/VList/VListItem.js +7 -3
  96. package/lib/components/VList/VListItem.js.map +1 -1
  97. package/lib/components/VList/list.d.ts +9 -2
  98. package/lib/components/VList/list.js +7 -0
  99. package/lib/components/VList/list.js.map +1 -1
  100. package/lib/components/VMenu/VMenu.d.ts +13 -0
  101. package/lib/components/VMenu/VMenu.js +2 -1
  102. package/lib/components/VMenu/VMenu.js.map +1 -1
  103. package/lib/components/VNumberInput/VNumberInput.d.ts +114 -89
  104. package/lib/components/VNumberInput/VNumberInput.js +43 -20
  105. package/lib/components/VNumberInput/VNumberInput.js.map +1 -1
  106. package/lib/components/VOtpInput/VOtpInput.js +19 -2
  107. package/lib/components/VOtpInput/VOtpInput.js.map +1 -1
  108. package/lib/components/VOverlay/VOverlay.css +1 -1
  109. package/lib/components/VOverlay/_variables.scss +1 -1
  110. package/lib/components/VRadio/VRadio.d.ts +20 -10
  111. package/lib/components/VRadioGroup/VRadioGroup.d.ts +23 -13
  112. package/lib/components/VRangeSlider/VRangeSlider.d.ts +3 -3
  113. package/lib/components/VSelect/VSelect.d.ts +204 -118
  114. package/lib/components/VSelect/VSelect.js +21 -3
  115. package/lib/components/VSelect/VSelect.js.map +1 -1
  116. package/lib/components/VSelectionControl/VSelectionControl.d.ts +20 -10
  117. package/lib/components/VSelectionControlGroup/VSelectionControlGroup.d.ts +28 -14
  118. package/lib/components/VSlideGroup/VSlideGroup.d.ts +10 -0
  119. package/lib/components/VSlideGroup/VSlideGroup.js +2 -1
  120. package/lib/components/VSlideGroup/VSlideGroup.js.map +1 -1
  121. package/lib/components/VSlider/VSlider.d.ts +3 -3
  122. package/lib/components/VSlider/VSliderThumb.d.ts +20 -10
  123. package/lib/components/VSpeedDial/VSpeedDial.d.ts +13 -0
  124. package/lib/components/VStepper/VStepperItem.d.ts +28 -14
  125. package/lib/components/VSwitch/VSwitch.d.ts +23 -13
  126. package/lib/components/VTable/VTable.css +6 -0
  127. package/lib/components/VTable/VTable.d.ts +55 -24
  128. package/lib/components/VTable/VTable.js +9 -2
  129. package/lib/components/VTable/VTable.js.map +1 -1
  130. package/lib/components/VTable/VTable.sass +14 -0
  131. package/lib/components/VTable/_variables.scss +1 -0
  132. package/lib/components/VTabs/VTab.d.ts +56 -28
  133. package/lib/components/VTabs/VTabs.d.ts +10 -0
  134. package/lib/components/VTextField/VTextField.d.ts +27 -27
  135. package/lib/components/VTextField/VTextField.js +4 -4
  136. package/lib/components/VTextField/VTextField.js.map +1 -1
  137. package/lib/components/VTextarea/VTextarea.d.ts +15 -15
  138. package/lib/components/VTextarea/VTextarea.js +4 -4
  139. package/lib/components/VTextarea/VTextarea.js.map +1 -1
  140. package/lib/components/VToolbar/VToolbar.d.ts +15 -3
  141. package/lib/components/VToolbar/VToolbar.js +6 -3
  142. package/lib/components/VToolbar/VToolbar.js.map +1 -1
  143. package/lib/composables/autofocus.d.ts +7 -0
  144. package/lib/composables/autofocus.js +10 -0
  145. package/lib/composables/autofocus.js.map +1 -0
  146. package/lib/composables/calendar.d.ts +5 -0
  147. package/lib/composables/calendar.js +2 -1
  148. package/lib/composables/calendar.js.map +1 -1
  149. package/lib/composables/date/DateAdapter.d.ts +3 -3
  150. package/lib/composables/date/DateAdapter.js.map +1 -1
  151. package/lib/composables/date/adapters/string.d.ts +54 -0
  152. package/lib/composables/date/adapters/string.js +153 -0
  153. package/lib/composables/date/adapters/string.js.map +1 -0
  154. package/lib/composables/date/adapters/vuetify.d.ts +1 -1
  155. package/lib/composables/date/adapters/vuetify.js +4 -4
  156. package/lib/composables/date/adapters/vuetify.js.map +1 -1
  157. package/lib/composables/date/date.d.ts +3 -3
  158. package/lib/composables/date/index.d.ts +1 -0
  159. package/lib/composables/date/index.js +1 -0
  160. package/lib/composables/date/index.js.map +1 -1
  161. package/lib/composables/filter.js +3 -0
  162. package/lib/composables/filter.js.map +1 -1
  163. package/lib/composables/group.js +1 -0
  164. package/lib/composables/group.js.map +1 -1
  165. package/lib/composables/iconSizes.d.ts +28 -0
  166. package/lib/composables/iconSizes.js +23 -0
  167. package/lib/composables/iconSizes.js.map +1 -0
  168. package/lib/composables/intersectionObserver.js +2 -2
  169. package/lib/composables/intersectionObserver.js.map +1 -1
  170. package/lib/composables/locale.d.ts +5 -1
  171. package/lib/composables/locale.js.map +1 -1
  172. package/lib/composables/mask.d.ts +38 -0
  173. package/lib/composables/mask.js +183 -0
  174. package/lib/composables/mask.js.map +1 -0
  175. package/lib/composables/selectLink.js +2 -2
  176. package/lib/composables/selectLink.js.map +1 -1
  177. package/lib/composables/theme.d.ts +6 -1
  178. package/lib/composables/theme.js +97 -29
  179. package/lib/composables/theme.js.map +1 -1
  180. package/lib/composables/virtual.js +6 -1
  181. package/lib/composables/virtual.js.map +1 -1
  182. package/lib/directives/ripple/index.d.ts +2 -1
  183. package/lib/directives/ripple/index.js +12 -7
  184. package/lib/directives/ripple/index.js.map +1 -1
  185. package/lib/entry-bundler.d.ts +4 -3
  186. package/lib/entry-bundler.js +1 -1
  187. package/lib/entry-bundler.js.map +1 -1
  188. package/lib/framework.d.ts +92 -73
  189. package/lib/framework.js +1 -1
  190. package/lib/framework.js.map +1 -1
  191. package/lib/labs/VCalendar/VCalendar.d.ts +10 -0
  192. package/lib/labs/VColorInput/VColorInput.d.ts +3 -3
  193. package/lib/labs/VDateInput/VDateInput.d.ts +97 -87
  194. package/lib/labs/VFileUpload/VFileUpload.d.ts +3 -3
  195. package/lib/labs/VFileUpload/VFileUploadItem.d.ts +20 -10
  196. package/lib/labs/VIconBtn/VIconBtn.d.ts +29 -29
  197. package/lib/labs/VIconBtn/VIconBtn.js +7 -11
  198. package/lib/labs/VIconBtn/VIconBtn.js.map +1 -1
  199. package/lib/labs/VMaskInput/VMaskInput.d.ts +6993 -0
  200. package/lib/labs/VMaskInput/VMaskInput.js +67 -0
  201. package/lib/labs/VMaskInput/VMaskInput.js.map +1 -0
  202. package/lib/labs/VMaskInput/index.d.ts +1 -0
  203. package/lib/labs/VMaskInput/index.js +2 -0
  204. package/lib/labs/VMaskInput/index.js.map +1 -0
  205. package/lib/labs/VStepperVertical/VStepperVertical.d.ts +20 -10
  206. package/lib/labs/VStepperVertical/VStepperVerticalItem.d.ts +20 -10
  207. package/lib/labs/VTreeview/VTreeview.d.ts +51 -38
  208. package/lib/labs/VTreeview/VTreeview.js +1 -1
  209. package/lib/labs/VTreeview/VTreeview.js.map +1 -1
  210. package/lib/labs/VTreeview/VTreeviewChildren.d.ts +35 -0
  211. package/lib/labs/VTreeview/VTreeviewChildren.js +21 -3
  212. package/lib/labs/VTreeview/VTreeviewChildren.js.map +1 -1
  213. package/lib/labs/VTreeview/VTreeviewGroup.d.ts +10 -0
  214. package/lib/labs/VTreeview/VTreeviewItem.d.ts +20 -10
  215. package/lib/labs/VTreeview/VTreeviewItem.js +1 -0
  216. package/lib/labs/VTreeview/VTreeviewItem.js.map +1 -1
  217. package/lib/labs/components.d.ts +1 -0
  218. package/lib/labs/components.js +1 -0
  219. package/lib/labs/components.js.map +1 -1
  220. package/lib/labs/entry-bundler.d.ts +4 -3
  221. package/lib/locale/adapters/vue-i18n.js +6 -1
  222. package/lib/locale/adapters/vue-i18n.js.map +1 -1
  223. package/lib/locale/adapters/vuetify.js +7 -1
  224. package/lib/locale/adapters/vuetify.js.map +1 -1
  225. package/lib/util/globals.d.ts +1 -0
  226. package/lib/util/globals.js +1 -0
  227. package/lib/util/globals.js.map +1 -1
  228. package/lib/util/helpers.d.ts +2 -1
  229. package/lib/util/helpers.js +12 -7
  230. package/lib/util/helpers.js.map +1 -1
  231. package/package.json +9 -7
package/dist/vuetify.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.8.9-master.2025-06-14
2
+ * Vuetify v3.8.10-dev.2025-06-18
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
@@ -14,6 +14,7 @@
14
14
  const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
15
15
  const SUPPORTS_TOUCH = IN_BROWSER && ('ontouchstart' in window || window.navigator.maxTouchPoints > 0);
16
16
  const SUPPORTS_EYE_DROPPER = IN_BROWSER && 'EyeDropper' in window;
17
+ const SUPPORTS_MATCH_MEDIA = IN_BROWSER && 'matchMedia' in window && typeof window.matchMedia === 'function';
17
18
 
18
19
  function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
19
20
  function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
@@ -514,18 +515,23 @@
514
515
  function isPrimitive(value) {
515
516
  return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint';
516
517
  }
517
- function extractNumber(text, decimalDigitsLimit) {
518
- const cleanText = text.split('').filter(x => /[\d\-.]/.test(x)).filter((x, i, all) => i === 0 && /[-]/.test(x) ||
518
+ function escapeForRegex(sign) {
519
+ return '\\^$*+?.()|{}[]'.includes(sign) ? `\\${sign}` : sign;
520
+ }
521
+ function extractNumber(text, decimalDigitsLimit, decimalSeparator) {
522
+ const onlyValidCharacters = new RegExp(`[\\d\\-${escapeForRegex(decimalSeparator)}]`);
523
+ const cleanText = text.split('').filter(x => onlyValidCharacters.test(x)).filter((x, i, all) => i === 0 && /[-]/.test(x) ||
519
524
  // sign allowed at the start
520
- x === '.' && i === all.indexOf('.') ||
525
+ x === decimalSeparator && i === all.indexOf(x) ||
521
526
  // decimal separator allowed only once
522
527
  /\d/.test(x)).join('');
523
528
  if (decimalDigitsLimit === 0) {
524
- return cleanText.split('.')[0];
529
+ return cleanText.split(decimalSeparator)[0];
525
530
  }
526
- if (decimalDigitsLimit !== null && /\.\d/.test(cleanText)) {
527
- const parts = cleanText.split('.');
528
- return [parts[0], parts[1].substring(0, decimalDigitsLimit)].join('.');
531
+ const decimalPart = new RegExp(`${escapeForRegex(decimalSeparator)}\\d`);
532
+ if (decimalDigitsLimit !== null && decimalPart.test(cleanText)) {
533
+ const parts = cleanText.split(decimalSeparator);
534
+ return [parts[0], parts[1].substring(0, decimalDigitsLimit)].join(decimalSeparator);
529
535
  }
530
536
  return cleanText;
531
537
  }
@@ -867,7 +873,7 @@
867
873
  // WoB should always return negative value.
868
874
 
869
875
  const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB;
870
- outputContrast = SAPC > -1e-3 ? 0.0 : SAPC > -0.078 ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
876
+ outputContrast = SAPC > -loClip ? 0.0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
871
877
  }
872
878
  return outputContrast * 100;
873
879
  }
@@ -2672,6 +2678,10 @@
2672
2678
  return numberFormat.format(value);
2673
2679
  };
2674
2680
  }
2681
+ function inferDecimalSeparator(current, fallback) {
2682
+ const format = createNumberFunction(current, fallback);
2683
+ return format(0.1).includes(',') ? ',' : '.';
2684
+ }
2675
2685
  function useProvided(props, prop, provided) {
2676
2686
  const internal = useProxiedModel(props, prop, props[prop] ?? provided.value);
2677
2687
 
@@ -2694,6 +2704,7 @@
2694
2704
  current,
2695
2705
  fallback,
2696
2706
  messages,
2707
+ decimalSeparator: vue.toRef(() => inferDecimalSeparator(current, fallback)),
2697
2708
  t: createTranslateFunction(current, fallback, messages),
2698
2709
  n: createNumberFunction(current, fallback),
2699
2710
  provide: createProvideFunction({
@@ -2716,6 +2727,7 @@
2716
2727
  current,
2717
2728
  fallback,
2718
2729
  messages,
2730
+ decimalSeparator: vue.toRef(() => options?.decimalSeparator ?? inferDecimalSeparator(current, fallback)),
2719
2731
  t: createTranslateFunction(current, fallback, messages),
2720
2732
  n: createNumberFunction(current, fallback),
2721
2733
  provide: createProvideFunction({
@@ -2842,6 +2854,7 @@
2842
2854
  function genDefaults$1() {
2843
2855
  return {
2844
2856
  defaultTheme: 'light',
2857
+ prefix: 'v-',
2845
2858
  variations: {
2846
2859
  colors: [],
2847
2860
  lighten: 0,
@@ -2879,8 +2892,8 @@
2879
2892
  'activated-opacity': 0.12,
2880
2893
  'pressed-opacity': 0.12,
2881
2894
  'dragged-opacity': 0.08,
2882
- 'theme-kbd': '#212529',
2883
- 'theme-on-kbd': '#FFFFFF',
2895
+ 'theme-kbd': '#EEEEEE',
2896
+ 'theme-on-kbd': '#000000',
2884
2897
  'theme-code': '#F5F5F5',
2885
2898
  'theme-on-code': '#000000'
2886
2899
  }
@@ -2916,14 +2929,17 @@
2916
2929
  'activated-opacity': 0.12,
2917
2930
  'pressed-opacity': 0.16,
2918
2931
  'dragged-opacity': 0.08,
2919
- 'theme-kbd': '#212529',
2932
+ 'theme-kbd': '#424242',
2920
2933
  'theme-on-kbd': '#FFFFFF',
2921
2934
  'theme-code': '#343434',
2922
2935
  'theme-on-code': '#CCCCCC'
2923
2936
  }
2924
2937
  }
2925
2938
  },
2926
- stylesheetId: 'vuetify-theme-stylesheet'
2939
+ stylesheetId: 'vuetify-theme-stylesheet',
2940
+ scoped: false,
2941
+ unimportant: false,
2942
+ utilities: true
2927
2943
  };
2928
2944
  }
2929
2945
  function parseThemeOptions() {
@@ -2946,21 +2962,21 @@
2946
2962
  function createCssClass(lines, selector, content, scope) {
2947
2963
  lines.push(`${getScopedSelector(selector, scope)} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
2948
2964
  }
2949
- function genCssVariables(theme) {
2965
+ function genCssVariables(theme, prefix) {
2950
2966
  const lightOverlay = theme.dark ? 2 : 1;
2951
2967
  const darkOverlay = theme.dark ? 1 : 2;
2952
2968
  const variables = [];
2953
2969
  for (const [key, value] of Object.entries(theme.colors)) {
2954
2970
  const rgb = parseColor(value);
2955
- variables.push(`--v-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2971
+ variables.push(`--${prefix}theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2956
2972
  if (!key.startsWith('on-')) {
2957
- variables.push(`--v-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2973
+ variables.push(`--${prefix}theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2958
2974
  }
2959
2975
  }
2960
2976
  for (const [key, value] of Object.entries(theme.variables)) {
2961
2977
  const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
2962
2978
  const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
2963
- variables.push(`--v-${key}: ${rgb ?? value}`);
2979
+ variables.push(`--${prefix}${key}: ${rgb ?? value}`);
2964
2980
  }
2965
2981
  return variables;
2966
2982
  }
@@ -3004,7 +3020,8 @@
3004
3020
  const scopeSelector = `:where(${scope})`;
3005
3021
  return selector === ':root' ? scopeSelector : `${scopeSelector} ${selector}`;
3006
3022
  }
3007
- function upsertStyles(styleEl, styles) {
3023
+ function upsertStyles(id, cspNonce, styles) {
3024
+ const styleEl = getOrCreateStyleElement(id, cspNonce);
3008
3025
  if (!styleEl) return;
3009
3026
  styleEl.innerHTML = styles;
3010
3027
  }
@@ -3024,8 +3041,17 @@
3024
3041
  // Composables
3025
3042
  function createTheme(options) {
3026
3043
  const parsedOptions = parseThemeOptions(options);
3027
- const name = vue.shallowRef(parsedOptions.defaultTheme);
3044
+ const _name = vue.shallowRef(parsedOptions.defaultTheme);
3028
3045
  const themes = vue.ref(parsedOptions.themes);
3046
+ const systemName = vue.shallowRef('light');
3047
+ const name = vue.computed({
3048
+ get() {
3049
+ return _name.value === 'system' ? systemName.value : _name.value;
3050
+ },
3051
+ set(val) {
3052
+ _name.value = val;
3053
+ }
3054
+ });
3029
3055
  const computedThemes = vue.computed(() => {
3030
3056
  const acc = {};
3031
3057
  for (const [name, original] of Object.entries(themes.value)) {
@@ -3046,28 +3072,49 @@
3046
3072
  const current = vue.toRef(() => computedThemes.value[name.value]);
3047
3073
  const styles = vue.computed(() => {
3048
3074
  const lines = [];
3075
+ const important = parsedOptions.unimportant ? '' : ' !important';
3076
+ const scoped = parsedOptions.scoped ? parsedOptions.prefix : '';
3049
3077
  if (current.value?.dark) {
3050
3078
  createCssClass(lines, ':root', ['color-scheme: dark'], parsedOptions.scope);
3051
3079
  }
3052
- createCssClass(lines, ':root', genCssVariables(current.value), parsedOptions.scope);
3080
+ createCssClass(lines, ':root', genCssVariables(current.value, parsedOptions.prefix), parsedOptions.scope);
3053
3081
  for (const [themeName, theme] of Object.entries(computedThemes.value)) {
3054
- createCssClass(lines, `.v-theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme)], parsedOptions.scope);
3055
- }
3056
- const bgLines = [];
3057
- const fgLines = [];
3058
- const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
3059
- for (const key of colors) {
3060
- if (key.startsWith('on-')) {
3061
- createCssClass(fgLines, `.${key}`, [`color: rgb(var(--v-theme-${key})) !important`], parsedOptions.scope);
3062
- } else {
3063
- createCssClass(bgLines, `.bg-${key}`, [`--v-theme-overlay-multiplier: var(--v-theme-${key}-overlay-multiplier)`, `background-color: rgb(var(--v-theme-${key})) !important`, `color: rgb(var(--v-theme-on-${key})) !important`], parsedOptions.scope);
3064
- createCssClass(fgLines, `.text-${key}`, [`color: rgb(var(--v-theme-${key})) !important`], parsedOptions.scope);
3065
- createCssClass(fgLines, `.border-${key}`, [`--v-border-color: var(--v-theme-${key})`], parsedOptions.scope);
3082
+ createCssClass(lines, `.${parsedOptions.prefix}theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme, parsedOptions.prefix)], parsedOptions.scope);
3083
+ }
3084
+ if (parsedOptions.utilities) {
3085
+ const bgLines = [];
3086
+ const fgLines = [];
3087
+ const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
3088
+ for (const key of colors) {
3089
+ if (key.startsWith('on-')) {
3090
+ createCssClass(fgLines, `.${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
3091
+ } else {
3092
+ createCssClass(bgLines, `.${scoped}bg-${key}`, [`--${parsedOptions.prefix}theme-overlay-multiplier: var(--${parsedOptions.prefix}theme-${key}-overlay-multiplier)`, `background-color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`, `color: rgb(var(--${parsedOptions.prefix}theme-on-${key}))${important}`], parsedOptions.scope);
3093
+ createCssClass(fgLines, `.${scoped}text-${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
3094
+ createCssClass(fgLines, `.${scoped}border-${key}`, [`--${parsedOptions.prefix}border-color: var(--${parsedOptions.prefix}theme-${key})`], parsedOptions.scope);
3095
+ }
3066
3096
  }
3097
+ lines.push(...bgLines, ...fgLines);
3067
3098
  }
3068
- lines.push(...bgLines, ...fgLines);
3069
3099
  return lines.map((str, i) => i === 0 ? str : ` ${str}`).join('');
3070
3100
  });
3101
+ const themeClasses = vue.toRef(() => parsedOptions.isDisabled ? undefined : `${parsedOptions.prefix}theme--${name.value}`);
3102
+ const themeNames = vue.toRef(() => Object.keys(computedThemes.value));
3103
+ if (SUPPORTS_MATCH_MEDIA) {
3104
+ const media = window.matchMedia('(prefers-color-scheme: dark)');
3105
+ function updateSystemName() {
3106
+ systemName.value = media.matches ? 'dark' : 'light';
3107
+ }
3108
+ updateSystemName();
3109
+ media.addEventListener('change', updateSystemName, {
3110
+ passive: true
3111
+ });
3112
+ if (vue.getCurrentScope()) {
3113
+ vue.onScopeDispose(() => {
3114
+ media.removeEventListener('change', updateSystemName);
3115
+ });
3116
+ }
3117
+ }
3071
3118
  function install(app) {
3072
3119
  if (parsedOptions.isDisabled) return;
3073
3120
  const head = app._context.provides.usehead;
@@ -3105,22 +3152,55 @@
3105
3152
  updateStyles();
3106
3153
  }
3107
3154
  function updateStyles() {
3108
- upsertStyles(getOrCreateStyleElement(parsedOptions.stylesheetId, parsedOptions.cspNonce), styles.value);
3155
+ upsertStyles(parsedOptions.stylesheetId, parsedOptions.cspNonce, styles.value);
3109
3156
  }
3110
3157
  }
3111
3158
  }
3112
- const themeClasses = vue.toRef(() => parsedOptions.isDisabled ? undefined : `v-theme--${name.value}`);
3159
+ function change(themeName) {
3160
+ if (!themeNames.value.includes(themeName)) {
3161
+ consoleWarn(`Theme "${themeName}" not found on the Vuetify theme instance`);
3162
+ return;
3163
+ }
3164
+ name.value = themeName;
3165
+ }
3166
+ function cycle() {
3167
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : themeNames.value;
3168
+ const currentIndex = themeArray.indexOf(name.value);
3169
+ const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % themeArray.length;
3170
+ change(themeArray[nextIndex]);
3171
+ }
3172
+ function toggle() {
3173
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['light', 'dark'];
3174
+ cycle(themeArray);
3175
+ }
3176
+ const globalName = new Proxy(name, {
3177
+ get(target, prop) {
3178
+ return target[prop];
3179
+ },
3180
+ set(target, prop, val) {
3181
+ if (prop === 'value') {
3182
+ deprecate(`theme.global.name.value = ${val}`, `theme.change('${val}')`);
3183
+ }
3184
+ // @ts-expect-error
3185
+ target[prop] = val;
3186
+ return true;
3187
+ }
3188
+ });
3113
3189
  return {
3114
3190
  install,
3191
+ change,
3192
+ cycle,
3193
+ toggle,
3115
3194
  isDisabled: parsedOptions.isDisabled,
3116
3195
  name,
3117
3196
  themes,
3118
3197
  current,
3119
3198
  computedThemes,
3199
+ prefix: parsedOptions.prefix,
3120
3200
  themeClasses,
3121
3201
  styles,
3122
3202
  global: {
3123
- name,
3203
+ name: globalName,
3124
3204
  current
3125
3205
  }
3126
3206
  };
@@ -3131,7 +3211,7 @@
3131
3211
  if (!theme) throw new Error('Could not find Vuetify theme injection');
3132
3212
  const name = vue.toRef(() => props.theme ?? theme.name.value);
3133
3213
  const current = vue.toRef(() => theme.themes.value[name.value]);
3134
- const themeClasses = vue.toRef(() => theme.isDisabled ? undefined : `v-theme--${name.value}`);
3214
+ const themeClasses = vue.toRef(() => theme.isDisabled ? undefined : `${theme.prefix}theme--${name.value}`);
3135
3215
  const newTheme = {
3136
3216
  ...theme,
3137
3217
  name,
@@ -4235,7 +4315,10 @@
4235
4315
  default: 'default',
4236
4316
  validator: v => allowedDensities$1.includes(v)
4237
4317
  },
4238
- extended: Boolean,
4318
+ extended: {
4319
+ type: Boolean,
4320
+ default: null
4321
+ },
4239
4322
  extensionHeight: {
4240
4323
  type: [Number, String],
4241
4324
  default: 48
@@ -4283,7 +4366,7 @@
4283
4366
  const {
4284
4367
  rtlClasses
4285
4368
  } = useRtl();
4286
- const isExtended = vue.shallowRef(!!(props.extended || slots.extension?.()));
4369
+ const isExtended = vue.shallowRef(props.extended === null ? !!slots.extension?.() : props.extended);
4287
4370
  const contentHeight = vue.computed(() => parseInt(Number(props.height) + (props.density === 'prominent' ? Number(props.height) : 0) - (props.density === 'comfortable' ? 8 : 0) - (props.density === 'compact' ? 16 : 0), 10));
4288
4371
  const extensionHeight = vue.computed(() => isExtended.value ? parseInt(Number(props.extensionHeight) + (props.density === 'prominent' ? Number(props.extensionHeight) : 0) - (props.density === 'comfortable' ? 4 : 0) - (props.density === 'compact' ? 8 : 0), 10) : 0);
4289
4372
  provideDefaults({
@@ -4295,7 +4378,7 @@
4295
4378
  const hasTitle = !!(props.title || slots.title);
4296
4379
  const hasImage = !!(slots.image || props.image);
4297
4380
  const extension = slots.extension?.();
4298
- isExtended.value = !!(props.extended || extension);
4381
+ isExtended.value = props.extended === null ? !!extension : props.extended;
4299
4382
  return vue.createVNode(props.tag, {
4300
4383
  "class": vue.normalizeClass(['v-toolbar', {
4301
4384
  'v-toolbar--absolute': props.absolute,
@@ -4678,9 +4761,15 @@
4678
4761
  };
4679
4762
  }
4680
4763
 
4764
+ // Types
4765
+
4681
4766
  const makeVBtnGroupProps = propsFactory({
4682
4767
  baseColor: String,
4683
4768
  divided: Boolean,
4769
+ direction: {
4770
+ type: String,
4771
+ default: 'horizontal'
4772
+ },
4684
4773
  ...makeBorderProps(),
4685
4774
  ...makeComponentProps(),
4686
4775
  ...makeDensityProps(),
@@ -4714,7 +4803,7 @@
4714
4803
  } = useRounded(props);
4715
4804
  provideDefaults({
4716
4805
  VBtn: {
4717
- height: 'auto',
4806
+ height: vue.toRef(() => props.direction === 'horizontal' ? 'auto' : null),
4718
4807
  baseColor: vue.toRef(() => props.baseColor),
4719
4808
  color: vue.toRef(() => props.color),
4720
4809
  density: vue.toRef(() => props.density),
@@ -4724,7 +4813,7 @@
4724
4813
  });
4725
4814
  useRender(() => {
4726
4815
  return vue.createVNode(props.tag, {
4727
- "class": vue.normalizeClass(['v-btn-group', {
4816
+ "class": vue.normalizeClass(['v-btn-group', `v-btn-group--${props.direction}`, {
4728
4817
  'v-btn-group--divided': props.divided
4729
4818
  }, themeClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class]),
4730
4819
  "style": vue.normalizeStyle(props.style)
@@ -4891,6 +4980,7 @@
4891
4980
  } else {
4892
4981
  const isSelected = selected.value.includes(id);
4893
4982
  if (props.mandatory && isSelected) return;
4983
+ if (!isSelected && !value) return;
4894
4984
  selected.value = value ?? !isSelected ? [id] : [];
4895
4985
  }
4896
4986
  }
@@ -5116,7 +5206,7 @@
5116
5206
  const observer = new IntersectionObserver(entries => {
5117
5207
  isIntersecting.value = !!entries.find(entry => entry.isIntersecting);
5118
5208
  }, options);
5119
- vue.onBeforeUnmount(() => {
5209
+ vue.onScopeDispose(() => {
5120
5210
  observer.disconnect();
5121
5211
  });
5122
5212
  vue.watch(intersectionRef, (newValue, oldValue) => {
@@ -5647,9 +5737,9 @@
5647
5737
 
5648
5738
  function useSelectLink(link, select) {
5649
5739
  vue.watch(() => link.isActive?.value, isActive => {
5650
- if (link.isLink.value && isActive && select) {
5740
+ if (link.isLink.value && isActive != null && select) {
5651
5741
  vue.nextTick(() => {
5652
- select(true);
5742
+ select(isActive);
5653
5743
  });
5654
5744
  }
5655
5745
  }, {
@@ -5847,8 +5937,8 @@
5847
5937
  window.clearTimeout(element._ripple.showTimer);
5848
5938
  }
5849
5939
  let keyboardRipple = false;
5850
- function keyboardRippleShow(e) {
5851
- if (!keyboardRipple && (e.keyCode === keyCodes.enter || e.keyCode === keyCodes.space)) {
5940
+ function keyboardRippleShow(e, keys) {
5941
+ if (!keyboardRipple && keys.includes(e.keyCode)) {
5852
5942
  keyboardRipple = true;
5853
5943
  rippleShow(e);
5854
5944
  }
@@ -5876,9 +5966,12 @@
5876
5966
  el._ripple.enabled = enabled;
5877
5967
  el._ripple.centered = modifiers.center;
5878
5968
  el._ripple.circle = modifiers.circle;
5879
- if (isObject(value) && value.class) {
5880
- el._ripple.class = value.class;
5969
+ const bindingValue = isObject(value) ? value : {};
5970
+ if (bindingValue.class) {
5971
+ el._ripple.class = bindingValue.class;
5881
5972
  }
5973
+ const allowedKeys = bindingValue.keys ?? [keyCodes.enter, keyCodes.space];
5974
+ el._ripple.keyDownHandler = e => keyboardRippleShow(e, allowedKeys);
5882
5975
  if (enabled && !wasEnabled) {
5883
5976
  if (modifiers.stop) {
5884
5977
  el.addEventListener('touchstart', rippleStop, {
@@ -5900,7 +5993,7 @@
5900
5993
  el.addEventListener('mousedown', rippleShow);
5901
5994
  el.addEventListener('mouseup', rippleHide);
5902
5995
  el.addEventListener('mouseleave', rippleHide);
5903
- el.addEventListener('keydown', keyboardRippleShow);
5996
+ el.addEventListener('keydown', e => keyboardRippleShow(e, allowedKeys));
5904
5997
  el.addEventListener('keyup', keyboardRippleHide);
5905
5998
  el.addEventListener('blur', focusRippleHide);
5906
5999
 
@@ -5920,7 +6013,9 @@
5920
6013
  el.removeEventListener('touchcancel', rippleHide);
5921
6014
  el.removeEventListener('mouseup', rippleHide);
5922
6015
  el.removeEventListener('mouseleave', rippleHide);
5923
- el.removeEventListener('keydown', keyboardRippleShow);
6016
+ if (el._ripple?.keyDownHandler) {
6017
+ el.removeEventListener('keydown', el._ripple.keyDownHandler);
6018
+ }
5924
6019
  el.removeEventListener('keyup', keyboardRippleHide);
5925
6020
  el.removeEventListener('dragstart', rippleHide);
5926
6021
  el.removeEventListener('blur', focusRippleHide);
@@ -5929,8 +6024,8 @@
5929
6024
  updateRipple(el, binding, false);
5930
6025
  }
5931
6026
  function unmounted$4(el) {
5932
- delete el._ripple;
5933
6027
  removeListeners(el);
6028
+ delete el._ripple;
5934
6029
  }
5935
6030
  function updated$1(el, binding) {
5936
6031
  if (binding.value === binding.oldValue) {
@@ -6203,6 +6298,31 @@
6203
6298
  // Utilities
6204
6299
  const VAlertTitle = createSimpleFunctional('v-alert-title');
6205
6300
 
6301
+ // Utilities
6302
+
6303
+ // Types
6304
+
6305
+ // Types
6306
+
6307
+ // Composables
6308
+ const makeIconSizeProps = propsFactory({
6309
+ iconSize: [Number, String],
6310
+ iconSizes: {
6311
+ type: Array,
6312
+ default: () => [['x-small', 10], ['small', 16], ['default', 24], ['large', 28], ['x-large', 32]]
6313
+ }
6314
+ }, 'iconSize');
6315
+ function useIconSizes(props, fallback) {
6316
+ const iconSize = vue.computed(() => {
6317
+ const iconSizeMap = new Map(props.iconSizes);
6318
+ const _iconSize = props.iconSize ?? fallback() ?? 'default';
6319
+ return iconSizeMap.has(_iconSize) ? iconSizeMap.get(_iconSize) : _iconSize;
6320
+ });
6321
+ return {
6322
+ iconSize
6323
+ };
6324
+ }
6325
+
6206
6326
  // Types
6207
6327
 
6208
6328
  const allowedTypes = ['success', 'info', 'warning', 'error'];
@@ -6242,6 +6362,7 @@
6242
6362
  ...makeDensityProps(),
6243
6363
  ...makeDimensionProps(),
6244
6364
  ...makeElevationProps(),
6365
+ ...makeIconSizeProps(),
6245
6366
  ...makeLocationProps(),
6246
6367
  ...makePositionProps(),
6247
6368
  ...makeRoundedProps(),
@@ -6269,6 +6390,9 @@
6269
6390
  if (!props.type) return props.icon;
6270
6391
  return props.icon ?? `$${props.type}`;
6271
6392
  });
6393
+ const {
6394
+ iconSize
6395
+ } = useIconSizes(props, () => props.prominent ? 44 : 28);
6272
6396
  const {
6273
6397
  themeClasses
6274
6398
  } = provideTheme(props);
@@ -6316,6 +6440,11 @@
6316
6440
  const hasPrepend = !!(slots.prepend || icon.value);
6317
6441
  const hasTitle = !!(slots.title || props.title);
6318
6442
  const hasClose = !!(slots.close || props.closable);
6443
+ const iconProps = {
6444
+ density: props.density,
6445
+ icon: icon.value,
6446
+ size: iconSize.value
6447
+ };
6319
6448
  return isActive.value && vue.createVNode(props.tag, {
6320
6449
  "class": vue.normalizeClass(['v-alert', props.border && {
6321
6450
  'v-alert--border': !!props.border,
@@ -6333,19 +6462,14 @@
6333
6462
  }, null), hasPrepend && vue.createElementVNode("div", {
6334
6463
  "key": "prepend",
6335
6464
  "class": "v-alert__prepend"
6336
- }, [!slots.prepend ? vue.createVNode(VIcon, {
6337
- "key": "prepend-icon",
6338
- "density": props.density,
6339
- "icon": icon.value,
6340
- "size": props.prominent ? 44 : 28
6341
- }, null) : vue.createVNode(VDefaultsProvider, {
6465
+ }, [!slots.prepend ? vue.createVNode(VIcon, vue.mergeProps({
6466
+ "key": "prepend-icon"
6467
+ }, iconProps), null) : vue.createVNode(VDefaultsProvider, {
6342
6468
  "key": "prepend-defaults",
6343
6469
  "disabled": !icon.value,
6344
6470
  "defaults": {
6345
6471
  VIcon: {
6346
- density: props.density,
6347
- icon: icon.value,
6348
- size: props.prominent ? 44 : 28
6472
+ ...iconProps
6349
6473
  }
6350
6474
  }
6351
6475
  }, slots.prepend)]), vue.createElementVNode("div", {
@@ -7870,6 +7994,7 @@
7870
7994
  const VSlideGroupSymbol = Symbol.for('vuetify:v-slide-group');
7871
7995
  const makeVSlideGroupProps = propsFactory({
7872
7996
  centerActive: Boolean,
7997
+ contentClass: null,
7873
7998
  direction: {
7874
7999
  type: String,
7875
8000
  default: 'horizontal'
@@ -8182,7 +8307,7 @@
8182
8307
  })]), vue.createElementVNode("div", {
8183
8308
  "key": "container",
8184
8309
  "ref": containerRef,
8185
- "class": "v-slide-group__container",
8310
+ "class": vue.normalizeClass(['v-slide-group__container', props.contentClass]),
8186
8311
  "onScroll": onScroll
8187
8312
  }, [vue.createElementVNode("div", {
8188
8313
  "ref": contentRef,
@@ -8545,16 +8670,85 @@
8545
8670
  }
8546
8671
  });
8547
8672
 
8673
+ const makeVDividerProps = propsFactory({
8674
+ color: String,
8675
+ inset: Boolean,
8676
+ length: [Number, String],
8677
+ opacity: [Number, String],
8678
+ thickness: [Number, String],
8679
+ vertical: Boolean,
8680
+ ...makeComponentProps(),
8681
+ ...makeThemeProps()
8682
+ }, 'VDivider');
8683
+ const VDivider = genericComponent()({
8684
+ name: 'VDivider',
8685
+ props: makeVDividerProps(),
8686
+ setup(props, _ref) {
8687
+ let {
8688
+ attrs,
8689
+ slots
8690
+ } = _ref;
8691
+ const {
8692
+ themeClasses
8693
+ } = provideTheme(props);
8694
+ const {
8695
+ textColorClasses,
8696
+ textColorStyles
8697
+ } = useTextColor(() => props.color);
8698
+ const dividerStyles = vue.computed(() => {
8699
+ const styles = {};
8700
+ if (props.length) {
8701
+ styles[props.vertical ? 'height' : 'width'] = convertToUnit(props.length);
8702
+ }
8703
+ if (props.thickness) {
8704
+ styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
8705
+ }
8706
+ return styles;
8707
+ });
8708
+ useRender(() => {
8709
+ const divider = vue.createElementVNode("hr", {
8710
+ "class": vue.normalizeClass([{
8711
+ 'v-divider': true,
8712
+ 'v-divider--inset': props.inset,
8713
+ 'v-divider--vertical': props.vertical
8714
+ }, themeClasses.value, textColorClasses.value, props.class]),
8715
+ "style": vue.normalizeStyle([dividerStyles.value, textColorStyles.value, {
8716
+ '--v-border-opacity': props.opacity
8717
+ }, props.style]),
8718
+ "aria-orientation": !attrs.role || attrs.role === 'separator' ? props.vertical ? 'vertical' : 'horizontal' : undefined,
8719
+ "role": `${attrs.role || 'separator'}`
8720
+ }, null);
8721
+ if (!slots.default) return divider;
8722
+ return vue.createElementVNode("div", {
8723
+ "class": vue.normalizeClass(['v-divider__wrapper', {
8724
+ 'v-divider__wrapper--vertical': props.vertical,
8725
+ 'v-divider__wrapper--inset': props.inset
8726
+ }])
8727
+ }, [divider, vue.createElementVNode("div", {
8728
+ "class": "v-divider__content"
8729
+ }, [slots.default()]), divider]);
8730
+ });
8731
+ return {};
8732
+ }
8733
+ });
8734
+
8548
8735
  // Utilities
8549
8736
 
8550
8737
  // List
8551
8738
  const ListKey = Symbol.for('vuetify:list');
8552
8739
  function createList() {
8740
+ let {
8741
+ filterable
8742
+ } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
8743
+ filterable: false
8744
+ };
8553
8745
  const parent = vue.inject(ListKey, {
8746
+ filterable: false,
8554
8747
  hasPrepend: vue.shallowRef(false),
8555
8748
  updateHasPrepend: () => null
8556
8749
  });
8557
8750
  const data = {
8751
+ filterable: parent.filterable || filterable,
8558
8752
  hasPrepend: vue.shallowRef(false),
8559
8753
  updateHasPrepend: value => {
8560
8754
  if (value) data.hasPrepend.value = value;
@@ -9263,6 +9457,7 @@
9263
9457
  type: IconValue,
9264
9458
  default: '$expand'
9265
9459
  },
9460
+ rawId: [String, Number],
9266
9461
  prependIcon: IconValue,
9267
9462
  appendIcon: IconValue,
9268
9463
  fluid: Boolean,
@@ -9284,13 +9479,12 @@
9284
9479
  open,
9285
9480
  id: _id
9286
9481
  } = useNestedItem(() => props.value, true);
9287
- const id = vue.computed(() => `v-list-group--id-${String(_id.value)}`);
9482
+ const id = vue.computed(() => `v-list-group--id-${String(props.rawId ?? _id.value)}`);
9288
9483
  const list = useList();
9289
9484
  const {
9290
9485
  isBooted
9291
9486
  } = useSsrBoot();
9292
9487
  function onClick(e) {
9293
- e.stopPropagation();
9294
9488
  if (['INPUT', 'TEXTAREA'].includes(e.target?.tagName)) return;
9295
9489
  open(!isOpen.value, e);
9296
9490
  }
@@ -9506,6 +9700,9 @@
9506
9700
  roundedClasses
9507
9701
  } = useRounded(roundedProps);
9508
9702
  const lineClasses = vue.toRef(() => props.lines ? `v-list-item--${props.lines}-line` : undefined);
9703
+ const rippleOptions = vue.toRef(() => props.ripple !== undefined && !!props.ripple && list?.filterable ? {
9704
+ keys: [keyCodes.enter]
9705
+ } : props.ripple);
9509
9706
  const slotProps = vue.computed(() => ({
9510
9707
  isActive: isActive.value,
9511
9708
  select,
@@ -9530,8 +9727,9 @@
9530
9727
  function onKeyDown(e) {
9531
9728
  const target = e.target;
9532
9729
  if (['INPUT', 'TEXTAREA'].includes(target.tagName)) return;
9533
- if (e.key === 'Enter' || e.key === ' ') {
9730
+ if (e.key === 'Enter' || e.key === ' ' && !list?.filterable) {
9534
9731
  e.preventDefault();
9732
+ e.stopPropagation();
9535
9733
  e.target.dispatchEvent(new MouseEvent('click', e));
9536
9734
  }
9537
9735
  }
@@ -9641,7 +9839,7 @@
9641
9839
  }), vue.createElementVNode("div", {
9642
9840
  "class": "v-list-item__spacer"
9643
9841
  }, null)])]
9644
- }), [[Ripple, isClickable.value && props.ripple]]);
9842
+ }), [[Ripple, isClickable.value && rippleOptions.value]]);
9645
9843
  });
9646
9844
  return {
9647
9845
  activate,
@@ -9696,68 +9894,6 @@
9696
9894
  }
9697
9895
  });
9698
9896
 
9699
- const makeVDividerProps = propsFactory({
9700
- color: String,
9701
- inset: Boolean,
9702
- length: [Number, String],
9703
- opacity: [Number, String],
9704
- thickness: [Number, String],
9705
- vertical: Boolean,
9706
- ...makeComponentProps(),
9707
- ...makeThemeProps()
9708
- }, 'VDivider');
9709
- const VDivider = genericComponent()({
9710
- name: 'VDivider',
9711
- props: makeVDividerProps(),
9712
- setup(props, _ref) {
9713
- let {
9714
- attrs,
9715
- slots
9716
- } = _ref;
9717
- const {
9718
- themeClasses
9719
- } = provideTheme(props);
9720
- const {
9721
- textColorClasses,
9722
- textColorStyles
9723
- } = useTextColor(() => props.color);
9724
- const dividerStyles = vue.computed(() => {
9725
- const styles = {};
9726
- if (props.length) {
9727
- styles[props.vertical ? 'height' : 'width'] = convertToUnit(props.length);
9728
- }
9729
- if (props.thickness) {
9730
- styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
9731
- }
9732
- return styles;
9733
- });
9734
- useRender(() => {
9735
- const divider = vue.createElementVNode("hr", {
9736
- "class": vue.normalizeClass([{
9737
- 'v-divider': true,
9738
- 'v-divider--inset': props.inset,
9739
- 'v-divider--vertical': props.vertical
9740
- }, themeClasses.value, textColorClasses.value, props.class]),
9741
- "style": vue.normalizeStyle([dividerStyles.value, textColorStyles.value, {
9742
- '--v-border-opacity': props.opacity
9743
- }, props.style]),
9744
- "aria-orientation": !attrs.role || attrs.role === 'separator' ? props.vertical ? 'vertical' : 'horizontal' : undefined,
9745
- "role": `${attrs.role || 'separator'}`
9746
- }, null);
9747
- if (!slots.default) return divider;
9748
- return vue.createElementVNode("div", {
9749
- "class": vue.normalizeClass(['v-divider__wrapper', {
9750
- 'v-divider__wrapper--vertical': props.vertical,
9751
- 'v-divider__wrapper--inset': props.inset
9752
- }])
9753
- }, [divider, vue.createElementVNode("div", {
9754
- "class": "v-divider__content"
9755
- }, [slots.default()]), divider]);
9756
- });
9757
- return {};
9758
- }
9759
- });
9760
-
9761
9897
  // Types
9762
9898
 
9763
9899
  const makeVListChildrenProps = propsFactory({
@@ -9808,9 +9944,10 @@
9808
9944
  }) : undefined
9809
9945
  };
9810
9946
  const listGroupProps = VListGroup.filterProps(itemProps);
9811
- return children ? vue.createVNode(VListGroup, vue.mergeProps({
9812
- "value": itemProps?.value
9813
- }, listGroupProps), {
9947
+ return children ? vue.createVNode(VListGroup, vue.mergeProps(listGroupProps, {
9948
+ "value": props.returnObject ? item : itemProps?.value,
9949
+ "rawId": itemProps?.value
9950
+ }), {
9814
9951
  activator: _ref3 => {
9815
9952
  let {
9816
9953
  props: activatorProps
@@ -10026,6 +10163,7 @@
10026
10163
  activeClass: String,
10027
10164
  bgColor: String,
10028
10165
  disabled: Boolean,
10166
+ filterable: Boolean,
10029
10167
  expandIcon: IconValue,
10030
10168
  collapseIcon: IconValue,
10031
10169
  lines: {
@@ -10109,7 +10247,9 @@
10109
10247
  const activeColor = vue.toRef(() => props.activeColor);
10110
10248
  const baseColor = vue.toRef(() => props.baseColor);
10111
10249
  const color = vue.toRef(() => props.color);
10112
- createList();
10250
+ createList({
10251
+ filterable: props.filterable
10252
+ });
10113
10253
  provideDefaults({
10114
10254
  VListGroup: {
10115
10255
  activeColor,
@@ -11792,6 +11932,7 @@
11792
11932
  // disableKeys: Boolean,
11793
11933
  id: String,
11794
11934
  submenu: Boolean,
11935
+ disableInitialFocus: Boolean,
11795
11936
  ...omit(makeVOverlayProps({
11796
11937
  closeDelay: 250,
11797
11938
  closeOnContentClick: true,
@@ -11866,7 +12007,7 @@
11866
12007
  vue.watch(isActive, val => {
11867
12008
  if (val) {
11868
12009
  parent?.register();
11869
- if (IN_BROWSER) {
12010
+ if (IN_BROWSER && !props.disableInitialFocus) {
11870
12011
  document.addEventListener('focusin', onFocusIn, {
11871
12012
  once: true
11872
12013
  });
@@ -12346,6 +12487,16 @@
12346
12487
  }
12347
12488
  });
12348
12489
 
12490
+ function useAutofocus(props) {
12491
+ function onIntersect(isIntersecting, entries) {
12492
+ if (!props.autofocus || !isIntersecting) return;
12493
+ entries[0].target?.focus?.();
12494
+ }
12495
+ return {
12496
+ onIntersect
12497
+ };
12498
+ }
12499
+
12349
12500
  // Types
12350
12501
 
12351
12502
  const activeTypes = ['color', 'file', 'time', 'date', 'datetime-local', 'week', 'month'];
@@ -12392,6 +12543,9 @@
12392
12543
  focus,
12393
12544
  blur
12394
12545
  } = useFocus(props);
12546
+ const {
12547
+ onIntersect
12548
+ } = useAutofocus(props);
12395
12549
  const counterValue = vue.computed(() => {
12396
12550
  return typeof props.counterValue === 'function' ? props.counterValue(model.value) : typeof props.counterValue === 'number' ? props.counterValue : (model.value ?? '').toString().length;
12397
12551
  });
@@ -12401,10 +12555,6 @@
12401
12555
  return props.counter;
12402
12556
  });
12403
12557
  const isPlainOrUnderlined = vue.computed(() => ['plain', 'underlined'].includes(props.variant));
12404
- function onIntersect(isIntersecting, entries) {
12405
- if (!props.autofocus || !isIntersecting) return;
12406
- entries[0].target?.focus?.();
12407
- }
12408
12558
  const vInputRef = vue.ref();
12409
12559
  const vFieldRef = vue.ref();
12410
12560
  const inputRef = vue.ref();
@@ -12694,7 +12844,12 @@
12694
12844
  }
12695
12845
  function calculateOffset(index) {
12696
12846
  index = clamp(index, 0, items.value.length - 1);
12697
- return offsets[index] || 0;
12847
+ const whole = Math.floor(index);
12848
+ const fraction = index % 1;
12849
+ const next = whole + 1;
12850
+ const wholeOffset = offsets[whole] || 0;
12851
+ const nextOffset = offsets[next] || wholeOffset;
12852
+ return wholeOffset + (nextOffset - wholeOffset) * fraction;
12698
12853
  }
12699
12854
  function calculateIndex(scrollTop) {
12700
12855
  return binaryClosest(offsets, scrollTop);
@@ -13048,6 +13203,7 @@
13048
13203
  },
13049
13204
  openOnClear: Boolean,
13050
13205
  itemColor: String,
13206
+ noAutoScroll: Boolean,
13051
13207
  ...makeItemsProps({
13052
13208
  itemChildren: false
13053
13209
  })
@@ -13262,7 +13418,7 @@
13262
13418
  vue.watch(menu, () => {
13263
13419
  if (!props.hideSelected && menu.value && model.value.length) {
13264
13420
  const index = displayItems.value.findIndex(item => model.value.some(s => (props.valueComparator || deepEqual)(s.value, item.value)));
13265
- IN_BROWSER && window.requestAnimationFrame(() => {
13421
+ IN_BROWSER && !props.noAutoScroll && window.requestAnimationFrame(() => {
13266
13422
  index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
13267
13423
  });
13268
13424
  }
@@ -13355,6 +13511,22 @@
13355
13511
  key: item.value,
13356
13512
  onClick: () => select(item, null)
13357
13513
  });
13514
+ if (item.raw.type === 'divider') {
13515
+ return slots.divider?.({
13516
+ props: item.raw,
13517
+ index
13518
+ }) ?? vue.createVNode(VDivider, vue.mergeProps(item.props, {
13519
+ "key": `divider-${index}`
13520
+ }), null);
13521
+ }
13522
+ if (item.raw.type === 'subheader') {
13523
+ return slots.subheader?.({
13524
+ props: item.raw,
13525
+ index
13526
+ }) ?? vue.createVNode(VListSubheader, vue.mergeProps(item.props, {
13527
+ "key": `subheader-${index}`
13528
+ }), null);
13529
+ }
13358
13530
  return slots.item?.({
13359
13531
  item,
13360
13532
  index,
@@ -13515,6 +13687,9 @@
13515
13687
  let match = -1;
13516
13688
  if ((query || customFiltersLength > 0) && !options?.noFilter) {
13517
13689
  if (typeof item === 'object') {
13690
+ if (['divider', 'subheader'].includes(item.raw?.type)) {
13691
+ continue;
13692
+ }
13518
13693
  const filterKeys = keys || Object.keys(transformed);
13519
13694
  for (const key of filterKeys) {
13520
13695
  const value = getPropertyFromItem(transformed, key);
@@ -13717,7 +13892,7 @@
13717
13892
  menu.value = !menu.value;
13718
13893
  }
13719
13894
  function onListKeydown(e) {
13720
- if (e.key !== ' ' && checkPrintable(e)) {
13895
+ if (checkPrintable(e) || e.key === 'Backspace') {
13721
13896
  vTextFieldRef.value?.focus();
13722
13897
  }
13723
13898
  }
@@ -13922,6 +14097,7 @@
13922
14097
  }, props.menuProps), {
13923
14098
  default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
13924
14099
  "ref": listRef,
14100
+ "filterable": true,
13925
14101
  "selected": selectedValues.value,
13926
14102
  "selectStrategy": props.multiple ? 'independent' : 'single-independent',
13927
14103
  "onMousedown": e => e.preventDefault(),
@@ -13953,6 +14129,22 @@
13953
14129
  active: highlightFirst.value && index === 0 ? true : undefined,
13954
14130
  onClick: () => select(item, null)
13955
14131
  });
14132
+ if (item.raw.type === 'divider') {
14133
+ return slots.divider?.({
14134
+ props: item.raw,
14135
+ index
14136
+ }) ?? vue.createVNode(VDivider, vue.mergeProps(item.props, {
14137
+ "key": `divider-${index}`
14138
+ }), null);
14139
+ }
14140
+ if (item.raw.type === 'subheader') {
14141
+ return slots.subheader?.({
14142
+ props: item.raw,
14143
+ index
14144
+ }) ?? vue.createVNode(VListSubheader, vue.mergeProps(item.props, {
14145
+ "key": `subheader-${index}`
14146
+ }), null);
14147
+ }
13956
14148
  return slots.item?.({
13957
14149
  item,
13958
14150
  index,
@@ -14097,7 +14289,8 @@
14097
14289
  ...makeThemeProps(),
14098
14290
  ...makeTransitionProps({
14099
14291
  transition: 'scale-rotate-transition'
14100
- })
14292
+ }),
14293
+ ...makeDimensionProps()
14101
14294
  }, 'VBadge');
14102
14295
  const VBadge = genericComponent()({
14103
14296
  name: 'VBadge',
@@ -14127,6 +14320,9 @@
14127
14320
  const base = props.floating ? props.dot ? 2 : 4 : props.dot ? 8 : 12;
14128
14321
  return base + (['top', 'bottom'].includes(side) ? Number(props.offsetY ?? 0) : ['left', 'right'].includes(side) ? Number(props.offsetX ?? 0) : 0);
14129
14322
  });
14323
+ const {
14324
+ dimensionStyles
14325
+ } = useDimension(props);
14130
14326
  useRender(() => {
14131
14327
  const value = Number(props.content);
14132
14328
  const content = !props.max || isNaN(value) ? props.content : value <= Number(props.max) ? value : `${props.max}+`;
@@ -14148,7 +14344,7 @@
14148
14344
  }, {
14149
14345
  default: () => [vue.withDirectives(vue.createElementVNode("span", vue.mergeProps({
14150
14346
  "class": ['v-badge__badge', themeClasses.value, backgroundColorClasses.value, roundedClasses.value, textColorClasses.value],
14151
- "style": [backgroundColorStyles.value, textColorStyles.value, props.inline ? {} : locationStyles.value],
14347
+ "style": [backgroundColorStyles.value, textColorStyles.value, dimensionStyles.value, props.inline ? {} : locationStyles.value],
14152
14348
  "aria-atomic": "true",
14153
14349
  "aria-label": t(props.label, value),
14154
14350
  "aria-live": "polite",
@@ -17557,13 +17753,13 @@
17557
17753
  return null;
17558
17754
  }
17559
17755
  const sundayJanuarySecond2000 = new Date(2000, 0, 2);
17560
- function getWeekdays(locale, firstDayOfWeek) {
17756
+ function getWeekdays(locale, firstDayOfWeek, weekdayFormat) {
17561
17757
  const daysFromSunday = firstDayOfWeek ?? weekInfo(locale)?.firstDay ?? 0;
17562
17758
  return createRange(7).map(i => {
17563
17759
  const weekday = new Date(sundayJanuarySecond2000);
17564
17760
  weekday.setDate(sundayJanuarySecond2000.getDate() + daysFromSunday + i);
17565
17761
  return new Intl.DateTimeFormat(locale, {
17566
- weekday: 'narrow'
17762
+ weekday: weekdayFormat ?? 'narrow'
17567
17763
  }).format(weekday);
17568
17764
  });
17569
17765
  }
@@ -18027,9 +18223,9 @@
18027
18223
  getDiff(date, comparing, unit) {
18028
18224
  return getDiff(date, comparing, unit);
18029
18225
  }
18030
- getWeekdays(firstDayOfWeek) {
18226
+ getWeekdays(firstDayOfWeek, weekdayFormat) {
18031
18227
  const firstDay = firstDayOfWeek !== undefined ? Number(firstDayOfWeek) : undefined;
18032
- return getWeekdays(this.locale, firstDay);
18228
+ return getWeekdays(this.locale, firstDay, weekdayFormat);
18033
18229
  }
18034
18230
  getYear(date) {
18035
18231
  return getYear(date);
@@ -18384,6 +18580,7 @@
18384
18580
  _search.value = val ?? '';
18385
18581
  if (!props.multiple && !hasSelectionSlot.value) {
18386
18582
  model.value = [transformItem$3(props, val)];
18583
+ vue.nextTick(() => vVirtualScrollRef.value?.scrollToIndex(0));
18387
18584
  }
18388
18585
  if (val && props.multiple && props.delimiters?.length) {
18389
18586
  const values = val.split(new RegExp(`(?:${props.delimiters.join('|')})+`));
@@ -18464,7 +18661,7 @@
18464
18661
  menu.value = !menu.value;
18465
18662
  }
18466
18663
  function onListKeydown(e) {
18467
- if (e.key !== ' ' && checkPrintable(e)) {
18664
+ if (checkPrintable(e) || e.key === 'Backspace') {
18468
18665
  vTextFieldRef.value?.focus();
18469
18666
  }
18470
18667
  }
@@ -18669,6 +18866,7 @@
18669
18866
  }, props.menuProps), {
18670
18867
  default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
18671
18868
  "ref": listRef,
18869
+ "filterable": true,
18672
18870
  "selected": selectedValues.value,
18673
18871
  "selectStrategy": props.multiple ? 'independent' : 'single-independent',
18674
18872
  "onMousedown": e => e.preventDefault(),
@@ -18700,6 +18898,22 @@
18700
18898
  active: highlightFirst.value && index === 0 ? true : undefined,
18701
18899
  onClick: () => select(item, null)
18702
18900
  });
18901
+ if (item.raw.type === 'divider') {
18902
+ return slots.divider?.({
18903
+ props: item.raw,
18904
+ index
18905
+ }) ?? vue.createVNode(VDivider, vue.mergeProps(item.props, {
18906
+ "key": `divider-${index}`
18907
+ }), null);
18908
+ }
18909
+ if (item.raw.type === 'subheader') {
18910
+ return slots.subheader?.({
18911
+ props: item.raw,
18912
+ index
18913
+ }) ?? vue.createVNode(VListSubheader, vue.mergeProps(item.props, {
18914
+ "key": `subheader-${index}`
18915
+ }), null);
18916
+ }
18703
18917
  return slots.item?.({
18704
18918
  item,
18705
18919
  index,
@@ -20582,6 +20796,7 @@
20582
20796
  color: String,
20583
20797
  disableSort: Boolean,
20584
20798
  fixedHeader: Boolean,
20799
+ lastFixed: Boolean,
20585
20800
  multiSort: Boolean,
20586
20801
  sortAscIcon: {
20587
20802
  type: IconValue,
@@ -20628,10 +20843,11 @@
20628
20843
  loaderClasses
20629
20844
  } = useLoader(props);
20630
20845
  function getFixedStyles(column, y) {
20631
- if (!(props.sticky || props.fixedHeader) && !column.fixed) return undefined;
20846
+ if (!(props.sticky || props.fixedHeader) && !(column.fixed || column.lastFixed)) return undefined;
20632
20847
  return {
20633
20848
  position: 'sticky',
20634
- left: column.fixed ? convertToUnit(column.fixedOffset) : undefined,
20849
+ left: column.fixed || column.lastFixed ? convertToUnit(column.fixedOffset) : undefined,
20850
+ right: column.lastFixed ? convertToUnit(column.fixedOffset ?? 0) : undefined,
20635
20851
  top: props.sticky || props.fixedHeader ? `calc(var(--v-table-header-height) * ${y})` : undefined
20636
20852
  };
20637
20853
  }
@@ -21147,11 +21363,18 @@
21147
21363
  }
21148
21364
  });
21149
21365
 
21366
+ // Types
21367
+
21150
21368
  const makeVTableProps = propsFactory({
21151
21369
  fixedHeader: Boolean,
21152
21370
  fixedFooter: Boolean,
21153
21371
  height: [Number, String],
21154
21372
  hover: Boolean,
21373
+ striped: {
21374
+ type: String,
21375
+ default: null,
21376
+ validator: v => ['even', 'odd'].includes(v)
21377
+ },
21155
21378
  ...makeComponentProps(),
21156
21379
  ...makeDensityProps(),
21157
21380
  ...makeTagProps(),
@@ -21178,7 +21401,9 @@
21178
21401
  'v-table--fixed-footer': props.fixedFooter,
21179
21402
  'v-table--has-top': !!slots.top,
21180
21403
  'v-table--has-bottom': !!slots.bottom,
21181
- 'v-table--hover': props.hover
21404
+ 'v-table--hover': props.hover,
21405
+ 'v-table--striped-even': props.striped === 'even',
21406
+ 'v-table--striped-odd': props.striped === 'odd'
21182
21407
  }, themeClasses.value, densityClasses.value, props.class]),
21183
21408
  "style": vue.normalizeStyle(props.style)
21184
21409
  }, {
@@ -22353,7 +22578,8 @@
22353
22578
  firstDayOfWeek: {
22354
22579
  type: [Number, String],
22355
22580
  default: undefined
22356
- }
22581
+ },
22582
+ weekdayFormat: String
22357
22583
  }, 'calendar');
22358
22584
  function useCalendar(props) {
22359
22585
  const adapter = useDate();
@@ -22594,7 +22820,7 @@
22594
22820
  "ref": daysRef,
22595
22821
  "key": daysInMonth.value[0].date?.toString(),
22596
22822
  "class": "v-date-picker-month__days"
22597
- }, [!props.hideWeekdays && adapter.getWeekdays(props.firstDayOfWeek).map(weekDay => vue.createElementVNode("div", {
22823
+ }, [!props.hideWeekdays && adapter.getWeekdays(props.firstDayOfWeek, props.weekdayFormat).map(weekDay => vue.createElementVNode("div", {
22598
22824
  "class": vue.normalizeClass(['v-date-picker-month__day', 'v-date-picker-month__weekday'])
22599
22825
  }, [weekDay])), daysInMonth.value.map((item, i) => {
22600
22826
  const slotProps = {
@@ -23103,7 +23329,9 @@
23103
23329
  "max": maxDate.value,
23104
23330
  "year": year.value,
23105
23331
  "allowedMonths": allowedMonths
23106
- }), null) : viewMode.value === 'year' ? vue.createVNode(VDatePickerYears, vue.mergeProps({
23332
+ }), {
23333
+ ...pick(slots, ['month'])
23334
+ }) : viewMode.value === 'year' ? vue.createVNode(VDatePickerYears, vue.mergeProps({
23107
23335
  "key": "date-picker-years"
23108
23336
  }, datePickerYearsProps, {
23109
23337
  "modelValue": year.value,
@@ -23111,7 +23339,9 @@
23111
23339
  "min": minDate.value,
23112
23340
  "max": maxDate.value,
23113
23341
  "allowedYears": allowedYears
23114
- }), null) : vue.createVNode(VDatePickerMonth, vue.mergeProps({
23342
+ }), {
23343
+ ...pick(slots, ['year'])
23344
+ }) : vue.createVNode(VDatePickerMonth, vue.mergeProps({
23115
23345
  "key": "date-picker-month"
23116
23346
  }, datePickerMonthProps, {
23117
23347
  "modelValue": model.value,
@@ -23122,7 +23352,9 @@
23122
23352
  "onUpdate:year": [$event => year.value = $event, onUpdateYear],
23123
23353
  "min": minDate.value,
23124
23354
  "max": maxDate.value
23125
- }), null)]
23355
+ }), {
23356
+ ...pick(slots, ['day'])
23357
+ })]
23126
23358
  })]),
23127
23359
  actions: slots.actions
23128
23360
  });
@@ -24213,6 +24445,9 @@
24213
24445
  startStatus.value = status;
24214
24446
  } else if (side === 'end') {
24215
24447
  endStatus.value = status;
24448
+ } else if (side === 'both') {
24449
+ startStatus.value = status;
24450
+ endStatus.value = status;
24216
24451
  }
24217
24452
  }
24218
24453
  function getStatus(side) {
@@ -24324,6 +24559,32 @@
24324
24559
  }, [renderSide('end', endStatus.value)])]
24325
24560
  });
24326
24561
  });
24562
+ function reset(side) {
24563
+ const effectiveSide = side ?? props.side;
24564
+ setStatus(effectiveSide, 'ok');
24565
+ vue.nextTick(() => {
24566
+ setScrollAmount(getScrollSize() - previousScrollSize + getScrollAmount());
24567
+ if (props.mode !== 'manual') {
24568
+ vue.nextTick(() => {
24569
+ window.requestAnimationFrame(() => {
24570
+ window.requestAnimationFrame(() => {
24571
+ window.requestAnimationFrame(() => {
24572
+ if (effectiveSide === 'both') {
24573
+ intersecting('start');
24574
+ intersecting('end');
24575
+ } else {
24576
+ intersecting(effectiveSide);
24577
+ }
24578
+ });
24579
+ });
24580
+ });
24581
+ });
24582
+ }
24583
+ });
24584
+ }
24585
+ return {
24586
+ reset
24587
+ };
24327
24588
  }
24328
24589
  });
24329
24590
 
@@ -24403,8 +24664,47 @@
24403
24664
  }
24404
24665
  });
24405
24666
 
24406
- // Styles
24407
- const VKbd = createSimpleFunctional('v-kbd', 'kbd');
24667
+ const makeVKbdProps = propsFactory({
24668
+ ...makeBorderProps(),
24669
+ ...makeComponentProps(),
24670
+ ...makeRoundedProps(),
24671
+ ...makeTagProps({
24672
+ tag: 'kbd'
24673
+ }),
24674
+ ...makeThemeProps(),
24675
+ ...makeElevationProps(),
24676
+ color: String
24677
+ }, 'VKbd');
24678
+ const VKbd = genericComponent()({
24679
+ name: 'VKbd',
24680
+ props: makeVKbdProps(),
24681
+ setup(props, _ref) {
24682
+ let {
24683
+ slots
24684
+ } = _ref;
24685
+ const {
24686
+ themeClasses
24687
+ } = provideTheme(props);
24688
+ const {
24689
+ borderClasses
24690
+ } = useBorder(props);
24691
+ const {
24692
+ roundedClasses
24693
+ } = useRounded(props);
24694
+ const {
24695
+ backgroundColorClasses,
24696
+ backgroundColorStyles
24697
+ } = useBackgroundColor(() => props.color);
24698
+ const {
24699
+ elevationClasses
24700
+ } = useElevation(props);
24701
+ useRender(() => vue.createVNode(props.tag, {
24702
+ "class": vue.normalizeClass(['v-kbd', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, props.class]),
24703
+ "style": vue.normalizeStyle([backgroundColorStyles.value, props.style])
24704
+ }, slots));
24705
+ return {};
24706
+ }
24707
+ });
24408
24708
 
24409
24709
  const makeVLayoutProps = propsFactory({
24410
24710
  ...makeComponentProps(),
@@ -25242,6 +25542,14 @@
25242
25542
  type: Number,
25243
25543
  default: 0
25244
25544
  },
25545
+ minFractionDigits: {
25546
+ type: Number,
25547
+ default: null
25548
+ },
25549
+ decimalSeparator: {
25550
+ type: String,
25551
+ validator: v => !v || v.length === 1
25552
+ },
25245
25553
  ...omit(makeVTextFieldProps(), ['modelValue', 'validationValue'])
25246
25554
  }, 'VNumberInput');
25247
25555
  const VNumberInput = genericComponent()({
@@ -25267,11 +25575,24 @@
25267
25575
  const form = useForm(props);
25268
25576
  const controlsDisabled = vue.computed(() => form.isDisabled.value || form.isReadonly.value);
25269
25577
  const isFocused = vue.shallowRef(props.focused);
25578
+ const {
25579
+ decimalSeparator: decimalSeparatorFromLocale
25580
+ } = useLocale();
25581
+ const decimalSeparator = vue.computed(() => props.decimalSeparator?.[0] || decimalSeparatorFromLocale.value);
25270
25582
  function correctPrecision(val) {
25271
25583
  let precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.precision;
25584
+ let trim = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
25272
25585
  const fixed = precision == null ? String(val) : val.toFixed(precision);
25273
- return isFocused.value ? Number(fixed).toString() // trim zeros
25274
- : fixed;
25586
+ if (isFocused.value && trim) {
25587
+ return Number(fixed).toString() // trim zeros
25588
+ .replace('.', decimalSeparator.value);
25589
+ }
25590
+ if (props.minFractionDigits === null || precision !== null && precision < props.minFractionDigits) {
25591
+ return fixed.replace('.', decimalSeparator.value);
25592
+ }
25593
+ let [baseDigits, fractionDigits] = fixed.split('.');
25594
+ fractionDigits = (fractionDigits ?? '').padEnd(props.minFractionDigits, '0').replace(new RegExp(`(?<=\\d{${props.minFractionDigits}})0`, 'g'), '');
25595
+ return [baseDigits, fractionDigits].filter(Boolean).join(decimalSeparator.value);
25275
25596
  }
25276
25597
  const model = useProxiedModel(props, 'modelValue', null, val => val ?? null, val => val == null ? val ?? null : clamp(Number(val), props.min, props.max));
25277
25598
  const _inputText = vue.shallowRef(null);
@@ -25288,8 +25609,11 @@
25288
25609
  if (val === null || val === '') {
25289
25610
  model.value = null;
25290
25611
  _inputText.value = null;
25291
- } else if (!isNaN(Number(val)) && Number(val) <= props.max && Number(val) >= props.min) {
25292
- model.value = Number(val);
25612
+ return;
25613
+ }
25614
+ const parsedValue = Number(val.replace(decimalSeparator.value, '.'));
25615
+ if (!isNaN(parsedValue) && parsedValue <= props.max && parsedValue >= props.min) {
25616
+ model.value = parsedValue;
25293
25617
  _inputText.value = val;
25294
25618
  }
25295
25619
  }
@@ -25326,6 +25650,7 @@
25326
25650
  }
25327
25651
  };
25328
25652
  vue.watch(() => props.precision, () => formatInputValue());
25653
+ vue.watch(() => props.minFractionDigits, () => formatInputValue());
25329
25654
  vue.onMounted(() => {
25330
25655
  clampModel();
25331
25656
  });
@@ -25359,24 +25684,24 @@
25359
25684
  selectionEnd
25360
25685
  } = inputElement ?? {};
25361
25686
  const potentialNewInputVal = existingTxt ? existingTxt.slice(0, selectionStart) + e.data + existingTxt.slice(selectionEnd) : e.data;
25362
- const potentialNewNumber = extractNumber(potentialNewInputVal, props.precision);
25687
+ const potentialNewNumber = extractNumber(potentialNewInputVal, props.precision, decimalSeparator.value);
25363
25688
 
25364
- // Only numbers, "-", "." are allowed
25365
- // AND "-", "." are allowed only once
25366
- // AND "-" is only allowed at the start
25367
- if (!/^-?(\d+(\.\d*)?|(\.\d+)|\d*|\.)$/.test(potentialNewInputVal)) {
25689
+ // Allow only numbers, "-" and {decimal separator}
25690
+ // Allow "-" and {decimal separator} only once
25691
+ // Allow "-" only at the start
25692
+ if (!new RegExp(`^-?\\d*${escapeForRegex(decimalSeparator.value)}?\\d*$`).test(potentialNewInputVal)) {
25368
25693
  e.preventDefault();
25369
25694
  inputElement.value = potentialNewNumber;
25370
25695
  }
25371
25696
  if (props.precision == null) return;
25372
25697
 
25373
25698
  // Ignore decimal digits above precision limit
25374
- if (potentialNewInputVal.split('.')[1]?.length > props.precision) {
25699
+ if (potentialNewInputVal.split(decimalSeparator.value)[1]?.length > props.precision) {
25375
25700
  e.preventDefault();
25376
25701
  inputElement.value = potentialNewNumber;
25377
25702
  }
25378
25703
  // Ignore decimal separator when precision = 0
25379
- if (props.precision === 0 && potentialNewInputVal.includes('.')) {
25704
+ if (props.precision === 0 && potentialNewInputVal.includes(decimalSeparator.value)) {
25380
25705
  e.preventDefault();
25381
25706
  inputElement.value = potentialNewNumber;
25382
25707
  }
@@ -25428,19 +25753,16 @@
25428
25753
  if (controlsDisabled.value) return;
25429
25754
  if (!vTextFieldRef.value) return;
25430
25755
  const actualText = vTextFieldRef.value.value;
25431
- if (actualText && !isNaN(Number(actualText))) {
25432
- inputText.value = correctPrecision(clamp(Number(actualText), props.min, props.max));
25756
+ const parsedValue = Number(actualText.replace(decimalSeparator.value, '.'));
25757
+ if (actualText && !isNaN(parsedValue)) {
25758
+ inputText.value = correctPrecision(clamp(parsedValue, props.min, props.max));
25433
25759
  } else {
25434
25760
  inputText.value = null;
25435
25761
  }
25436
25762
  }
25437
25763
  function formatInputValue() {
25438
25764
  if (controlsDisabled.value) return;
25439
- if (model.value === null || isNaN(model.value)) {
25440
- inputText.value = null;
25441
- return;
25442
- }
25443
- inputText.value = props.precision == null ? String(model.value) : model.value.toFixed(props.precision);
25765
+ inputText.value = model.value !== null && !isNaN(model.value) ? correctPrecision(model.value, props.precision, false) : null;
25444
25766
  }
25445
25767
  function trimDecimalZeros() {
25446
25768
  if (controlsDisabled.value) return;
@@ -25448,7 +25770,7 @@
25448
25770
  inputText.value = null;
25449
25771
  return;
25450
25772
  }
25451
- inputText.value = model.value.toString();
25773
+ inputText.value = model.value.toString().replace('.', decimalSeparator.value);
25452
25774
  }
25453
25775
  function onFocus() {
25454
25776
  trimDecimalZeros();
@@ -25650,6 +25972,21 @@
25650
25972
  const contentRef = vue.ref();
25651
25973
  const inputRef = vue.ref([]);
25652
25974
  const current = vue.computed(() => inputRef.value[focusIndex.value]);
25975
+ const intersectScope = vue.effectScope();
25976
+ intersectScope.run(() => {
25977
+ const {
25978
+ intersectionRef,
25979
+ isIntersecting
25980
+ } = useIntersectionObserver();
25981
+ vue.watch(isIntersecting, v => {
25982
+ if (!v) return;
25983
+ intersectionRef.value?.focus();
25984
+ intersectScope.stop();
25985
+ });
25986
+ vue.watchEffect(() => {
25987
+ intersectionRef.value = inputRef.value[0];
25988
+ });
25989
+ });
25653
25990
  function onInput() {
25654
25991
  // The maxlength attribute doesn't work for the number type input, so the text type is used.
25655
25992
  // The following logic simulates the behavior of a number input.
@@ -25700,9 +26037,10 @@
25700
26037
  e.preventDefault();
25701
26038
  e.stopPropagation();
25702
26039
  const clipboardText = e?.clipboardData?.getData('Text').trim().slice(0, length.value) ?? '';
26040
+ const finalIndex = clipboardText.length - 1 === -1 ? index : clipboardText.length - 1;
25703
26041
  if (isValidNumber(clipboardText)) return;
25704
26042
  model.value = clipboardText.split('');
25705
- inputRef.value?.[index].blur();
26043
+ inputRef.value?.[finalIndex].focus();
25706
26044
  }
25707
26045
  function reset() {
25708
26046
  model.value = [];
@@ -28396,6 +28734,9 @@
28396
28734
  focus,
28397
28735
  blur
28398
28736
  } = useFocus(props);
28737
+ const {
28738
+ onIntersect
28739
+ } = useAutofocus(props);
28399
28740
  const counterValue = vue.computed(() => {
28400
28741
  return typeof props.counterValue === 'function' ? props.counterValue(model.value) : (model.value || '').toString().length;
28401
28742
  });
@@ -28404,10 +28745,6 @@
28404
28745
  if (!props.counter || typeof props.counter !== 'number' && typeof props.counter !== 'string') return undefined;
28405
28746
  return props.counter;
28406
28747
  });
28407
- function onIntersect(isIntersecting, entries) {
28408
- if (!props.autofocus || !isIntersecting) return;
28409
- entries[0].target?.focus?.();
28410
- }
28411
28748
  const vInputRef = vue.ref();
28412
28749
  const vFieldRef = vue.ref();
28413
28750
  const controlHeight = vue.shallowRef('');
@@ -29487,7 +29824,7 @@
29487
29824
  };
29488
29825
  });
29489
29826
  }
29490
- const version$1 = "3.8.9-master.2025-06-14";
29827
+ const version$1 = "3.8.10-dev.2025-06-18";
29491
29828
  createVuetify$1.version = version$1;
29492
29829
 
29493
29830
  // Vue's inject() can only be used in setup
@@ -29512,7 +29849,7 @@
29512
29849
  ...options
29513
29850
  });
29514
29851
  };
29515
- const version = "3.8.9-master.2025-06-14";
29852
+ const version = "3.8.10-dev.2025-06-18";
29516
29853
  createVuetify.version = version;
29517
29854
 
29518
29855
  exports.blueprints = index;