@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
@@ -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
  */
@@ -85,6 +85,7 @@
85
85
  const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
86
86
  const SUPPORTS_TOUCH = IN_BROWSER && ('ontouchstart' in window || window.navigator.maxTouchPoints > 0);
87
87
  const SUPPORTS_EYE_DROPPER = IN_BROWSER && 'EyeDropper' in window;
88
+ const SUPPORTS_MATCH_MEDIA = IN_BROWSER && 'matchMedia' in window && typeof window.matchMedia === 'function';
88
89
 
89
90
  function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
90
91
  function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
@@ -591,18 +592,23 @@
591
592
  function isPrimitive(value) {
592
593
  return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint';
593
594
  }
594
- function extractNumber(text, decimalDigitsLimit) {
595
- const cleanText = text.split('').filter(x => /[\d\-.]/.test(x)).filter((x, i, all) => i === 0 && /[-]/.test(x) ||
595
+ function escapeForRegex(sign) {
596
+ return '\\^$*+?.()|{}[]'.includes(sign) ? `\\${sign}` : sign;
597
+ }
598
+ function extractNumber(text, decimalDigitsLimit, decimalSeparator) {
599
+ const onlyValidCharacters = new RegExp(`[\\d\\-${escapeForRegex(decimalSeparator)}]`);
600
+ const cleanText = text.split('').filter(x => onlyValidCharacters.test(x)).filter((x, i, all) => i === 0 && /[-]/.test(x) ||
596
601
  // sign allowed at the start
597
- x === '.' && i === all.indexOf('.') ||
602
+ x === decimalSeparator && i === all.indexOf(x) ||
598
603
  // decimal separator allowed only once
599
604
  /\d/.test(x)).join('');
600
605
  if (decimalDigitsLimit === 0) {
601
- return cleanText.split('.')[0];
606
+ return cleanText.split(decimalSeparator)[0];
602
607
  }
603
- if (decimalDigitsLimit !== null && /\.\d/.test(cleanText)) {
604
- const parts = cleanText.split('.');
605
- return [parts[0], parts[1].substring(0, decimalDigitsLimit)].join('.');
608
+ const decimalPart = new RegExp(`${escapeForRegex(decimalSeparator)}\\d`);
609
+ if (decimalDigitsLimit !== null && decimalPart.test(cleanText)) {
610
+ const parts = cleanText.split(decimalSeparator);
611
+ return [parts[0], parts[1].substring(0, decimalDigitsLimit)].join(decimalSeparator);
606
612
  }
607
613
  return cleanText;
608
614
  }
@@ -944,7 +950,7 @@
944
950
  // WoB should always return negative value.
945
951
 
946
952
  const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB;
947
- outputContrast = SAPC > -1e-3 ? 0.0 : SAPC > -0.078 ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
953
+ outputContrast = SAPC > -loClip ? 0.0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
948
954
  }
949
955
  return outputContrast * 100;
950
956
  }
@@ -2185,6 +2191,10 @@
2185
2191
  return numberFormat.format(value);
2186
2192
  };
2187
2193
  }
