@vuetify/nightly 3.8.9-master.2025-06-17 → 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 (218) hide show
  1. package/CHANGELOG.md +46 -17
  2. package/dist/json/attributes.json +3715 -3311
  3. package/dist/json/importMap-labs.json +20 -16
  4. package/dist/json/importMap.json +172 -172
  5. package/dist/json/tags.json +108 -2
  6. package/dist/json/web-types.json +7670 -6023
  7. package/dist/vuetify-labs.cjs +760 -187
  8. package/dist/vuetify-labs.css +5981 -5933
  9. package/dist/vuetify-labs.d.ts +10425 -3094
  10. package/dist/vuetify-labs.esm.js +761 -188
  11. package/dist/vuetify-labs.esm.js.map +1 -1
  12. package/dist/vuetify-labs.js +760 -187
  13. package/dist/vuetify-labs.min.css +2 -2
  14. package/dist/vuetify.cjs +485 -172
  15. package/dist/vuetify.cjs.map +1 -1
  16. package/dist/vuetify.css +4378 -4330
  17. package/dist/vuetify.d.ts +2793 -2086
  18. package/dist/vuetify.esm.js +486 -173
  19. package/dist/vuetify.esm.js.map +1 -1
  20. package/dist/vuetify.js +485 -172
  21. package/dist/vuetify.js.map +1 -1
  22. package/dist/vuetify.min.css +2 -2
  23. package/dist/vuetify.min.js +1255 -1233
  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 +30 -7
  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 +44 -17
  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 +2 -1
  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/VTextarea/VTextarea.d.ts +15 -15
  136. package/lib/components/VToolbar/VToolbar.d.ts +15 -3
  137. package/lib/components/VToolbar/VToolbar.js +6 -3
  138. package/lib/components/VToolbar/VToolbar.js.map +1 -1
  139. package/lib/composables/calendar.d.ts +5 -0
  140. package/lib/composables/calendar.js +2 -1
  141. package/lib/composables/calendar.js.map +1 -1
  142. package/lib/composables/date/DateAdapter.d.ts +3 -3
  143. package/lib/composables/date/DateAdapter.js.map +1 -1
  144. package/lib/composables/date/adapters/string.d.ts +54 -0
  145. package/lib/composables/date/adapters/string.js +153 -0
  146. package/lib/composables/date/adapters/string.js.map +1 -0
  147. package/lib/composables/date/adapters/vuetify.d.ts +1 -1
  148. package/lib/composables/date/adapters/vuetify.js +4 -4
  149. package/lib/composables/date/adapters/vuetify.js.map +1 -1
  150. package/lib/composables/date/date.d.ts +3 -3
  151. package/lib/composables/date/index.d.ts +1 -0
  152. package/lib/composables/date/index.js +1 -0
  153. package/lib/composables/date/index.js.map +1 -1
  154. package/lib/composables/filter.js +3 -0
  155. package/lib/composables/filter.js.map +1 -1
  156. package/lib/composables/iconSizes.d.ts +28 -0
  157. package/lib/composables/iconSizes.js +23 -0
  158. package/lib/composables/iconSizes.js.map +1 -0
  159. package/lib/composables/locale.d.ts +5 -1
  160. package/lib/composables/locale.js.map +1 -1
  161. package/lib/composables/mask.d.ts +38 -0
  162. package/lib/composables/mask.js +183 -0
  163. package/lib/composables/mask.js.map +1 -0
  164. package/lib/composables/theme.d.ts +6 -1
  165. package/lib/composables/theme.js +97 -29
  166. package/lib/composables/theme.js.map +1 -1
  167. package/lib/composables/virtual.js +6 -1
  168. package/lib/composables/virtual.js.map +1 -1
  169. package/lib/directives/ripple/index.d.ts +2 -1
  170. package/lib/directives/ripple/index.js +12 -7
  171. package/lib/directives/ripple/index.js.map +1 -1
  172. package/lib/entry-bundler.d.ts +4 -3
  173. package/lib/entry-bundler.js +1 -1
  174. package/lib/entry-bundler.js.map +1 -1
  175. package/lib/framework.d.ts +87 -68
  176. package/lib/framework.js +1 -1
  177. package/lib/framework.js.map +1 -1
  178. package/lib/labs/VCalendar/VCalendar.d.ts +10 -0
  179. package/lib/labs/VColorInput/VColorInput.d.ts +3 -3
  180. package/lib/labs/VDateInput/VDateInput.d.ts +97 -87
  181. package/lib/labs/VFileUpload/VFileUpload.d.ts +3 -3
  182. package/lib/labs/VFileUpload/VFileUploadItem.d.ts +20 -10
  183. package/lib/labs/VIconBtn/VIconBtn.d.ts +29 -29
  184. package/lib/labs/VIconBtn/VIconBtn.js +7 -11
  185. package/lib/labs/VIconBtn/VIconBtn.js.map +1 -1
  186. package/lib/labs/VMaskInput/VMaskInput.d.ts +6993 -0
  187. package/lib/labs/VMaskInput/VMaskInput.js +67 -0
  188. package/lib/labs/VMaskInput/VMaskInput.js.map +1 -0
  189. package/lib/labs/VMaskInput/index.d.ts +1 -0
  190. package/lib/labs/VMaskInput/index.js +2 -0
  191. package/lib/labs/VMaskInput/index.js.map +1 -0
  192. package/lib/labs/VStepperVertical/VStepperVertical.d.ts +20 -10
  193. package/lib/labs/VStepperVertical/VStepperVerticalItem.d.ts +20 -10
  194. package/lib/labs/VTreeview/VTreeview.d.ts +51 -38
  195. package/lib/labs/VTreeview/VTreeview.js +1 -1
  196. package/lib/labs/VTreeview/VTreeview.js.map +1 -1
  197. package/lib/labs/VTreeview/VTreeviewChildren.d.ts +35 -0
  198. package/lib/labs/VTreeview/VTreeviewChildren.js +21 -3
  199. package/lib/labs/VTreeview/VTreeviewChildren.js.map +1 -1
  200. package/lib/labs/VTreeview/VTreeviewGroup.d.ts +10 -0
  201. package/lib/labs/VTreeview/VTreeviewItem.d.ts +20 -10
  202. package/lib/labs/VTreeview/VTreeviewItem.js +1 -0
  203. package/lib/labs/VTreeview/VTreeviewItem.js.map +1 -1
  204. package/lib/labs/components.d.ts +1 -0
  205. package/lib/labs/components.js +1 -0
  206. package/lib/labs/components.js.map +1 -1
  207. package/lib/labs/entry-bundler.d.ts +4 -3
  208. package/lib/locale/adapters/vue-i18n.js +6 -1
  209. package/lib/locale/adapters/vue-i18n.js.map +1 -1
  210. package/lib/locale/adapters/vuetify.js +7 -1
  211. package/lib/locale/adapters/vuetify.js.map +1 -1
  212. package/lib/util/globals.d.ts +1 -0
  213. package/lib/util/globals.js +1 -0
  214. package/lib/util/globals.js.map +1 -1
  215. package/lib/util/helpers.d.ts +2 -1
  216. package/lib/util/helpers.js +12 -7
  217. package/lib/util/helpers.js.map +1 -1
  218. package/package.json +9 -7
