@vuetify/nightly 3.8.7-master.2025-06-02 → 3.8.8-dev.2025-06-04

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 (180) hide show
  1. package/CHANGELOG.md +33 -11
  2. package/dist/json/attributes.json +2042 -1942
  3. package/dist/json/importMap-labs.json +24 -24
  4. package/dist/json/importMap.json +146 -146
  5. package/dist/json/tags.json +25 -0
  6. package/dist/json/web-types.json +3842 -3510
  7. package/dist/vuetify-labs.cjs +380 -152
  8. package/dist/vuetify-labs.css +5726 -5686
  9. package/dist/vuetify-labs.d.ts +2393 -1889
  10. package/dist/vuetify-labs.esm.js +381 -153
  11. package/dist/vuetify-labs.esm.js.map +1 -1
  12. package/dist/vuetify-labs.js +380 -152
  13. package/dist/vuetify-labs.min.css +2 -2
  14. package/dist/vuetify.cjs +374 -141
  15. package/dist/vuetify.cjs.map +1 -1
  16. package/dist/vuetify.css +2674 -2634
  17. package/dist/vuetify.d.ts +1548 -1084
  18. package/dist/vuetify.esm.js +375 -142
  19. package/dist/vuetify.esm.js.map +1 -1
  20. package/dist/vuetify.js +374 -141
  21. package/dist/vuetify.js.map +1 -1
  22. package/dist/vuetify.min.css +2 -2
  23. package/dist/vuetify.min.js +1226 -1208
  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.css +6 -6
  33. package/lib/components/VAutocomplete/VAutocomplete.d.ts +154 -103
  34. package/lib/components/VAutocomplete/VAutocomplete.js +21 -3
  35. package/lib/components/VAutocomplete/VAutocomplete.js.map +1 -1
  36. package/lib/components/VAutocomplete/VAutocomplete.sass +3 -9
  37. package/lib/components/VBtn/VBtn.d.ts +20 -10
  38. package/lib/components/VBtnGroup/VBtnGroup.css +30 -7
  39. package/lib/components/VBtnGroup/VBtnGroup.d.ts +58 -32
  40. package/lib/components/VBtnGroup/VBtnGroup.js +7 -3
  41. package/lib/components/VBtnGroup/VBtnGroup.js.map +1 -1
  42. package/lib/components/VBtnGroup/VBtnGroup.sass +44 -17
  43. package/lib/components/VBtnToggle/VBtnToggle.d.ts +25 -0
  44. package/lib/components/VCard/VCard.d.ts +20 -10
  45. package/lib/components/VCheckbox/VCheckbox.d.ts +23 -13
  46. package/lib/components/VCheckbox/VCheckboxBtn.d.ts +20 -10
  47. package/lib/components/VChip/VChip.d.ts +20 -10
  48. package/lib/components/VChip/VChip.js +1 -0
  49. package/lib/components/VChip/VChip.js.map +1 -1
  50. package/lib/components/VChipGroup/VChipGroup.d.ts +10 -0
  51. package/lib/components/VCombobox/VCombobox.css +6 -6
  52. package/lib/components/VCombobox/VCombobox.d.ts +154 -103
  53. package/lib/components/VCombobox/VCombobox.js +22 -3
  54. package/lib/components/VCombobox/VCombobox.js.map +1 -1
  55. package/lib/components/VCombobox/VCombobox.sass +3 -9
  56. package/lib/components/VDataTable/VDataTable.d.ts +60 -0
  57. package/lib/components/VDataTable/VDataTableHeaders.d.ts +13 -0
  58. package/lib/components/VDataTable/VDataTableHeaders.js +4 -2
  59. package/lib/components/VDataTable/VDataTableHeaders.js.map +1 -1
  60. package/lib/components/VDataTable/VDataTableServer.d.ts +42 -0
  61. package/lib/components/VDataTable/VDataTableVirtual.d.ts +42 -0
  62. package/lib/components/VDatePicker/VDatePicker.d.ts +10 -0
  63. package/lib/components/VDatePicker/VDatePickerMonth.d.ts +10 -0
  64. package/lib/components/VDatePicker/VDatePickerMonth.js +1 -1
  65. package/lib/components/VDatePicker/VDatePickerMonth.js.map +1 -1
  66. package/lib/components/VExpansionPanel/VExpansionPanel.d.ts +20 -10
  67. package/lib/components/VExpansionPanel/VExpansionPanelTitle.d.ts +20 -10
  68. package/lib/components/VExpansionPanel/VExpansionPanels.d.ts +20 -10
  69. package/lib/components/VFab/VFab.d.ts +20 -10
  70. package/lib/components/VField/VField.d.ts +3 -3
  71. package/lib/components/VFileInput/VFileInput.d.ts +15 -15
  72. package/lib/components/VInput/VInput.d.ts +4 -4
  73. package/lib/components/VList/VList.d.ts +13 -0
  74. package/lib/components/VList/VList.js +4 -1
  75. package/lib/components/VList/VList.js.map +1 -1
  76. package/lib/components/VList/VListChildren.js.map +1 -1
  77. package/lib/components/VList/VListItem.d.ts +23 -10
  78. package/lib/components/VList/VListItem.js +7 -3
  79. package/lib/components/VList/VListItem.js.map +1 -1
  80. package/lib/components/VList/list.d.ts +9 -2
  81. package/lib/components/VList/list.js +7 -0
  82. package/lib/components/VList/list.js.map +1 -1
  83. package/lib/components/VNumberInput/VNumberInput.d.ts +103 -89
  84. package/lib/components/VNumberInput/VNumberInput.js +19 -4
  85. package/lib/components/VNumberInput/VNumberInput.js.map +1 -1
  86. package/lib/components/VOtpInput/VOtpInput.js +2 -1
  87. package/lib/components/VOtpInput/VOtpInput.js.map +1 -1
  88. package/lib/components/VOverlay/VOverlay.css +1 -1
  89. package/lib/components/VOverlay/_variables.scss +1 -1
  90. package/lib/components/VRadio/VRadio.d.ts +20 -10
  91. package/lib/components/VRadioGroup/VRadioGroup.d.ts +23 -13
  92. package/lib/components/VRangeSlider/VRangeSlider.d.ts +3 -3
  93. package/lib/components/VSelect/VSelect.css +6 -0
  94. package/lib/components/VSelect/VSelect.d.ts +171 -107
  95. package/lib/components/VSelect/VSelect.js +21 -3
  96. package/lib/components/VSelect/VSelect.js.map +1 -1
  97. package/lib/components/VSelect/VSelect.sass +3 -0
  98. package/lib/components/VSelect/_mixins.scss +14 -0
  99. package/lib/components/VSelectionControl/VSelectionControl.d.ts +20 -10
  100. package/lib/components/VSelectionControlGroup/VSelectionControlGroup.d.ts +28 -14
  101. package/lib/components/VSlideGroup/VSlideGroup.d.ts +10 -0
  102. package/lib/components/VSlideGroup/VSlideGroup.js +2 -1
  103. package/lib/components/VSlideGroup/VSlideGroup.js.map +1 -1
  104. package/lib/components/VSlider/VSlider.d.ts +3 -3
  105. package/lib/components/VSlider/VSliderThumb.d.ts +20 -10
  106. package/lib/components/VSlider/VSliderThumb.js +12 -6
  107. package/lib/components/VSlider/VSliderThumb.js.map +1 -1
  108. package/lib/components/VSlider/slider.js +4 -1
  109. package/lib/components/VSlider/slider.js.map +1 -1
  110. package/lib/components/VStepper/VStepperItem.d.ts +28 -14
  111. package/lib/components/VSwitch/VSwitch.d.ts +23 -13
  112. package/lib/components/VTable/VTable.css +6 -0
  113. package/lib/components/VTable/VTable.d.ts +55 -24
  114. package/lib/components/VTable/VTable.js +9 -2
  115. package/lib/components/VTable/VTable.js.map +1 -1
  116. package/lib/components/VTable/VTable.sass +14 -0
  117. package/lib/components/VTable/_variables.scss +1 -0
  118. package/lib/components/VTabs/VTab.d.ts +56 -28
  119. package/lib/components/VTabs/VTabs.d.ts +10 -0
  120. package/lib/components/VTextField/VTextField.d.ts +27 -27
  121. package/lib/components/VTextarea/VTextarea.d.ts +15 -15
  122. package/lib/components/VToolbar/VToolbar.d.ts +15 -3
  123. package/lib/components/VToolbar/VToolbar.js +6 -3
  124. package/lib/components/VToolbar/VToolbar.js.map +1 -1
  125. package/lib/composables/calendar.d.ts +6 -0
  126. package/lib/composables/calendar.js +2 -1
  127. package/lib/composables/calendar.js.map +1 -1
  128. package/lib/composables/date/DateAdapter.d.ts +3 -3
  129. package/lib/composables/date/DateAdapter.js.map +1 -1
  130. package/lib/composables/date/adapters/string.d.ts +54 -0
  131. package/lib/composables/date/adapters/string.js +153 -0
  132. package/lib/composables/date/adapters/string.js.map +1 -0
  133. package/lib/composables/date/adapters/vuetify.d.ts +1 -1
  134. package/lib/composables/date/adapters/vuetify.js +4 -4
  135. package/lib/composables/date/adapters/vuetify.js.map +1 -1
  136. package/lib/composables/date/date.d.ts +3 -3
  137. package/lib/composables/date/index.d.ts +1 -0
  138. package/lib/composables/date/index.js +1 -0
  139. package/lib/composables/date/index.js.map +1 -1
  140. package/lib/composables/filter.js +3 -0
  141. package/lib/composables/filter.js.map +1 -1
  142. package/lib/composables/iconSizes.d.ts +28 -0
  143. package/lib/composables/iconSizes.js +23 -0
  144. package/lib/composables/iconSizes.js.map +1 -0
  145. package/lib/composables/list-items.js +2 -2
  146. package/lib/composables/list-items.js.map +1 -1
  147. package/lib/composables/theme.d.ts +6 -1
  148. package/lib/composables/theme.js +94 -26
  149. package/lib/composables/theme.js.map +1 -1
  150. package/lib/composables/virtual.js +6 -1
  151. package/lib/composables/virtual.js.map +1 -1
  152. package/lib/directives/ripple/index.d.ts +2 -1
  153. package/lib/directives/ripple/index.js +12 -7
  154. package/lib/directives/ripple/index.js.map +1 -1
  155. package/lib/entry-bundler.d.ts +3 -3
  156. package/lib/entry-bundler.js +1 -1
  157. package/lib/entry-bundler.js.map +1 -1
  158. package/lib/framework.d.ts +73 -58
  159. package/lib/framework.js +1 -1
  160. package/lib/framework.js.map +1 -1
  161. package/lib/labs/VCalendar/VCalendar.d.ts +10 -0
  162. package/lib/labs/VColorInput/VColorInput.d.ts +3 -3
  163. package/lib/labs/VDateInput/VDateInput.d.ts +97 -87
  164. package/lib/labs/VFileUpload/VFileUpload.d.ts +3 -3
  165. package/lib/labs/VFileUpload/VFileUploadItem.d.ts +20 -10
  166. package/lib/labs/VIconBtn/VIconBtn.d.ts +29 -29
  167. package/lib/labs/VIconBtn/VIconBtn.js +7 -11
  168. package/lib/labs/VIconBtn/VIconBtn.js.map +1 -1
  169. package/lib/labs/VStepperVertical/VStepperVertical.d.ts +20 -10
  170. package/lib/labs/VStepperVertical/VStepperVerticalItem.d.ts +20 -10
  171. package/lib/labs/VTreeview/VTreeview.d.ts +13 -0
  172. package/lib/labs/VTreeview/VTreeviewItem.d.ts +20 -10
  173. package/lib/labs/entry-bundler.d.ts +3 -3
  174. package/lib/util/globals.d.ts +1 -0
  175. package/lib/util/globals.js +1 -0
  176. package/lib/util/globals.js.map +1 -1
  177. package/lib/util/helpers.d.ts +1 -0
  178. package/lib/util/helpers.js +9 -1
  179. package/lib/util/helpers.js.map +1 -1
  180. package/package.json +3 -1