2194
+ function inferDecimalSeparator(current, fallback) {
2195
+ const format = createNumberFunction(current, fallback);
2196
+ return format(0.1).includes(',') ? ',' : '.';
2197
+ }
2188
2198
  function useProvided(props, prop, provided) {
2189
2199
  const internal = useProxiedModel(props, prop, props[prop] ?? provided.value);
2190
2200
 
@@ -2207,6 +2217,7 @@
2207
2217
  current,
2208
2218
  fallback,
2209
2219
  messages,
2220
+ decimalSeparator: vue.toRef(() => inferDecimalSeparator(current, fallback)),
2210
2221
  t: createTranslateFunction(current, fallback, messages),
2211
2222
  n: createNumberFunction(current, fallback),
2212
2223
  provide: createProvideFunction({
@@ -2229,6 +2240,7 @@
2229
2240
  current,
2230
2241
  fallback,
2231
2242
  messages,
2243
+ decimalSeparator: vue.toRef(() => options?.decimalSeparator ?? inferDecimalSeparator(current, fallback)),
2232
2244
  t: createTranslateFunction(current, fallback, messages),
2233
2245
  n: createNumberFunction(current, fallback),
2234
2246
  provide: createProvideFunction({
@@ -2355,6 +2367,7 @@
2355
2367
  function genDefaults$2() {
2356
2368
  return {
2357
2369
  defaultTheme: 'light',
2370
+ prefix: 'v-',
2358
2371
  variations: {
2359
2372
  colors: [],
2360
2373
  lighten: 0,
@@ -2392,8 +2405,8 @@
2392
2405
  'activated-opacity': 0.12,
2393
2406
  'pressed-opacity': 0.12,
2394
2407
  'dragged-opacity': 0.08,
2395
- 'theme-kbd': '#212529',
2396
- 'theme-on-kbd': '#FFFFFF',
2408
+ 'theme-kbd': '#EEEEEE',
2409
+ 'theme-on-kbd': '#000000',
2397
2410
  'theme-code': '#F5F5F5',
2398
2411
  'theme-on-code': '#000000'
2399
2412
  }
@@ -2429,14 +2442,17 @@
2429
2442
  'activated-opacity': 0.12,
2430
2443
  'pressed-opacity': 0.16,
2431
2444
  'dragged-opacity': 0.08,
2432
- 'theme-kbd': '#212529',
2445
+ 'theme-kbd': '#424242',
2433
2446
  'theme-on-kbd': '#FFFFFF',
2434
2447
  'theme-code': '#343434',
2435
2448
  'theme-on-code': '#CCCCCC'
2436
2449
  }
2437
2450
  }
2438
2451
  },
2439
- stylesheetId: 'vuetify-theme-stylesheet'
2452
+ stylesheetId: 'vuetify-theme-stylesheet',
2453
+ scoped: false,
2454
+ unimportant: false,
2455
+ utilities: true
2440
2456
  };
2441
2457
  }
2442
2458
  function parseThemeOptions() {
@@ -2459,21 +2475,21 @@
2459
2475
  function createCssClass(lines, selector, content, scope) {
2460
2476
  lines.push(`${getScopedSelector(selector, scope)} {\n`, ...content.map(line => ` ${line};\n`), '}\n');
2461
2477
  }
2462
- function genCssVariables(theme) {
2478
+ function genCssVariables(theme, prefix) {
2463
2479
  const lightOverlay = theme.dark ? 2 : 1;
2464
2480
  const darkOverlay = theme.dark ? 1 : 2;
2465
2481
  const variables = [];
2466
2482
  for (const [key, value] of Object.entries(theme.colors)) {
2467
2483
  const rgb = parseColor(value);
2468
- variables.push(`--v-theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2484
+ variables.push(`--${prefix}theme-${key}: ${rgb.r},${rgb.g},${rgb.b}`);
2469
2485
  if (!key.startsWith('on-')) {
2470
- variables.push(`--v-theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2486
+ variables.push(`--${prefix}theme-${key}-overlay-multiplier: ${getLuma(value) > 0.18 ? lightOverlay : darkOverlay}`);
2471
2487
  }
2472
2488
  }
2473
2489
  for (const [key, value] of Object.entries(theme.variables)) {
2474
2490
  const color = typeof value === 'string' && value.startsWith('#') ? parseColor(value) : undefined;
2475
2491
  const rgb = color ? `${color.r}, ${color.g}, ${color.b}` : undefined;
2476
- variables.push(`--v-${key}: ${rgb ?? value}`);
2492
+ variables.push(`--${prefix}${key}: ${rgb ?? value}`);
2477
2493
  }
2478
2494
  return variables;
2479
2495
  }
@@ -2517,7 +2533,8 @@
2517
2533
  const scopeSelector = `:where(${scope})`;
2518
2534
  return selector === ':root' ? scopeSelector : `${scopeSelector} ${selector}`;
2519
2535
  }
2520
- function upsertStyles(styleEl, styles) {
2536
+ function upsertStyles(id, cspNonce, styles) {
2537
+ const styleEl = getOrCreateStyleElement(id, cspNonce);
2521
2538
  if (!styleEl) return;
2522
2539
  styleEl.innerHTML = styles;
2523
2540
  }
@@ -2537,8 +2554,17 @@
2537
2554
  // Composables
2538
2555
  function createTheme(options) {
2539
2556
  const parsedOptions = parseThemeOptions(options);
2540
- const name = vue.shallowRef(parsedOptions.defaultTheme);
2557
+ const _name = vue.shallowRef(parsedOptions.defaultTheme);
2541
2558
  const themes = vue.ref(parsedOptions.themes);
2559
+ const systemName = vue.shallowRef('light');
2560
+ const name = vue.computed({
2561
+ get() {
2562
+ return _name.value === 'system' ? systemName.value : _name.value;
2563
+ },
2564
+ set(val) {
2565
+ _name.value = val;
2566
+ }
2567
+ });
2542
2568
  const computedThemes = vue.computed(() => {
2543
2569
  const acc = {};
2544
2570
  for (const [name, original] of Object.entries(themes.value)) {
@@ -2559,28 +2585,49 @@
2559
2585
  const current = vue.toRef(() => computedThemes.value[name.value]);
2560
2586
  const styles = vue.computed(() => {
2561
2587
  const lines = [];
2588
+ const important = parsedOptions.unimportant ? '' : ' !important';
2589
+ const scoped = parsedOptions.scoped ? parsedOptions.prefix : '';
2562
2590
  if (current.value?.dark) {
2563
2591
  createCssClass(lines, ':root', ['color-scheme: dark'], parsedOptions.scope);
2564
2592
  }
2565
- createCssClass(lines, ':root', genCssVariables(current.value), parsedOptions.scope);
2593
+ createCssClass(lines, ':root', genCssVariables(current.value, parsedOptions.prefix), parsedOptions.scope);
2566
2594
  for (const [themeName, theme] of Object.entries(computedThemes.value)) {
2567
- createCssClass(lines, `.v-theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme)], parsedOptions.scope);
2568
- }
2569
- const bgLines = [];
2570
- const fgLines = [];
2571
- const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
2572
- for (const key of colors) {
2573
- if (key.startsWith('on-')) {
2574
- createCssClass(fgLines, `.${key}`, [`color: rgb(var(--v-theme-${key})) !important`], parsedOptions.scope);
2575
- } else {
2576
- 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);
2577
- createCssClass(fgLines, `.text-${key}`, [`color: rgb(var(--v-theme-${key})) !important`], parsedOptions.scope);
2578
- createCssClass(fgLines, `.border-${key}`, [`--v-border-color: var(--v-theme-${key})`], parsedOptions.scope);
2595
+ createCssClass(lines, `.${parsedOptions.prefix}theme--${themeName}`, [`color-scheme: ${theme.dark ? 'dark' : 'normal'}`, ...genCssVariables(theme, parsedOptions.prefix)], parsedOptions.scope);
2596
+ }
2597
+ if (parsedOptions.utilities) {
2598
+ const bgLines = [];
2599
+ const fgLines = [];
2600
+ const colors = new Set(Object.values(computedThemes.value).flatMap(theme => Object.keys(theme.colors)));
2601
+ for (const key of colors) {
2602
+ if (key.startsWith('on-')) {
2603
+ createCssClass(fgLines, `.${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
2604
+ } else {
2605
+ 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);
2606
+ createCssClass(fgLines, `.${scoped}text-${key}`, [`color: rgb(var(--${parsedOptions.prefix}theme-${key}))${important}`], parsedOptions.scope);
2607
+ createCssClass(fgLines, `.${scoped}border-${key}`, [`--${parsedOptions.prefix}border-color: var(--${parsedOptions.prefix}theme-${key})`], parsedOptions.scope);
2608
+ }
2579
2609
  }
2610
+ lines.push(...bgLines, ...fgLines);
2580
2611
  }
2581
- lines.push(...bgLines, ...fgLines);
2582
2612
  return lines.map((str, i) => i === 0 ? str : ` ${str}`).join('');
2583
2613
  });
2614
+ const themeClasses = vue.toRef(() => parsedOptions.isDisabled ? undefined : `${parsedOptions.prefix}theme--${name.value}`);
2615
+ const themeNames = vue.toRef(() => Object.keys(computedThemes.value));
2616
+ if (SUPPORTS_MATCH_MEDIA) {
2617
+ const media = window.matchMedia('(prefers-color-scheme: dark)');
2618
+ function updateSystemName() {
2619
+ systemName.value = media.matches ? 'dark' : 'light';
2620
+ }
2621
+ updateSystemName();
2622
+ media.addEventListener('change', updateSystemName, {
2623
+ passive: true
2624
+ });
2625
+ if (vue.getCurrentScope()) {
2626
+ vue.onScopeDispose(() => {
2627
+ media.removeEventListener('change', updateSystemName);
2628
+ });
2629
+ }
2630
+ }
2584
2631
  function install(app) {
2585
2632
  if (parsedOptions.isDisabled) return;
2586
2633
  const head = app._context.provides.usehead;
@@ -2618,22 +2665,55 @@
2618
2665
  updateStyles();
2619
2666
  }
2620
2667
  function updateStyles() {
2621
- upsertStyles(getOrCreateStyleElement(parsedOptions.stylesheetId, parsedOptions.cspNonce), styles.value);
2668
+ upsertStyles(parsedOptions.stylesheetId, parsedOptions.cspNonce, styles.value);
2622
2669
  }
2623
2670
  }
2624
2671
  }
2625
- const themeClasses = vue.toRef(() => parsedOptions.isDisabled ? undefined : `v-theme--${name.value}`);
2672
+ function change(themeName) {
2673
+ if (!themeNames.value.includes(themeName)) {
2674
+ consoleWarn(`Theme "${themeName}" not found on the Vuetify theme instance`);
2675
+ return;
2676
+ }
2677
+ name.value = themeName;
2678
+ }
2679
+ function cycle() {
2680
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : themeNames.value;
2681
+ const currentIndex = themeArray.indexOf(name.value);
2682
+ const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % themeArray.length;
2683
+ change(themeArray[nextIndex]);
2684
+ }
2685
+ function toggle() {
2686
+ let themeArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['light', 'dark'];
2687
+ cycle(themeArray);
2688
+ }
2689
+ const globalName = new Proxy(name, {
2690
+ get(target, prop) {
2691
+ return target[prop];
2692
+ },
2693
+ set(target, prop, val) {
2694
+ if (prop === 'value') {
2695
+ deprecate(`theme.global.name.value = ${val}`, `theme.change('${val}')`);
2696
+ }
2697
+ // @ts-expect-error
2698
+ target[prop] = val;
2699
+ return true;
2700
+ }
2701
+ });
2626
2702
  return {
2627
2703
  install,
2704
+ change,
2705
+ cycle,
2706
+ toggle,
2628
2707
  isDisabled: parsedOptions.isDisabled,
2629
2708
  name,
2630
2709
  themes,
2631
2710
  current,
2632
2711
  computedThemes,
2712
+ prefix: parsedOptions.prefix,
2633
2713
  themeClasses,
2634
2714
  styles,
2635
2715
  global: {
2636
- name,
2716
+ name: globalName,
2637
2717
  current
2638
2718
  }
2639
2719
  };
@@ -2644,7 +2724,7 @@
2644
2724
  if (!theme) throw new Error('Could not find Vuetify theme injection');
2645
2725
  const name = vue.toRef(() => props.theme ?? theme.name.value);
2646
2726
  const current = vue.toRef(() => theme.themes.value[name.value]);
2647
- const themeClasses = vue.toRef(() => theme.isDisabled ? undefined : `v-theme--${name.value}`);
2727
+ const themeClasses = vue.toRef(() => theme.isDisabled ? undefined : `${theme.prefix}theme--${name.value}`);
2648
2728
  const newTheme = {
2649
2729
  ...theme,
2650
2730
  name,
@@ -3748,7 +3828,10 @@
3748
3828
  default: 'default',
3749
3829
  validator: v => allowedDensities$1.includes(v)
3750
3830
  },
3751
- extended: Boolean,
3831
+ extended: {
3832
+ type: Boolean,
3833
+ default: null
3834
+ },
3752
3835
  extensionHeight: {
3753
3836
  type: [Number, String],
3754
3837
  default: 48
@@ -3796,7 +3879,7 @@
3796
3879
  const {
3797
3880
  rtlClasses
3798
3881
  } = useRtl();
3799
- const isExtended = vue.shallowRef(!!(props.extended || slots.extension?.()));
3882
+ const isExtended = vue.shallowRef(props.extended === null ? !!slots.extension?.() : props.extended);
3800
3883
  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));
3801
3884
  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);
3802
3885
  provideDefaults({
@@ -3808,7 +3891,7 @@
3808
3891
  const hasTitle = !!(props.title || slots.title);
3809
3892
  const hasImage = !!(slots.image || props.image);
3810
3893
  const extension = slots.extension?.();
3811
- isExtended.value = !!(props.extended || extension);
3894
+ isExtended.value = props.extended === null ? !!extension : props.extended;
3812
3895
  return vue.createVNode(props.tag, {
3813
3896
  "class": vue.normalizeClass(['v-toolbar', {
3814
3897
  'v-toolbar--absolute': props.absolute,
@@ -4191,9 +4274,15 @@
4191
4274
  };
4192
4275
  }
4193
4276
 
4277
+ // Types
4278
+
4194
4279
  const makeVBtnGroupProps = propsFactory({
4195
4280
  baseColor: String,
4196
4281
  divided: Boolean,
4282
+ direction: {
4283
+ type: String,
4284
+ default: 'horizontal'
4285
+ },
4197
4286
  ...makeBorderProps(),
4198
4287
  ...makeComponentProps(),
4199
4288
  ...makeDensityProps(),
@@ -4227,7 +4316,7 @@
4227
4316
  } = useRounded(props);
4228
4317
  provideDefaults({
4229
4318
  VBtn: {
4230
- height: 'auto',
4319
+ height: vue.toRef(() => props.direction === 'horizontal' ? 'auto' : null),
4231
4320
  baseColor: vue.toRef(() => props.baseColor),
4232
4321
  color: vue.toRef(() => props.color),
4233
4322
  density: vue.toRef(() => props.density),
@@ -4237,7 +4326,7 @@
4237
4326
  });
4238
4327
  useRender(() => {
4239
4328
  return vue.createVNode(props.tag, {
4240
- "class": vue.normalizeClass(['v-btn-group', {
4329
+ "class": vue.normalizeClass(['v-btn-group', `v-btn-group--${props.direction}`, {
4241
4330
  'v-btn-group--divided': props.divided
4242
4331
  }, themeClasses.value, borderClasses.value, densityClasses.value, elevationClasses.value, roundedClasses.value, props.class]),
4243
4332
  "style": vue.normalizeStyle(props.style)
@@ -5570,8 +5659,8 @@
5570
5659
  window.clearTimeout(element._ripple.showTimer);
5571
5660
  }
5572
5661
  let keyboardRipple = false;
5573
- function keyboardRippleShow(e) {
5574
- if (!keyboardRipple && (e.keyCode === keyCodes.enter || e.keyCode === keyCodes.space)) {
5662
+ function keyboardRippleShow(e, keys) {
5663
+ if (!keyboardRipple && keys.includes(e.keyCode)) {
5575
5664
  keyboardRipple = true;
5576
5665
  rippleShow(e);
5577
5666
  }
@@ -5599,9 +5688,12 @@
5599
5688
  el._ripple.enabled = enabled;
5600
5689
  el._ripple.centered = modifiers.center;
5601
5690
  el._ripple.circle = modifiers.circle;
5602
- if (isObject(value) && value.class) {
5603
- el._ripple.class = value.class;
5691
+ const bindingValue = isObject(value) ? value : {};
5692
+ if (bindingValue.class) {
5693
+ el._ripple.class = bindingValue.class;
5604
5694
  }
5695
+ const allowedKeys = bindingValue.keys ?? [keyCodes.enter, keyCodes.space];
5696
+ el._ripple.keyDownHandler = e => keyboardRippleShow(e, allowedKeys);
5605
5697
  if (enabled && !wasEnabled) {
5606
5698
  if (modifiers.stop) {
5607
5699
  el.addEventListener('touchstart', rippleStop, {
@@ -5623,7 +5715,7 @@
5623
5715
  el.addEventListener('mousedown', rippleShow);
5624
5716
  el.addEventListener('mouseup', rippleHide);
5625
5717
  el.addEventListener('mouseleave', rippleHide);
5626
- el.addEventListener('keydown', keyboardRippleShow);
5718
+ el.addEventListener('keydown', e => keyboardRippleShow(e, allowedKeys));
5627
5719
  el.addEventListener('keyup', keyboardRippleHide);
5628
5720
  el.addEventListener('blur', focusRippleHide);
5629
5721
 
@@ -5643,7 +5735,9 @@
5643
5735
  el.removeEventListener('touchcancel', rippleHide);
5644
5736
  el.removeEventListener('mouseup', rippleHide);
5645
5737
  el.removeEventListener('mouseleave', rippleHide);
5646
- el.removeEventListener('keydown', keyboardRippleShow);
5738
+ if (el._ripple?.keyDownHandler) {
5739
+ el.removeEventListener('keydown', el._ripple.keyDownHandler);
5740
+ }
5647
5741
  el.removeEventListener('keyup', keyboardRippleHide);
5648
5742
  el.removeEventListener('dragstart', rippleHide);
5649
5743
  el.removeEventListener('blur', focusRippleHide);
@@ -5652,8 +5746,8 @@
5652
5746
  updateRipple(el, binding, false);
5653
5747
  }
5654
5748
  function unmounted$4(el) {
5655
- delete el._ripple;
5656
5749
  removeListeners(el);
5750
+ delete el._ripple;
5657
5751
  }
5658
5752
  function updated$1(el, binding) {
5659
5753
  if (binding.value === binding.oldValue) {
@@ -5926,6 +6020,31 @@
5926
6020
  // Utilities
5927
6021
  const VAlertTitle = createSimpleFunctional('v-alert-title');
5928
6022
 
6023
+ // Utilities
6024
+
6025
+ // Types
6026
+
6027
+ // Types
6028
+
6029
+ // Composables
6030
+ const makeIconSizeProps = propsFactory({
6031
+ iconSize: [Number, String],
6032
+ iconSizes: {
6033
+ type: Array,
6034
+ default: () => [['x-small', 10], ['small', 16], ['default', 24], ['large', 28], ['x-large', 32]]
6035
+ }
6036
+ }, 'iconSize');
6037
+ function useIconSizes(props, fallback) {
6038
+ const iconSize = vue.computed(() => {
6039
+ const iconSizeMap = new Map(props.iconSizes);
6040
+ const _iconSize = props.iconSize ?? fallback() ?? 'default';
6041
+ return iconSizeMap.has(_iconSize) ? iconSizeMap.get(_iconSize) : _iconSize;
6042
+ });
6043
+ return {
6044
+ iconSize
6045
+ };
6046
+ }
6047
+
5929
6048
  // Types
5930
6049
 
5931
6050
  const allowedTypes = ['success', 'info', 'warning', 'error'];
@@ -5965,6 +6084,7 @@
5965
6084
  ...makeDensityProps(),
5966
6085
  ...makeDimensionProps(),
5967
6086
  ...makeElevationProps(),
6087
+ ...makeIconSizeProps(),
5968
6088
  ...makeLocationProps(),
5969
6089
  ...makePositionProps(),
5970
6090
  ...makeRoundedProps(),
@@ -5992,6 +6112,9 @@
5992
6112
  if (!props.type) return props.icon;
5993
6113
  return props.icon ?? `$${props.type}`;
5994
6114
  });
6115
+ const {
6116
+ iconSize
6117
+ } = useIconSizes(props, () => props.prominent ? 44 : 28);
5995
6118
  const {
5996
6119
  themeClasses
5997
6120
  } = provideTheme(props);
@@ -6039,6 +6162,11 @@
6039
6162
  const hasPrepend = !!(slots.prepend || icon.value);
6040
6163
  const hasTitle = !!(slots.title || props.title);
6041
6164
  const hasClose = !!(slots.close || props.closable);
6165
+ const iconProps = {
6166
+ density: props.density,
6167
+ icon: icon.value,
6168
+ size: iconSize.value
6169
+ };
6042
6170
  return isActive.value && vue.createVNode(props.tag, {
6043
6171
  "class": vue.normalizeClass(['v-alert', props.border && {
6044
6172
  'v-alert--border': !!props.border,
@@ -6056,19 +6184,14 @@
6056
6184
  }, null), hasPrepend && vue.createElementVNode("div", {
6057
6185
  "key": "prepend",
6058
6186
  "class": "v-alert__prepend"
6059
- }, [!slots.prepend ? vue.createVNode(VIcon, {
6060
- "key": "prepend-icon",
6061
- "density": props.density,
6062
- "icon": icon.value,
6063
- "size": props.prominent ? 44 : 28
6064
- }, null) : vue.createVNode(VDefaultsProvider, {
6187
+ }, [!slots.prepend ? vue.createVNode(VIcon, vue.mergeProps({
6188
+ "key": "prepend-icon"
6189
+ }, iconProps), null) : vue.createVNode(VDefaultsProvider, {
6065
6190
  "key": "prepend-defaults",
6066
6191
  "disabled": !icon.value,
6067
6192
  "defaults": {
6068
6193
  VIcon: {
6069
- density: props.density,
6070
- icon: icon.value,
6071
- size: props.prominent ? 44 : 28
6194
+ ...iconProps
6072
6195
  }
6073
6196
  }
6074
6197
  }, slots.prepend)]), vue.createElementVNode("div", {
@@ -7593,6 +7716,7 @@
7593
7716
  const VSlideGroupSymbol = Symbol.for('vuetify:v-slide-group');
7594
7717
  const makeVSlideGroupProps = propsFactory({
7595
7718
  centerActive: Boolean,
7719
+ contentClass: null,
7596
7720
  direction: {
7597
7721
  type: String,
7598
7722
  default: 'horizontal'
@@ -7905,7 +8029,7 @@
7905
8029
  })]), vue.createElementVNode("div", {
7906
8030
  "key": "container",
7907
8031
  "ref": containerRef,
7908
- "class": "v-slide-group__container",
8032
+ "class": vue.normalizeClass(['v-slide-group__container', props.contentClass]),
7909
8033
  "onScroll": onScroll
7910
8034
  }, [vue.createElementVNode("div", {
7911
8035
  "ref": contentRef,
@@ -8268,16 +8392,85 @@
8268
8392
  }
8269
8393
  });
8270
8394
 
8395
+ const makeVDividerProps = propsFactory({
8396
+ color: String,
8397
+ inset: Boolean,
8398
+ length: [Number, String],
8399
+ opacity: [Number, String],
8400
+ thickness: [Number, String],
8401
+ vertical: Boolean,
8402
+ ...makeComponentProps(),
8403
+ ...makeThemeProps()
8404
+ }, 'VDivider');
8405
+ const VDivider = genericComponent()({
8406
+ name: 'VDivider',
8407
+ props: makeVDividerProps(),
8408
+ setup(props, _ref) {
8409
+ let {
8410
+ attrs,
8411
+ slots
8412
+ } = _ref;
8413
+ const {
8414
+ themeClasses
8415
+ } = provideTheme(props);
8416
+ const {
8417
+ textColorClasses,
8418
+ textColorStyles
8419
+ } = useTextColor(() => props.color);
8420
+ const dividerStyles = vue.computed(() => {
8421
+ const styles = {};
8422
+ if (props.length) {
8423
+ styles[props.vertical ? 'height' : 'width'] = convertToUnit(props.length);
8424
+ }
8425
+ if (props.thickness) {
8426
+ styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
8427
+ }
8428
+ return styles;
8429
+ });
8430
+ useRender(() => {
8431
+ const divider = vue.createElementVNode("hr", {
8432
+ "class": vue.normalizeClass([{
8433
+ 'v-divider': true,
8434
+ 'v-divider--inset': props.inset,
8435
+ 'v-divider--vertical': props.vertical
8436
+ }, themeClasses.value, textColorClasses.value, props.class]),
8437
+ "style": vue.normalizeStyle([dividerStyles.value, textColorStyles.value, {
8438
+ '--v-border-opacity': props.opacity
8439
+ }, props.style]),
8440
+ "aria-orientation": !attrs.role || attrs.role === 'separator' ? props.vertical ? 'vertical' : 'horizontal' : undefined,
8441
+ "role": `${attrs.role || 'separator'}`
8442
+ }, null);
8443
+ if (!slots.default) return divider;
8444
+ return vue.createElementVNode("div", {
8445
+ "class": vue.normalizeClass(['v-divider__wrapper', {
8446
+ 'v-divider__wrapper--vertical': props.vertical,
8447
+ 'v-divider__wrapper--inset': props.inset
8448
+ }])
8449
+ }, [divider, vue.createElementVNode("div", {
8450
+ "class": "v-divider__content"
8451
+ }, [slots.default()]), divider]);
8452
+ });
8453
+ return {};
8454
+ }
8455
+ });
8456
+
8271
8457
  // Utilities
8272
8458
 
8273
8459
  // List
8274
8460
  const ListKey = Symbol.for('vuetify:list');
8275
8461
  function createList() {
8462
+ let {
8463
+ filterable
8464
+ } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
8465
+ filterable: false
8466
+ };
8276
8467
  const parent = vue.inject(ListKey, {
8468
+ filterable: false,
8277
8469
  hasPrepend: vue.shallowRef(false),
8278
8470
  updateHasPrepend: () => null
8279
8471
  });
8280
8472
  const data = {
8473
+ filterable: parent.filterable || filterable,
8281
8474
  hasPrepend: vue.shallowRef(false),
8282
8475
  updateHasPrepend: value => {
8283
8476
  if (value) data.hasPrepend.value = value;
@@ -8986,6 +9179,7 @@
8986
9179
  type: IconValue,
8987
9180
  default: '$expand'
8988
9181
  },
9182
+ rawId: [String, Number],
8989
9183
  prependIcon: IconValue,
8990
9184
  appendIcon: IconValue,
8991
9185
  fluid: Boolean,
@@ -9007,13 +9201,12 @@
9007
9201
  open,
9008
9202
  id: _id
9009
9203
  } = useNestedItem(() => props.value, true);
9010
- const id = vue.computed(() => `v-list-group--id-${String(_id.value)}`);
9204
+ const id = vue.computed(() => `v-list-group--id-${String(props.rawId ?? _id.value)}`);
9011
9205
  const list = useList();
9012
9206
  const {
9013
9207
  isBooted
9014
9208
  } = useSsrBoot();
9015
9209
  function onClick(e) {
9016
- e.stopPropagation();
9017
9210
  if (['INPUT', 'TEXTAREA'].includes(e.target?.tagName)) return;
9018
9211
  open(!isOpen.value, e);
9019
9212
  }
@@ -9229,6 +9422,9 @@
9229
9422
  roundedClasses
9230
9423
  } = useRounded(roundedProps);
9231
9424
  const lineClasses = vue.toRef(() => props.lines ? `v-list-item--${props.lines}-line` : undefined);
9425
+ const rippleOptions = vue.toRef(() => props.ripple !== undefined && !!props.ripple && list?.filterable ? {
9426
+ keys: [keyCodes.enter]
9427
+ } : props.ripple);
9232
9428
  const slotProps = vue.computed(() => ({
9233
9429
  isActive: isActive.value,
9234
9430
  select,
@@ -9253,8 +9449,9 @@
9253
9449
  function onKeyDown(e) {
9254
9450
  const target = e.target;
9255
9451
  if (['INPUT', 'TEXTAREA'].includes(target.tagName)) return;
9256
- if (e.key === 'Enter' || e.key === ' ') {
9452
+ if (e.key === 'Enter' || e.key === ' ' && !list?.filterable) {
9257
9453
  e.preventDefault();
9454
+ e.stopPropagation();
9258
9455
  e.target.dispatchEvent(new MouseEvent('click', e));
9259
9456
  }
9260
9457
  }
@@ -9364,7 +9561,7 @@
9364
9561
  }), vue.createElementVNode("div", {
9365
9562
  "class": "v-list-item__spacer"
9366
9563
  }, null)])]
9367
- }), [[Ripple, isClickable.value && props.ripple]]);
9564
+ }), [[Ripple, isClickable.value && rippleOptions.value]]);
9368
9565
  });
9369
9566
  return {
9370
9567
  activate,
@@ -9419,68 +9616,6 @@
9419
9616
  }
9420
9617
  });
9421
9618
 
9422
- const makeVDividerProps = propsFactory({
9423
- color: String,
9424
- inset: Boolean,
9425
- length: [Number, String],
9426
- opacity: [Number, String],
9427
- thickness: [Number, String],
9428
- vertical: Boolean,
9429
- ...makeComponentProps(),
9430
- ...makeThemeProps()
9431
- }, 'VDivider');
9432
- const VDivider = genericComponent()({
9433
- name: 'VDivider',
9434
- props: makeVDividerProps(),
9435
- setup(props, _ref) {
9436
- let {
9437
- attrs,
9438
- slots
9439
- } = _ref;
9440
- const {
9441
- themeClasses
9442
- } = provideTheme(props);
9443
- const {
9444
- textColorClasses,
9445
- textColorStyles
9446
- } = useTextColor(() => props.color);
9447
- const dividerStyles = vue.computed(() => {
9448
- const styles = {};
9449
- if (props.length) {
9450
- styles[props.vertical ? 'height' : 'width'] = convertToUnit(props.length);
9451
- }
9452
- if (props.thickness) {
9453
- styles[props.vertical ? 'borderRightWidth' : 'borderTopWidth'] = convertToUnit(props.thickness);
9454
- }
9455
- return styles;
9456
- });
9457
- useRender(() => {
9458
- const divider = vue.createElementVNode("hr", {
9459
- "class": vue.normalizeClass([{
9460
- 'v-divider': true,
9461
- 'v-divider--inset': props.inset,
9462
- 'v-divider--vertical': props.vertical
9463
- }, themeClasses.value, textColorClasses.value, props.class]),
9464
- "style": vue.normalizeStyle([dividerStyles.value, textColorStyles.value, {
9465
- '--v-border-opacity': props.opacity
9466
- }, props.style]),
9467
- "aria-orientation": !attrs.role || attrs.role === 'separator' ? props.vertical ? 'vertical' : 'horizontal' : undefined,
9468
- "role": `${attrs.role || 'separator'}`
9469
- }, null);
9470
- if (!slots.default) return divider;
9471
- return vue.createElementVNode("div", {
9472
- "class": vue.normalizeClass(['v-divider__wrapper', {
9473
- 'v-divider__wrapper--vertical': props.vertical,
9474
- 'v-divider__wrapper--inset': props.inset
9475
- }])
9476
- }, [divider, vue.createElementVNode("div", {
9477
- "class": "v-divider__content"
9478
- }, [slots.default()]), divider]);
9479
- });
9480
- return {};
9481
- }
9482
- });
9483
-
9484
9619
  // Types
9485
9620
 
9486
9621
  const makeVListChildrenProps = propsFactory({
@@ -9531,9 +9666,10 @@
9531
9666
  }) : undefined
9532
9667
  };
9533
9668
  const listGroupProps = VListGroup.filterProps(itemProps);
9534
- return children ? vue.createVNode(VListGroup, vue.mergeProps({
9535
- "value": itemProps?.value
9536
- }, listGroupProps), {
9669
+ return children ? vue.createVNode(VListGroup, vue.mergeProps(listGroupProps, {
9670
+ "value": props.returnObject ? item : itemProps?.value,
9671
+ "rawId": itemProps?.value
9672
+ }), {
9537
9673
  activator: _ref3 => {
9538
9674
  let {
9539
9675
  props: activatorProps
@@ -9749,6 +9885,7 @@
9749
9885
  activeClass: String,
9750
9886
  bgColor: String,
9751
9887
  disabled: Boolean,
9888
+ filterable: Boolean,
9752
9889
  expandIcon: IconValue,
9753
9890
  collapseIcon: IconValue,
9754
9891
  lines: {
@@ -9832,7 +9969,9 @@
9832
9969
  const activeColor = vue.toRef(() => props.activeColor);
9833
9970
  const baseColor = vue.toRef(() => props.baseColor);
9834
9971
  const color = vue.toRef(() => props.color);
9835
- createList();
9972
+ createList({
9973
+ filterable: props.filterable
9974
+ });
9836
9975
  provideDefaults({
9837
9976
  VListGroup: {
9838
9977
  activeColor,
@@ -11515,6 +11654,7 @@
11515
11654
  // disableKeys: Boolean,
11516
11655
  id: String,
11517
11656
  submenu: Boolean,
11657
+ disableInitialFocus: Boolean,
11518
11658
  ...omit(makeVOverlayProps({
11519
11659
  closeDelay: 250,
11520
11660
  closeOnContentClick: true,
@@ -11589,7 +11729,7 @@
11589
11729
  vue.watch(isActive, val => {
11590
11730
  if (val) {
11591
11731
  parent?.register();
11592
- if (IN_BROWSER) {
11732
+ if (IN_BROWSER && !props.disableInitialFocus) {
11593
11733
  document.addEventListener('focusin', onFocusIn, {
11594
11734
  once: true
11595
11735
  });
@@ -12426,7 +12566,12 @@
12426
12566
  }
12427
12567
  function calculateOffset(index) {
12428
12568
  index = clamp(index, 0, items.value.length - 1);
12429
- return offsets[index] || 0;
12569
+ const whole = Math.floor(index);
12570
+ const fraction = index % 1;
12571
+ const next = whole + 1;
12572
+ const wholeOffset = offsets[whole] || 0;
12573
+ const nextOffset = offsets[next] || wholeOffset;
12574
+ return wholeOffset + (nextOffset - wholeOffset) * fraction;
12430
12575
  }
12431
12576
  function calculateIndex(scrollTop) {
12432
12577
  return binaryClosest(offsets, scrollTop);
@@ -12780,6 +12925,7 @@
12780
12925
  },
12781
12926
  openOnClear: Boolean,
12782
12927
  itemColor: String,
12928
+ noAutoScroll: Boolean,
12783
12929
  ...makeItemsProps({
12784
12930
  itemChildren: false
12785
12931
  })
@@ -12994,7 +13140,7 @@
12994
13140
  vue.watch(menu, () => {
12995
13141
  if (!props.hideSelected && menu.value && model.value.length) {
12996
13142
  const index = displayItems.value.findIndex(item => model.value.some(s => (props.valueComparator || deepEqual)(s.value, item.value)));
12997
- IN_BROWSER && window.requestAnimationFrame(() => {
13143
+ IN_BROWSER && !props.noAutoScroll && window.requestAnimationFrame(() => {
12998
13144
  index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
12999
13145
  });
13000
13146
  }
@@ -13087,6 +13233,22 @@
13087
13233
  key: item.value,
13088
13234
  onClick: () => select(item, null)
13089
13235
  });
13236
+ if (item.raw.type === 'divider') {
13237
+ return slots.divider?.({
13238
+ props: item.raw,
13239
+ index
13240
+ }) ?? vue.createVNode(VDivider, vue.mergeProps(item.props, {
13241
+ "key": `divider-${index}`
13242
+ }), null);
13243
+ }
13244
+ if (item.raw.type === 'subheader') {
13245
+ return slots.subheader?.({
13246
+ props: item.raw,
13247
+ index
13248
+ }) ?? vue.createVNode(VListSubheader, vue.mergeProps(item.props, {
13249
+ "key": `subheader-${index}`
13250
+ }), null);
13251
+ }
13090
13252
  return slots.item?.({
13091
13253
  item,
13092
13254
  index,
@@ -13247,6 +13409,9 @@
13247
13409
  let match = -1;
13248
13410
  if ((query || customFiltersLength > 0) && !options?.noFilter) {
13249
13411
  if (typeof item === 'object') {
13412
+ if (['divider', 'subheader'].includes(item.raw?.type)) {
13413
+ continue;
13414
+ }
13250
13415
  const filterKeys = keys || Object.keys(transformed);
13251
13416
  for (const key of filterKeys) {
13252
13417
  const value = getPropertyFromItem(transformed, key);
@@ -13449,7 +13614,7 @@
13449
13614
  menu.value = !menu.value;
13450
13615
  }
13451
13616
  function onListKeydown(e) {
13452
- if (e.key !== ' ' && checkPrintable(e)) {
13617
+ if (checkPrintable(e) || e.key === 'Backspace') {
13453
13618
  vTextFieldRef.value?.focus();
13454
13619
  }
13455
13620
  }
@@ -13654,6 +13819,7 @@
13654
13819
  }, props.menuProps), {
13655
13820
  default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
13656
13821
  "ref": listRef,
13822
+ "filterable": true,
13657
13823
  "selected": selectedValues.value,
13658
13824
  "selectStrategy": props.multiple ? 'independent' : 'single-independent',
13659
13825
  "onMousedown": e => e.preventDefault(),
@@ -13685,6 +13851,22 @@
13685
13851
  active: highlightFirst.value && index === 0 ? true : undefined,
13686
13852
  onClick: () => select(item, null)
13687
13853
  });
13854
+ if (item.raw.type === 'divider') {
13855
+ return slots.divider?.({
13856
+ props: item.raw,
13857
+ index
13858
+ }) ?? vue.createVNode(VDivider, vue.mergeProps(item.props, {
13859
+ "key": `divider-${index}`
13860
+ }), null);
13861
+ }
13862
+ if (item.raw.type === 'subheader') {
13863
+ return slots.subheader?.({
13864
+ props: item.raw,
13865
+ index
13866
+ }) ?? vue.createVNode(VListSubheader, vue.mergeProps(item.props, {
13867
+ "key": `subheader-${index}`
13868
+ }), null);
13869
+ }
13688
13870
  return slots.item?.({
13689
13871
  item,
13690
13872
  index,
@@ -13829,7 +14011,8 @@
13829
14011
  ...makeThemeProps(),
13830
14012
  ...makeTransitionProps({
13831
14013
  transition: 'scale-rotate-transition'
13832
- })
14014
+ }),
14015
+ ...makeDimensionProps()
13833
14016
  }, 'VBadge');
13834
14017
  const VBadge = genericComponent()({
13835
14018
  name: 'VBadge',
@@ -13859,6 +14042,9 @@
13859
14042
  const base = props.floating ? props.dot ? 2 : 4 : props.dot ? 8 : 12;
13860
14043
  return base + (['top', 'bottom'].includes(side) ? Number(props.offsetY ?? 0) : ['left', 'right'].includes(side) ? Number(props.offsetX ?? 0) : 0);
13861
14044
  });
14045
+ const {
14046
+ dimensionStyles
14047
+ } = useDimension(props);
13862
14048
  useRender(() => {
13863
14049
  const value = Number(props.content);
13864
14050
  const content = !props.max || isNaN(value) ? props.content : value <= Number(props.max) ? value : `${props.max}+`;
@@ -13880,7 +14066,7 @@
13880
14066
  }, {
13881
14067
  default: () => [vue.withDirectives(vue.createElementVNode("span", vue.mergeProps({
13882
14068
  "class": ['v-badge__badge', themeClasses.value, backgroundColorClasses.value, roundedClasses.value, textColorClasses.value],
13883
- "style": [backgroundColorStyles.value, textColorStyles.value, props.inline ? {} : locationStyles.value],
14069
+ "style": [backgroundColorStyles.value, textColorStyles.value, dimensionStyles.value, props.inline ? {} : locationStyles.value],
13884
14070
  "aria-atomic": "true",
13885
14071
  "aria-label": t(props.label, value),
13886
14072
  "aria-live": "polite",
@@ -17289,13 +17475,13 @@
17289
17475
  return null;
17290
17476
  }
17291
17477
  const sundayJanuarySecond2000 = new Date(2000, 0, 2);
17292
- function getWeekdays(locale, firstDayOfWeek) {
17478
+ function getWeekdays(locale, firstDayOfWeek, weekdayFormat) {
17293
17479
  const daysFromSunday = firstDayOfWeek ?? weekInfo(locale)?.firstDay ?? 0;
17294
17480
  return createRange(7).map(i => {
17295
17481
  const weekday = new Date(sundayJanuarySecond2000);
17296
17482
  weekday.setDate(sundayJanuarySecond2000.getDate() + daysFromSunday + i);
17297
17483
  return new Intl.DateTimeFormat(locale, {
17298
- weekday: 'narrow'
17484
+ weekday: weekdayFormat ?? 'narrow'
17299
17485
  }).format(weekday);
17300
17486
  });
17301
17487
  }
@@ -17759,9 +17945,9 @@
17759
17945
  getDiff(date, comparing, unit) {
17760
17946
  return getDiff(date, comparing, unit);
17761
17947
  }
17762
- getWeekdays(firstDayOfWeek) {
17948
+ getWeekdays(firstDayOfWeek, weekdayFormat) {
17763
17949
  const firstDay = firstDayOfWeek !== undefined ? Number(firstDayOfWeek) : undefined;
17764
- return getWeekdays(this.locale, firstDay);
17950
+ return getWeekdays(this.locale, firstDay, weekdayFormat);
17765
17951
  }
17766
17952
  getYear(date) {
17767
17953
  return getYear(date);
@@ -18116,6 +18302,7 @@
18116
18302
  _search.value = val ?? '';
18117
18303
  if (!props.multiple && !hasSelectionSlot.value) {
18118
18304
  model.value = [transformItem$3(props, val)];
18305
+ vue.nextTick(() => vVirtualScrollRef.value?.scrollToIndex(0));
18119
18306
  }
18120
18307
  if (val && props.multiple && props.delimiters?.length) {
18121
18308
  const values = val.split(new RegExp(`(?:${props.delimiters.join('|')})+`));
@@ -18196,7 +18383,7 @@
18196
18383
  menu.value = !menu.value;
18197
18384
  }
18198
18385
  function onListKeydown(e) {
18199
- if (e.key !== ' ' && checkPrintable(e)) {
18386
+ if (checkPrintable(e) || e.key === 'Backspace') {
18200
18387
  vTextFieldRef.value?.focus();
18201
18388
  }
18202
18389
  }
@@ -18401,6 +18588,7 @@
18401
18588
  }, props.menuProps), {
18402
18589
  default: () => [hasList && vue.createVNode(VList, vue.mergeProps({
18403
18590
  "ref": listRef,
18591
+ "filterable": true,
18404
18592
  "selected": selectedValues.value,
18405
18593
  "selectStrategy": props.multiple ? 'independent' : 'single-independent',
18406
18594
  "onMousedown": e => e.preventDefault(),
@@ -18432,6 +18620,22 @@
18432
18620
  active: highlightFirst.value && index === 0 ? true : undefined,
18433
18621
  onClick: () => select(item, null)
18434
18622
  });
18623
+ if (item.raw.type === 'divider') {
18624
+ return slots.divider?.({
18625
+ props: item.raw,
18626
+ index
18627
+ }) ?? vue.createVNode(VDivider, vue.mergeProps(item.props, {
18628
+ "key": `divider-${index}`
18629
+ }), null);
18630
+ }
18631
+ if (item.raw.type === 'subheader') {
18632
+ return slots.subheader?.({
18633
+ props: item.raw,
18634
+ index
18635
+ }) ?? vue.createVNode(VListSubheader, vue.mergeProps(item.props, {
18636
+ "key": `subheader-${index}`
18637
+ }), null);
18638
+ }
18435
18639
  return slots.item?.({
18436
18640
  item,
18437
18641
  index,
@@ -20314,6 +20518,7 @@
20314
20518
  color: String,
20315
20519
  disableSort: Boolean,
20316
20520
  fixedHeader: Boolean,
20521
+ lastFixed: Boolean,
20317
20522
  multiSort: Boolean,
20318
20523
  sortAscIcon: {
20319
20524
  type: IconValue,
@@ -20360,10 +20565,11 @@
20360
20565
  loaderClasses
20361
20566
  } = useLoader(props);
20362
20567
  function getFixedStyles(column, y) {
20363
- if (!(props.sticky || props.fixedHeader) && !column.fixed) return undefined;
20568
+ if (!(props.sticky || props.fixedHeader) && !(column.fixed || column.lastFixed)) return undefined;
20364
20569
  return {
20365
20570
  position: 'sticky',
20366
- left: column.fixed ? convertToUnit(column.fixedOffset) : undefined,
20571
+ left: column.fixed || column.lastFixed ? convertToUnit(column.fixedOffset) : undefined,
20572
+ right: column.lastFixed ? convertToUnit(column.fixedOffset ?? 0) : undefined,
20367
20573
  top: props.sticky || props.fixedHeader ? `calc(var(--v-table-header-height) * ${y})` : undefined
20368
20574
  };
20369
20575
  }
@@ -20879,11 +21085,18 @@
20879
21085
  }
20880
21086
  });
20881
21087
 
21088
+ // Types
21089
+
20882
21090
  const makeVTableProps = propsFactory({
20883
21091
  fixedHeader: Boolean,
20884
21092
  fixedFooter: Boolean,
20885
21093
  height: [Number, String],
20886
21094
  hover: Boolean,
21095
+ striped: {
21096
+ type: String,
21097
+ default: null,
21098
+ validator: v => ['even', 'odd'].includes(v)
21099
+ },
20887
21100
  ...makeComponentProps(),
20888
21101
  ...makeDensityProps(),
20889
21102
  ...makeTagProps(),
@@ -20910,7 +21123,9 @@
20910
21123
  'v-table--fixed-footer': props.fixedFooter,
20911
21124
  'v-table--has-top': !!slots.top,
20912
21125
  'v-table--has-bottom': !!slots.bottom,
20913
- 'v-table--hover': props.hover
21126
+ 'v-table--hover': props.hover,
21127
+ 'v-table--striped-even': props.striped === 'even',
21128
+ 'v-table--striped-odd': props.striped === 'odd'
20914
21129
  }, themeClasses.value, densityClasses.value, props.class]),
20915
21130
  "style": vue.normalizeStyle(props.style)
20916
21131
  }, {
@@ -22085,7 +22300,8 @@
22085
22300
  firstDayOfWeek: {
22086
22301
  type: [Number, String],
22087
22302
  default: undefined
22088
- }
22303
+ },
22304
+ weekdayFormat: String
22089
22305
  }, 'calendar');
22090
22306
  function useCalendar(props) {
22091
22307
  const adapter = useDate();
@@ -22326,7 +22542,7 @@
22326
22542
  "ref": daysRef,
22327
22543
  "key": daysInMonth.value[0].date?.toString(),
22328
22544
  "class": "v-date-picker-month__days"
22329
- }, [!props.hideWeekdays && adapter.getWeekdays(props.firstDayOfWeek).map(weekDay => vue.createElementVNode("div", {
22545
+ }, [!props.hideWeekdays && adapter.getWeekdays(props.firstDayOfWeek, props.weekdayFormat).map(weekDay => vue.createElementVNode("div", {
22330
22546
  "class": vue.normalizeClass(['v-date-picker-month__day', 'v-date-picker-month__weekday'])
22331
22547
  }, [weekDay])), daysInMonth.value.map((item, i) => {
22332
22548
  const slotProps = {
@@ -22835,7 +23051,9 @@
22835
23051
  "max": maxDate.value,
22836
23052
  "year": year.value,
22837
23053
  "allowedMonths": allowedMonths
22838
- }), null) : viewMode.value === 'year' ? vue.createVNode(VDatePickerYears, vue.mergeProps({
23054
+ }), {
23055
+ ...pick(slots, ['month'])
23056
+ }) : viewMode.value === 'year' ? vue.createVNode(VDatePickerYears, vue.mergeProps({
22839
23057
  "key": "date-picker-years"
22840
23058
  }, datePickerYearsProps, {
22841
23059
  "modelValue": year.value,
@@ -22843,7 +23061,9 @@
22843
23061
  "min": minDate.value,
22844
23062
  "max": maxDate.value,
22845
23063
  "allowedYears": allowedYears
22846
- }), null) : vue.createVNode(VDatePickerMonth, vue.mergeProps({
23064
+ }), {
23065
+ ...pick(slots, ['year'])
23066
+ }) : vue.createVNode(VDatePickerMonth, vue.mergeProps({
22847
23067
  "key": "date-picker-month"
22848
23068
  }, datePickerMonthProps, {
22849
23069
  "modelValue": model.value,
@@ -22854,7 +23074,9 @@
22854
23074
  "onUpdate:year": [$event => year.value = $event, onUpdateYear],
22855
23075
  "min": minDate.value,
22856
23076
  "max": maxDate.value
22857
- }), null)]
23077
+ }), {
23078
+ ...pick(slots, ['day'])
23079
+ })]
22858
23080
  })]),
22859
23081
  actions: slots.actions
22860
23082
  });
@@ -23945,6 +24167,9 @@
23945
24167
  startStatus.value = status;
23946
24168
  } else if (side === 'end') {
23947
24169
  endStatus.value = status;
24170
+ } else if (side === 'both') {
24171
+ startStatus.value = status;
24172
+ endStatus.value = status;
23948
24173
  }
23949
24174
  }
23950
24175
  function getStatus(side) {
@@ -24056,6 +24281,32 @@
24056
24281
  }, [renderSide('end', endStatus.value)])]
24057
24282
  });
24058
24283
  });
24284
+ function reset(side) {
24285
+ const effectiveSide = side ?? props.side;
24286
+ setStatus(effectiveSide, 'ok');
24287
+ vue.nextTick(() => {
24288
+ setScrollAmount(getScrollSize() - previousScrollSize + getScrollAmount());
24289
+ if (props.mode !== 'manual') {
24290
+ vue.nextTick(() => {
24291
+ window.requestAnimationFrame(() => {
24292
+ window.requestAnimationFrame(() => {
24293
+ window.requestAnimationFrame(() => {
24294
+ if (effectiveSide === 'both') {
24295
+ intersecting('start');
24296
+ intersecting('end');
24297
+ } else {
24298
+ intersecting(effectiveSide);
24299
+ }
24300
+ });
24301
+ });
24302
+ });
24303
+ });
24304
+ }
24305
+ });
24306
+ }
24307
+ return {
24308
+ reset
24309
+ };
24059
24310
  }
24060
24311
  });
24061
24312
 
@@ -24135,8 +24386,47 @@
24135
24386
  }
24136
24387
  });
24137
24388
 
24138
- // Styles
24139
- const VKbd = createSimpleFunctional('v-kbd', 'kbd');
24389
+ const makeVKbdProps = propsFactory({
24390
+ ...makeBorderProps(),
24391
+ ...makeComponentProps(),
24392
+ ...makeRoundedProps(),
24393
+ ...makeTagProps({
24394
+ tag: 'kbd'
24395
+ }),
24396
+ ...makeThemeProps(),
24397
+ ...makeElevationProps(),
24398
+ color: String
24399
+ }, 'VKbd');
24400
+ const VKbd = genericComponent()({
24401
+ name: 'VKbd',
24402
+ props: makeVKbdProps(),
24403
+ setup(props, _ref) {
24404
+ let {
24405
+ slots
24406
+ } = _ref;
24407
+ const {
24408
+ themeClasses
24409
+ } = provideTheme(props);
24410
+ const {
24411
+ borderClasses
24412
+ } = useBorder(props);
24413
+ const {
24414
+ roundedClasses
24415
+ } = useRounded(props);
24416
+ const {
24417
+ backgroundColorClasses,
24418
+ backgroundColorStyles
24419
+ } = useBackgroundColor(() => props.color);
24420
+ const {
24421
+ elevationClasses
24422
+ } = useElevation(props);
24423
+ useRender(() => vue.createVNode(props.tag, {
24424
+ "class": vue.normalizeClass(['v-kbd', themeClasses.value, backgroundColorClasses.value, borderClasses.value, elevationClasses.value, roundedClasses.value, props.class]),
24425
+ "style": vue.normalizeStyle([backgroundColorStyles.value, props.style])
24426
+ }, slots));
24427
+ return {};
24428
+ }
24429
+ });
24140
24430
 
24141
24431
  const makeVLayoutProps = propsFactory({
24142
24432
  ...makeComponentProps(),
@@ -24974,6 +25264,14 @@
24974
25264
  type: Number,
24975
25265
  default: 0
24976
25266
  },
25267
+ minFractionDigits: {
25268
+ type: Number,
25269
+ default: null
25270
+ },
25271
+ decimalSeparator: {
25272
+ type: String,
25273
+ validator: v => !v || v.length === 1
25274
+ },
24977
25275
  ...omit(makeVTextFieldProps(), ['modelValue', 'validationValue'])
24978
25276
  }, 'VNumberInput');
24979
25277
  const VNumberInput = genericComponent()({
@@ -24999,11 +25297,24 @@
24999
25297
  const form = useForm(props);
25000
25298
  const controlsDisabled = vue.computed(() => form.isDisabled.value || form.isReadonly.value);
25001
25299
  const isFocused = vue.shallowRef(props.focused);
25300
+ const {
25301
+ decimalSeparator: decimalSeparatorFromLocale
25302
+ } = useLocale();
25303
+ const decimalSeparator = vue.computed(() => props.decimalSeparator?.[0] || decimalSeparatorFromLocale.value);
25002
25304
  function correctPrecision(val) {
25003
25305
  let precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.precision;
25306
+ let trim = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
25004
25307
  const fixed = precision == null ? String(val) : val.toFixed(precision);
25005
- return isFocused.value ? Number(fixed).toString() // trim zeros
25006
- : fixed;
25308
+ if (isFocused.value && trim) {
25309
+ return Number(fixed).toString() // trim zeros
25310
+ .replace('.', decimalSeparator.value);
25311
+ }
25312
+ if (props.minFractionDigits === null || precision !== null && precision < props.minFractionDigits) {
25313
+ return fixed.replace('.', decimalSeparator.value);
25314
+ }
25315
+ let [baseDigits, fractionDigits] = fixed.split('.');
25316
+ fractionDigits = (fractionDigits ?? '').padEnd(props.minFractionDigits, '0').replace(new RegExp(`(?<=\\d{${props.minFractionDigits}})0`, 'g'), '');
25317
+ return [baseDigits, fractionDigits].filter(Boolean).join(decimalSeparator.value);
25007
25318
  }
25008
25319
  const model = useProxiedModel(props, 'modelValue', null, val => val ?? null, val => val == null ? val ?? null : clamp(Number(val), props.min, props.max));
25009
25320
  const _inputText = vue.shallowRef(null);
@@ -25020,8 +25331,11 @@
25020
25331
  if (val === null || val === '') {
25021
25332
  model.value = null;
25022
25333
  _inputText.value = null;
25023
- } else if (!isNaN(Number(val)) && Number(val) <= props.max && Number(val) >= props.min) {
25024
- model.value = Number(val);
25334
+ return;
25335
+ }
25336
+ const parsedValue = Number(val.replace(decimalSeparator.value, '.'));
25337
+ if (!isNaN(parsedValue) && parsedValue <= props.max && parsedValue >= props.min) {
25338
+ model.value = parsedValue;
25025
25339
  _inputText.value = val;
25026
25340
  }
25027
25341
  }
@@ -25058,6 +25372,7 @@
25058
25372
  }
25059
25373
  };
25060
25374
  vue.watch(() => props.precision, () => formatInputValue());
25375
+ vue.watch(() => props.minFractionDigits, () => formatInputValue());
25061
25376
  vue.onMounted(() => {
25062
25377
  clampModel();
25063
25378
  });
@@ -25091,24 +25406,24 @@
25091
25406
  selectionEnd
25092
25407
  } = inputElement ?? {};
25093
25408
  const potentialNewInputVal = existingTxt ? existingTxt.slice(0, selectionStart) + e.data + existingTxt.slice(selectionEnd) : e.data;
25094
- const potentialNewNumber = extractNumber(potentialNewInputVal, props.precision);
25409
+ const potentialNewNumber = extractNumber(potentialNewInputVal, props.precision, decimalSeparator.value);
25095
25410
 
25096
- // Only numbers, "-", "." are allowed
25097
- // AND "-", "." are allowed only once
25098
- // AND "-" is only allowed at the start
25099
- if (!/^-?(\d+(\.\d*)?|(\.\d+)|\d*|\.)$/.test(potentialNewInputVal)) {
25411
+ // Allow only numbers, "-" and {decimal separator}
25412
+ // Allow "-" and {decimal separator} only once
25413
+ // Allow "-" only at the start
25414
+ if (!new RegExp(`^-?\\d*${escapeForRegex(decimalSeparator.value)}?\\d*$`).test(potentialNewInputVal)) {
25100
25415
  e.preventDefault();
25101
25416
  inputElement.value = potentialNewNumber;
25102
25417
  }
25103
25418
  if (props.precision == null) return;
25104
25419
 
25105
25420
  // Ignore decimal digits above precision limit
25106
- if (potentialNewInputVal.split('.')[1]?.length > props.precision) {
25421
+ if (potentialNewInputVal.split(decimalSeparator.value)[1]?.length > props.precision) {
25107
25422
  e.preventDefault();
25108
25423
  inputElement.value = potentialNewNumber;
25109
25424
  }
25110
25425
  // Ignore decimal separator when precision = 0
25111
- if (props.precision === 0 && potentialNewInputVal.includes('.')) {
25426
+ if (props.precision === 0 && potentialNewInputVal.includes(decimalSeparator.value)) {
25112
25427
  e.preventDefault();
25113
25428
  inputElement.value = potentialNewNumber;
25114
25429
  }
@@ -25160,19 +25475,16 @@
25160
25475
  if (controlsDisabled.value) return;
25161
25476
  if (!vTextFieldRef.value) return;
25162
25477
  const actualText = vTextFieldRef.value.value;
25163
- if (actualText && !isNaN(Number(actualText))) {
25164
- inputText.value = correctPrecision(clamp(Number(actualText), props.min, props.max));
25478
+ const parsedValue = Number(actualText.replace(decimalSeparator.value, '.'));
25479
+ if (actualText && !isNaN(parsedValue)) {
25480
+ inputText.value = correctPrecision(clamp(parsedValue, props.min, props.max));
25165
25481
  } else {
25166
25482
  inputText.value = null;
25167
25483
  }
25168
25484
  }
25169
25485
  function formatInputValue() {
25170
25486
  if (controlsDisabled.value) return;
25171
- if (model.value === null || isNaN(model.value)) {
25172
- inputText.value = null;
25173
- return;
25174
- }
25175
- inputText.value = props.precision == null ? String(model.value) : model.value.toFixed(props.precision);
25487
+ inputText.value = model.value !== null && !isNaN(model.value) ? correctPrecision(model.value, props.precision, false) : null;
25176
25488
  }
25177
25489
  function trimDecimalZeros() {
25178
25490
  if (controlsDisabled.value) return;
@@ -25180,7 +25492,7 @@
25180
25492
  inputText.value = null;
25181
25493
  return;
25182
25494
  }
25183
- inputText.value = model.value.toString();
25495
+ inputText.value = model.value.toString().replace('.', decimalSeparator.value);
25184
25496
  }
25185
25497
  function onFocus() {
25186
25498
  trimDecimalZeros();
@@ -25447,9 +25759,10 @@
25447
25759
  e.preventDefault();
25448
25760
  e.stopPropagation();
25449
25761
  const clipboardText = e?.clipboardData?.getData('Text').trim().slice(0, length.value) ?? '';
25762
+ const finalIndex = clipboardText.length - 1 === -1 ? index : clipboardText.length - 1;
25450
25763
  if (isValidNumber(clipboardText)) return;
25451
25764
  model.value = clipboardText.split('');
25452
- inputRef.value?.[index].blur();
25765
+ inputRef.value?.[finalIndex].focus();
25453
25766
  }
25454
25767
  function reset() {
25455
25768
  model.value = [];
@@ -30149,11 +30462,6 @@
30149
30462
  hideOverlay: Boolean,
30150
30463
  icon: [String, Function, Object],
30151
30464
  iconColor: String,
30152
- iconSize: [Number, String],
30153
- iconSizes: {
30154
- type: Array,
30155
- default: () => [['x-small', 10], ['small', 16], ['default', 24], ['large', 28], ['x-large', 32]]
30156
- },
30157
30465
  loading: Boolean,
30158
30466
  opacity: [Number, String],
30159
30467
  readonly: Boolean,
@@ -30173,6 +30481,7 @@
30173
30481
  ...makeBorderProps(),
30174
30482
  ...makeComponentProps(),
30175
30483
  ...makeElevationProps(),
30484
+ ...makeIconSizeProps(),
30176
30485
  ...makeRoundedProps(),
30177
30486
  ...makeTagProps({
30178
30487
  tag: 'button'
@@ -30227,7 +30536,6 @@
30227
30536
  })()
30228
30537
  }));
30229
30538
  const btnSizeMap = new Map(props.sizes);
30230
- const iconSizeMap = new Map(props.iconSizes);
30231
30539
  function onClick() {
30232
30540
  if (props.disabled || props.readonly || isActive.value === undefined || props.tag === 'a' && attrs.href) return;
30233
30541
  isActive.value = !isActive.value;
@@ -30239,12 +30547,12 @@
30239
30547
  const btnSize = hasNamedSize ? btnSizeMap.get(_btnSize) : _btnSize;
30240
30548
  const btnHeight = props.height ?? btnSize;
30241
30549
  const btnWidth = props.width ?? btnSize;
30242
- const _iconSize = props.iconSize;
30243
- const hasNamedIconSize = iconSizeMap.has(_iconSize);
30244
- const iconSize = !_iconSize ? hasNamedSize ? iconSizeMap.get(_btnSize) : iconSizeMap.get('default') : hasNamedIconSize ? iconSizeMap.get(_iconSize) : _iconSize;
30550
+ const {
30551
+ iconSize
30552
+ } = useIconSizes(props, () => new Map(props.iconSizes).get(_btnSize));
30245
30553
  const iconProps = {
30246
30554
  icon,
30247
- size: iconSize,
30555
+ size: iconSize.value,
30248
30556
  iconColor: props.iconColor,
30249
30557
  opacity: props.opacity
30250
30558
  };
@@ -30287,7 +30595,7 @@
30287
30595
  "color": typeof props.loading === 'boolean' ? undefined : props.loading,
30288
30596
  "indeterminate": "disable-shrink",
30289
30597
  "width": "2",
30290
- "size": iconSize
30598
+ "size": iconSize.value
30291
30599
  }, null)])]
30292
30600
  });
30293
30601
  });
@@ -30295,6 +30603,251 @@
30295
30603
  }
30296
30604
  });
30297
30605
 
30606
+ // Utilities
30607
+
30608
+ // Types
30609
+
30610
+ const makeMaskProps = propsFactory({
30611
+ mask: [String, Object],
30612
+ returnMaskedValue: Boolean
30613
+ }, 'mask');
30614
+ const defaultDelimiters = /[-!$%^&*()_+|~=`{}[\]:";'<>?,./\\ ]/;
30615
+ const presets = {
30616
+ 'credit-card': '#### - #### - #### - ####',
30617
+ date: '##/##/####',
30618
+ 'date-time': '##/##/#### ##:##',
30619
+ 'iso-date': '####-##-##',
30620
+ 'iso-date-time': '####-##-## ##:##',
30621
+ phone: '(###) ### - ####',
30622
+ social: '###-##-####',
30623
+ time: '##:##',
30624
+ 'time-with-seconds': '##:##:##'
30625
+ };
30626
+ function isMaskDelimiter(char) {
30627
+ return char ? defaultDelimiters.test(char) : false;
30628
+ }
30629
+ const defaultTokens = {
30630
+ '#': {
30631
+ pattern: /[0-9]/
30632
+ },
30633
+ A: {
30634
+ pattern: /[A-Z]/i,
30635
+ convert: v => v.toUpperCase()
30636
+ },
30637
+ a: {
30638
+ pattern: /[a-z]/i,
30639
+ convert: v => v.toLowerCase()
30640
+ },
30641
+ N: {
30642
+ pattern: /[0-9A-Z]/i,
30643
+ convert: v => v.toUpperCase()
30644
+ },
30645
+ n: {
30646
+ pattern: /[0-9a-z]/i,
30647
+ convert: v => v.toLowerCase()
30648
+ },
30649
+ X: {
30650
+ pattern: defaultDelimiters
30651
+ }
30652
+ };
30653
+ function useMask(props, inputRef) {
30654
+ const mask = vue.computed(() => {
30655
+ if (typeof props.mask === 'string') {
30656
+ if (props.mask in presets) return presets[props.mask];
30657
+ return props.mask;
30658
+ }
30659
+ return props.mask?.mask ?? '';
30660
+ });
30661
+ const tokens = vue.computed(() => {
30662
+ return {
30663
+ ...defaultTokens,
30664
+ ...(isObject(props.mask) ? props.mask.tokens : null)
30665
+ };
30666
+ });
30667
+ const selection = vue.shallowRef(0);
30668
+ const lazySelection = vue.shallowRef(0);
30669
+ function isMask(char) {
30670
+ return char in tokens.value;
30671
+ }
30672
+ function maskValidates(mask, char) {
30673
+ if (char == null || !isMask(mask)) return false;
30674
+ const item = tokens.value[mask];
30675
+ if (item.pattern) return item.pattern.test(char);
30676
+ return item.test(char);
30677
+ }
30678
+ function convert(mask, char) {
30679
+ const item = tokens.value[mask];
30680
+ return item.convert ? item.convert(char) : char;
30681
+ }
30682
+ function maskText(text) {
30683
+ const trimmedText = text?.trim().replace(/\s+/g, ' ');
30684
+ if (trimmedText == null) return '';
30685
+ if (!mask.value.length || !trimmedText.length) return trimmedText;
30686
+ let textIndex = 0;
30687
+ let maskIndex = 0;
30688
+ let newText = '';
30689
+ while (maskIndex < mask.value.length) {
30690
+ const mchar = mask.value[maskIndex];
30691
+ const tchar = trimmedText[textIndex];
30692
+
30693
+ // Escaped character in mask, the next mask character is inserted
30694
+ if (mchar === '\\') {
30695
+ newText += mask.value[maskIndex + 1];
30696
+ maskIndex += 2;
30697
+ continue;
30698
+ }
30699
+ if (!isMask(mchar)) {
30700
+ newText += mchar;
30701
+ if (tchar === mchar) {
30702
+ textIndex++;
30703
+ }
30704
+ } else if (maskValidates(mchar, tchar)) {
30705
+ newText += convert(mchar, tchar);
30706
+ textIndex++;
30707
+ } else {
30708
+ break;
30709
+ }
30710
+ maskIndex++;
30711
+ }
30712
+ return newText;
30713
+ }
30714
+ function unmaskText(text) {
30715
+ if (text == null) return null;
30716
+ if (!mask.value.length || !text.length) return text;
30717
+ let textIndex = 0;
30718
+ let maskIndex = 0;
30719
+ let newText = '';
30720
+ while (true) {
30721
+ const mchar = mask.value[maskIndex];
30722
+ const tchar = text[textIndex];
30723
+ if (tchar == null) break;
30724
+ if (mchar == null) {
30725
+ newText += tchar;
30726
+ textIndex++;
30727
+ continue;
30728
+ }
30729
+
30730
+ // Escaped character in mask, skip the next input character
30731
+ if (mchar === '\\') {
30732
+ if (tchar === mask.value[maskIndex + 1]) {
30733
+ textIndex++;
30734
+ }
30735
+ maskIndex += 2;
30736
+ continue;
30737
+ }
30738
+ if (maskValidates(mchar, tchar)) {
30739
+ // masked char
30740
+ newText += tchar;
30741
+ textIndex++;
30742
+ maskIndex++;
30743
+ continue;
30744
+ } else if (mchar !== tchar) {
30745
+ // input doesn't match mask, skip forward until it does
30746
+ while (true) {
30747
+ const mchar = mask.value[maskIndex++];
30748
+ if (mchar == null || maskValidates(mchar, tchar)) break;
30749
+ }
30750
+ continue;
30751
+ }
30752
+ textIndex++;
30753
+ maskIndex++;
30754
+ }
30755
+ return newText;
30756
+ }
30757
+ function setCaretPosition(newSelection) {
30758
+ selection.value = newSelection;
30759
+ inputRef.value && inputRef.value.setSelectionRange(selection.value, selection.value);
30760
+ }
30761
+ function resetSelections() {
30762
+ if (!inputRef.value?.selectionEnd) return;
30763
+ selection.value = inputRef.value.selectionEnd;
30764
+ lazySelection.value = 0;
30765
+ for (let index = 0; index < selection.value; index++) {
30766
+ isMaskDelimiter(inputRef.value.value[index]) || lazySelection.value++;
30767
+ }
30768
+ }
30769
+ function updateRange() {
30770
+ if (!inputRef.value) return;
30771
+ resetSelections();
30772
+ let selection = 0;
30773
+ const newValue = inputRef.value.value;
30774
+ if (newValue) {
30775
+ for (let index = 0; index < newValue.length; index++) {
30776
+ if (lazySelection.value <= 0) break;
30777
+ isMaskDelimiter(newValue[index]) || lazySelection.value--;
30778
+ selection++;
30779
+ }
30780
+ }
30781
+ setCaretPosition(selection);
30782
+ }
30783
+ return {
30784
+ updateRange,
30785
+ maskText,
30786
+ unmaskText
30787
+ };
30788
+ }
30789
+
30790
+ // Types
30791
+
30792
+ const makeVMaskInputProps = propsFactory({
30793
+ ...makeVTextFieldProps(),
30794
+ ...makeMaskProps()
30795
+ }, 'VMaskInput');
30796
+ const VMaskInput = genericComponent()({
30797
+ name: 'VMaskInput',
30798
+ props: makeVMaskInputProps(),
30799
+ emits: {
30800
+ 'update:modelValue': val => true
30801
+ },
30802
+ setup(props, _ref) {
30803
+ let {
30804
+ slots,
30805
+ emit
30806
+ } = _ref;
30807
+ const vTextFieldRef = vue.ref();
30808
+ const {
30809
+ maskText,
30810
+ updateRange,
30811
+ unmaskText
30812
+ } = useMask(props, vTextFieldRef);
30813
+ const returnMaskedValue = vue.computed(() => props.mask && props.returnMaskedValue);
30814
+ const model = useProxiedModel(props, 'modelValue', undefined,
30815
+ // Always display masked value in input when mask is applied
30816
+ val => props.mask ? maskText(unmaskText(val)) : val, val => {
30817
+ if (props.mask) {
30818
+ const valueBeforeChange = unmaskText(model.value);
30819
+ // E.g. mask is #-# and the input value is '2-23'
30820
+ // model-value should be enforced to '2-2'
30821
+ const enforcedMaskedValue = maskText(unmaskText(val));
30822
+ const newUnmaskedValue = unmaskText(enforcedMaskedValue);
30823
+ if (newUnmaskedValue === valueBeforeChange) {
30824
+ vTextFieldRef.value.value = enforcedMaskedValue;
30825
+ }
30826
+ val = newUnmaskedValue;
30827
+ updateRange();
30828
+ return returnMaskedValue.value ? maskText(val) : val;
30829
+ }
30830
+ return val;
30831
+ });
30832
+ vue.onBeforeMount(() => {
30833
+ if (props.returnMaskedValue) {
30834
+ emit('update:modelValue', model.value);
30835
+ }
30836
+ });
30837
+ useRender(() => {
30838
+ const textFieldProps = VTextField.filterProps(props);
30839
+ return vue.createVNode(VTextField, vue.mergeProps(textFieldProps, {
30840
+ "modelValue": model.value,
30841
+ "onUpdate:modelValue": $event => model.value = $event,
30842
+ "ref": vTextFieldRef
30843
+ }), {
30844
+ ...slots
30845
+ });
30846
+ });
30847
+ return forwardRefs({}, vTextFieldRef);
30848
+ }
30849
+ });
30850
+
30298
30851
  // Types
30299
30852
 
30300
30853
  const makeVStepperVerticalActionsProps = propsFactory({
@@ -31366,6 +31919,7 @@
31366
31919
  }
31367
31920
  function onClickAction(e) {
31368
31921
  e.preventDefault();
31922
+ e.stopPropagation();
31369
31923
  emit('toggleExpand', e);
31370
31924
  }
31371
31925
  useRender(() => {
@@ -31436,6 +31990,11 @@
31436
31990
  selectable: Boolean,
31437
31991
  selectedColor: String,
31438
31992
  selectStrategy: [String, Function, Object],
31993
+ index: Number,
31994
+ path: {
31995
+ type: Array,
31996
+ default: () => []
31997
+ },
31439
31998
  ...makeDensityProps()
31440
31999
  }, 'VTreeviewChildren');
31441
32000
  const VTreeviewChildren = genericComponent()({
@@ -31463,12 +32022,19 @@
31463
32022
  select(!isSelected);
31464
32023
  }
31465
32024
  }
31466
- return () => slots.default?.() ?? props.items?.map(item => {
32025
+ return () => slots.default?.() ?? props.items?.map((item, index) => {
31467
32026
  const {
31468
32027
  children,
31469
32028
  props: itemProps
31470
32029
  } = item;
31471
32030
  const loading = isLoading.has(item.value);
32031
+ const treeItemProps = {
32032
+ index,
32033
+ depth: props.path?.length ?? 0,
32034
+ isFirst: index === 0,
32035
+ isLast: props.items ? props.items.length - 1 === index : false,
32036
+ path: [...props.path, index]
32037
+ };
31472
32038
  const slotsWithItem = {
31473
32039
  prepend: slotProps => vue.createElementVNode(vue.Fragment, null, [props.selectable && (!children || children && !['leaf', 'single-leaf'].includes(props.selectStrategy)) && vue.createElementVNode("div", null, [vue.createVNode(VCheckboxBtn, {
31474
32040
  "key": item.value,
@@ -31489,11 +32055,13 @@
31489
32055
  }
31490
32056
  }, null)]), slots.prepend?.({
31491
32057
  ...slotProps,
32058
+ ...treeItemProps,
31492
32059
  item: item.raw,
31493
32060
  internalItem: item
31494
32061
  })]),
31495
32062
  append: slots.append ? slotProps => slots.append?.({
31496
32063
  ...slotProps,
32064
+ ...treeItemProps,
31497
32065
  item: item.raw,
31498
32066
  internalItem: item
31499
32067
  }) : undefined,
@@ -31509,9 +32077,13 @@
31509
32077
  }) : undefined
31510
32078
  };
31511
32079
  const treeviewGroupProps = VTreeviewGroup.filterProps(itemProps);
31512
- const treeviewChildrenProps = VTreeviewChildren.filterProps(props);
32080
+ const treeviewChildrenProps = VTreeviewChildren.filterProps({
32081
+ ...props,
32082
+ ...treeItemProps
32083
+ });
31513
32084
  return children ? vue.createVNode(VTreeviewGroup, vue.mergeProps(treeviewGroupProps, {
31514
- "value": props.returnObject ? item.raw : treeviewGroupProps?.value
32085
+ "value": props.returnObject ? item.raw : treeviewGroupProps?.value,
32086
+ "rawId": treeviewGroupProps?.value
31515
32087
  }), {
31516
32088
  activator: _ref2 => {
31517
32089
  let {
@@ -31559,7 +32131,7 @@
31559
32131
  ...makeFilterProps({
31560
32132
  filterKeys: ['title']
31561
32133
  }),
31562
- ...makeVTreeviewChildrenProps(),
32134
+ ...omit(makeVTreeviewChildrenProps(), ['index', 'path']),
31563
32135
  ...omit(makeVListProps({
31564
32136
  collapseIcon: '$treeviewCollapse',
31565
32137
  expandIcon: '$treeviewExpand',
@@ -31802,6 +32374,7 @@
31802
32374
  VListSubheader: VListSubheader,
31803
32375
  VLocaleProvider: VLocaleProvider,
31804
32376
  VMain: VMain,
32377
+ VMaskInput: VMaskInput,
31805
32378
  VMenu: VMenu,
31806
32379
  VMessages: VMessages,
31807
32380
  VNavigationDrawer: VNavigationDrawer,
@@ -32199,7 +32772,7 @@
32199
32772
  };
32200
32773
  });
32201
32774
  }
32202
- const version$1 = "3.8.9-master.2025-06-17";
32775
+ const version$1 = "3.8.10-dev.2025-06-18";
32203
32776
  createVuetify$1.version = version$1;
32204
32777
 
32205
32778
  // Vue's inject() can only be used in setup
@@ -32497,7 +33070,7 @@
32497
33070
 
32498
33071
  /* eslint-disable local-rules/sort-imports */
32499
33072
 
32500
- const version = "3.8.9-master.2025-06-17";
33073
+ const version = "3.8.10-dev.2025-06-18";
32501
33074
 
32502
33075
  /* eslint-disable local-rules/sort-imports */
32503
33076