package/dist/vuetify.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.8.9-master.2025-06-17
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)
@@ -5848,8 +5937,8 @@
5848
5937
  window.clearTimeout(element._ripple.showTimer);
5849
5938
  }
5850
5939
  let keyboardRipple = false;
5851
- function keyboardRippleShow(e) {
5852
- if (!keyboardRipple && (e.keyCode === keyCodes.enter || e.keyCode === keyCodes.space)) {
5940
+ function keyboardRippleShow(e, keys) {
5941
+ if (!keyboardRipple && keys.includes(e.keyCode)) {
5853
5942
  keyboardRipple = true;
5854
5943
  rippleShow(e);
5855
5944
  }
@@ -5877,9 +5966,12 @@
5877
5966
  el._ripple.enabled = enabled;
5878
5967
  el._ripple.centered = modifiers.center;
5879
5968
  el._ripple.circle = modifiers.circle;
5880
- if (isObject(value) && value.class) {
5881
- el._ripple.class = value.class;
5969
+ const bindingValue = isObject(value) ? value : {};
5970
+ if (bindingValue.class) {
5971
+ el._ripple.class = bindingValue.class;
5882
5972
  }
5973
+ const allowedKeys = bindingValue.keys ?? [keyCodes.enter, keyCodes.space];
5974
+ el._ripple.keyDownHandler = e => keyboardRippleShow(e, allowedKeys);
5883
5975
  if (enabled && !wasEnabled) {
5884
5976
  if (modifiers.stop) {
5885
5977
  el.addEventListener('touchstart', rippleStop, {
@@ -5901,7 +5993,7 @@
5901
5993
  el.addEventListener('mousedown', rippleShow);
5902
5994
  el.addEventListener('mouseup', rippleHide);
5903
5995
  el.addEventListener('mouseleave', rippleHide);
5904
- el.addEventListener('keydown', keyboardRippleShow);
5996
+ el.addEventListener('keydown', e => keyboardRippleShow(e, allowedKeys));
5905
5997
  el.addEventListener('keyup', keyboardRippleHide);
5906
5998
  el.addEventListener('blur', focusRippleHide);
5907
5999
 
@@ -5921,7 +6013,9 @@
5921
6013
  el.removeEventListener('touchcancel', rippleHide);
5922
6014
  el.removeEventListener('mouseup', rippleHide);
5923
6015
  el.removeEventListener('mouseleave', rippleHide);
5924
- el.removeEventListener('keydown', keyboardRippleShow);
6016
+ if (el._ripple?.keyDownHandler) {
6017
+ el.removeEventListener('keydown', el._ripple.keyDownHandler);
6018
+ }
5925
6019
  el.removeEventListener('keyup', keyboardRippleHide);
5926
6020
  el.removeEventListener('dragstart', rippleHide);
5927
6021
  el.removeEventListener('blur', focusRippleHide);
@@ -5930,8 +6024,8 @@
5930
6024
  updateRipple(el, binding, false);
5931
6025
  }
5932
6026
  function unmounted$4(el) {
5933
- delete el._ripple;
5934
6027
  removeListeners(el);
6028
+ delete el._ripple;
5935
6029
  }
5936
6030
  function updated$1(el, binding) {
5937
6031
  if (binding.value === binding.oldValue) {
@@ -6204,6 +6298,31 @@
6204
6298
  // Utilities
6205
6299
  const VAlertTitle = createSimpleFunctional('v-alert-title');
6206
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
+
6207
6326
  // Types
6208
6327
 
6209
6328
  const allowedTypes = ['success', 'info', 'warning', 'error'];
@@ -6243,6 +6362,7 @@
6243
6362
  ...makeDensityProps(),
6244
6363
  ...makeDimensionProps(),
6245
6364
  ...makeElevationProps(),
6365
+ ...makeIconSizeProps(),
6246
6366
  ...makeLocationProps(),
6247
6367
  ...makePositionProps(),
6248
6368
  ...makeRoundedProps(),
@@ -6270,6 +6390,9 @@
6270
6390
  if (!props.type) return props.icon;
6271
6391
  return props.icon ?? `$${props.type}`;
6272
6392
  });
6393
+ const {
6394
+ iconSize
6395
+ } = useIconSizes(props, () => props.prominent ? 44 : 28);
6273
6396
  const {
6274
6397
  themeClasses
6275
6398
  } = provideTheme(props);
@@ -6317,6 +6440,11 @@
6317
6440
  const hasPrepend = !!(slots.prepend || icon.value);
6318
6441
  const hasTitle = !!(slots.title || props.title);
6319
6442
  const hasClose = !!(slots.close || props.closable);
6443
+ const iconProps = {
6444
+ density: props.density,
6445
+ icon: icon.value,
6446
+ size: iconSize.value
6447
+ };
6320
6448
  return isActive.value && vue.createVNode(props.tag, {
6321
6449
  "class": vue.normalizeClass(['v-alert', props.border && {
6322
6450
  'v-alert--border': !!props.border,
@@ -6334,19 +6462,14 @@
6334
6462
  }, null), hasPrepend && vue.createElementVNode("div", {
6335
6463
  "key": "prepend",
6336
6464
  "class": "v-alert__prepend"
6337
- }, [!slots.prepend ? vue.createVNode(VIcon, {
6338
- "key": "prepend-icon",
6339
- "density": props.density,
6340
- "icon": icon.value,
6341
- "size": props.prominent ? 44 : 28
6342
- }, null) : vue.createVNode(VDefaultsProvider, {
6465
+ }, [!slots.prepend ? vue.createVNode(VIcon, vue.mergeProps({
6466
+ "key": "prepend-icon"
6467
+ }, iconProps), null) : vue.createVNode(VDefaultsProvider, {
6343
6468
  "key": "prepend-defaults",
6344
6469
  "disabled": !icon.value,
6345
6470
  "defaults": {
6346
6471
  VIcon: {
6347
- density: props.density,
6348
- icon: icon.value,
6349
- size: props.prominent ? 44 : 28
6472
+ ...iconProps
6350
6473
  }
6351
6474
  }
6352
6475
  }, slots.prepend)]), vue.createElementVNode("div", {
@@ -7871,6 +7994,7 @@
7871
7994
  const VSlideGroupSymbol = Symbol.for('vuetify:v-slide-group');
7872
7995
  const makeVSlideGroupProps = propsFactory({
7873
7996
  centerActive: Boolean,
7997
+ contentClass: null,
7874
7998
  direction: {
7875
7999
  type: String,
7876
8000
  default: 'horizontal'
@@ -8183,7 +8307,7 @@
8183
8307
  })]), vue.createElementVNode("div", {
8184
8308
  "key": "container",
8185
8309
  "ref": containerRef,
8186
- "class": "v-slide-group__container",
8310
+ "class": vue.normalizeClass(['v-slide-group__container', props.contentClass]),
8187
8311
  "onScroll": onScroll
8188
8312
  }, [vue.createElementVNode("div", {
8189
8313
  "ref": contentRef,
@@ -8546,16 +8670,85 @@
8546
8670
  }
8547
8671
  });
8548
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
+
8549
8735
  // Utilities
8550
8736
 
8551
8737
  // List
8552
8738
  const ListKey = Symbol.for('vuetify:list');
8553
8739
  function createList() {
8740
+ let {
8741
+ filterable
8742
+ } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
8743
+ filterable: false
8744
+ };
8554
8745
  const parent = vue.inject(ListKey, {
8746
+ filterable: false,
8555
8747
  hasPrepend: vue.shallowRef(false),
8556
8748
  updateHasPrepend: () => null
8557
8749
  });
8558
8750
  const data = {
8751
+ filterable: parent.filterable || filterable,
8559
8752
  hasPrepend: vue.shallowRef(false),
8560
8753
  updateHasPrepend: value => {
8561
8754
  if (value) data.hasPrepend.value = value;
@@ -9264,6 +9457,7 @@
9264
9457
  type: IconValue,
9265
9458
  default: '$expand'
9266
9459
  },
9460
+ rawId: [String, Number],
9267
9461
  prependIcon: IconValue,
9268
9462
  appendIcon: IconValue,
9269
9463
  fluid: Boolean,
@@ -9285,13 +9479,12 @@
9285
9479
  open,
9286
9480
  id: _id
9287
9481
  } = useNestedItem(() => props.value, true);
9288
- 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)}`);
9289
9483
  const list = useList();
9290
9484
  const {
9291
9485
  isBooted
9292
9486
  } = useSsrBoot();
9293
9487
  function onClick(e) {
9294
- e.stopPropagation();
9295
9488
  if (['INPUT', 'TEXTAREA'].includes(e.target?.tagName)) return;
9296
9489
  open(!isOpen.value, e);
9297
9490
  }
@@ -9507,6 +9700,9 @@
9507
9700
  roundedClasses
9508
9701
  } = useRounded(roundedProps);
9509
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);
9510
9706
  const slotProps = vue.computed(() => ({
9511
9707
  isActive: isActive.value,
9512
9708
  select,
@@ -9531,8 +9727,9 @@
9531
9727
  function onKeyDown(e) {
9532
9728
  const target = e.target;
9533
9729
  if (['INPUT', 'TEXTAREA'].includes(target.tagName)) return;
9534
- if (e.key === 'Enter' || e.key === ' ') {
9730
+ if (e.key === 'Enter' || e.key === ' ' && !list?.filterable) {
9535
9731
  e.preventDefault();
9732
+ e.stopPropagation();
9536
9733
  e.target.dispatchEvent(new MouseEvent('click', e));
9537
9734
  }
9538
9735
  }
@@ -9642,7 +9839,7 @@
9642
9839
  }), vue.createElementVNode("div", {
9643
9840
  "class": "v-list-item__spacer"
9644
9841
  }, null)])]
9645
- }), [[Ripple, isClickable.value && props.ripple]]);
9842
+ }), [[Ripple, isClickable.value && rippleOptions.value]]);
9646
9843
  });
9647
9844
  return {
9648
9845
  activate,
@@ -9697,68 +9894,6 @@
9697
9894
  }
9698
9895
  });
9699
9896
 
9700
- const makeVDividerProps = propsFactory({
9701
- color: String,
9702
- inset: Boolean,
9703
- length: [Number, String],
9704
- opacity: [Number, String],
9705
- thickness: [Number, String],
9706
- vertical: Boolean,
9707
- ...makeComponentProps(),
9708
- ...makeThemeProps()
9709
- }, 'VDivider');
9710
- const VDivider = genericComponent()({
9711
- name: 'VDivider',
9712
- props: makeVDividerProps(),
9713
- setup(props, _ref) {
9714
- let {
9715
- attrs,
9716
- slots
9717
- } = _ref;
9718
- const {
9719
- themeClasses
9720
- } = provideTheme(props);
9721
- const {
9722
- textColorClasses,
9723
- textColorStyles
9724
- } = useTextColor(() => props.color);
9725
- const dividerStyles = vue.computed(() => {
9726
- const styles = {};
9727
- if (props.length) {
9728
- styles[props.vertical ? 'height' : 'width'] = convertToUnit(props.length);
9729
- }
9730
- if (props.thickness) {
9731
- styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
9732
- }
9733
- return styles;
9734
- });
9735
- useRender(() => {
9736
- const divider = vue.createElementVNode("hr", {
9737
- "class": vue.normalizeClass([{
9738
- 'v-divider': true,
9739
- 'v-divider--inset': props.inset,
9740
- 'v-divider--vertical': props.vertical
9741
- }, themeClasses.value, textColorClasses.value, props.class]),
9742
- "style": vue.normalizeStyle([dividerStyles.value, textColorStyles.value, {
9743
- '--v-border-opacity': props.opacity
9744
- }, props.style]),
9745
- "aria-orientation": !attrs.role || attrs.role === 'separator' ? props.vertical ? 'vertical' : 'horizontal' : undefined,
9746
- "role": `${attrs.role || 'separator'}`
9747
- }, null);
9748
- if (!slots.default) return divider;
9749
- return vue.createElementVNode("div", {
9750
- "class": vue.normalizeClass(['v-divider__wrapper', {
9751
- 'v-divider__wrapper--vertical': props.vertical,
9752
- 'v-divider__wrapper--inset': props.inset
9753
- }])
9754
- }, [divider, vue.createElementVNode("div", {
9755
- "class": "v-divider__content"
9756
- }, [slots.default()]), divider]);
9757
- });
9758
- return {};
9759
- }
9760
- });
9761
-
9762
9897
  // Types
9763
9898
 
9764
9899
  const makeVListChildrenProps = propsFactory({
@@ -9809,9 +9944,10 @@
9809
9944
  }) : undefined
9810
9945
  };
9811
9946
  const listGroupProps = VListGroup.filterProps(itemProps);
9812
- return children ? vue.createVNode(VListGroup, vue.mergeProps({
9813
- "value": itemProps?.value
9814
- }, listGroupProps), {
9947
+ return children ? vue.createVNode(VListGroup, vue.mergeProps(listGroupProps, {
9948
+ "value": props.returnObject ? item : itemProps?.value,
9949
+ "rawId": itemProps?.value
9950
+ }), {
9815
9951
  activator: _ref3 => {
9816
9952
  let {
9817
9953
  props: activatorProps
@@ -10027,6 +10163,7 @@
10027
10163
  activeClass: String,
10028
10164
  bgColor: String,
10029
10165
  disabled: Boolean,
10166
+ filterable: Boolean,
10030
10167
  expandIcon: IconValue,
10031
10168
  collapseIcon: IconValue,
10032
10169
  lines: {
@@ -10110,7 +10247,9 @@
10110
10247
  const activeColor = vue.toRef(() => props.activeColor);
10111
10248
  const baseColor = vue.toRef(() => props.baseColor);
10112
10249
  const color = vue.toRef(() => props.color);
10113
- createList();
10250
+ createList({
10251
+ filterable: props.filterable
10252
+ });
10114
10253
  provideDefaults({
10115
10254
  VListGroup: {
10116
10255
  activeColor,
@@ -11793,6 +11932,7 @@
11793
11932
  // disableKeys: Boolean,
11794
11933
  id: String,
11795
11934
  submenu: Boolean,
11935
+ disableInitialFocus: Boolean,
11796
11936
  ...omit(makeVOverlayProps({
11797
11937
  closeDelay: 250,
11798
11938
  closeOnContentClick: true,
@@ -11867,7 +12007,7 @@
11867
12007
  vue.watch(isActive, val => {
11868
12008
  if (val) {
11869
12009
  parent?.register();
11870
- if (IN_BROWSER) {
12010
+ if (IN_BROWSER && !props.disableInitialFocus) {
11871
12011
  document.addEventListener('focusin', onFocusIn, {
11872
12012
  once: true
11873
12013
  });
@@ -12704,7 +12844,12 @@
12704
12844
  }
12705
12845
  function calculateOffset(index) {
12706
12846
  index = clamp(index, 0, items.value.length - 1);
12707
- 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;
12708
12853
  }
12709
12854
  function calculateIndex(scrollTop) {
12710
12855
  return binaryClosest(offsets, scrollTop);
@@ -13058,6 +13203,7 @@
13058
13203
  },
13059
13204
  openOnClear: Boolean,
13060
13205
  itemColor: String,
13206
+ noAutoScroll: Boolean,
13061
13207
  ...makeItemsProps({
13062
13208
  itemChildren: false
13063
13209
  })
@@ -13272,7 +13418,7 @@
13272
13418
  vue.watch(menu, () => {
13273
13419
  if (!props.hideSelected && menu.value && model.value.length) {
13274
13420
  const index = displayItems.value.findIndex(item => model.value.some(s => (props.valueComparator || deepEqual)(s.value, item.value)));
13275
- IN_BROWSER && window.requestAnimationFrame(() => {
13421
+ IN_BROWSER && !props.noAutoScroll && window.requestAnimationFrame(() => {
13276
13422
  index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
13277
13423
  });
13278
13424
  }
@@ -13365,6 +13511,22 @@
13365
13511
  key: item.value,
13366
13512
  onClick: () => select(item, null)
13367
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
+ }
13368
13530
  return slots.item?.({
13369
13531
  item,
13370
13532
  index,
@@ -13525,6 +13687,9 @@
13525
13687
  let match = -1;
13526
13688
  if ((query || customFiltersLength > 0) && !options?.noFilter) {
13527
13689
  if (typeof item === 'object') {
13690
+ if (['divider', 'subheader'].includes(item.raw?.type)) {
13691
+ continue;
13692
+ }
13528
13693
  const filterKeys = keys || Object.keys(transformed);
13529
13694
  for (const key of filterKeys) {
13530
13695
  const value = getPropertyFromItem(transformed, key);
@@ -13727,7 +13892,7 @@
13727
13892
  menu.value = !menu.value;
13728
13893
  }
13729
13894
  function onListKeydown(e) {
13730
- if (e.key !== ' ' && checkPrintable(e)) {
13895
+ if (checkPrintable(e) || e.key === 'Backspace') {
13731
13896
  vTextFieldRef.value?.focus();
13732
13897
  }
13733
13898
  }
@@ -13932,6 +14097,7 @@
13932
14097
  }, props.menuProps), {
13933
14098
  default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
13934
14099
  "ref": listRef,
14100
+ "filterable": true,
13935
14101
  "selected": selectedValues.value,
13936
14102
  "selectStrategy": props.multiple ? 'independent' : 'single-independent',
13937
14103
  "onMousedown": e => e.preventDefault(),
@@ -13963,6 +14129,22 @@
13963
14129
  active: highlightFirst.value && index === 0 ? true : undefined,
13964
14130
  onClick: () => select(item, null)
13965
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
+ }
13966
14148
  return slots.item?.({
13967
14149
  item,
13968
14150
  index,
@@ -14107,7 +14289,8 @@
14107
14289
  ...makeThemeProps(),
14108
14290
  ...makeTransitionProps({
14109
14291
  transition: 'scale-rotate-transition'
14110
- })
14292
+ }),
14293
+ ...makeDimensionProps()
14111
14294
  }, 'VBadge');
14112
14295
  const VBadge = genericComponent()({
14113
14296
  name: 'VBadge',
@@ -14137,6 +14320,9 @@
14137
14320
  const base = props.floating ? props.dot ? 2 : 4 : props.dot ? 8 : 12;
14138
14321
  return base + (['top', 'bottom'].includes(side) ? Number(props.offsetY ?? 0) : ['left', 'right'].includes(side) ? Number(props.offsetX ?? 0) : 0);
14139
14322
  });
14323
+ const {
14324
+ dimensionStyles
14325
+ } = useDimension(props);
14140
14326
  useRender(() => {
14141
14327
  const value = Number(props.content);
14142
14328
  const content = !props.max || isNaN(value) ? props.content : value <= Number(props.max) ? value : `${props.max}+`;
@@ -14158,7 +14344,7 @@
14158
14344
  }, {
14159
14345
  default: () => [vue.withDirectives(vue.createElementVNode("span", vue.mergeProps({
14160
14346
  "class": ['v-badge__badge', themeClasses.value, backgroundColorClasses.value, roundedClasses.value, textColorClasses.value],
14161
- "style": [backgroundColorStyles.value, textColorStyles.value, props.inline ? {} : locationStyles.value],
14347
+ "style": [backgroundColorStyles.value, textColorStyles.value, dimensionStyles.value, props.inline ? {} : locationStyles.value],
14162
14348
  "aria-atomic": "true",
14163
14349
  "aria-label": t(props.label, value),
14164
14350
  "aria-live": "polite",
@@ -17567,13 +17753,13 @@
17567
17753
  return null;
17568
17754
  }
17569
17755
  const sundayJanuarySecond2000 = new Date(2000, 0, 2);
17570
- function getWeekdays(locale, firstDayOfWeek) {
17756
+ function getWeekdays(locale, firstDayOfWeek, weekdayFormat) {
17571
17757
  const daysFromSunday = firstDayOfWeek ?? weekInfo(locale)?.firstDay ?? 0;
17572
17758
  return createRange(7).map(i => {
17573
17759
  const weekday = new Date(sundayJanuarySecond2000);
17574
17760
  weekday.setDate(sundayJanuarySecond2000.getDate() + daysFromSunday + i);
17575
17761
  return new Intl.DateTimeFormat(locale, {
17576
- weekday: 'narrow'
17762
+ weekday: weekdayFormat ?? 'narrow'
17577
17763
  }).format(weekday);
17578
17764
  });
17579
17765
  }
@@ -18037,9 +18223,9 @@
18037
18223
  getDiff(date, comparing, unit) {
18038
18224
  return getDiff(date, comparing, unit);
18039
18225
  }
18040
- getWeekdays(firstDayOfWeek) {
18226
+ getWeekdays(firstDayOfWeek, weekdayFormat) {
18041
18227
  const firstDay = firstDayOfWeek !== undefined ? Number(firstDayOfWeek) : undefined;
18042
- return getWeekdays(this.locale, firstDay);
18228
+ return getWeekdays(this.locale, firstDay, weekdayFormat);
18043
18229
  }
18044
18230
  getYear(date) {
18045
18231
  return getYear(date);
@@ -18394,6 +18580,7 @@
18394
18580
  _search.value = val ?? '';
18395
18581
  if (!props.multiple && !hasSelectionSlot.value) {
18396
18582
  model.value = [transformItem$3(props, val)];
18583
+ vue.nextTick(() => vVirtualScrollRef.value?.scrollToIndex(0));
18397
18584
  }
18398
18585
  if (val && props.multiple && props.delimiters?.length) {
18399
18586
  const values = val.split(new RegExp(`(?:${props.delimiters.join('|')})+`));
@@ -18474,7 +18661,7 @@
18474
18661
  menu.value = !menu.value;
18475
18662
  }
18476
18663
  function onListKeydown(e) {
18477
- if (e.key !== ' ' && checkPrintable(e)) {
18664
+ if (checkPrintable(e) || e.key === 'Backspace') {
18478
18665
  vTextFieldRef.value?.focus();
18479
18666
  }
18480
18667
  }
@@ -18679,6 +18866,7 @@
18679
18866
  }, props.menuProps), {
18680
18867
  default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
18681
18868
  "ref": listRef,
18869
+ "filterable": true,
18682
18870
  "selected": selectedValues.value,
18683
18871
  "selectStrategy": props.multiple ? 'independent' : 'single-independent',
18684
18872
  "onMousedown": e => e.preventDefault(),
@@ -18710,6 +18898,22 @@
18710
18898
  active: highlightFirst.value && index === 0 ? true : undefined,
18711
18899
  onClick: () => select(item, null)
18712
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
+ }
18713
18917
  return slots.item?.({
18714
18918
  item,
18715
18919
  index,
@@ -20592,6 +20796,7 @@
20592
20796
  color: String,
20593
20797
  disableSort: Boolean,
20594
20798
  fixedHeader: Boolean,
20799
+ lastFixed: Boolean,
20595
20800
  multiSort: Boolean,
20596
20801
  sortAscIcon: {
20597
20802
  type: IconValue,
@@ -20638,10 +20843,11 @@
20638
20843
  loaderClasses
20639
20844
  } = useLoader(props);
20640
20845
  function getFixedStyles(column, y) {
20641
- if (!(props.sticky || props.fixedHeader) && !column.fixed) return undefined;
20846
+ if (!(props.sticky || props.fixedHeader) && !(column.fixed || column.lastFixed)) return undefined;
20642
20847
  return {
20643
20848
  position: 'sticky',
20644
- 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,
20645
20851
  top: props.sticky || props.fixedHeader ? `calc(var(--v-table-header-height) * ${y})` : undefined
20646
20852
  };
20647
20853
  }
@@ -21157,11 +21363,18 @@
21157
21363
  }
21158
21364
  });
21159
21365
 
21366
+ // Types
21367
+
21160
21368
  const makeVTableProps = propsFactory({
21161
21369
  fixedHeader: Boolean,
21162
21370
  fixedFooter: Boolean,
21163
21371
  height: [Number, String],
21164
21372
  hover: Boolean,
21373
+ striped: {
21374
+ type: String,
21375
+ default: null,
21376
+ validator: v => ['even', 'odd'].includes(v)
21377
+ },
21165
21378
  ...makeComponentProps(),
21166
21379
  ...makeDensityProps(),
21167
21380
  ...makeTagProps(),
@@ -21188,7 +21401,9 @@
21188
21401
  'v-table--fixed-footer': props.fixedFooter,
21189
21402
  'v-table--has-top': !!slots.top,
21190
21403
  'v-table--has-bottom': !!slots.bottom,
21191
- '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'
21192
21407
  }, themeClasses.value, densityClasses.value, props.class]),
21193
21408
  "style": vue.normalizeStyle(props.style)
21194
21409
  }, {
@@ -22363,7 +22578,8 @@
22363
22578
  firstDayOfWeek: {
22364
22579
  type: [Number, String],
22365
22580
  default: undefined
22366
- }
22581
+ },
22582
+ weekdayFormat: String
22367
22583
  }, 'calendar');
22368
22584
  function useCalendar(props) {
22369
22585
  const adapter = useDate();
@@ -22604,7 +22820,7 @@
22604
22820
  "ref": daysRef,
22605
22821
  "key": daysInMonth.value[0].date?.toString(),
22606
22822
  "class": "v-date-picker-month__days"
22607
- }, [!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", {
22608
22824
  "class": vue.normalizeClass(['v-date-picker-month__day', 'v-date-picker-month__weekday'])
22609
22825
  }, [weekDay])), daysInMonth.value.map((item, i) => {
22610
22826
  const slotProps = {
@@ -23113,7 +23329,9 @@
23113
23329
  "max": maxDate.value,
23114
23330
  "year": year.value,
23115
23331
  "allowedMonths": allowedMonths
23116
- }), null) : viewMode.value === 'year' ? vue.createVNode(VDatePickerYears, vue.mergeProps({
23332
+ }), {
23333
+ ...pick(slots, ['month'])
23334
+ }) : viewMode.value === 'year' ? vue.createVNode(VDatePickerYears, vue.mergeProps({
23117
23335
  "key": "date-picker-years"
23118
23336
  }, datePickerYearsProps, {
23119
23337
  "modelValue": year.value,
@@ -23121,7 +23339,9 @@
23121
23339
  "min": minDate.value,
23122
23340
  "max": maxDate.value,
23123
23341
  "allowedYears": allowedYears
23124
- }), null) : vue.createVNode(VDatePickerMonth, vue.mergeProps({
23342
+ }), {
23343
+ ...pick(slots, ['year'])
23344
+ }) : vue.createVNode(VDatePickerMonth, vue.mergeProps({
23125
23345
  "key": "date-picker-month"
23126
23346
  }, datePickerMonthProps, {
23127
23347
  "modelValue": model.value,
@@ -23132,7 +23352,9 @@
23132
23352
  "onUpdate:year": [$event => year.value = $event, onUpdateYear],
23133
23353
  "min": minDate.value,
23134
23354
  "max": maxDate.value
23135
- }), null)]
23355
+ }), {
23356
+ ...pick(slots, ['day'])
23357
+ })]
23136
23358
  })]),
23137
23359
  actions: slots.actions
23138
23360
  });
@@ -24223,6 +24445,9 @@
24223
24445
  startStatus.value = status;
24224
24446
  } else if (side === 'end') {
24225
24447
  endStatus.value = status;
24448
+ } else if (side === 'both') {
24449
+ startStatus.value = status;
24450
+ endStatus.value = status;
24226
24451
  }
24227
24452
  }
24228
24453
  function getStatus(side) {
@@ -24334,6 +24559,32 @@
24334
24559
  }, [renderSide('end', endStatus.value)])]
24335
24560
  });
24336
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
+ };
24337
24588
  }
24338
24589
  });
24339
24590
 
@@ -24413,8 +24664,47 @@
24413
24664
  }
24414
24665
  });
24415
24666
 
24416
- // Styles
24417
- 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
+ });
24418
24708
 
24419
24709
  const makeVLayoutProps = propsFactory({
24420
24710
  ...makeComponentProps(),
@@ -25252,6 +25542,14 @@
25252
25542
  type: Number,
25253
25543
  default: 0
25254
25544
  },
25545
+ minFractionDigits: {
25546
+ type: Number,
25547
+ default: null
25548
+ },
25549
+ decimalSeparator: {
25550
+ type: String,
25551
+ validator: v => !v || v.length === 1
25552
+ },
25255
25553
  ...omit(makeVTextFieldProps(), ['modelValue', 'validationValue'])
25256
25554
  }, 'VNumberInput');
25257
25555
  const VNumberInput = genericComponent()({
@@ -25277,11 +25575,24 @@
25277
25575
  const form = useForm(props);
25278
25576
  const controlsDisabled = vue.computed(() => form.isDisabled.value || form.isReadonly.value);
25279
25577
  const isFocused = vue.shallowRef(props.focused);
25578
+ const {
25579
+ decimalSeparator: decimalSeparatorFromLocale
25580
+ } = useLocale();
25581
+ const decimalSeparator = vue.computed(() => props.decimalSeparator?.[0] || decimalSeparatorFromLocale.value);
25280
25582
  function correctPrecision(val) {
25281
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;
25282
25585
  const fixed = precision == null ? String(val) : val.toFixed(precision);
25283
- return isFocused.value ? Number(fixed).toString() // trim zeros
25284
- : 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);
25285
25596
  }
25286
25597
  const model = useProxiedModel(props, 'modelValue', null, val => val ?? null, val => val == null ? val ?? null : clamp(Number(val), props.min, props.max));
25287
25598
  const _inputText = vue.shallowRef(null);
@@ -25298,8 +25609,11 @@
25298
25609
  if (val === null || val === '') {
25299
25610
  model.value = null;
25300
25611
  _inputText.value = null;
25301
- } else if (!isNaN(Number(val)) && Number(val) <= props.max && Number(val) >= props.min) {
25302
- 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;
25303
25617
  _inputText.value = val;
25304
25618
  }
25305
25619
  }
@@ -25336,6 +25650,7 @@
25336
25650
  }
25337
25651
  };
25338
25652
  vue.watch(() => props.precision, () => formatInputValue());
25653
+ vue.watch(() => props.minFractionDigits, () => formatInputValue());
25339
25654
  vue.onMounted(() => {
25340
25655
  clampModel();
25341
25656
  });
@@ -25369,24 +25684,24 @@
25369
25684
  selectionEnd
25370
25685
  } = inputElement ?? {};
25371
25686
  const potentialNewInputVal = existingTxt ? existingTxt.slice(0, selectionStart) + e.data + existingTxt.slice(selectionEnd) : e.data;
25372
- const potentialNewNumber = extractNumber(potentialNewInputVal, props.precision);
25687
+ const potentialNewNumber = extractNumber(potentialNewInputVal, props.precision, decimalSeparator.value);
25373
25688
 
25374
- // Only numbers, "-", "." are allowed
25375
- // AND "-", "." are allowed only once
25376
- // AND "-" is only allowed at the start
25377
- 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)) {
25378
25693
  e.preventDefault();
25379
25694
  inputElement.value = potentialNewNumber;
25380
25695
  }
25381
25696
  if (props.precision == null) return;
25382
25697
 
25383
25698
  // Ignore decimal digits above precision limit
25384
- if (potentialNewInputVal.split('.')[1]?.length > props.precision) {
25699
+ if (potentialNewInputVal.split(decimalSeparator.value)[1]?.length > props.precision) {
25385
25700
  e.preventDefault();
25386
25701
  inputElement.value = potentialNewNumber;
25387
25702
  }
25388
25703
  // Ignore decimal separator when precision = 0
25389
- if (props.precision === 0 && potentialNewInputVal.includes('.')) {
25704
+ if (props.precision === 0 && potentialNewInputVal.includes(decimalSeparator.value)) {
25390
25705
  e.preventDefault();
25391
25706
  inputElement.value = potentialNewNumber;
25392
25707
  }
@@ -25438,19 +25753,16 @@
25438
25753
  if (controlsDisabled.value) return;
25439
25754
  if (!vTextFieldRef.value) return;
25440
25755
  const actualText = vTextFieldRef.value.value;
25441
- if (actualText && !isNaN(Number(actualText))) {
25442
- 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));
25443
25759
  } else {
25444
25760
  inputText.value = null;
25445
25761
  }
25446
25762
  }
25447
25763
  function formatInputValue() {
25448
25764
  if (controlsDisabled.value) return;
25449
- if (model.value === null || isNaN(model.value)) {
25450
- inputText.value = null;
25451
- return;
25452
- }
25453
- 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;
25454
25766
  }
25455
25767
  function trimDecimalZeros() {
25456
25768
  if (controlsDisabled.value) return;
@@ -25458,7 +25770,7 @@
25458
25770
  inputText.value = null;
25459
25771
  return;
25460
25772
  }
25461
- inputText.value = model.value.toString();
25773
+ inputText.value = model.value.toString().replace('.', decimalSeparator.value);
25462
25774
  }
25463
25775
  function onFocus() {
25464
25776
  trimDecimalZeros();
@@ -25725,9 +26037,10 @@
25725
26037
  e.preventDefault();
25726
26038
  e.stopPropagation();
25727
26039
  const clipboardText = e?.clipboardData?.getData('Text').trim().slice(0, length.value) ?? '';
26040
+ const finalIndex = clipboardText.length - 1 === -1 ? index : clipboardText.length - 1;
25728
26041
  if (isValidNumber(clipboardText)) return;
25729
26042
  model.value = clipboardText.split('');
25730
- inputRef.value?.[index].blur();
26043
+ inputRef.value?.[finalIndex].focus();
25731
26044
  }
25732
26045
  function reset() {
25733
26046
  model.value = [];
@@ -29511,7 +29824,7 @@
29511
29824
  };
29512
29825
  });
29513
29826
  }
29514
- const version$1 = "3.8.9-master.2025-06-17";
29827
+ const version$1 = "3.8.10-dev.2025-06-18";
29515
29828
  createVuetify$1.version = version$1;
29516
29829
 
29517
29830
  // Vue's inject() can only be used in setup
@@ -29536,7 +29849,7 @@
29536
29849
  ...options
29537
29850
  });
29538
29851
  };
29539
- const version = "3.8.9-master.2025-06-17";
29852
+ const version = "3.8.10-dev.2025-06-18";
29540
29853
  createVuetify.version = version;
29541
29854
 
29542
29855
  exports.blueprints = index;