package/dist/vuetify.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.8.7-master.2025-06-02
2
+ * Vuetify v3.8.8-dev.2025-06-04
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"); }
@@ -529,6 +530,14 @@
529
530
  }
530
531
  return cleanText;
531
532
  }
533
+ function camelizeProps(props) {
534
+ if (!props) return;
535
+ const out = {};
536
+ for (const prop in props) {
537
+ out[vue.camelize(prop)] = props[prop];
538
+ }
539
+ return out;
540
+ }
532
541
 
533
542
  // Utilities
534
543
  const block = ['top', 'bottom'];
@@ -2828,6 +2837,7 @@
2828
2837
  function genDefaults$1() {
2829
2838
  return {
2830
2839
  defaultTheme: 'light',
2840
+ prefix: 'v-',
2831
2841
  variations: {
2832
2842
  colors: [],
2833
2843
  lighten: 0,
@@ -2909,7 +2919,10 @@
2909
2919
  }
2910
2920
  }
2911
2921
  },
2912
- stylesheetId: 'vuetify-theme-stylesheet'
2922
+ stylesheetId: 'vuetify-theme-stylesheet',
2923
+ scoped: false,
2924
+ unimportant: false,
2925
+ utilities: true
2913
2926
  };
2914
2927
  }
2915
2928
  function parseThemeOptions() {
@@ -2932,21 +2945,21 @@
2932
2945
  function createCssClass(lines, selector, content, scope) {
2933
2946
  lines.push(`${getScopedSelector(selector, scope)} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
2934
2947
  }
2935
- function genCssVariables(theme) {
2948
+ function genCssVariables(theme, prefix) {
2936
2949
  const lightOverlay = theme.dark ? 2 : 1;
2937
2950
  const darkOverlay = theme.dark ? 1 : 2;
2938
2951
  const variables = [];
2939
2952
  for (const [key, value] of Object.entries(theme.colors)) {
2940
2953
  const rgb = parseColor(value);
2941
- variables.push(`--v-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2954
+ variables.push(`--${prefix}theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2942
2955
  if (!key.startsWith('on-')) {
2943
- variables.push(`--v-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2956
+ variables.push(`--${prefix}theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2944
2957
  }
2945
2958
  }
2946
2959
  for (const [key, value] of Object.entries(theme.variables)) {
2947
2960
  const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
2948
2961
  const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
2949
- variables.push(`--v-${key}: ${rgb ?? value}`);
2962
+ variables.push(`--${prefix}${key}: ${rgb ?? value}`);
2950
2963
  }
2951
2964
  return variables;
2952
2965
  }
@@ -2990,7 +3003,8 @@
2990
3003
  const scopeSelector = `:where(${scope})`;
2991
3004
  return selector === ':root' ? scopeSelector : `${scopeSelector} ${selector}`;
2992
3005
  }
2993
- function upsertStyles(styleEl, styles) {
3006
+ function upsertStyles(id, cspNonce, styles) {
3007
+ const styleEl = getOrCreateStyleElement(id, cspNonce);
2994
3008
  if (!styleEl) return;
2995
3009
  styleEl.innerHTML = styles;
2996
3010
  }
@@ -3010,8 +3024,17 @@
3010
3024
  // Composables
3011
3025
  function createTheme(options) {
3012
3026
  const parsedOptions = parseThemeOptions(options);
3013
- const name = vue.shallowRef(parsedOptions.defaultTheme);
3027
+ const _name = vue.shallowRef(parsedOptions.defaultTheme);
3014
3028
  const themes = vue.ref(parsedOptions.themes);
3029
+ const systemName = vue.shallowRef('light');
3030
+ const name = vue.computed({
3031
+ get() {
3032
+ return _name.value === 'system' ? systemName.value : _name.value;
3033
+ },
3034
+ set(val) {
3035
+ _name.value = val;
3036
+ }
3037
+ });
3015
3038
  const computedThemes = vue.computed(() => {
3016
3039
  const acc = {};
3017
3040
  for (const [name, original] of Object.entries(themes.value)) {
@@ -3032,28 +3055,49 @@
3032
3055
  const current = vue.toRef(() => computedThemes.value[name.value]);
3033
3056
  const styles = vue.computed(() => {
3034
3057
  const lines = [];
3058
+ const important = parsedOptions.unimportant ? '' : ' !important';
3059
+ const scoped = parsedOptions.scoped ? parsedOptions.prefix : '';
3035
3060
  if (current.value?.dark) {
3036
3061
  createCssClass(lines, ':root', ['color-scheme: dark'], parsedOptions.scope);
3037
3062
  }
3038
- createCssClass(lines, ':root', genCssVariables(current.value), parsedOptions.scope);
3063
+ createCssClass(lines, ':root', genCssVariables(current.value, parsedOptions.prefix), parsedOptions.scope);
3039
3064
  for (const [themeName, theme] of Object.entries(computedThemes.value)) {
3040
- createCssClass(lines, `.v-theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme)], parsedOptions.scope);
3041
- }
3042
- const bgLines = [];
3043
- const fgLines = [];
3044
- const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
3045
- for (const key of colors) {
3046
- if (key.startsWith('on-')) {
3047
- createCssClass(fgLines, `.${key}`, [`color: rgb(var(--v-theme-${key})) !important`], parsedOptions.scope);
3048
- } else {
3049
- 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);
3050
- createCssClass(fgLines, `.text-${key}`, [`color: rgb(var(--v-theme-${key})) !important`], parsedOptions.scope);
3051
- createCssClass(fgLines, `.border-${key}`, [`--v-border-color: var(--v-theme-${key})`], parsedOptions.scope);
3065
+ createCssClass(lines, `.${parsedOptions.prefix}theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme, parsedOptions.prefix)], parsedOptions.scope);
3066
+ }
3067
+ if (parsedOptions.utilities) {
3068
+ const bgLines = [];
3069
+ const fgLines = [];
3070
+ const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
3071
+ for (const key of colors) {
3072
+ if (key.startsWith('on-')) {
3073
+ createCssClass(fgLines, `.${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
3074
+ } else {
3075
+ 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);
3076
+ createCssClass(fgLines, `.${scoped}text-${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
3077
+ createCssClass(fgLines, `.${scoped}border-${key}`, [`--${parsedOptions.prefix}border-color: var(--${parsedOptions.prefix}theme-${key})`], parsedOptions.scope);
3078
+ }
3052
3079
  }
3080
+ lines.push(...bgLines, ...fgLines);
3053
3081
  }
3054
- lines.push(...bgLines, ...fgLines);
3055
3082
  return lines.map((str, i) => i === 0 ? str : ` ${str}`).join('');
3056
3083
  });
3084
+ const themeClasses = vue.toRef(() => parsedOptions.isDisabled ? undefined : `${parsedOptions.prefix}theme--${name.value}`);
3085
+ const themeNames = vue.toRef(() => Object.keys(computedThemes.value));
3086
+ if (SUPPORTS_MATCH_MEDIA) {
3087
+ const media = window.matchMedia('(prefers-color-scheme: dark)');
3088
+ function updateSystemName() {
3089
+ systemName.value = media.matches ? 'dark' : 'light';
3090
+ }
3091
+ updateSystemName();
3092
+ media.addEventListener('change', updateSystemName, {
3093
+ passive: true
3094
+ });
3095
+ if (vue.getCurrentScope()) {
3096
+ vue.onScopeDispose(() => {
3097
+ media.removeEventListener('change', updateSystemName);
3098
+ });
3099
+ }
3100
+ }
3057
3101
  function install(app) {
3058
3102
  if (parsedOptions.isDisabled) return;
3059
3103
  const head = app._context.provides.usehead;
@@ -3091,22 +3135,55 @@
3091
3135
  updateStyles();
3092
3136
  }
3093
3137
  function updateStyles() {
3094
- upsertStyles(getOrCreateStyleElement(parsedOptions.stylesheetId, parsedOptions.cspNonce), styles.value);
3138
+ upsertStyles(parsedOptions.stylesheetId, parsedOptions.cspNonce, styles.value);
3095
3139
  }
3096
3140
  }
3097
3141
  }
3098
- const themeClasses = vue.toRef(() => parsedOptions.isDisabled ? undefined : `v-theme--${name.value}`);
3142
+ function change(themeName) {
3143
+ if (!themeNames.value.includes(themeName)) {
3144
+ consoleWarn(`Theme "${themeName}" not found on the Vuetify theme instance`);
3145
+ return;
3146
+ }
3147
+ name.value = themeName;
3148
+ }
3149
+ function cycle() {
3150
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : themeNames.value;
3151
+ const currentIndex = themeArray.indexOf(name.value);
3152
+ const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % themeArray.length;
3153
+ change(themeArray[nextIndex]);
3154
+ }
3155
+ function toggle() {
3156
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['light', 'dark'];
3157
+ cycle(themeArray);
3158
+ }
3159
+ const globalName = new Proxy(name, {
3160
+ get(target, prop) {
3161
+ return target[prop];
3162
+ },
3163
+ set(target, prop, val) {
3164
+ if (prop === 'value') {
3165
+ deprecate(`theme.global.name.value = ${val}`, `theme.change('${val}')`);
3166
+ }
3167
+ // @ts-expect-error
3168
+ target[prop] = val;
3169
+ return true;
3170
+ }
3171
+ });
3099
3172
  return {
3100
3173
  install,
3174
+ change,
3175
+ cycle,
3176
+ toggle,
3101
3177
  isDisabled: parsedOptions.isDisabled,
3102
3178
  name,
3103
3179
  themes,
3104
3180
  current,
3105
3181
  computedThemes,
3182
+ prefix: parsedOptions.prefix,
3106
3183
  themeClasses,
3107
3184
  styles,
3108
3185
  global: {
3109
- name,
3186
+ name: globalName,
3110
3187
  current
3111
3188
  }
3112
3189
  };
@@ -3117,7 +3194,7 @@
3117
3194
  if (!theme) throw new Error('Could not find Vuetify theme injection');
3118
3195
  const name = vue.toRef(() => props.theme ?? theme.name.value);
3119
3196
  const current = vue.toRef(() => theme.themes.value[name.value]);
3120
- const themeClasses = vue.toRef(() => theme.isDisabled ? undefined : `v-theme--${name.value}`);
3197
+ const themeClasses = vue.toRef(() => theme.isDisabled ? undefined : `${theme.prefix}theme--${name.value}`);
3121
3198
  const newTheme = {
3122
3199
  ...theme,
3123
3200
  name,
@@ -4221,7 +4298,10 @@
4221
4298
  default: 'default',
4222
4299
  validator: v => allowedDensities$1.includes(v)
4223
4300
  },
4224
- extended: Boolean,
4301
+ extended: {
4302
+ type: Boolean,
4303
+ default: null
4304
+ },
4225
4305
  extensionHeight: {
4226
4306
  type: [Number, String],
4227
4307
  default: 48
@@ -4269,7 +4349,7 @@
4269
4349
  const {
4270
4350
  rtlClasses
4271
4351
  } = useRtl();
4272
- const isExtended = vue.shallowRef(!!(props.extended || slots.extension?.()));
4352
+ const isExtended = vue.shallowRef(props.extended === null ? !!slots.extension?.() : props.extended);
4273
4353
  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));
4274
4354
  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);
4275
4355
  provideDefaults({
@@ -4281,7 +4361,7 @@
4281
4361
  const hasTitle = !!(props.title || slots.title);
4282
4362
  const hasImage = !!(slots.image || props.image);
4283
4363
  const extension = slots.extension?.();
4284
- isExtended.value = !!(props.extended || extension);
4364
+ isExtended.value = props.extended === null ? !!extension : props.extended;
4285
4365
  return vue.createVNode(props.tag, {
4286
4366
  "class": vue.normalizeClass(['v-toolbar', {
4287
4367
  'v-toolbar--absolute': props.absolute,
@@ -4664,9 +4744,15 @@
4664
4744
  };
4665
4745
  }
4666
4746
 
4747
+ // Types
4748
+
4667
4749
  const makeVBtnGroupProps = propsFactory({
4668
4750
  baseColor: String,
4669
4751
  divided: Boolean,
4752
+ direction: {
4753
+ type: String,
4754
+ default: 'horizontal'
4755
+ },
4670
4756
  ...makeBorderProps(),
4671
4757
  ...makeComponentProps(),
4672
4758
  ...makeDensityProps(),
@@ -4700,7 +4786,7 @@
4700
4786
  } = useRounded(props);
4701
4787
  provideDefaults({
4702
4788
  VBtn: {
4703
- height: 'auto',
4789
+ height: vue.toRef(() => props.direction === 'horizontal' ? 'auto' : null),
4704
4790
  baseColor: vue.toRef(() => props.baseColor),
4705
4791
  color: vue.toRef(() => props.color),
4706
4792
  density: vue.toRef(() => props.density),
@@ -4710,7 +4796,7 @@
4710
4796
  });
4711
4797
  useRender(() => {
4712
4798
  return vue.createVNode(props.tag, {
4713
- "class": vue.normalizeClass(['v-btn-group', {
4799
+ "class": vue.normalizeClass(['v-btn-group', `v-btn-group--${props.direction}`, {
4714
4800
  'v-btn-group--divided': props.divided
4715
4801
  }, themeClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class]),
4716
4802
  "style": vue.normalizeStyle(props.style)
@@ -5833,8 +5919,8 @@
5833
5919
  window.clearTimeout(element._ripple.showTimer);
5834
5920
  }
5835
5921
  let keyboardRipple = false;
5836
- function keyboardRippleShow(e) {
5837
- if (!keyboardRipple && (e.keyCode === keyCodes.enter || e.keyCode === keyCodes.space)) {
5922
+ function keyboardRippleShow(e, keys) {
5923
+ if (!keyboardRipple && keys.includes(e.keyCode)) {
5838
5924
  keyboardRipple = true;
5839
5925
  rippleShow(e);
5840
5926
  }
@@ -5862,9 +5948,12 @@
5862
5948
  el._ripple.enabled = enabled;
5863
5949
  el._ripple.centered = modifiers.center;
5864
5950
  el._ripple.circle = modifiers.circle;
5865
- if (isObject(value) && value.class) {
5866
- el._ripple.class = value.class;
5951
+ const bindingValue = isObject(value) ? value : {};
5952
+ if (bindingValue.class) {
5953
+ el._ripple.class = bindingValue.class;
5867
5954
  }
5955
+ const allowedKeys = bindingValue.keys ?? [keyCodes.enter, keyCodes.space];
5956
+ el._ripple.keyDownHandler = e => keyboardRippleShow(e, allowedKeys);
5868
5957
  if (enabled && !wasEnabled) {
5869
5958
  if (modifiers.stop) {
5870
5959
  el.addEventListener('touchstart', rippleStop, {
@@ -5886,7 +5975,7 @@
5886
5975
  el.addEventListener('mousedown', rippleShow);
5887
5976
  el.addEventListener('mouseup', rippleHide);
5888
5977
  el.addEventListener('mouseleave', rippleHide);
5889
- el.addEventListener('keydown', keyboardRippleShow);
5978
+ el.addEventListener('keydown', e => keyboardRippleShow(e, allowedKeys));
5890
5979
  el.addEventListener('keyup', keyboardRippleHide);
5891
5980
  el.addEventListener('blur', focusRippleHide);
5892
5981
 
@@ -5906,7 +5995,9 @@
5906
5995
  el.removeEventListener('touchcancel', rippleHide);
5907
5996
  el.removeEventListener('mouseup', rippleHide);
5908
5997
  el.removeEventListener('mouseleave', rippleHide);
5909
- el.removeEventListener('keydown', keyboardRippleShow);
5998
+ if (el._ripple?.keyDownHandler) {
5999
+ el.removeEventListener('keydown', el._ripple.keyDownHandler);
6000
+ }
5910
6001
  el.removeEventListener('keyup', keyboardRippleHide);
5911
6002
  el.removeEventListener('dragstart', rippleHide);
5912
6003
  el.removeEventListener('blur', focusRippleHide);
@@ -5915,8 +6006,8 @@
5915
6006
  updateRipple(el, binding, false);
5916
6007
  }
5917
6008
  function unmounted$4(el) {
5918
- delete el._ripple;
5919
6009
  removeListeners(el);
6010
+ delete el._ripple;
5920
6011
  }
5921
6012
  function updated$1(el, binding) {
5922
6013
  if (binding.value === binding.oldValue) {
@@ -6189,6 +6280,31 @@
6189
6280
  // Utilities
6190
6281
  const VAlertTitle = createSimpleFunctional('v-alert-title');
6191
6282
 
6283
+ // Utilities
6284
+
6285
+ // Types
6286
+
6287
+ // Types
6288
+
6289
+ // Composables
6290
+ const makeIconSizeProps = propsFactory({
6291
+ iconSize: [Number, String],
6292
+ iconSizes: {
6293
+ type: Array,
6294
+ default: () => [['x-small', 10], ['small', 16], ['default', 24], ['large', 28], ['x-large', 32]]
6295
+ }
6296
+ }, 'iconSize');
6297
+ function useIconSizes(props, fallback) {
6298
+ const iconSize = vue.computed(() => {
6299
+ const iconSizeMap = new Map(props.iconSizes);
6300
+ const _iconSize = props.iconSize ?? fallback() ?? 'default';
6301
+ return iconSizeMap.has(_iconSize) ? iconSizeMap.get(_iconSize) : _iconSize;
6302
+ });
6303
+ return {
6304
+ iconSize
6305
+ };
6306
+ }
6307
+
6192
6308
  // Types
6193
6309
 
6194
6310
  const allowedTypes = ['success', 'info', 'warning', 'error'];
@@ -6228,6 +6344,7 @@
6228
6344
  ...makeDensityProps(),
6229
6345
  ...makeDimensionProps(),
6230
6346
  ...makeElevationProps(),
6347
+ ...makeIconSizeProps(),
6231
6348
  ...makeLocationProps(),
6232
6349
  ...makePositionProps(),
6233
6350
  ...makeRoundedProps(),
@@ -6255,6 +6372,9 @@
6255
6372
  if (!props.type) return props.icon;
6256
6373
  return props.icon ?? `$${props.type}`;
6257
6374
  });
6375
+ const {
6376
+ iconSize
6377
+ } = useIconSizes(props, () => props.prominent ? 44 : 28);
6258
6378
  const {
6259
6379
  themeClasses
6260
6380
  } = provideTheme(props);
@@ -6302,6 +6422,11 @@
6302
6422
  const hasPrepend = !!(slots.prepend || icon.value);
6303
6423
  const hasTitle = !!(slots.title || props.title);
6304
6424
  const hasClose = !!(slots.close || props.closable);
6425
+ const iconProps = {
6426
+ density: props.density,
6427
+ icon: icon.value,
6428
+ size: iconSize.value
6429
+ };
6305
6430
  return isActive.value && vue.createVNode(props.tag, {
6306
6431
  "class": vue.normalizeClass(['v-alert', props.border && {
6307
6432
  'v-alert--border': !!props.border,
@@ -6319,19 +6444,14 @@
6319
6444
  }, null), hasPrepend && vue.createElementVNode("div", {
6320
6445
  "key": "prepend",
6321
6446
  "class": "v-alert__prepend"
6322
- }, [!slots.prepend ? vue.createVNode(VIcon, {
6323
- "key": "prepend-icon",
6324
- "density": props.density,
6325
- "icon": icon.value,
6326
- "size": props.prominent ? 44 : 28
6327
- }, null) : vue.createVNode(VDefaultsProvider, {
6447
+ }, [!slots.prepend ? vue.createVNode(VIcon, vue.mergeProps({
6448
+ "key": "prepend-icon"
6449
+ }, iconProps), null) : vue.createVNode(VDefaultsProvider, {
6328
6450
  "key": "prepend-defaults",
6329
6451
  "disabled": !icon.value,
6330
6452
  "defaults": {
6331
6453
  VIcon: {
6332
- density: props.density,
6333
- icon: icon.value,
6334
- size: props.prominent ? 44 : 28
6454
+ ...iconProps
6335
6455
  }
6336
6456
  }
6337
6457
  }, slots.prepend)]), vue.createElementVNode("div", {
@@ -7856,6 +7976,7 @@
7856
7976
  const VSlideGroupSymbol = Symbol.for('vuetify:v-slide-group');
7857
7977
  const makeVSlideGroupProps = propsFactory({
7858
7978
  centerActive: Boolean,
7979
+ contentClass: null,
7859
7980
  direction: {
7860
7981
  type: String,
7861
7982
  default: 'horizontal'
@@ -8168,7 +8289,7 @@
8168
8289
  })]), vue.createElementVNode("div", {
8169
8290
  "key": "container",
8170
8291
  "ref": containerRef,
8171
- "class": "v-slide-group__container",
8292
+ "class": vue.normalizeClass(['v-slide-group__container', props.contentClass]),
8172
8293
  "onScroll": onScroll
8173
8294
  }, [vue.createElementVNode("div", {
8174
8295
  "ref": contentRef,
@@ -8378,6 +8499,7 @@
8378
8499
  const isClickable = vue.computed(() => !props.disabled && props.link !== false && (!!group || props.link || link.isClickable.value));
8379
8500
  const closeProps = vue.toRef(() => ({
8380
8501
  'aria-label': t(props.closeLabel),
8502
+ disabled: props.disabled,
8381
8503
  onClick(e) {
8382
8504
  e.preventDefault();
8383
8505
  e.stopPropagation();
@@ -8530,16 +8652,85 @@
8530
8652
  }
8531
8653
  });
8532
8654
 
8655
+ const makeVDividerProps = propsFactory({
8656
+ color: String,
8657
+ inset: Boolean,
8658
+ length: [Number, String],
8659
+ opacity: [Number, String],
8660
+ thickness: [Number, String],
8661
+ vertical: Boolean,
8662
+ ...makeComponentProps(),
8663
+ ...makeThemeProps()
8664
+ }, 'VDivider');
8665
+ const VDivider = genericComponent()({
8666
+ name: 'VDivider',
8667
+ props: makeVDividerProps(),
8668
+ setup(props, _ref) {
8669
+ let {
8670
+ attrs,
8671
+ slots
8672
+ } = _ref;
8673
+ const {
8674
+ themeClasses
8675
+ } = provideTheme(props);
8676
+ const {
8677
+ textColorClasses,
8678
+ textColorStyles
8679
+ } = useTextColor(() => props.color);
8680
+ const dividerStyles = vue.computed(() => {
8681
+ const styles = {};
8682
+ if (props.length) {
8683
+ styles[props.vertical ? 'height' : 'width'] = convertToUnit(props.length);
8684
+ }
8685
+ if (props.thickness) {
8686
+ styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
8687
+ }
8688
+ return styles;
8689
+ });
8690
+ useRender(() => {
8691
+ const divider = vue.createElementVNode("hr", {
8692
+ "class": vue.normalizeClass([{
8693
+ 'v-divider': true,
8694
+ 'v-divider--inset': props.inset,
8695
+ 'v-divider--vertical': props.vertical
8696
+ }, themeClasses.value, textColorClasses.value, props.class]),
8697
+ "style": vue.normalizeStyle([dividerStyles.value, textColorStyles.value, {
8698
+ '--v-border-opacity': props.opacity
8699
+ }, props.style]),
8700
+ "aria-orientation": !attrs.role || attrs.role === 'separator' ? props.vertical ? 'vertical' : 'horizontal' : undefined,
8701
+ "role": `${attrs.role || 'separator'}`
8702
+ }, null);
8703
+ if (!slots.default) return divider;
8704
+ return vue.createElementVNode("div", {
8705
+ "class": vue.normalizeClass(['v-divider__wrapper', {
8706
+ 'v-divider__wrapper--vertical': props.vertical,
8707
+ 'v-divider__wrapper--inset': props.inset
8708
+ }])
8709
+ }, [divider, vue.createElementVNode("div", {
8710
+ "class": "v-divider__content"
8711
+ }, [slots.default()]), divider]);
8712
+ });
8713
+ return {};
8714
+ }
8715
+ });
8716
+
8533
8717
  // Utilities
8534
8718
 
8535
8719
  // List
8536
8720
  const ListKey = Symbol.for('vuetify:list');
8537
8721
  function createList() {
8722
+ let {
8723
+ filterable
8724
+ } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
8725
+ filterable: false
8726
+ };
8538
8727
  const parent = vue.inject(ListKey, {
8728
+ filterable: false,
8539
8729
  hasPrepend: vue.shallowRef(false),
8540
8730
  updateHasPrepend: () => null
8541
8731
  });
8542
8732
  const data = {
8733
+ filterable: parent.filterable || filterable,
8543
8734
  hasPrepend: vue.shallowRef(false),
8544
8735
  updateHasPrepend: value => {
8545
8736
  if (value) data.hasPrepend.value = value;
@@ -9491,6 +9682,9 @@
9491
9682
  roundedClasses
9492
9683
  } = useRounded(roundedProps);
9493
9684
  const lineClasses = vue.toRef(() => props.lines ? `v-list-item--${props.lines}-line` : undefined);
9685
+ const rippleOptions = vue.toRef(() => props.ripple !== undefined && !!props.ripple && list?.filterable ? {
9686
+ keys: [keyCodes.enter]
9687
+ } : props.ripple);
9494
9688
  const slotProps = vue.computed(() => ({
9495
9689
  isActive: isActive.value,
9496
9690
  select,
@@ -9515,8 +9709,9 @@
9515
9709
  function onKeyDown(e) {
9516
9710
  const target = e.target;
9517
9711
  if (['INPUT', 'TEXTAREA'].includes(target.tagName)) return;
9518
- if (e.key === 'Enter' || e.key === ' ') {
9712
+ if (e.key === 'Enter' || e.key === ' ' && !list?.filterable) {
9519
9713
  e.preventDefault();
9714
+ e.stopPropagation();
9520
9715
  e.target.dispatchEvent(new MouseEvent('click', e));
9521
9716
  }
9522
9717
  }
@@ -9626,7 +9821,7 @@
9626
9821
  }), vue.createElementVNode("div", {
9627
9822
  "class": "v-list-item__spacer"
9628
9823
  }, null)])]
9629
- }), [[Ripple, isClickable.value && props.ripple]]);
9824
+ }), [[Ripple, isClickable.value && rippleOptions.value]]);
9630
9825
  });
9631
9826
  return {
9632
9827
  activate,
@@ -9681,68 +9876,6 @@
9681
9876
  }
9682
9877
  });
9683
9878
 
9684
- const makeVDividerProps = propsFactory({
9685
- color: String,
9686
- inset: Boolean,
9687
- length: [Number, String],
9688
- opacity: [Number, String],
9689
- thickness: [Number, String],
9690
- vertical: Boolean,
9691
- ...makeComponentProps(),
9692
- ...makeThemeProps()
9693
- }, 'VDivider');
9694
- const VDivider = genericComponent()({
9695
- name: 'VDivider',
9696
- props: makeVDividerProps(),
9697
- setup(props, _ref) {
9698
- let {
9699
- attrs,
9700
- slots
9701
- } = _ref;
9702
- const {
9703
- themeClasses
9704
- } = provideTheme(props);
9705
- const {
9706
- textColorClasses,
9707
- textColorStyles
9708
- } = useTextColor(() => props.color);
9709
- const dividerStyles = vue.computed(() => {
9710
- const styles = {};
9711
- if (props.length) {
9712
- styles[props.vertical ? 'height' : 'width'] = convertToUnit(props.length);
9713
- }
9714
- if (props.thickness) {
9715
- styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
9716
- }
9717
- return styles;
9718
- });
9719
- useRender(() => {
9720
- const divider = vue.createElementVNode("hr", {
9721
- "class": vue.normalizeClass([{
9722
- 'v-divider': true,
9723
- 'v-divider--inset': props.inset,
9724
- 'v-divider--vertical': props.vertical
9725
- }, themeClasses.value, textColorClasses.value, props.class]),
9726
- "style": vue.normalizeStyle([dividerStyles.value, textColorStyles.value, {
9727
- '--v-border-opacity': props.opacity
9728
- }, props.style]),
9729
- "aria-orientation": !attrs.role || attrs.role === 'separator' ? props.vertical ? 'vertical' : 'horizontal' : undefined,
9730
- "role": `${attrs.role || 'separator'}`
9731
- }, null);
9732
- if (!slots.default) return divider;
9733
- return vue.createElementVNode("div", {
9734
- "class": vue.normalizeClass(['v-divider__wrapper', {
9735
- 'v-divider__wrapper--vertical': props.vertical,
9736
- 'v-divider__wrapper--inset': props.inset
9737
- }])
9738
- }, [divider, vue.createElementVNode("div", {
9739
- "class": "v-divider__content"
9740
- }, [slots.default()]), divider]);
9741
- });
9742
- return {};
9743
- }
9744
- });
9745
-
9746
9879
  // Types
9747
9880
 
9748
9881
  const makeVListChildrenProps = propsFactory({
@@ -9859,7 +9992,7 @@
9859
9992
  const _props = {
9860
9993
  title,
9861
9994
  value,
9862
- ...itemProps
9995
+ ...camelizeProps(itemProps)
9863
9996
  };
9864
9997
  return {
9865
9998
  title: String(_props.title ?? ''),
@@ -10011,6 +10144,7 @@
10011
10144
  activeClass: String,
10012
10145
  bgColor: String,
10013
10146
  disabled: Boolean,
10147
+ filterable: Boolean,
10014
10148
  expandIcon: IconValue,
10015
10149
  collapseIcon: IconValue,
10016
10150
  lines: {
@@ -10094,7 +10228,9 @@
10094
10228
  const activeColor = vue.toRef(() => props.activeColor);
10095
10229
  const baseColor = vue.toRef(() => props.baseColor);
10096
10230
  const color = vue.toRef(() => props.color);
10097
- createList();
10231
+ createList({
10232
+ filterable: props.filterable
10233
+ });
10098
10234
  provideDefaults({
10099
10235
  VListGroup: {
10100
10236
  activeColor,
@@ -12670,7 +12806,12 @@
12670
12806
  }
12671
12807
  function calculateOffset(index) {
12672
12808
  index = clamp(index, 0, items.value.length - 1);
12673
- return offsets[index] || 0;
12809
+ const whole = Math.floor(index);
12810
+ const fraction = index % 1;
12811
+ const next = whole + 1;
12812
+ const wholeOffset = offsets[whole] || 0;
12813
+ const nextOffset = offsets[next] || wholeOffset;
12814
+ return wholeOffset + (nextOffset - wholeOffset) * fraction;
12674
12815
  }
12675
12816
  function calculateIndex(scrollTop) {
12676
12817
  return binaryClosest(offsets, scrollTop);
@@ -13024,6 +13165,7 @@
13024
13165
  },
13025
13166
  openOnClear: Boolean,
13026
13167
  itemColor: String,
13168
+ noAutoScroll: Boolean,
13027
13169
  ...makeItemsProps({
13028
13170
  itemChildren: false
13029
13171
  })
@@ -13238,7 +13380,7 @@
13238
13380
  vue.watch(menu, () => {
13239
13381
  if (!props.hideSelected && menu.value && model.value.length) {
13240
13382
  const index = displayItems.value.findIndex(item => model.value.some(s => (props.valueComparator || deepEqual)(s.value, item.value)));
13241
- IN_BROWSER && window.requestAnimationFrame(() => {
13383
+ IN_BROWSER && !props.noAutoScroll && window.requestAnimationFrame(() => {
13242
13384
  index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
13243
13385
  });
13244
13386
  }
@@ -13330,6 +13472,22 @@
13330
13472
  key: item.value,
13331
13473
  onClick: () => select(item, null)
13332
13474
  });
13475
+ if (item.raw.type === 'divider') {
13476
+ return slots.divider?.({
13477
+ props: item.raw,
13478
+ index
13479
+ }) ?? vue.createVNode(VDivider, vue.mergeProps(item.props, {
13480
+ "key": `divider-${index}`
13481
+ }), null);
13482
+ }
13483
+ if (item.raw.type === 'subheader') {
13484
+ return slots.subheader?.({
13485
+ props: item.raw,
13486
+ index
13487
+ }) ?? vue.createVNode(VListSubheader, vue.mergeProps(item.props, {
13488
+ "key": `subheader-${index}`
13489
+ }), null);
13490
+ }
13333
13491
  return slots.item?.({
13334
13492
  item,
13335
13493
  index,
@@ -13490,6 +13648,9 @@
13490
13648
  let match = -1;
13491
13649
  if ((query || customFiltersLength > 0) && !options?.noFilter) {
13492
13650
  if (typeof item === 'object') {
13651
+ if (['divider', 'subheader'].includes(item.raw?.type)) {
13652
+ continue;
13653
+ }
13493
13654
  const filterKeys = keys || Object.keys(transformed);
13494
13655
  for (const key of filterKeys) {
13495
13656
  const value = getPropertyFromItem(transformed, key);
@@ -13692,7 +13853,7 @@
13692
13853
  menu.value = !menu.value;
13693
13854
  }
13694
13855
  function onListKeydown(e) {
13695
- if (e.key !== ' ' && checkPrintable(e)) {
13856
+ if (checkPrintable(e) || e.key === 'Backspace') {
13696
13857
  vTextFieldRef.value?.focus();
13697
13858
  }
13698
13859
  }
@@ -13897,6 +14058,7 @@
13897
14058
  }, props.menuProps), {
13898
14059
  default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
13899
14060
  "ref": listRef,
14061
+ "filterable": true,
13900
14062
  "selected": selectedValues.value,
13901
14063
  "selectStrategy": props.multiple ? 'independent' : 'single-independent',
13902
14064
  "onMousedown": e => e.preventDefault(),
@@ -13928,6 +14090,22 @@
13928
14090
  active: highlightFirst.value && index === 0 ? true : undefined,
13929
14091
  onClick: () => select(item, null)
13930
14092
  });
14093
+ if (item.raw.type === 'divider') {
14094
+ return slots.divider?.({
14095
+ props: item.raw,
14096
+ index
14097
+ }) ?? vue.createVNode(VDivider, vue.mergeProps(item.props, {
14098
+ "key": `divider-${index}`
14099
+ }), null);
14100
+ }
14101
+ if (item.raw.type === 'subheader') {
14102
+ return slots.subheader?.({
14103
+ props: item.raw,
14104
+ index
14105
+ }) ?? vue.createVNode(VListSubheader, vue.mergeProps(item.props, {
14106
+ "key": `subheader-${index}`
14107
+ }), null);
14108
+ }
13931
14109
  return slots.item?.({
13932
14110
  item,
13933
14111
  index,
@@ -16166,7 +16344,10 @@
16166
16344
  if (step.value <= 0) return value;
16167
16345
  const clamped = clamp(value, min.value, max.value);
16168
16346
  const offset = min.value % step.value;
16169
- const newValue = Math.round((clamped - offset) / step.value) * step.value + offset;
16347
+ let newValue = Math.round((clamped - offset) / step.value) * step.value + offset;
16348
+ if (clamped > newValue && newValue + step.value > max.value) {
16349
+ newValue = max.value;
16350
+ }
16170
16351
  return parseFloat(Math.min(newValue, max.value).toFixed(decimals.value));
16171
16352
  }
16172
16353
  return {
@@ -16422,6 +16603,8 @@
16422
16603
  } = useRtl();
16423
16604
  if (!slider) throw new Error('[Vuetify] v-slider-thumb must be used inside v-slider or v-range-slider');
16424
16605
  const {
16606
+ min,
16607
+ max,
16425
16608
  thumbColor,
16426
16609
  step,
16427
16610
  disabled,
@@ -16462,16 +16645,20 @@
16462
16645
  if (!relevantKeys.includes(e.key)) return;
16463
16646
  e.preventDefault();
16464
16647
  const _step = step.value || 0.1;
16465
- const steps = (props.max - props.min) / _step;
16648
+ const steps = (max.value - min.value) / _step;
16466
16649
  if ([left, right, down, up].includes(e.key)) {
16467
16650
  const increase = vertical.value ? [isRtl.value ? left : right, isReversed.value ? down : up] : indexFromEnd.value !== isRtl.value ? [left, up] : [right, up];
16468
16651
  const direction = increase.includes(e.key) ? 1 : -1;
16469
16652
  const multiplier = e.shiftKey ? 2 : e.ctrlKey ? 1 : 0;
16470
- value = value + direction * _step * multipliers.value[multiplier];
16653
+ if (direction === -1 && value === max.value && !multiplier && !Number.isInteger(steps)) {
16654
+ value = value - steps % 1 * _step;
16655
+ } else {
16656
+ value = value + direction * _step * multipliers.value[multiplier];
16657
+ }
16471
16658
  } else if (e.key === home) {
16472
- value = props.min;
16659
+ value = min.value;
16473
16660
  } else if (e.key === end) {
16474
- value = props.max;
16661
+ value = max.value;
16475
16662
  } else {
16476
16663
  const direction = e.key === pagedown ? 1 : -1;
16477
16664
  value = value - direction * _step * (steps > 100 ? steps / 10 : 10);
@@ -16496,8 +16683,8 @@
16496
16683
  "role": "slider",
16497
16684
  "tabindex": disabled.value ? -1 : 0,
16498
16685
  "aria-label": props.name,
16499
- "aria-valuemin": props.min,
16500
- "aria-valuemax": props.max,
16686
+ "aria-valuemin": min.value,
16687
+ "aria-valuemax": max.value,
16501
16688
  "aria-valuenow": props.modelValue,
16502
16689
  "aria-readonly": !!readonly.value,
16503
16690
  "aria-orientation": direction.value,
@@ -17523,13 +17710,13 @@
17523
17710
  return null;
17524
17711
  }
17525
17712
  const sundayJanuarySecond2000 = new Date(2000, 0, 2);
17526
- function getWeekdays(locale, firstDayOfWeek) {
17713
+ function getWeekdays(locale, firstDayOfWeek, weekdayFormat) {
17527
17714
  const daysFromSunday = firstDayOfWeek ?? weekInfo(locale)?.firstDay ?? 0;
17528
17715
  return createRange(7).map(i => {
17529
17716
  const weekday = new Date(sundayJanuarySecond2000);
17530
17717
  weekday.setDate(sundayJanuarySecond2000.getDate() + daysFromSunday + i);
17531
17718
  return new Intl.DateTimeFormat(locale, {
17532
- weekday: 'narrow'
17719
+ weekday: weekdayFormat ?? 'narrow'
17533
17720
  }).format(weekday);
17534
17721
  });
17535
17722
  }
@@ -17993,9 +18180,9 @@
17993
18180
  getDiff(date, comparing, unit) {
17994
18181
  return getDiff(date, comparing, unit);
17995
18182
  }
17996
- getWeekdays(firstDayOfWeek) {
18183
+ getWeekdays(firstDayOfWeek, weekdayFormat) {
17997
18184
  const firstDay = firstDayOfWeek !== undefined ? Number(firstDayOfWeek) : undefined;
17998
- return getWeekdays(this.locale, firstDay);
18185
+ return getWeekdays(this.locale, firstDay, weekdayFormat);
17999
18186
  }
18000
18187
  getYear(date) {
18001
18188
  return getYear(date);
@@ -18351,6 +18538,7 @@
18351
18538
  _search.value = val ?? '';
18352
18539
  if (!props.multiple && !hasSelectionSlot.value) {
18353
18540
  model.value = [transformItem$3(props, val)];
18541
+ vue.nextTick(() => vVirtualScrollRef.value?.scrollToIndex(0));
18354
18542
  }
18355
18543
  if (val && props.multiple && props.delimiters?.length) {
18356
18544
  const values = val.split(new RegExp(`(?:${props.delimiters.join('|')})+`));
@@ -18431,7 +18619,7 @@
18431
18619
  menu.value = !menu.value;
18432
18620
  }
18433
18621
  function onListKeydown(e) {
18434
- if (e.key !== ' ' && checkPrintable(e)) {
18622
+ if (checkPrintable(e) || e.key === 'Backspace') {
18435
18623
  vTextFieldRef.value?.focus();
18436
18624
  }
18437
18625
  }
@@ -18636,6 +18824,7 @@
18636
18824
  }, props.menuProps), {
18637
18825
  default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
18638
18826
  "ref": listRef,
18827
+ "filterable": true,
18639
18828
  "selected": selectedValues.value,
18640
18829
  "selectStrategy": props.multiple ? 'independent' : 'single-independent',
18641
18830
  "onMousedown": e => e.preventDefault(),
@@ -18667,6 +18856,22 @@
18667
18856
  active: highlightFirst.value && index === 0 ? true : undefined,
18668
18857
  onClick: () => select(item, null)
18669
18858
  });
18859
+ if (item.raw.type === 'divider') {
18860
+ return slots.divider?.({
18861
+ props: item.raw,
18862
+ index
18863
+ }) ?? vue.createVNode(VDivider, vue.mergeProps(item.props, {
18864
+ "key": `divider-${index}`
18865
+ }), null);
18866
+ }
18867
+ if (item.raw.type === 'subheader') {
18868
+ return slots.subheader?.({
18869
+ props: item.raw,
18870
+ index
18871
+ }) ?? vue.createVNode(VListSubheader, vue.mergeProps(item.props, {
18872
+ "key": `subheader-${index}`
18873
+ }), null);
18874
+ }
18670
18875
  return slots.item?.({
18671
18876
  item,
18672
18877
  index,
@@ -20546,6 +20751,7 @@
20546
20751
  color: String,
20547
20752
  disableSort: Boolean,
20548
20753
  fixedHeader: Boolean,
20754
+ lastFixed: Boolean,
20549
20755
  multiSort: Boolean,
20550
20756
  sortAscIcon: {
20551
20757
  type: IconValue,
@@ -20592,10 +20798,11 @@
20592
20798
  loaderClasses
20593
20799
  } = useLoader(props);
20594
20800
  function getFixedStyles(column, y) {
20595
- if (!(props.sticky || props.fixedHeader) && !column.fixed) return undefined;
20801
+ if (!(props.sticky || props.fixedHeader) && !(column.fixed || column.lastFixed)) return undefined;
20596
20802
  return {
20597
20803
  position: 'sticky',
20598
- left: column.fixed ? convertToUnit(column.fixedOffset) : undefined,
20804
+ left: column.fixed || column.lastFixed ? convertToUnit(column.fixedOffset) : undefined,
20805
+ right: column.lastFixed ? convertToUnit(column.fixedOffset ?? 0) : undefined,
20599
20806
  top: props.sticky || props.fixedHeader ? `calc(var(--v-table-header-height) * ${y})` : undefined
20600
20807
  };
20601
20808
  }
@@ -21104,11 +21311,18 @@
21104
21311
  }
21105
21312
  });
21106
21313
 
21314
+ // Types
21315
+
21107
21316
  const makeVTableProps = propsFactory({
21108
21317
  fixedHeader: Boolean,
21109
21318
  fixedFooter: Boolean,
21110
21319
  height: [Number, String],
21111
21320
  hover: Boolean,
21321
+ striped: {
21322
+ type: String,
21323
+ default: null,
21324
+ validator: v => ['even', 'odd'].includes(v)
21325
+ },
21112
21326
  ...makeComponentProps(),
21113
21327
  ...makeDensityProps(),
21114
21328
  ...makeTagProps(),
@@ -21135,7 +21349,9 @@
21135
21349
  'v-table--fixed-footer': props.fixedFooter,
21136
21350
  'v-table--has-top': !!slots.top,
21137
21351
  'v-table--has-bottom': !!slots.bottom,
21138
- 'v-table--hover': props.hover
21352
+ 'v-table--hover': props.hover,
21353
+ 'v-table--striped-even': props.striped === 'even',
21354
+ 'v-table--striped-odd': props.striped === 'odd'
21139
21355
  }, themeClasses.value, densityClasses.value, props.class]),
21140
21356
  "style": vue.normalizeStyle(props.style)
21141
21357
  }, {
@@ -22310,7 +22526,8 @@
22310
22526
  firstDayOfWeek: {
22311
22527
  type: [Number, String],
22312
22528
  default: undefined
22313
- }
22529
+ },
22530
+ weekdayFormat: String
22314
22531
  }, 'calendar');
22315
22532
  function useCalendar(props) {
22316
22533
  const adapter = useDate();
@@ -22551,7 +22768,7 @@
22551
22768
  "ref": daysRef,
22552
22769
  "key": daysInMonth.value[0].date?.toString(),
22553
22770
  "class": "v-date-picker-month__days"
22554
- }, [!props.hideWeekdays && adapter.getWeekdays(props.firstDayOfWeek).map(weekDay => vue.createElementVNode("div", {
22771
+ }, [!props.hideWeekdays && adapter.getWeekdays(props.firstDayOfWeek, props.weekdayFormat).map(weekDay => vue.createElementVNode("div", {
22555
22772
  "class": vue.normalizeClass(['v-date-picker-month__day', 'v-date-picker-month__weekday'])
22556
22773
  }, [weekDay])), daysInMonth.value.map((item, i) => {
22557
22774
  const slotProps = {
@@ -25141,6 +25358,10 @@
25141
25358
  type: Number,
25142
25359
  default: 0
25143
25360
  },
25361
+ minFractionDigits: {
25362
+ type: Number,
25363
+ default: null
25364
+ },
25144
25365
  ...omit(makeVTextFieldProps(), ['modelValue', 'validationValue'])
25145
25366
  }, 'VNumberInput');
25146
25367
  const VNumberInput = genericComponent()({
@@ -25171,9 +25392,19 @@
25171
25392
  } = useFocus(props);
25172
25393
  function correctPrecision(val) {
25173
25394
  let precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.precision;
25174
- const fixed = precision == null ? String(val) : val.toFixed(precision);
25175
- return isFocused.value ? Number(fixed).toString() // trim zeros
25176
- : fixed;
25395
+ if (precision == null) {
25396
+ return String(val);
25397
+ }
25398
+ let fixed = val.toFixed(precision);
25399
+ if (isFocused.value) {
25400
+ return Number(fixed).toString(); // trim zeros
25401
+ }
25402
+ if ((props.minFractionDigits ?? precision) < precision) {
25403
+ const trimLimit = precision - props.minFractionDigits;
25404
+ const [baseDigits, fractionDigits] = fixed.split('.');
25405
+ fixed = [baseDigits, fractionDigits.replace(new RegExp(`0{1,${trimLimit}}$`), '')].filter(Boolean).join('.');
25406
+ }
25407
+ return fixed;
25177
25408
  }
25178
25409
  const model = useProxiedModel(props, 'modelValue', null, val => val ?? null, val => val == null ? val ?? null : clamp(Number(val), props.min, props.max));
25179
25410
  const _inputText = vue.shallowRef(null);
@@ -25228,6 +25459,7 @@
25228
25459
  }
25229
25460
  };
25230
25461
  vue.watch(() => props.precision, () => formatInputValue());
25462
+ vue.watch(() => props.minFractionDigits, () => formatInputValue());
25231
25463
  vue.onMounted(() => {
25232
25464
  clampModel();
25233
25465
  });
@@ -25342,7 +25574,7 @@
25342
25574
  inputText.value = null;
25343
25575
  return;
25344
25576
  }
25345
- inputText.value = props.precision == null ? String(model.value) : model.value.toFixed(props.precision);
25577
+ inputText.value = correctPrecision(model.value);
25346
25578
  }
25347
25579
  function trimDecimalZeros() {
25348
25580
  if (controlsDisabled.value) return;
@@ -25602,9 +25834,10 @@
25602
25834
  e.preventDefault();
25603
25835
  e.stopPropagation();
25604
25836
  const clipboardText = e?.clipboardData?.getData('Text').slice(0, length.value) ?? '';
25837
+ const finalIndex = clipboardText.length - 1 === -1 ? index : clipboardText.length - 1;
25605
25838
  if (isValidNumber(clipboardText)) return;
25606
25839
  model.value = clipboardText.split('');
25607
- inputRef.value?.[index].blur();
25840
+ inputRef.value?.[finalIndex].focus();
25608
25841
  }
25609
25842
  function reset() {
25610
25843
  model.value = [];
@@ -29386,7 +29619,7 @@
29386
29619
  };
29387
29620
  });
29388
29621
  }
29389
- const version$1 = "3.8.7-master.2025-06-02";
29622
+ const version$1 = "3.8.8-dev.2025-06-04";
29390
29623
  createVuetify$1.version = version$1;
29391
29624
 
29392
29625
  // Vue's inject() can only be used in setup
@@ -29411,7 +29644,7 @@
29411
29644
  ...options
29412
29645
  });
29413
29646
  };
29414
- const version = "3.8.7-master.2025-06-02";
29647
+ const version = "3.8.8-dev.2025-06-04";
29415
29648
  createVuetify.version = version;
29416
29649
 
29417
29650
  exports.blueprints = index;