vuetify 3.3.13 → 3.3.14

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 (94) hide show
  1. package/dist/json/attributes.json +70 -66
  2. package/dist/json/importMap-labs.json +4 -4
  3. package/dist/json/importMap.json +12 -12
  4. package/dist/json/tags.json +5 -4
  5. package/dist/json/web-types.json +180 -140
  6. package/dist/vuetify-labs.css +363 -304
  7. package/dist/vuetify-labs.d.ts +384 -236
  8. package/dist/vuetify-labs.esm.js +410 -297
  9. package/dist/vuetify-labs.esm.js.map +1 -1
  10. package/dist/vuetify-labs.js +409 -296
  11. package/dist/vuetify-labs.min.css +2 -2
  12. package/dist/vuetify.css +291 -232
  13. package/dist/vuetify.d.ts +232 -76
  14. package/dist/vuetify.esm.js +210 -160
  15. package/dist/vuetify.esm.js.map +1 -1
  16. package/dist/vuetify.js +209 -159
  17. package/dist/vuetify.js.map +1 -1
  18. package/dist/vuetify.min.css +2 -2
  19. package/dist/vuetify.min.js +838 -827
  20. package/dist/vuetify.min.js.map +1 -1
  21. package/lib/components/VAppBar/VAppBar.mjs.map +1 -1
  22. package/lib/components/VAppBar/index.d.mts +6 -6
  23. package/lib/components/VAutocomplete/VAutocomplete.mjs +12 -2
  24. package/lib/components/VAutocomplete/VAutocomplete.mjs.map +1 -1
  25. package/lib/components/VBadge/VBadge.css +1 -1
  26. package/lib/components/VBadge/_variables.scss +1 -1
  27. package/lib/components/VCheckbox/VCheckbox.mjs +2 -2
  28. package/lib/components/VCheckbox/VCheckbox.mjs.map +1 -1
  29. package/lib/components/VCheckbox/VCheckboxBtn.mjs +14 -11
  30. package/lib/components/VCheckbox/VCheckboxBtn.mjs.map +1 -1
  31. package/lib/components/VColorPicker/VColorPickerEdit.css +4 -2
  32. package/lib/components/VColorPicker/VColorPickerPreview.css +11 -6
  33. package/lib/components/VCombobox/VCombobox.mjs +11 -1
  34. package/lib/components/VCombobox/VCombobox.mjs.map +1 -1
  35. package/lib/components/VField/VField.css +22 -7
  36. package/lib/components/VField/VField.sass +8 -1
  37. package/lib/components/VField/_variables.scss +1 -0
  38. package/lib/components/VGrid/VGrid.css +153 -142
  39. package/lib/components/VProgressLinear/VProgressLinear.css +3 -2
  40. package/lib/components/VRadioGroup/VRadioGroup.mjs +2 -2
  41. package/lib/components/VRadioGroup/VRadioGroup.mjs.map +1 -1
  42. package/lib/components/VRangeSlider/index.d.mts +114 -33
  43. package/lib/components/VSelect/VSelect.mjs +12 -2
  44. package/lib/components/VSelect/VSelect.mjs.map +1 -1
  45. package/lib/components/VSelectionControl/VSelectionControl.mjs +2 -1
  46. package/lib/components/VSelectionControl/VSelectionControl.mjs.map +1 -1
  47. package/lib/components/VSlider/VSlider.mjs.map +1 -1
  48. package/lib/components/VSlider/VSliderThumb.css +8 -4
  49. package/lib/components/VSlider/VSliderTrack.css +22 -12
  50. package/lib/components/VSlider/index.d.mts +114 -33
  51. package/lib/components/VSwitch/VSwitch.mjs +9 -9
  52. package/lib/components/VSwitch/VSwitch.mjs.map +1 -1
  53. package/lib/components/VTimeline/VTimeline.css +19 -10
  54. package/lib/components/VTimeline/VTimeline.sass +5 -0
  55. package/lib/components/VToolbar/VToolbar.css +4 -2
  56. package/lib/components/index.d.mts +228 -72
  57. package/lib/composables/color.mjs +6 -1
  58. package/lib/composables/color.mjs.map +1 -1
  59. package/lib/composables/defaults.mjs +9 -9
  60. package/lib/composables/defaults.mjs.map +1 -1
  61. package/lib/composables/theme.mjs +2 -5
  62. package/lib/composables/theme.mjs.map +1 -1
  63. package/lib/entry-bundler.mjs +1 -1
  64. package/lib/framework.mjs +1 -1
  65. package/lib/index.d.mts +4 -4
  66. package/lib/labs/VDateInput/index.d.mts +2 -2
  67. package/lib/labs/VDatePicker/VDateCard.mjs +3 -0
  68. package/lib/labs/VDatePicker/VDateCard.mjs.map +1 -1
  69. package/lib/labs/VDatePicker/VDatePicker.mjs +51 -21
  70. package/lib/labs/VDatePicker/VDatePicker.mjs.map +1 -1
  71. package/lib/labs/VDatePicker/VDatePickerControls.css +1 -1
  72. package/lib/labs/VDatePicker/VDatePickerControls.mjs +53 -35
  73. package/lib/labs/VDatePicker/VDatePickerControls.mjs.map +1 -1
  74. package/lib/labs/VDatePicker/VDatePickerMonth.mjs +37 -28
  75. package/lib/labs/VDatePicker/VDatePickerMonth.mjs.map +1 -1
  76. package/lib/labs/VDatePicker/VDatePickerYears.mjs +19 -17
  77. package/lib/labs/VDatePicker/VDatePickerYears.mjs.map +1 -1
  78. package/lib/labs/VDatePicker/index.d.mts +148 -156
  79. package/lib/labs/VDateRangePicker/VDateRangeCard.mjs +3 -0
  80. package/lib/labs/VDateRangePicker/VDateRangeCard.mjs.map +1 -1
  81. package/lib/labs/VDateRangePicker/index.d.mts +59 -52
  82. package/lib/labs/VSkeletonLoader/VSkeletonLoader.mjs.map +1 -1
  83. package/lib/labs/VSkeletonLoader/index.d.mts +8 -8
  84. package/lib/labs/components.d.mts +156 -164
  85. package/lib/locale/no.mjs +1 -1
  86. package/lib/locale/no.mjs.map +1 -1
  87. package/lib/styles/tools/_rtl.sass +4 -2
  88. package/lib/util/colorUtils.mjs +6 -0
  89. package/lib/util/colorUtils.mjs.map +1 -1
  90. package/lib/util/helpers.mjs +10 -4
  91. package/lib/util/helpers.mjs.map +1 -1
  92. package/lib/util/injectSelf.mjs +2 -1
  93. package/lib/util/injectSelf.mjs.map +1 -1
  94. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.3.13
2
+ * Vuetify v3.3.14
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
@@ -233,14 +233,22 @@
233
233
  include.forEach(prop => clone[prop] = obj[prop]);
234
234
  return clone;
235
235
  }
236
+ const onRE = /^on[^a-z]/;
237
+ const isOn = key => onRE.test(key);
238
+ const bubblingEvents = ['onAfterscriptexecute', 'onAnimationcancel', 'onAnimationend', 'onAnimationiteration', 'onAnimationstart', 'onAuxclick', 'onBeforeinput', 'onBeforescriptexecute', 'onChange', 'onClick', 'onCompositionend', 'onCompositionstart', 'onCompositionupdate', 'onContextmenu', 'onCopy', 'onCut', 'onDblclick', 'onFocusin', 'onFocusout', 'onFullscreenchange', 'onFullscreenerror', 'onGesturechange', 'onGestureend', 'onGesturestart', 'onGotpointercapture', 'onInput', 'onKeydown', 'onKeypress', 'onKeyup', 'onLostpointercapture', 'onMousedown', 'onMousemove', 'onMouseout', 'onMouseover', 'onMouseup', 'onMousewheel', 'onPaste', 'onPointercancel', 'onPointerdown', 'onPointerenter', 'onPointerleave', 'onPointermove', 'onPointerout', 'onPointerover', 'onPointerup', 'onReset', 'onSelect', 'onSubmit', 'onTouchcancel', 'onTouchend', 'onTouchmove', 'onTouchstart', 'onTransitioncancel', 'onTransitionend', 'onTransitionrun', 'onTransitionstart', 'onWheel'];
236
239
 
237
240
  /**
238
241
  * Filter attributes that should be applied to
239
- * the root element of a an input component. Remaining
242
+ * the root element of an input component. Remaining
240
243
  * attributes should be passed to the <input> element inside.
241
244
  */
242
245
  function filterInputAttrs(attrs) {
243
- return pick(attrs, ['class', 'style', 'id', /^data-/]);
246
+ const [events, props] = pick(attrs, [onRE]);
247
+ const inputEvents = omit(events, bubblingEvents);
248
+ const [rootAttrs, inputAttrs] = pick(props, ['class', 'style', 'id', /^data-/]);
249
+ Object.assign(rootAttrs, events);
250
+ Object.assign(inputAttrs, inputEvents);
251
+ return [rootAttrs, inputAttrs];
244
252
  }
245
253
  function wrapInArray(v) {
246
254
  return v == null ? [] : Array.isArray(v) ? v : [v];
@@ -393,8 +401,6 @@
393
401
  function includes(arr, val) {
394
402
  return arr.includes(val);
395
403
  }
396
- const onRE = /^on[^a-z]/;
397
- const isOn = key => onRE.test(key);
398
404
  function eventName(propName) {
399
405
  return propName[2].toLowerCase() + propName.slice(3);
400
406
  }
@@ -664,6 +670,94 @@
664
670
  });
665
671
  }
666
672
 
673
+ /**
674
+ * WCAG 3.0 APCA perceptual contrast algorithm from https://github.com/Myndex/SAPC-APCA
675
+ * @licence https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
676
+ * @see https://www.w3.org/WAI/GL/task-forces/silver/wiki/Visual_Contrast_of_Text_Subgroup
677
+ */
678
+ // Types
679
+
680
+ // MAGICAL NUMBERS
681
+
682
+ // sRGB Conversion to Relative Luminance (Y)
683
+
684
+ // Transfer Curve (aka "Gamma") for sRGB linearization
685
+ // Simple power curve vs piecewise described in docs
686
+ // Essentially, 2.4 best models actual display
687
+ // characteristics in combination with the total method
688
+ const mainTRC = 2.4;
689
+ const Rco = 0.2126729; // sRGB Red Coefficient (from matrix)
690
+ const Gco = 0.7151522; // sRGB Green Coefficient (from matrix)
691
+ const Bco = 0.0721750; // sRGB Blue Coefficient (from matrix)
692
+
693
+ // For Finding Raw SAPC Contrast from Relative Luminance (Y)
694
+
695
+ // Constants for SAPC Power Curve Exponents
696
+ // One pair for normal text, and one for reverse
697
+ // These are the "beating heart" of SAPC
698
+ const normBG = 0.55;
699
+ const normTXT = 0.58;
700
+ const revTXT = 0.57;
701
+ const revBG = 0.62;
702
+
703
+ // For Clamping and Scaling Values
704
+
705
+ const blkThrs = 0.03; // Level that triggers the soft black clamp
706
+ const blkClmp = 1.45; // Exponent for the soft black clamp curve
707
+ const deltaYmin = 0.0005; // Lint trap
708
+ const scaleBoW = 1.25; // Scaling for dark text on light
709
+ const scaleWoB = 1.25; // Scaling for light text on dark
710
+ const loConThresh = 0.078; // Threshold for new simple offset scale
711
+ const loConFactor = 12.82051282051282; // = 1/0.078,
712
+ const loConOffset = 0.06; // The simple offset
713
+ const loClip = 0.001; // Output clip (lint trap #2)
714
+
715
+ function APCAcontrast(text, background) {
716
+ // Linearize sRGB
717
+ const Rtxt = (text.r / 255) ** mainTRC;
718
+ const Gtxt = (text.g / 255) ** mainTRC;
719
+ const Btxt = (text.b / 255) ** mainTRC;
720
+ const Rbg = (background.r / 255) ** mainTRC;
721
+ const Gbg = (background.g / 255) ** mainTRC;
722
+ const Bbg = (background.b / 255) ** mainTRC;
723
+
724
+ // Apply the standard coefficients and sum to Y
725
+ let Ytxt = Rtxt * Rco + Gtxt * Gco + Btxt * Bco;
726
+ let Ybg = Rbg * Rco + Gbg * Gco + Bbg * Bco;
727
+
728
+ // Soft clamp Y when near black.
729
+ // Now clamping all colors to prevent crossover errors
730
+ if (Ytxt <= blkThrs) Ytxt += (blkThrs - Ytxt) ** blkClmp;
731
+ if (Ybg <= blkThrs) Ybg += (blkThrs - Ybg) ** blkClmp;
732
+
733
+ // Return 0 Early for extremely low ∆Y (lint trap #1)
734
+ if (Math.abs(Ybg - Ytxt) < deltaYmin) return 0.0;
735
+
736
+ // SAPC CONTRAST
737
+
738
+ let outputContrast; // For weighted final values
739
+ if (Ybg > Ytxt) {
740
+ // For normal polarity, black text on white
741
+ // Calculate the SAPC contrast value and scale
742
+
743
+ const SAPC = (Ybg ** normBG - Ytxt ** normTXT) * scaleBoW;
744
+
745
+ // NEW! SAPC SmoothScale™
746
+ // Low Contrast Smooth Scale Rollout to prevent polarity reversal
747
+ // and also a low clip for very low contrasts (lint trap #2)
748
+ // much of this is for very low contrasts, less than 10
749
+ // therefore for most reversing needs, only loConOffset is important
750
+ outputContrast = SAPC < loClip ? 0.0 : SAPC < loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC - loConOffset;
751
+ } else {
752
+ // For reverse polarity, light text on dark
753
+ // WoB should always return negative value.
754
+
755
+ const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB;
756
+ outputContrast = SAPC > -loClip ? 0.0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
757
+ }
758
+ return outputContrast * 100;
759
+ }
760
+
667
761
  /* eslint-disable no-console */
668
762
 
669
763
  function consoleWarn(message) {
@@ -1020,36 +1114,13 @@
1020
1114
  const dark = Math.min(l1, l2);
1021
1115
  return (light + 0.05) / (dark + 0.05);
1022
1116
  }
1023
-
1024
- // Utilities
1025
-
1026
- // Types
1027
-
1028
- function useToggleScope(source, fn) {
1029
- let scope;
1030
- function start() {
1031
- scope = vue.effectScope();
1032
- scope.run(() => fn.length ? fn(() => {
1033
- scope?.stop();
1034
- start();
1035
- }) : fn());
1036
- }
1037
- vue.watch(source, active => {
1038
- if (active && !scope) {
1039
- start();
1040
- } else if (!active) {
1041
- scope?.stop();
1042
- scope = undefined;
1043
- }
1044
- }, {
1045
- immediate: true
1046
- });
1047
- vue.onScopeDispose(() => {
1048
- scope?.stop();
1049
- });
1117
+ function getForeground(color) {
1118
+ const blackContrast = Math.abs(APCAcontrast(parseColor(0), parseColor(color)));
1119
+ const whiteContrast = Math.abs(APCAcontrast(parseColor(0xffffff), parseColor(color)));
1120
+ return whiteContrast > Math.min(blackContrast, 50) ? '#fff' : '#000';
1050
1121
  }
1051
1122
 
1052
- // Composables
1123
+ // Utilities
1053
1124
 
1054
1125
  // Types
1055
1126
 
@@ -1071,6 +1142,7 @@
1071
1142
  const scoped = vue.unref(options?.scoped);
1072
1143
  const reset = vue.unref(options?.reset);
1073
1144
  const root = vue.unref(options?.root);
1145
+ if (providedDefaults.value == null && !(scoped || reset || root)) return injectedDefaults.value;
1074
1146
  let properties = mergeDeep(providedDefaults.value, {
1075
1147
  prev: injectedDefaults.value
1076
1148
  });
@@ -1126,16 +1198,16 @@
1126
1198
  let [key] = _ref;
1127
1199
  return key.startsWith(key[0].toUpperCase());
1128
1200
  });
1129
- if (subComponents.length) _subcomponentDefaults.value = Object.fromEntries(subComponents);
1201
+ _subcomponentDefaults.value = subComponents.length ? Object.fromEntries(subComponents) : undefined;
1202
+ } else {
1203
+ _subcomponentDefaults.value = undefined;
1130
1204
  }
1131
1205
  });
1132
1206
  function provideSubDefaults() {
1133
- // If subcomponent defaults are provided, override any
1134
- // subcomponents provided by the component's setup function.
1135
- // This uses injectSelf so must be done after the original setup to work.
1136
- useToggleScope(_subcomponentDefaults, () => {
1137
- provideDefaults(mergeDeep(injectSelf(DefaultsSymbol)?.value ?? {}, _subcomponentDefaults.value));
1138
- });
1207
+ const injected = injectSelf(DefaultsSymbol, vm);
1208
+ vue.provide(DefaultsSymbol, vue.computed(() => {
1209
+ return _subcomponentDefaults.value ? mergeDeep(injected?.value ?? {}, _subcomponentDefaults.value) : injected?.value;
1210
+ }));
1139
1211
  }
1140
1212
  return {
1141
1213
  props: _props,
@@ -1317,9 +1389,10 @@
1317
1389
  // Types
1318
1390
 
1319
1391
  function injectSelf(key) {
1392
+ let vm = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getCurrentInstance('injectSelf');
1320
1393
  const {
1321
1394
  provides
1322
- } = getCurrentInstance('injectSelf');
1395
+ } = vm;
1323
1396
  if (provides && key in provides) {
1324
1397
  // TS doesn't allow symbol as index type
1325
1398
  return provides[key];
@@ -1796,6 +1869,34 @@
1796
1869
  zhHant: false
1797
1870
  };
1798
1871
 
1872
+ // Utilities
1873
+
1874
+ // Types
1875
+
1876
+ function useToggleScope(source, fn) {
1877
+ let scope;
1878
+ function start() {
1879
+ scope = vue.effectScope();
1880
+ scope.run(() => fn.length ? fn(() => {
1881
+ scope?.stop();
1882
+ start();
1883
+ }) : fn());
1884
+ }
1885
+ vue.watch(source, active => {
1886
+ if (active && !scope) {
1887
+ start();
1888
+ } else if (!active) {
1889
+ scope?.stop();
1890
+ scope = undefined;
1891
+ }
1892
+ }, {
1893
+ immediate: true
1894
+ });
1895
+ vue.onScopeDispose(() => {
1896
+ scope?.stop();
1897
+ });
1898
+ }
1899
+
1799
1900
  // Composables
1800
1901
 
1801
1902
  // Types
@@ -1997,94 +2098,6 @@
1997
2098
  };
1998
2099
  }
1999
2100
 
2000
- /**
2001
- * WCAG 3.0 APCA perceptual contrast algorithm from https://github.com/Myndex/SAPC-APCA
2002
- * @licence https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
2003
- * @see https://www.w3.org/WAI/GL/task-forces/silver/wiki/Visual_Contrast_of_Text_Subgroup
2004
- */
2005
- // Types
2006
-
2007
- // MAGICAL NUMBERS
2008
-
2009
- // sRGB Conversion to Relative Luminance (Y)
2010
-
2011
- // Transfer Curve (aka "Gamma") for sRGB linearization
2012
- // Simple power curve vs piecewise described in docs
2013
- // Essentially, 2.4 best models actual display
2014
- // characteristics in combination with the total method
2015
- const mainTRC = 2.4;
2016
- const Rco = 0.2126729; // sRGB Red Coefficient (from matrix)
2017
- const Gco = 0.7151522; // sRGB Green Coefficient (from matrix)
2018
- const Bco = 0.0721750; // sRGB Blue Coefficient (from matrix)
2019
-
2020
- // For Finding Raw SAPC Contrast from Relative Luminance (Y)
2021
-
2022
- // Constants for SAPC Power Curve Exponents
2023
- // One pair for normal text, and one for reverse
2024
- // These are the "beating heart" of SAPC
2025
- const normBG = 0.55;
2026
- const normTXT = 0.58;
2027
- const revTXT = 0.57;
2028
- const revBG = 0.62;
2029
-
2030
- // For Clamping and Scaling Values
2031
-
2032
- const blkThrs = 0.03; // Level that triggers the soft black clamp
2033
- const blkClmp = 1.45; // Exponent for the soft black clamp curve
2034
- const deltaYmin = 0.0005; // Lint trap
2035
- const scaleBoW = 1.25; // Scaling for dark text on light
2036
- const scaleWoB = 1.25; // Scaling for light text on dark
2037
- const loConThresh = 0.078; // Threshold for new simple offset scale
2038
- const loConFactor = 12.82051282051282; // = 1/0.078,
2039
- const loConOffset = 0.06; // The simple offset
2040
- const loClip = 0.001; // Output clip (lint trap #2)
2041
-
2042
- function APCAcontrast(text, background) {
2043
- // Linearize sRGB
2044
- const Rtxt = (text.r / 255) ** mainTRC;
2045
- const Gtxt = (text.g / 255) ** mainTRC;
2046
- const Btxt = (text.b / 255) ** mainTRC;
2047
- const Rbg = (background.r / 255) ** mainTRC;
2048
- const Gbg = (background.g / 255) ** mainTRC;
2049
- const Bbg = (background.b / 255) ** mainTRC;
2050
-
2051
- // Apply the standard coefficients and sum to Y
2052
- let Ytxt = Rtxt * Rco + Gtxt * Gco + Btxt * Bco;
2053
- let Ybg = Rbg * Rco + Gbg * Gco + Bbg * Bco;
2054
-
2055
- // Soft clamp Y when near black.
2056
- // Now clamping all colors to prevent crossover errors
2057
- if (Ytxt <= blkThrs) Ytxt += (blkThrs - Ytxt) ** blkClmp;
2058
- if (Ybg <= blkThrs) Ybg += (blkThrs - Ybg) ** blkClmp;
2059
-
2060
- // Return 0 Early for extremely low ∆Y (lint trap #1)
2061
- if (Math.abs(Ybg - Ytxt) < deltaYmin) return 0.0;
2062
-
2063
- // SAPC CONTRAST
2064
-
2065
- let outputContrast; // For weighted final values
2066
- if (Ybg > Ytxt) {
2067
- // For normal polarity, black text on white
2068
- // Calculate the SAPC contrast value and scale
2069
-
2070
- const SAPC = (Ybg ** normBG - Ytxt ** normTXT) * scaleBoW;
2071
-
2072
- // NEW! SAPC SmoothScale™
2073
- // Low Contrast Smooth Scale Rollout to prevent polarity reversal
2074
- // and also a low clip for very low contrasts (lint trap #2)
2075
- // much of this is for very low contrasts, less than 10
2076
- // therefore for most reversing needs, only loConOffset is important
2077
- outputContrast = SAPC < loClip ? 0.0 : SAPC < loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC - loConOffset;
2078
- } else {
2079
- // For reverse polarity, light text on dark
2080
- // WoB should always return negative value.
2081
-
2082
- const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB;
2083
- outputContrast = SAPC > -loClip ? 0.0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset;
2084
- }
2085
- return outputContrast * 100;
2086
- }
2087
-
2088
2101
  // Utilities
2089
2102
 
2090
2103
  // Types
@@ -2220,8 +2233,6 @@
2220
2233
  if (/^on-[a-z]/.test(color) || theme.colors[`on-${color}`]) continue;
2221
2234
  const onColor = `on-${color}`;
2222
2235
  const colorVal = parseColor(theme.colors[color]);
2223
- const blackContrast = Math.abs(APCAcontrast(parseColor(0), colorVal));
2224
- const whiteContrast = Math.abs(APCAcontrast(parseColor(0xffffff), colorVal));
2225
2236
 
2226
2237
  // TODO: warn about poor color selections
2227
2238
  // const contrastAsText = Math.abs(APCAcontrast(colorVal, colorToInt(theme.colors.background)))
@@ -2233,7 +2244,7 @@
2233
2244
  // }
2234
2245
 
2235
2246
  // Prefer white text if both have an acceptable contrast ratio
2236
- theme.colors[onColor] = whiteContrast > Math.min(blackContrast, 50) ? '#fff' : '#000';
2247
+ theme.colors[onColor] = getForeground(colorVal);
2237
2248
  }
2238
2249
  }
2239
2250
  return acc;
@@ -3262,6 +3273,11 @@
3262
3273
  if (colors.value.background) {
3263
3274
  if (isCssColor(colors.value.background)) {
3264
3275
  styles.backgroundColor = colors.value.background;
3276
+ if (!colors.value.text) {
3277
+ const textColor = getForeground(styles.backgroundColor);
3278
+ styles.color = textColor;
3279
+ styles.caretColor = textColor;
3280
+ }
3265
3281
  } else {
3266
3282
  classes.push(`bg-${colors.value.background}`);
3267
3283
  }
@@ -5907,7 +5923,8 @@
5907
5923
  "icon": icon.value
5908
5924
  }, null), inputNode])]), [[vue.resolveDirective("ripple"), props.ripple && [!props.disabled && !props.readonly, null, ['center', 'circle']]]])]), label && vue.createVNode(VLabel, {
5909
5925
  "for": id.value,
5910
- "clickable": true
5926
+ "clickable": true,
5927
+ "onClick": e => e.stopPropagation()
5911
5928
  }, {
5912
5929
  default: () => [label]
5913
5930
  })]);
@@ -5956,16 +5973,19 @@
5956
5973
  const trueIcon = vue.computed(() => {
5957
5974
  return indeterminate.value ? props.indeterminateIcon : props.trueIcon;
5958
5975
  });
5959
- useRender(() => vue.createVNode(VSelectionControl, vue.mergeProps(props, {
5960
- "modelValue": model.value,
5961
- "onUpdate:modelValue": [$event => model.value = $event, onChange],
5962
- "class": ['v-checkbox-btn', props.class],
5963
- "style": props.style,
5964
- "type": "checkbox",
5965
- "falseIcon": falseIcon.value,
5966
- "trueIcon": trueIcon.value,
5967
- "aria-checked": indeterminate.value ? 'mixed' : undefined
5968
- }), slots));
5976
+ useRender(() => {
5977
+ const controlProps = omit(VSelectionControl.filterProps(props)[0], ['modelValue']);
5978
+ return vue.createVNode(VSelectionControl, vue.mergeProps(controlProps, {
5979
+ "modelValue": model.value,
5980
+ "onUpdate:modelValue": [$event => model.value = $event, onChange],
5981
+ "class": ['v-checkbox-btn', props.class],
5982
+ "style": props.style,
5983
+ "type": "checkbox",
5984
+ "falseIcon": falseIcon.value,
5985
+ "trueIcon": trueIcon.value,
5986
+ "aria-checked": indeterminate.value ? 'mixed' : undefined
5987
+ }), slots);
5988
+ });
5969
5989
  return {};
5970
5990
  }
5971
5991
  });
@@ -6529,12 +6549,12 @@
6529
6549
  const uid = getUid();
6530
6550
  const id = vue.computed(() => props.id || `checkbox-${uid}`);
6531
6551
  useRender(() => {
6532
- const [inputAttrs, controlAttrs] = filterInputAttrs(attrs);
6552
+ const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
6533
6553
  const [inputProps, _1] = VInput.filterProps(props);
6534
6554
  const [checkboxProps, _2] = VCheckboxBtn.filterProps(props);
6535
6555
  return vue.createVNode(VInput, vue.mergeProps({
6536
6556
  "class": ['v-checkbox', props.class]
6537
- }, inputAttrs, inputProps, {
6557
+ }, rootAttrs, inputProps, {
6538
6558
  "modelValue": model.value,
6539
6559
  "onUpdate:modelValue": $event => model.value = $event,
6540
6560
  "id": id.value,
@@ -10862,6 +10882,7 @@
10862
10882
  } = useLocale();
10863
10883
  const vTextFieldRef = vue.ref();
10864
10884
  const vMenuRef = vue.ref();
10885
+ const vVirtualScrollRef = vue.ref();
10865
10886
  const _menu = useProxiedModel(props, 'menu');
10866
10887
  const menu = vue.computed({
10867
10888
  get: () => _menu.value,
@@ -10991,6 +11012,14 @@
10991
11012
  vTextFieldRef.value.value = '';
10992
11013
  }
10993
11014
  }
11015
+ vue.watch(menu, () => {
11016
+ if (!props.hideSelected && menu.value && selections.value.length) {
11017
+ const index = displayItems.value.findIndex(item => selections.value.some(s => item.value === s.value));
11018
+ IN_BROWSER && window.requestAnimationFrame(() => {
11019
+ index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
11020
+ });
11021
+ }
11022
+ });
10994
11023
  useRender(() => {
10995
11024
  const hasChips = !!(props.chips || slots.chip);
10996
11025
  const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
@@ -11052,6 +11081,7 @@
11052
11081
  default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
11053
11082
  "title": t(props.noDataText)
11054
11083
  }, null)), vue.createVNode(VVirtualScroll, {
11084
+ "ref": vVirtualScrollRef,
11055
11085
  "renderless": true,
11056
11086
  "items": displayItems.value
11057
11087
  }, {
@@ -11312,6 +11342,7 @@
11312
11342
  const isPristine = vue.shallowRef(true);
11313
11343
  const listHasFocus = vue.shallowRef(false);
11314
11344
  const vMenuRef = vue.ref();
11345
+ const vVirtualScrollRef = vue.ref();
11315
11346
  const _menu = useProxiedModel(props, 'menu');
11316
11347
  const menu = vue.computed({
11317
11348
  get: () => _menu.value,
@@ -11402,7 +11433,7 @@
11402
11433
  menu.value = false;
11403
11434
  }
11404
11435
  if (highlightFirst.value && ['Enter', 'Tab'].includes(e.key)) {
11405
- select(filteredItems.value[0]);
11436
+ select(displayItems.value[0]);
11406
11437
  }
11407
11438
  if (e.key === 'ArrowDown' && highlightFirst.value) {
11408
11439
  listRef.value?.focus('next');
@@ -11515,6 +11546,14 @@
11515
11546
  if (val) menu.value = true;
11516
11547
  isPristine.value = !val;
11517
11548
  });
11549
+ vue.watch(menu, () => {
11550
+ if (!props.hideSelected && menu.value && selections.value.length) {
11551
+ const index = displayItems.value.findIndex(item => selections.value.some(s => item.value === s.value));
11552
+ IN_BROWSER && window.requestAnimationFrame(() => {
11553
+ index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
11554
+ });
11555
+ }
11556
+ });
11518
11557
  useRender(() => {
11519
11558
  const hasChips = !!(props.chips || slots.chip);
11520
11559
  const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
@@ -11574,6 +11613,7 @@
11574
11613
  default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
11575
11614
  "title": t(props.noDataText)
11576
11615
  }, null)), vue.createVNode(VVirtualScroll, {
11616
+ "ref": vVirtualScrollRef,
11577
11617
  "renderless": true,
11578
11618
  "items": displayItems.value
11579
11619
  }, {
@@ -14845,6 +14885,7 @@
14845
14885
  const isPristine = vue.shallowRef(true);
14846
14886
  const listHasFocus = vue.shallowRef(false);
14847
14887
  const vMenuRef = vue.ref();
14888
+ const vVirtualScrollRef = vue.ref();
14848
14889
  const _menu = useProxiedModel(props, 'menu');
14849
14890
  const menu = vue.computed({
14850
14891
  get: () => _menu.value,
@@ -15078,6 +15119,14 @@
15078
15119
  search.value = '';
15079
15120
  }
15080
15121
  });
15122
+ vue.watch(menu, () => {
15123
+ if (!props.hideSelected && menu.value && selections.value.length) {
15124
+ const index = displayItems.value.findIndex(item => selections.value.some(s => item.value === s.value));
15125
+ IN_BROWSER && window.requestAnimationFrame(() => {
15126
+ index >= 0 && vVirtualScrollRef.value?.scrollToIndex(index);
15127
+ });
15128
+ }
15129
+ });
15081
15130
  useRender(() => {
15082
15131
  const hasChips = !!(props.chips || slots.chip);
15083
15132
  const hasList = !!(!props.hideNoData || displayItems.value.length || slots['prepend-item'] || slots['append-item'] || slots['no-data']);
@@ -15136,6 +15185,7 @@
15136
15185
  default: () => [slots['prepend-item']?.(), !displayItems.value.length && !props.hideNoData && (slots['no-data']?.() ?? vue.createVNode(VListItem, {
15137
15186
  "title": t(props.noDataText)
15138
15187
  }, null)), vue.createVNode(VVirtualScroll, {
15188
+ "ref": vVirtualScrollRef,
15139
15189
  "renderless": true,
15140
15190
  "items": displayItems.value
15141
15191
  }, {
@@ -17527,7 +17577,7 @@
17527
17577
  const id = vue.computed(() => props.id || `radio-group-${uid}`);
17528
17578
  const model = useProxiedModel(props, 'modelValue');
17529
17579
  useRender(() => {
17530
- const [inputAttrs, controlAttrs] = filterInputAttrs(attrs);
17580
+ const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
17531
17581
  const [inputProps, _1] = VInput.filterProps(props);
17532
17582
  const [controlProps, _2] = VSelectionControl.filterProps(props);
17533
17583
  const label = slots.label ? slots.label({
@@ -17539,7 +17589,7 @@
17539
17589
  return vue.createVNode(VInput, vue.mergeProps({
17540
17590
  "class": ['v-radio-group', props.class],
17541
17591
  "style": props.style
17542
- }, inputAttrs, inputProps, {
17592
+ }, rootAttrs, inputProps, {
17543
17593
  "modelValue": model.value,
17544
17594
  "onUpdate:modelValue": $event => model.value = $event,
17545
17595
  "id": id.value
@@ -18516,6 +18566,7 @@
18516
18566
  focus,
18517
18567
  blur
18518
18568
  } = useFocus(props);
18569
+ const control = vue.ref();
18519
18570
  const loaderColor = vue.computed(() => {
18520
18571
  return typeof props.loading === 'string' && props.loading !== '' ? props.loading : props.color;
18521
18572
  });
@@ -18526,16 +18577,15 @@
18526
18577
  indeterminate.value = false;
18527
18578
  }
18528
18579
  }
18580
+ function onTrackClick(e) {
18581
+ e.stopPropagation();
18582
+ e.preventDefault();
18583
+ control.value?.input?.click();
18584
+ }
18529
18585
  useRender(() => {
18530
- const [inputAttrs, controlAttrs] = filterInputAttrs(attrs);
18586
+ const [rootAttrs, controlAttrs] = filterInputAttrs(attrs);
18531
18587
  const [inputProps, _1] = VInput.filterProps(props);
18532
18588
  const [controlProps, _2] = VSelectionControl.filterProps(props);
18533
- const control = vue.ref();
18534
- function onClick(e) {
18535
- e.stopPropagation();
18536
- e.preventDefault();
18537
- control.value?.input?.click();
18538
- }
18539
18589
  return vue.createVNode(VInput, vue.mergeProps({
18540
18590
  "class": ['v-switch', {
18541
18591
  'v-switch--inset': props.inset
@@ -18543,7 +18593,7 @@
18543
18593
  'v-switch--indeterminate': indeterminate.value
18544
18594
  }, loaderClasses.value, props.class],
18545
18595
  "style": props.style
18546
- }, inputAttrs, inputProps, {
18596
+ }, rootAttrs, inputProps, {
18547
18597
  "id": id.value,
18548
18598
  "focused": isFocused.value
18549
18599
  }), {
@@ -18573,7 +18623,7 @@
18573
18623
  ...slots,
18574
18624
  default: () => vue.createVNode("div", {
18575
18625
  "class": "v-switch__track",
18576
- "onClick": onClick
18626
+ "onClick": onTrackClick
18577
18627
  }, null),
18578
18628
  input: _ref3 => {
18579
18629
  let {
@@ -21725,6 +21775,98 @@
21725
21775
  }
21726
21776
  });
21727
21777
 
21778
+ // Types
21779
+
21780
+ const makeVDatePickerControlsProps = propsFactory({
21781
+ displayDate: String,
21782
+ disabled: {
21783
+ type: [Boolean, String],
21784
+ default: false
21785
+ },
21786
+ nextIcon: {
21787
+ type: [String],
21788
+ default: '$next'
21789
+ },
21790
+ prevIcon: {
21791
+ type: [String],
21792
+ default: '$prev'
21793
+ },
21794
+ expandIcon: {
21795
+ type: [String],
21796
+ default: '$expand'
21797
+ },
21798
+ collapseIcon: {
21799
+ type: [String],
21800
+ default: '$collapse'
21801
+ },
21802
+ viewMode: {
21803
+ type: String,
21804
+ default: 'month'
21805
+ }
21806
+ }, 'VDatePickerControls');
21807
+ const VDatePickerControls = genericComponent()({
21808
+ name: 'VDatePickerControls',
21809
+ props: makeVDatePickerControlsProps(),
21810
+ emits: {
21811
+ 'click:mode': () => true,
21812
+ 'click:prev': () => true,
21813
+ 'click:next': () => true
21814
+ },
21815
+ setup(props, _ref) {
21816
+ let {
21817
+ emit
21818
+ } = _ref;
21819
+ const modeIcon = vue.computed(() => {
21820
+ return props.viewMode === 'month' ? props.expandIcon : props.collapseIcon;
21821
+ });
21822
+ const disableMode = vue.computed(() => {
21823
+ return Array.isArray(props.disabled) ? props.disabled.includes('mode') : props.disabled;
21824
+ });
21825
+ const disablePrev = vue.computed(() => {
21826
+ return Array.isArray(props.disabled) ? props.disabled.includes('prev') : props.disabled;
21827
+ });
21828
+ const disableNext = vue.computed(() => {
21829
+ return Array.isArray(props.disabled) ? props.disabled.includes('next') : props.disabled;
21830
+ });
21831
+ function onClickPrev() {
21832
+ emit('click:prev');
21833
+ }
21834
+ function onClickNext() {
21835
+ emit('click:next');
21836
+ }
21837
+ function onClickMode() {
21838
+ emit('click:mode');
21839
+ }
21840
+ useRender(() => {
21841
+ return vue.createVNode("div", {
21842
+ "class": "v-date-picker-controls"
21843
+ }, [vue.createVNode("div", {
21844
+ "class": "v-date-picker-controls__date"
21845
+ }, [props.displayDate]), vue.createVNode(VBtn, {
21846
+ "disabled": disableMode.value,
21847
+ "key": "expand-btn",
21848
+ "icon": modeIcon.value,
21849
+ "variant": "text",
21850
+ "onClick": onClickMode
21851
+ }, null), vue.createVNode(VSpacer, null, null), vue.createVNode("div", {
21852
+ "key": "month-buttons",
21853
+ "class": "v-date-picker-controls__month"
21854
+ }, [vue.createVNode(VBtn, {
21855
+ "disabled": disablePrev.value,
21856
+ "icon": props.prevIcon,
21857
+ "variant": "text",
21858
+ "onClick": onClickPrev
21859
+ }, null), vue.createVNode(VBtn, {
21860
+ "disabled": disableNext.value,
21861
+ "icon": props.nextIcon,
21862
+ "variant": "text",
21863
+ "onClick": onClickNext
21864
+ }, null)])]);
21865
+ });
21866
+ return {};
21867
+ }
21868
+ });
21869
+
21728
21870
  // Utilities
21729
21871
 
21730
21872
  // Types
@@ -22293,76 +22435,6 @@
22293
22435
  };
22294
22436
  }
22295
22437
 
22296
- const makeVDatePickerControlsProps = propsFactory({
22297
- nextIcon: {
22298
- type: [String],
22299
- default: '$next'
22300
- },
22301
- prevIcon: {
22302
- type: [String],
22303
- default: '$prev'
22304
- },
22305
- expandIcon: {
22306
- type: [String],
22307
- default: '$expand'
22308
- },
22309
- collapseIcon: {
22310
- type: [String],
22311
- default: '$collapse'
22312
- },
22313
- range: {
22314
- default: false,
22315
- type: [Boolean, String],
22316
- validator: v => v === false || ['start', 'end'].includes(v)
22317
- },
22318
- ...omit(makeDateProps(), ['modelValue', 'inputMode'])
22319
- }, 'VDatePickerControls');
22320
- const VDatePickerControls = genericComponent()({
22321
- name: 'VDatePickerControls',
22322
- props: makeVDatePickerControlsProps(),
22323
- emits: {
22324
- ...omit(dateEmits, ['update:modelValue', 'update:inputMode'])
22325
- },
22326
- setup(props, _ref) {
22327
- let {
22328
- emit
22329
- } = _ref;
22330
- const adapter = useDate();
22331
- const monthAndYear = vue.computed(() => {
22332
- const month = props.range === 'end' ? adapter.addMonths(props.displayDate, 1) : props.displayDate;
22333
- return adapter.format(month, 'monthAndYear');
22334
- });
22335
- useRender(() => {
22336
- const prevBtn = vue.createVNode(VBtn, {
22337
- "variant": "text",
22338
- "icon": props.prevIcon,
22339
- "onClick": () => emit('update:displayDate', adapter.addMonths(props.displayDate, -1))
22340
- }, null);
22341
- const nextBtn = vue.createVNode(VBtn, {
22342
- "variant": "text",
22343
- "icon": props.nextIcon,
22344
- "onClick": () => emit('update:displayDate', adapter.addMonths(props.displayDate, 1))
22345
- }, null);
22346
- return vue.createVNode("div", {
22347
- "class": "v-date-picker-controls"
22348
- }, [props.viewMode === 'month' && props.range === 'start' && prevBtn, !!props.range && vue.createVNode(VSpacer, {
22349
- "key": "range-spacer"
22350
- }, null), vue.createVNode("div", {
22351
- "class": "v-date-picker-controls__date"
22352
- }, [monthAndYear.value]), vue.createVNode(VBtn, {
22353
- "key": "expand-btn",
22354
- "variant": "text",
22355
- "icon": props.viewMode === 'month' ? props.expandIcon : props.collapseIcon,
22356
- "onClick": () => emit('update:viewMode', props.viewMode === 'month' ? 'year' : 'month')
22357
- }, null), vue.createVNode(VSpacer, null, null), props.viewMode === 'month' && !props.range && vue.createVNode("div", {
22358
- "class": "v-date-picker-controls__month",
22359
- "key": "month-buttons"
22360
- }, [prevBtn, nextBtn]), props.viewMode === 'month' && props.range === 'end' && nextBtn]);
22361
- });
22362
- return {};
22363
- }
22364
- });
22365
-
22366
22438
  // Composables
22367
22439
 
22368
22440
  // Types
@@ -22419,6 +22491,8 @@
22419
22491
  side: {
22420
22492
  type: String
22421
22493
  },
22494
+ min: [Number, String, Date],
22495
+ max: [Number, String, Date],
22422
22496
  ...omit(makeDateProps(), ['inputMode', 'viewMode'])
22423
22497
  }, 'VDatePickerMonth');
22424
22498
  const VDatePickerMonth = genericComponent()({
@@ -22494,6 +22568,7 @@
22494
22568
  const startDate = validDates[0];
22495
22569
  const endDate = validDates[1];
22496
22570
  return days.map((date, index) => {
22571
+ const isDisabled = !!(props.min && adapter.isAfter(props.min, date) || props.max && adapter.isAfter(date, props.max));
22497
22572
  const isStart = startDate && adapter.isSameDay(date, startDate);
22498
22573
  const isEnd = endDate && adapter.isSameDay(date, endDate);
22499
22574
  const isAdjacent = !adapter.isSameMonth(date, month.value);
@@ -22504,6 +22579,7 @@
22504
22579
  formatted: adapter.format(date, 'keyboardDate'),
22505
22580
  year: adapter.getYear(date),
22506
22581
  month: adapter.getMonth(date),
22582
+ isDisabled,
22507
22583
  isWeekStart: index % 7 === 0,
22508
22584
  isWeekEnd: index % 7 === 6,
22509
22585
  isSelected: isStart || isEnd,
@@ -22646,50 +22722,55 @@
22646
22722
  "onTouchstart": handleMousedown
22647
22723
  }, [!props.hideWeekdays && adapter.getWeekdays().map(weekDay => vue.createVNode("div", {
22648
22724
  "class": ['v-date-picker-month__day', 'v-date-picker-month__weekday']
22649
- }, [weekDay])), daysInMonth.value.map((item, index) => vue.createVNode("div", {
22650
- "class": ['v-date-picker-month__day', {
22651
- 'v-date-picker-month__day--selected': item.isSelected,
22652
- 'v-date-picker-month__day--start': item.isStart,
22653
- 'v-date-picker-month__day--end': item.isEnd,
22654
- 'v-date-picker-month__day--adjacent': item.isAdjacent,
22655
- 'v-date-picker-month__day--hide-adjacent': item.isHidden,
22656
- 'v-date-picker-month__day--week-start': item.isWeekStart,
22657
- 'v-date-picker-month__day--week-end': item.isWeekEnd,
22658
- 'v-date-picker-month__day--hovered': item.isHovered
22659
- }],
22660
- "data-v-date": !item.isHidden ? item.isoDate : undefined
22661
- }, [item.inRange && vue.createVNode("div", {
22662
- "key": "in-range",
22663
- "class": ['v-date-picker-month__day--range', backgroundColorClasses.value],
22664
- "style": backgroundColorStyles.value
22665
- }, null), item.inHover && !item.isStart && !item.isEnd && !item.isHovered && !item.inRange && vue.createVNode("div", {
22666
- "key": "in-hover",
22667
- "class": "v-date-picker-month__day--hover"
22668
- }, null), (props.showAdjacentMonths || !item.isAdjacent) && vue.createVNode(VBtn, {
22669
- "icon": true,
22670
- "ripple": false,
22671
- "variant": (item.isToday || item.isHovered) && !item.isSelected ? 'outlined' : 'flat',
22672
- "active": item.isSelected,
22673
- "color": item.isSelected || item.isToday ? props.color : item.isHovered ? undefined : 'transparent'
22674
- }, {
22675
- default: () => [item.localized]
22676
- })]))])]);
22725
+ }, [weekDay])), daysInMonth.value.map((item, index) => {
22726
+ const color = item.isSelected || item.isToday ? props.color : item.isHovered || item.isDisabled ? undefined : 'transparent';
22727
+ const variant = item.isDisabled ? 'text' : (item.isToday || item.isHovered) && !item.isSelected ? 'outlined' : 'flat';
22728
+ return vue.createVNode("div", {
22729
+ "class": ['v-date-picker-month__day', {
22730
+ 'v-date-picker-month__day--selected': item.isSelected,
22731
+ 'v-date-picker-month__day--start': item.isStart,
22732
+ 'v-date-picker-month__day--end': item.isEnd,
22733
+ 'v-date-picker-month__day--adjacent': item.isAdjacent,
22734
+ 'v-date-picker-month__day--hide-adjacent': item.isHidden,
22735
+ 'v-date-picker-month__day--week-start': item.isWeekStart,
22736
+ 'v-date-picker-month__day--week-end': item.isWeekEnd,
22737
+ 'v-date-picker-month__day--hovered': item.isHovered
22738
+ }],
22739
+ "data-v-date": !item.isHidden && !item.isDisabled ? item.isoDate : undefined
22740
+ }, [item.inRange && vue.createVNode("div", {
22741
+ "key": "in-range",
22742
+ "class": ['v-date-picker-month__day--range', backgroundColorClasses.value],
22743
+ "style": backgroundColorStyles.value
22744
+ }, null), item.inHover && !item.isStart && !item.isEnd && !item.isHovered && !item.inRange && vue.createVNode("div", {
22745
+ "key": "in-hover",
22746
+ "class": "v-date-picker-month__day--hover"
22747
+ }, null), (props.showAdjacentMonths || !item.isAdjacent) && vue.createVNode(VBtn, {
22748
+ "active": item.isSelected,
22749
+ "color": color,
22750
+ "disabled": item.isDisabled,
22751
+ "icon": true,
22752
+ "ripple": false,
22753
+ "variant": variant
22754
+ }, {
22755
+ default: () => [item.localized]
22756
+ })]);
22757
+ })])]);
22677
22758
  }
22678
22759
  });
22679
22760
 
22680
22761
  const makeVDatePickerYearsProps = propsFactory({
22681
22762
  color: String,
22682
- min: Number,
22683
- max: Number,
22684
22763
  height: [String, Number],
22685
- displayDate: null
22764
+ displayDate: null,
22765
+ min: [Number, String, Date],
22766
+ max: [Number, String, Date]
22686
22767
  }, 'VDatePickerYears');
22687
22768
  const VDatePickerYears = genericComponent()({
22688
22769
  name: 'VDatePickerYears',
22689
22770
  props: makeVDatePickerYearsProps(),
22690
22771
  emits: {
22691
22772
  'update:displayDate': date => true,
22692
- 'update:viewMode': date => true
22773
+ 'click:mode': () => true
22693
22774
  },
22694
22775
  setup(props, _ref) {
22695
22776
  let {
@@ -22698,8 +22779,8 @@
22698
22779
  const adapter = useDate();
22699
22780
  const displayYear = vue.computed(() => adapter.getYear(props.displayDate ?? new Date()));
22700
22781
  const years = vue.computed(() => {
22701
- const min = props.min ?? displayYear.value - 50 - 2;
22702
- const max = props.max ?? displayYear.value + 50;
22782
+ const min = props.min ? adapter.date(props.min).getFullYear() : displayYear.value - 100;
22783
+ const max = props.max ? adapter.date(props.max).getFullYear() : displayYear.value + 50;
22703
22784
  return createRange(max - min, min);
22704
22785
  });
22705
22786
  const yearRef = vue.ref();
@@ -22715,19 +22796,21 @@
22715
22796
  }
22716
22797
  }, [vue.createVNode("div", {
22717
22798
  "class": "v-date-picker-years__content"
22718
- }, [years.value.map(year => vue.createVNode(VBtn, {
22719
- "ref": year === displayYear.value ? yearRef : undefined,
22720
- "variant": year === displayYear.value ? 'flat' : 'text',
22721
- "rounded": "xl",
22722
- "active": year === displayYear.value,
22723
- "color": year === displayYear.value ? props.color : undefined,
22724
- "onClick": () => {
22799
+ }, [years.value.map(year => {
22800
+ function onClick() {
22725
22801
  emit('update:displayDate', adapter.setYear(props.displayDate, year));
22726
- emit('update:viewMode', 'month');
22727
- }
22728
- }, {
22729
- default: () => [year]
22730
- }))])]));
22802
+ emit('click:mode');
22803
+ }
22804
+ return vue.createVNode(VBtn, {
22805
+ "ref": year === displayYear.value ? yearRef : undefined,
22806
+ "active": year === displayYear.value,
22807
+ "color": year === displayYear.value ? props.color : undefined,
22808
+ "rounded": "xl",
22809
+ "text": String(year),
22810
+ "variant": year === displayYear.value ? 'flat' : 'text',
22811
+ "onClick": onClick
22812
+ }, null);
22813
+ })])]));
22731
22814
  return {};
22732
22815
  }
22733
22816
  });
@@ -23012,21 +23095,24 @@
23012
23095
  const header = vue.computed(() => model.value.length ? adapter.format(model.value[0], 'normalDateWithWeekday') : t(props.header));
23013
23096
  const headerIcon = vue.computed(() => inputMode.value === 'calendar' ? props.keyboardIcon : props.calendarIcon);
23014
23097
  const headerTransition = vue.computed(() => `date-picker-header${isReversing.value ? '-reverse' : ''}-transition`);
23015
- function updateFromInput(input, index) {
23016
- const {
23017
- isValid,
23018
- date
23019
- } = adapter;
23020
- if (isValid(input)) {
23021
- const newModel = model.value.slice();
23022
- newModel[index] = date(input);
23023
- if (props.hideActions) {
23024
- model.value = newModel;
23025
- } else {
23026
- temporaryModel.value = newModel;
23027
- }
23098
+ const minDate = vue.computed(() => props.min && adapter.isValid(props.min) ? adapter.date(props.min) : null);
23099
+ const maxDate = vue.computed(() => props.max && adapter.isValid(props.max) ? adapter.date(props.max) : null);
23100
+ const disabled = vue.computed(() => {
23101
+ if (!minDate.value && !maxDate.value) return false;
23102
+ const targets = [];
23103
+ if (minDate.value) {
23104
+ const date = adapter.addDays(adapter.startOfMonth(displayDate.value), -1);
23105
+ adapter.isAfter(minDate.value, date) && targets.push('prev');
23028
23106
  }
23029
- }
23107
+ if (maxDate.value) {
23108
+ const date = adapter.addDays(adapter.endOfMonth(displayDate.value), 1);
23109
+ adapter.isAfter(date, maxDate.value) && targets.push('next');
23110
+ }
23111
+ if (minDate.value?.getFullYear() === maxDate.value?.getFullYear()) {
23112
+ targets.push('mode');
23113
+ }
23114
+ return targets;
23115
+ });
23030
23116
  vue.watch(model, val => {
23031
23117
  if (!isEqual(val, temporaryModel.value)) {
23032
23118
  temporaryModel.value = val;
@@ -23041,6 +23127,21 @@
23041
23127
  isReversing.value = adapter.isBefore(val[0], oldVal[0]);
23042
23128
  }
23043
23129
  });
23130
+ function updateFromInput(input, index) {
23131
+ const {
23132
+ isValid,
23133
+ date
23134
+ } = adapter;
23135
+ if (isValid(input)) {
23136
+ const newModel = model.value.slice();
23137
+ newModel[index] = date(input);
23138
+ if (props.hideActions) {
23139
+ model.value = newModel;
23140
+ } else {
23141
+ temporaryModel.value = newModel;
23142
+ }
23143
+ }
23144
+ }
23044
23145
  function onClickCancel() {
23045
23146
  emit('click:cancel');
23046
23147
  }
@@ -23051,6 +23152,15 @@
23051
23152
  function onClickAppend() {
23052
23153
  inputMode.value = inputMode.value === 'calendar' ? 'keyboard' : 'calendar';
23053
23154
  }
23155
+ function onClickNext() {
23156
+ displayDate.value = adapter.addMonths(displayDate.value, 1);
23157
+ }
23158
+ function onClickPrev() {
23159
+ displayDate.value = adapter.addMonths(displayDate.value, -1);
23160
+ }
23161
+ function onClickMode() {
23162
+ viewMode.value = viewMode.value === 'month' ? 'year' : 'month';
23163
+ }
23054
23164
  const headerSlotProps = vue.computed(() => ({
23055
23165
  header: header.value,
23056
23166
  appendIcon: headerIcon.value,
@@ -23072,10 +23182,11 @@
23072
23182
  "key": "header"
23073
23183
  }, headerSlotProps.value), null),
23074
23184
  default: () => inputMode.value === 'calendar' ? vue.createVNode(vue.Fragment, null, [vue.createVNode(VDatePickerControls, vue.mergeProps(datePickerControlsProps, {
23075
- "displayDate": displayDate.value,
23076
- "onUpdate:displayDate": $event => displayDate.value = $event,
23077
- "viewMode": viewMode.value,
23078
- "onUpdate:viewMode": $event => viewMode.value = $event
23185
+ "disabled": disabled.value,
23186
+ "displayDate": adapter.format(displayDate.value, 'monthAndYear'),
23187
+ "onClick:next": onClickNext,
23188
+ "onClick:prev": onClickPrev,
23189
+ "onClick:mode": onClickMode
23079
23190
  }), null), vue.createVNode(VFadeTransition, {
23080
23191
  "hideOnLeave": true
23081
23192
  }, {
@@ -23085,14 +23196,16 @@
23085
23196
  "modelValue": temporaryModel.value,
23086
23197
  "onUpdate:modelValue": $event => temporaryModel.value = $event,
23087
23198
  "displayDate": displayDate.value,
23088
- "onUpdate:displayDate": $event => displayDate.value = $event
23199
+ "min": minDate.value,
23200
+ "max": maxDate.value
23089
23201
  }), null) : vue.createVNode(VDatePickerYears, vue.mergeProps({
23090
23202
  "key": "date-picker-years"
23091
23203
  }, datePickerYearsProps, {
23092
23204
  "displayDate": displayDate.value,
23093
23205
  "onUpdate:displayDate": $event => displayDate.value = $event,
23094
- "viewMode": viewMode.value,
23095
- "onUpdate:viewMode": $event => viewMode.value = $event
23206
+ "min": minDate.value,
23207
+ "max": maxDate.value,
23208
+ "onClick:mode": onClickMode
23096
23209
  }), null)]
23097
23210
  })]) : vue.createVNode("div", {
23098
23211
  "class": "v-date-picker__input"
@@ -24435,7 +24548,7 @@
24435
24548
  date
24436
24549
  };
24437
24550
  }
24438
- const version$1 = "3.3.13";
24551
+ const version$1 = "3.3.14";
24439
24552
  createVuetify$1.version = version$1;
24440
24553
 
24441
24554
  // Vue's inject() can only be used in setup
@@ -24449,7 +24562,7 @@
24449
24562
 
24450
24563
  /* eslint-disable local-rules/sort-imports */
24451
24564
 
24452
- const version = "3.3.13";
24565
+ const version = "3.3.14";
24453
24566
 
24454
24567
  /* eslint-disable local-rules/sort-imports */
24455
24568