vuetify 3.10.8 → 3.10.10

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 (68) hide show
  1. package/dist/json/attributes.json +1543 -1543
  2. package/dist/json/importMap-labs.json +18 -18
  3. package/dist/json/importMap.json +174 -174
  4. package/dist/json/web-types.json +2937 -2937
  5. package/dist/vuetify-labs.cjs +205 -216
  6. package/dist/vuetify-labs.css +4754 -4730
  7. package/dist/vuetify-labs.d.ts +72 -72
  8. package/dist/vuetify-labs.esm.js +205 -216
  9. package/dist/vuetify-labs.esm.js.map +1 -1
  10. package/dist/vuetify-labs.js +205 -216
  11. package/dist/vuetify-labs.min.css +2 -2
  12. package/dist/vuetify.cjs +137 -99
  13. package/dist/vuetify.cjs.map +1 -1
  14. package/dist/vuetify.css +2766 -2730
  15. package/dist/vuetify.d.ts +56 -56
  16. package/dist/vuetify.esm.js +137 -99
  17. package/dist/vuetify.esm.js.map +1 -1
  18. package/dist/vuetify.js +137 -99
  19. package/dist/vuetify.js.map +1 -1
  20. package/dist/vuetify.min.css +2 -2
  21. package/dist/vuetify.min.js +334 -330
  22. package/dist/vuetify.min.js.map +1 -1
  23. package/lib/components/VAvatar/VAvatar.css +1 -1
  24. package/lib/components/VAvatar/_variables.scss +1 -1
  25. package/lib/components/VBtnToggle/VBtnToggle.css +21 -0
  26. package/lib/components/VBtnToggle/VBtnToggle.sass +22 -0
  27. package/lib/components/VCard/VCard.js +8 -1
  28. package/lib/components/VCard/VCard.js.map +1 -1
  29. package/lib/components/VDatePicker/VDatePicker.js +7 -16
  30. package/lib/components/VDatePicker/VDatePicker.js.map +1 -1
  31. package/lib/components/VList/VList.css +6 -0
  32. package/lib/components/VList/VList.sass +6 -0
  33. package/lib/components/VList/VListItem.css +0 -3
  34. package/lib/components/VList/VListItem.sass +0 -4
  35. package/lib/components/VOverlay/useActivator.js +2 -1
  36. package/lib/components/VOverlay/useActivator.js.map +1 -1
  37. package/lib/components/VTabs/VTab.css +8 -0
  38. package/lib/components/VTabs/VTab.sass +7 -0
  39. package/lib/components/VTextField/VTextField.js +17 -7
  40. package/lib/components/VTextField/VTextField.js.map +1 -1
  41. package/lib/components/VTextarea/VTextarea.js +17 -7
  42. package/lib/components/VTextarea/VTextarea.js.map +1 -1
  43. package/lib/composables/calendar.d.ts +6 -0
  44. package/lib/composables/calendar.js +37 -2
  45. package/lib/composables/calendar.js.map +1 -1
  46. package/lib/composables/delay.js +3 -2
  47. package/lib/composables/delay.js.map +1 -1
  48. package/lib/composables/hotkey/hotkey.js +42 -53
  49. package/lib/composables/hotkey/hotkey.js.map +1 -1
  50. package/lib/entry-bundler.js +1 -1
  51. package/lib/entry-bundler.js.map +1 -1
  52. package/lib/framework.d.ts +56 -56
  53. package/lib/framework.js +1 -1
  54. package/lib/framework.js.map +1 -1
  55. package/lib/labs/VDateInput/VDateInput.js +8 -12
  56. package/lib/labs/VDateInput/VDateInput.js.map +1 -1
  57. package/lib/labs/VHotkey/VHotkey.css +4 -16
  58. package/lib/labs/VHotkey/VHotkey.d.ts +29 -29
  59. package/lib/labs/VHotkey/VHotkey.js +62 -106
  60. package/lib/labs/VHotkey/VHotkey.js.map +1 -1
  61. package/lib/labs/VHotkey/VHotkey.scss +8 -25
  62. package/lib/styles/main.css +4 -0
  63. package/lib/styles/settings/_variables.scss +1 -0
  64. package/lib/util/box.js +3 -8
  65. package/lib/util/box.js.map +1 -1
  66. package/lib/util/throttle.js +2 -2
  67. package/lib/util/throttle.js.map +1 -1
  68. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.10.8
2
+ * Vuetify v3.10.10
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
@@ -684,7 +684,8 @@
684
684
  class Box {
685
685
  constructor(args) {
686
686
  const pageScale = document.body.currentCSSZoom ?? 1;
687
- const factor = args instanceof DOMRect ? 1 + (1 - pageScale) / pageScale : 1;
687
+ const ignoreZoom = args.top === undefined; // detect DOMRect without breaking in jsdom
688
+ const factor = ignoreZoom ? 1 : 1 + (1 - pageScale) / pageScale;
688
689
  const {
689
690
  x,
690
691
  y,
@@ -754,13 +755,7 @@
754
755
  });
755
756
  }
756
757
  } else {
757
- const rect = el.getBoundingClientRect();
758
- return new Box({
759
- x: rect.x,
760
- y: rect.y,
761
- width: el.clientWidth,
762
- height: el.clientHeight
763
- });
758
+ return new Box(el.getBoundingClientRect());
764
759
  }
765
760
  }
766
761
 
@@ -1798,7 +1793,7 @@
1798
1793
  const elapsed = now - Math.max(start, lastExec);
1799
1794
  function invoke() {
1800
1795
  lastExec = Date.now();
1801
- timeoutId = window.setTimeout(clear, delay);
1796
+ timeoutId = setTimeout(clear, delay);
1802
1797
  fn(...args);
1803
1798
  }
1804
1799
  if (!throttling) {
@@ -1809,7 +1804,7 @@
1809
1804
  } else if (elapsed >= delay) {
1810
1805
  invoke();
1811
1806
  } else if (options.trailing) {
1812
- timeoutId = window.setTimeout(invoke, delay - elapsed);
1807
+ timeoutId = setTimeout(invoke, delay - elapsed);
1813
1808
  }
1814
1809
  };
1815
1810
  wrap.clear = clear;
@@ -11329,9 +11324,10 @@
11329
11324
  let clearDelay = () => {};
11330
11325
  function runDelay(isOpening, options) {
11331
11326
  clearDelay?.();
11332
- const delay = Math.max(options?.minDelay ?? 0, Number(isOpening ? props.openDelay : props.closeDelay));
11327
+ const delay = isOpening ? props.openDelay : props.closeDelay;
11328
+ const normalizedDelay = Math.max(options?.minDelay ?? 0, Number(delay ?? 0));
11333
11329
  return new Promise(resolve => {
11334
- clearDelay = defer(delay, () => {
11330
+ clearDelay = defer(normalizedDelay, () => {
11335
11331
  cb?.(isOpening);
11336
11332
  resolve(isOpening);
11337
11333
  });
@@ -11459,7 +11455,8 @@
11459
11455
  };
11460
11456
  }
11461
11457
  if (openOnFocus.value) {
11462
- events.onFocusin = () => {
11458
+ events.onFocusin = e => {
11459
+ if (!e.target.matches(':focus-visible')) return;
11463
11460
  isFocused = true;
11464
11461
  runOpenDelay();
11465
11462
  };
@@ -12837,14 +12834,24 @@
12837
12834
  }
12838
12835
  function onInput(e) {
12839
12836
  const el = e.target;
12840
- model.value = el.value;
12841
- if (props.modelModifiers?.trim && ['text', 'search', 'password', 'tel', 'url'].includes(props.type)) {
12842
- const caretPosition = [el.selectionStart, el.selectionEnd];
12843
- vue.nextTick(() => {
12844
- el.selectionStart = caretPosition[0];
12845
- el.selectionEnd = caretPosition[1];
12846
- });
12837
+ if (!(props.modelModifiers?.trim && ['text', 'search', 'password', 'tel', 'url'].includes(props.type))) {
12838
+ model.value = el.value;
12839
+ return;
12847
12840
  }
12841
+ const value = el.value;
12842
+ const start = el.selectionStart;
12843
+ const end = el.selectionEnd;
12844
+ model.value = value;
12845
+ vue.nextTick(() => {
12846
+ let offset = 0;
12847
+ if (value.trimStart().length === el.value.length) {
12848
+ // #22307 - Whitespace has been removed from the
12849
+ // start, offset the caret position to compensate
12850
+ offset = value.length - el.value.length;
12851
+ }
12852
+ if (start != null) el.selectionStart = start - offset;
12853
+ if (end != null) el.selectionEnd = end - offset;
12854
+ });
12848
12855
  }
12849
12856
  useRender(() => {
12850
12857
  const hasCounter = !!(slots.counter || props.counter !== false && props.counter != null);
@@ -15571,6 +15578,12 @@
15571
15578
  roundedClasses
15572
15579
  } = useRounded(props);
15573
15580
  const link = useLink(props, attrs);
15581
+ const loadingColor = vue.shallowRef(undefined);
15582
+ vue.watch(() => props.loading, (val, old) => {
15583
+ loadingColor.value = !val && typeof old === 'string' ? old : typeof val === 'boolean' ? undefined : val;
15584
+ }, {
15585
+ immediate: true
15586
+ });
15574
15587
  useRender(() => {
15575
15588
  const isLink = props.link !== false && link.isLink.value;
15576
15589
  const isClickable = !props.disabled && props.link !== false && (props.link || link.isClickable.value);
@@ -15613,7 +15626,7 @@
15613
15626
  }, slots.image)]), vue.createVNode(LoaderSlot, {
15614
15627
  "name": "v-card",
15615
15628
  "active": !!props.loading,
15616
- "color": typeof props.loading === 'boolean' ? undefined : props.loading
15629
+ "color": loadingColor.value
15617
15630
  }, {
15618
15631
  default: slots.loader
15619
15632
  }), hasCardItem && vue.createVNode(VCardItem, {
@@ -19036,11 +19049,6 @@
19036
19049
  let keyGroups;
19037
19050
  let isSequence = false;
19038
19051
  let groupIndex = 0;
19039
- function clearTimer() {
19040
- if (!timeout) return;
19041
- clearTimeout(timeout);
19042
- timeout = 0;
19043
- }
19044
19052
  function isInputFocused() {
19045
19053
  if (vue.toValue(inputs)) return false;
19046
19054
  const activeElement = document.activeElement;
@@ -19048,12 +19056,12 @@
19048
19056
  }
19049
19057
  function resetSequence() {
19050
19058
  groupIndex = 0;
19051
- clearTimer();
19059
+ clearTimeout(timeout);
19052
19060
  }
19053
19061
  function handler(e) {
19054
19062
  const group = keyGroups[groupIndex];
19055
19063
  if (!group || isInputFocused()) return;
19056
- if (!matchesKeyGroup(e, group)) {
19064
+ if (!matchesKeyGroup(e, group, isMac)) {
19057
19065
  if (isSequence) resetSequence();
19058
19066
  return;
19059
19067
  }
@@ -19062,7 +19070,7 @@
19062
19070
  callback(e);
19063
19071
  return;
19064
19072
  }
19065
- clearTimer();
19073
+ clearTimeout(timeout);
19066
19074
  groupIndex++;
19067
19075
  if (groupIndex === keyGroups.length) {
19068
19076
  callback(e);
@@ -19073,12 +19081,12 @@
19073
19081
  }
19074
19082
  function cleanup() {
19075
19083
  window.removeEventListener(vue.toValue(event), handler);
19076
- clearTimer();
19084
+ clearTimeout(timeout);
19077
19085
  }
19078
- vue.watch(() => vue.toValue(keys), function (unrefKeys) {
19086
+ vue.watch(() => vue.toValue(keys), newKeys => {
19079
19087
  cleanup();
19080
- if (unrefKeys) {
19081
- const groups = splitKeySequence(unrefKeys.toLowerCase());
19088
+ if (newKeys) {
19089
+ const groups = splitKeySequence(newKeys.toLowerCase());
19082
19090
  isSequence = groups.length > 1;
19083
19091
  keyGroups = groups;
19084
19092
  resetSequence();
@@ -19089,55 +19097,50 @@
19089
19097
  });
19090
19098
 
19091
19099
  // Watch for changes in the event type to re-register the listener
19092
- vue.watch(() => vue.toValue(event), function (newEvent, oldEvent) {
19100
+ vue.watch(() => vue.toValue(event), (newEvent, oldEvent) => {
19093
19101
  if (oldEvent && keyGroups && keyGroups.length > 0) {
19094
19102
  window.removeEventListener(oldEvent, handler);
19095
19103
  window.addEventListener(newEvent, handler);
19096
19104
  }
19097
19105
  });
19098
- try {
19099
- getCurrentInstance('useHotkey');
19100
- vue.onBeforeUnmount(cleanup);
19101
- } catch {
19102
- // Not in Vue setup context
19103
- }
19104
- function parseKeyGroup(group) {
19105
- const MODIFIERS = ['ctrl', 'shift', 'alt', 'meta', 'cmd'];
19106
+ vue.onScopeDispose(cleanup, true);
19107
+ return cleanup;
19108
+ }
19109
+ function matchesKeyGroup(e, group, isMac) {
19110
+ const {
19111
+ modifiers,
19112
+ actualKey
19113
+ } = parseKeyGroup(group);
19114
+ const expectCtrl = modifiers.ctrl || !isMac && (modifiers.cmd || modifiers.meta);
19115
+ const expectMeta = isMac && (modifiers.cmd || modifiers.meta);
19116
+ return e.ctrlKey === expectCtrl && e.metaKey === expectMeta && e.shiftKey === modifiers.shift && e.altKey === modifiers.alt && e.key.toLowerCase() === actualKey?.toLowerCase();
19117
+ }
19118
+ function parseKeyGroup(group) {
19119
+ const MODIFIERS = ['ctrl', 'shift', 'alt', 'meta', 'cmd'];
19106
19120
 
19107
- // Use the shared combination splitting logic
19108
- const parts = splitKeyCombination(group.toLowerCase());
19121
+ // Use the shared combination splitting logic
19122
+ const parts = splitKeyCombination(group.toLowerCase());
19109
19123
 
19110
- // If the combination is invalid, return empty result
19111
- if (parts.length === 0) {
19112
- return {
19113
- modifiers: Object.fromEntries(MODIFIERS.map(m => [m, false])),
19114
- actualKey: undefined
19115
- };
19116
- }
19117
- const modifiers = Object.fromEntries(MODIFIERS.map(m => [m, false]));
19118
- let actualKey;
19119
- for (const part of parts) {
19120
- if (MODIFIERS.includes(part)) {
19121
- modifiers[part] = true;
19122
- } else {
19123
- actualKey = part;
19124
- }
19125
- }
19124
+ // If the combination is invalid, return empty result
19125
+ if (parts.length === 0) {
19126
19126
  return {
19127
- modifiers,
19128
- actualKey
19127
+ modifiers: Object.fromEntries(MODIFIERS.map(m => [m, false])),
19128
+ actualKey: undefined
19129
19129
  };
19130
19130
  }
19131
- function matchesKeyGroup(e, group) {
19132
- const {
19133
- modifiers,
19134
- actualKey
19135
- } = parseKeyGroup(group);
19136
- const expectCtrl = modifiers.ctrl || !isMac && (modifiers.cmd || modifiers.meta);
19137
- const expectMeta = isMac && (modifiers.cmd || modifiers.meta);
19138
- return e.ctrlKey === expectCtrl && e.metaKey === expectMeta && e.shiftKey === modifiers.shift && e.altKey === modifiers.alt && e.key.toLowerCase() === actualKey?.toLowerCase();
19131
+ const modifiers = Object.fromEntries(MODIFIERS.map(m => [m, false]));
19132
+ let actualKey;
19133
+ for (const part of parts) {
19134
+ if (MODIFIERS.includes(part)) {
19135
+ modifiers[part] = true;
19136
+ } else {
19137
+ actualKey = part;
19138
+ }
19139
19139
  }
19140
- return cleanup;
19140
+ return {
19141
+ modifiers,
19142
+ actualKey
19143
+ };
19141
19144
  }
19142
19145
 
19143
19146
  // Utilities
@@ -23767,11 +23770,15 @@
23767
23770
  return week.length ? adapter.getWeek(week[0], props.firstDayOfWeek, props.firstDayOfYear) : null;
23768
23771
  });
23769
23772
  });
23773
+ const {
23774
+ minDate,
23775
+ maxDate
23776
+ } = useCalendarRange(props);
23770
23777
  function isDisabled(value) {
23771
23778
  if (props.disabled) return true;
23772
23779
  const date = adapter.date(value);
23773
- if (props.min && adapter.isBefore(adapter.endOfDay(date), adapter.date(props.min))) return true;
23774
- if (props.max && adapter.isAfter(date, adapter.date(props.max))) return true;
23780
+ if (minDate.value && adapter.isBefore(adapter.endOfDay(date), minDate.value)) return true;
23781
+ if (maxDate.value && adapter.isAfter(date, maxDate.value)) return true;
23775
23782
  if (Array.isArray(props.allowedDates) && props.allowedDates.length > 0) {
23776
23783
  return !props.allowedDates.some(d => adapter.isSameDay(adapter.date(d), date));
23777
23784
  }
@@ -23791,6 +23798,37 @@
23791
23798
  weekNumbers
23792
23799
  };
23793
23800
  }
23801
+ function useCalendarRange(props) {
23802
+ const adapter = useDate();
23803
+ const minDate = vue.computed(() => {
23804
+ if (!props.min) return null;
23805
+ const date = adapter.date(props.min);
23806
+ return adapter.isValid(date) ? date : null;
23807
+ });
23808
+ const maxDate = vue.computed(() => {
23809
+ if (!props.max) return null;
23810
+ const date = adapter.date(props.max);
23811
+ return adapter.isValid(date) ? date : null;
23812
+ });
23813
+ function clampDate(date) {
23814
+ if (minDate.value && adapter.isBefore(date, minDate.value)) {
23815
+ return minDate.value;
23816
+ }
23817
+ if (maxDate.value && adapter.isAfter(date, maxDate.value)) {
23818
+ return maxDate.value;
23819
+ }
23820
+ return date;
23821
+ }
23822
+ function isInAllowedRange(date) {
23823
+ return (!minDate.value || adapter.isAfter(date, minDate.value)) && (!maxDate.value || adapter.isBefore(date, maxDate.value));
23824
+ }
23825
+ return {
23826
+ minDate,
23827
+ maxDate,
23828
+ clampDate,
23829
+ isInAllowedRange
23830
+ };
23831
+ }
23794
23832
 
23795
23833
  // Types
23796
23834
 
@@ -24231,24 +24269,14 @@
24231
24269
  const viewMode = useProxiedModel(props, 'viewMode');
24232
24270
  // const inputMode = useProxiedModel(props, 'inputMode')
24233
24271
 
24234
- const minDate = vue.computed(() => {
24235
- const date = adapter.date(props.min);
24236
- return props.min && adapter.isValid(date) ? date : null;
24237
- });
24238
- const maxDate = vue.computed(() => {
24239
- const date = adapter.date(props.max);
24240
- return props.max && adapter.isValid(date) ? date : null;
24241
- });
24272
+ const {
24273
+ minDate,
24274
+ maxDate,
24275
+ clampDate
24276
+ } = useCalendarRange(props);
24242
24277
  const internal = vue.computed(() => {
24243
24278
  const today = adapter.date();
24244
- let value = today;
24245
- if (model.value?.[0]) {
24246
- value = adapter.date(model.value[0]);
24247
- } else if (minDate.value && adapter.isBefore(today, minDate.value)) {
24248
- value = minDate.value;
24249
- } else if (maxDate.value && adapter.isAfter(today, maxDate.value)) {
24250
- value = maxDate.value;
24251
- }
24279
+ const value = model.value?.[0] ? adapter.date(model.value[0]) : clampDate(today);
24252
24280
  return value && adapter.isValid(value) ? value : today;
24253
24281
  });
24254
24282
  const headerColor = vue.toRef(() => props.headerColor ?? props.color);
@@ -30035,14 +30063,24 @@
30035
30063
  }
30036
30064
  function onInput(e) {
30037
30065
  const el = e.target;
30038
- model.value = el.value;
30039
- if (props.modelModifiers?.trim) {
30040
- const caretPosition = [el.selectionStart, el.selectionEnd];
30041
- vue.nextTick(() => {
30042
- el.selectionStart = caretPosition[0];
30043
- el.selectionEnd = caretPosition[1];
30044
- });
30066
+ if (!props.modelModifiers?.trim) {
30067
+ model.value = el.value;
30068
+ return;
30045
30069
  }
30070
+ const value = el.value;
30071
+ const start = el.selectionStart;
30072
+ const end = el.selectionEnd;
30073
+ model.value = value;
30074
+ vue.nextTick(() => {
30075
+ let offset = 0;
30076
+ if (value.trimStart().length === el.value.length) {
30077
+ // #22307 - Whitespace has been removed from the
30078
+ // start, offset the caret position to compensate
30079
+ offset = value.length - el.value.length;
30080
+ }
30081
+ if (start != null) el.selectionStart = start - offset;
30082
+ if (end != null) el.selectionEnd = end - offset;
30083
+ });
30046
30084
  }
30047
30085
  const sizerRef = vue.ref();
30048
30086
  const rows = vue.ref(Number(props.rows));
@@ -34841,15 +34879,10 @@
34841
34879
  const {
34842
34880
  mobile
34843
34881
  } = useDisplay(props);
34844
- const clamp = date => {
34845
- if (props.max && adapter.isAfter(date, props.max)) {
34846
- return props.max;
34847
- }
34848
- if (props.min && adapter.isBefore(date, props.min)) {
34849
- return props.min;
34850
- }
34851
- return date;
34852
- };
34882
+ const {
34883
+ clampDate,
34884
+ isInAllowedRange
34885
+ } = useCalendarRange(props);
34853
34886
  const emptyModelValue = () => props.multiple ? [] : null;
34854
34887
  const model = useProxiedModel(props, 'modelValue', emptyModelValue(), val => Array.isArray(val) ? val.map(item => adapter.toJsDate(item)) : val ? adapter.toJsDate(val) : val, val => Array.isArray(val) ? val.map(item => adapter.date(item)) : val ? adapter.date(val) : val);
34855
34888
  const menu = useProxiedModel(props, 'menu');
@@ -34945,16 +34978,16 @@
34945
34978
  model.value = emptyModelValue();
34946
34979
  } else if (!props.multiple) {
34947
34980
  if (isValid(value)) {
34948
- model.value = clamp(parseDate(value));
34981
+ model.value = clampDate(parseDate(value));
34949
34982
  }
34950
34983
  } else {
34951
34984
  const parts = value.trim().split(/\D+-\D+|[^\d\-/.]+/);
34952
34985
  if (parts.every(isValid)) {
34953
34986
  if (props.multiple === 'range') {
34954
- const [start, stop] = parts.map(parseDate).map(clamp).toSorted((a, b) => adapter.isAfter(a, b) ? 1 : -1);
34987
+ const [start, stop] = parts.map(parseDate).map(clampDate).toSorted((a, b) => adapter.isAfter(a, b) ? 1 : -1);
34955
34988
  model.value = createDateRange(adapter, start, stop);
34956
34989
  } else {
34957
- model.value = parts.map(parseDate).map(clamp);
34990
+ model.value = parts.map(parseDate).filter(isInAllowedRange);
34958
34991
  }
34959
34992
  }
34960
34993
  }
@@ -36568,7 +36601,7 @@
36568
36601
 
36569
36602
  // Key display tuple: [mode, content] where content is string or IconValue
36570
36603
 
36571
- // Key tuple: [mode, content] where content is string or IconValue
36604
+ // Key tuple: [mode, content, keycode] where content is string or IconValue
36572
36605
 
36573
36606
  function processKey(config, requestedMode, isMac) {
36574
36607
  const keyCfg = isMac && config.mac ? config.mac : config.default;
@@ -36707,15 +36740,6 @@
36707
36740
  }
36708
36741
  }
36709
36742
  };
36710
-
36711
- // Create custom variant props that extend the base variant props with our 'contained' option
36712
- const makeVHotkeyVariantProps = propsFactory({
36713
- variant: {
36714
- type: String,
36715
- default: 'elevated',
36716
- validator: v => ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain', 'contained'].includes(v)
36717
- }
36718
- }, 'VHotkeyVariant');
36719
36743
  const makeVHotkeyProps = propsFactory({
36720
36744
  // String representing keyboard shortcuts (e.g., "ctrl+k", "meta+shift+p")
36721
36745
  keys: String,
@@ -36737,30 +36761,21 @@
36737
36761
  disabled: Boolean,
36738
36762
  prefix: String,
36739
36763
  suffix: String,
36764
+ variant: {
36765
+ type: String,
36766
+ default: 'elevated',
36767
+ validator: v => ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain', 'contained'].includes(v)
36768
+ },
36740
36769
  ...makeComponentProps(),
36741
36770
  ...makeThemeProps(),
36742
36771
  ...makeBorderProps(),
36743
36772
  ...makeRoundedProps(),
36744
36773
  ...makeElevationProps(),
36745
- ...makeVHotkeyVariantProps(),
36746
36774
  color: String
36747
36775
  }, 'VHotkey');
36748
- class Delineator {
36749
- constructor(delineator) {
36750
- if (['and', 'then'].includes(delineator)) this.val = delineator;else {
36751
- throw new Error('Not a valid delineator');
36752
- }
36753
- }
36754
- isEqual(d) {
36755
- return this.val === d.val;
36756
- }
36757
- }
36758
- function isDelineator(value) {
36759
- return value instanceof Delineator;
36760
- }
36761
- function isString(value) {
36762
- return typeof value === 'string';
36763
- }
36776
+ const AND_DELINEATOR = Symbol('VHotkey:AND_DELINEATOR'); // For + separators
36777
+ const THEN_DELINEATOR = Symbol('VHotkey:THEN_DELINEATOR'); // For - separators
36778
+
36764
36779
  function getKeyText(keyMap, key, isMac) {
36765
36780
  const lowerKey = key.toLowerCase();
36766
36781
  if (lowerKey in keyMap) {
@@ -36802,57 +36817,38 @@
36802
36817
  const {
36803
36818
  elevationClasses
36804
36819
  } = useElevation(props);
36805
- const isContainedVariant = vue.computed(() => props.variant === 'contained');
36806
- const effectiveVariantProps = vue.computed(() => ({
36807
- ...props,
36808
- variant: isContainedVariant.value ? 'elevated' : props.variant
36809
- }));
36810
36820
  const {
36811
36821
  colorClasses,
36812
36822
  colorStyles,
36813
36823
  variantClasses
36814
- } = useVariant(effectiveVariantProps);
36824
+ } = useVariant(() => ({
36825
+ color: props.color,
36826
+ variant: props.variant === 'contained' ? 'elevated' : props.variant
36827
+ }));
36815
36828
  const isMac = vue.computed(() => props.platform === 'auto' ? typeof navigator !== 'undefined' && /macintosh/i.test(navigator.userAgent) : props.platform === 'mac');
36816
- const effectiveDisplayMode = vue.computed(() => props.displayMode);
36817
- const AND_DELINEATOR = new Delineator('and'); // For + separators
36818
- const THEN_DELINEATOR = new Delineator('then'); // For - separators
36819
-
36820
- const effectiveKeyMap = vue.computed(() => props.keyMap);
36821
36829
  const keyCombinations = vue.computed(() => {
36822
36830
  if (!props.keys) return [];
36823
36831
 
36824
36832
  // Split by spaces to handle multiple key combinations
36825
36833
  // Example: "ctrl+k meta+p" -> ["ctrl+k", "meta+p"]
36826
36834
  return props.keys.split(' ').map(combination => {
36827
- // Use the shared sequence splitting logic
36835
+ const result = [];
36828
36836
  const sequenceGroups = splitKeySequence(combination);
36829
-
36830
- // Process each sequence group
36831
- return sequenceGroups.flatMap((group, groupIndex) => {
36832
- // Use the shared key combination splitting logic
36833
- const keyParts = splitKeyCombination(group);
36834
- const parts = keyParts.reduce((acc, part, index) => {
36835
- if (index !== 0) {
36836
- // Add AND delineator between keys
36837
- return [...acc, AND_DELINEATOR, part];
36838
- }
36839
- return [...acc, part];
36840
- }, []);
36837
+ for (let i = 0; i < sequenceGroups.length; i++) {
36838
+ const group = sequenceGroups[i];
36841
36839
 
36842
36840
  // Add THEN delineator between sequence groups
36843
- const result = parts.map(key => {
36844
- if (isString(key)) {
36845
- return applyDisplayModeToKey(effectiveKeyMap.value, effectiveDisplayMode.value, key, isMac.value);
36846
- }
36847
- return key;
36848
- });
36841
+ if (i > 0) result.push(THEN_DELINEATOR);
36842
+ const keyParts = splitKeyCombination(group);
36843
+ for (let j = 0; j < keyParts.length; j++) {
36844
+ const part = keyParts[j];
36849
36845
 
36850
- // Add sequence separator if not the last group
36851
- if (groupIndex < sequenceGroups.length - 1) {
36852
- result.push(THEN_DELINEATOR);
36846
+ // Add AND delineator between keys
36847
+ if (j > 0) result.push(AND_DELINEATOR);
36848
+ result.push(applyDisplayModeToKey(props.keyMap, props.displayMode, part, isMac.value));
36853
36849
  }
36854
- return result;
36855
- });
36850
+ }
36851
+ return result;
36856
36852
  });
36857
36853
  });
36858
36854
  const accessibleLabel = vue.computed(() => {
@@ -36862,16 +36858,16 @@
36862
36858
  const readableShortcuts = keyCombinations.value.map(combination => {
36863
36859
  const readableParts = [];
36864
36860
  for (const key of combination) {
36865
- if (isDelineator(key)) {
36866
- if (AND_DELINEATOR.isEqual(key)) {
36867
- readableParts.push(t('$vuetify.hotkey.plus'));
36868
- } else if (THEN_DELINEATOR.isEqual(key)) {
36869
- readableParts.push(t('$vuetify.hotkey.then'));
36870
- }
36871
- } else {
36861
+ if (Array.isArray(key)) {
36872
36862
  // Always use text representation for screen readers
36873
36863
  const textKey = key[0] === 'icon' || key[0] === 'symbol' ? applyDisplayModeToKey(mergeDeep(hotkeyMap, props.keyMap), 'text', String(key[1]), isMac.value)[1] : key[1];
36874
36864
  readableParts.push(translateKey(textKey));
36865
+ } else {
36866
+ if (key === AND_DELINEATOR) {
36867
+ readableParts.push(t('$vuetify.hotkey.plus'));
36868
+ } else if (key === THEN_DELINEATOR) {
36869
+ readableParts.push(t('$vuetify.hotkey.then'));
36870
+ }
36875
36871
  }
36876
36872
  }
36877
36873
  return readableParts.join(' ');
@@ -36883,11 +36879,12 @@
36883
36879
  return key.startsWith('$vuetify.') ? t(key) : key;
36884
36880
  }
36885
36881
  function getKeyTooltip(key) {
36886
- if (effectiveDisplayMode.value === 'text') return undefined;
36887
- const textKey = getKeyText(effectiveKeyMap.value, String(key[2]), isMac.value);
36882
+ if (props.displayMode === 'text') return undefined;
36883
+ const textKey = getKeyText(props.keyMap, String(key[2]), isMac.value);
36888
36884
  return translateKey(textKey);
36889
36885
  }
36890
- function renderKey(key, keyIndex, isContained) {
36886
+ function renderKey(key, keyIndex) {
36887
+ const isContained = props.variant === 'contained';
36891
36888
  const KeyComponent = isContained ? 'kbd' : VKbd;
36892
36889
  const keyClasses = ['v-hotkey__key', `v-hotkey__key-${key[0]}`, ...(isContained ? ['v-hotkey__key--nested'] : [borderClasses.value, roundedClasses.value, elevationClasses.value, colorClasses.value])];
36893
36890
  return vue.createVNode(KeyComponent, {
@@ -36908,47 +36905,39 @@
36908
36905
  "key": keyIndex,
36909
36906
  "class": "v-hotkey__divider",
36910
36907
  "aria-hidden": "true"
36911
- }, [AND_DELINEATOR.isEqual(key) ? '+' : t('$vuetify.hotkey.then')]);
36908
+ }, [key === AND_DELINEATOR ? '+' : t('$vuetify.hotkey.then')]);
36912
36909
  }
36913
- useRender(() => vue.createElementVNode("div", {
36914
- "class": vue.normalizeClass(['v-hotkey', {
36915
- 'v-hotkey--disabled': props.disabled,
36916
- 'v-hotkey--inline': props.inline,
36917
- 'v-hotkey--contained': isContainedVariant.value
36918
- }, themeClasses.value, rtlClasses.value, variantClasses.value, props.class]),
36919
- "style": vue.normalizeStyle(props.style),
36920
- "role": "img",
36921
- "aria-label": accessibleLabel.value
36922
- }, [isContainedVariant.value ? vue.createVNode(VKbd, {
36923
- "key": "contained",
36924
- "class": vue.normalizeClass(['v-hotkey__contained-wrapper', borderClasses.value, roundedClasses.value, elevationClasses.value, colorClasses.value]),
36925
- "style": vue.normalizeStyle(colorStyles.value),
36926
- "aria-hidden": "true"
36927
- }, {
36928
- default: () => [props.prefix && vue.createElementVNode("span", {
36929
- "key": "contained-prefix",
36910
+ useRender(() => {
36911
+ const content = vue.createElementVNode(vue.Fragment, null, [props.prefix && vue.createElementVNode("span", {
36912
+ "key": "prefix",
36930
36913
  "class": "v-hotkey__prefix"
36931
36914
  }, [props.prefix]), keyCombinations.value.map((combination, comboIndex) => vue.createElementVNode("span", {
36932
36915
  "class": "v-hotkey__combination",
36933
36916
  "key": comboIndex
36934
- }, [combination.map((key, keyIndex) => isDelineator(key) ? renderDivider(key, keyIndex) : renderKey(key, keyIndex, true)), comboIndex < keyCombinations.value.length - 1 && vue.createElementVNode("span", {
36917
+ }, [combination.map((key, keyIndex) => Array.isArray(key) ? renderKey(key, keyIndex) : renderDivider(key, keyIndex)), comboIndex < keyCombinations.value.length - 1 && vue.createElementVNode("span", {
36935
36918
  "aria-hidden": "true"
36936
36919
  }, [vue.createTextVNode("\xA0")])])), props.suffix && vue.createElementVNode("span", {
36937
- "key": "contained-suffix",
36920
+ "key": "suffix",
36938
36921
  "class": "v-hotkey__suffix"
36939
- }, [props.suffix])]
36940
- }) : vue.createElementVNode(vue.Fragment, null, [props.prefix && vue.createElementVNode("span", {
36941
- "key": "prefix",
36942
- "class": "v-hotkey__prefix"
36943
- }, [props.prefix]), keyCombinations.value.map((combination, comboIndex) => vue.createElementVNode("span", {
36944
- "class": "v-hotkey__combination",
36945
- "key": comboIndex
36946
- }, [combination.map((key, keyIndex) => isDelineator(key) ? renderDivider(key, keyIndex) : renderKey(key, keyIndex, false)), comboIndex < keyCombinations.value.length - 1 && vue.createElementVNode("span", {
36947
- "aria-hidden": "true"
36948
- }, [vue.createTextVNode("\xA0")])])), props.suffix && vue.createElementVNode("span", {
36949
- "key": "suffix",
36950
- "class": "v-hotkey__suffix"
36951
- }, [props.suffix])])]));
36922
+ }, [props.suffix])]);
36923
+ return vue.createElementVNode("div", {
36924
+ "class": vue.normalizeClass(['v-hotkey', {
36925
+ 'v-hotkey--disabled': props.disabled,
36926
+ 'v-hotkey--inline': props.inline,
36927
+ 'v-hotkey--contained': props.variant === 'contained'
36928
+ }, themeClasses.value, rtlClasses.value, variantClasses.value, props.class]),
36929
+ "style": vue.normalizeStyle(props.style),
36930
+ "role": "img",
36931
+ "aria-label": accessibleLabel.value
36932
+ }, [props.variant !== 'contained' ? content : vue.createVNode(VKbd, {
36933
+ "key": "contained",
36934
+ "class": vue.normalizeClass(['v-hotkey__contained-wrapper', borderClasses.value, roundedClasses.value, elevationClasses.value, colorClasses.value]),
36935
+ "style": vue.normalizeStyle(colorStyles.value),
36936
+ "aria-hidden": "true"
36937
+ }, {
36938
+ default: () => [content]
36939
+ })]);
36940
+ });
36952
36941
  }
36953
36942
  });
36954
36943
 
@@ -38154,7 +38143,7 @@
38154
38143
  };
38155
38144
  });
38156
38145
  }
38157
- const version$1 = "3.10.8";
38146
+ const version$1 = "3.10.10";
38158
38147
  createVuetify$1.version = version$1;
38159
38148
 
38160
38149
  // Vue's inject() can only be used in setup
@@ -38452,7 +38441,7 @@
38452
38441
 
38453
38442
  /* eslint-disable local-rules/sort-imports */
38454
38443
 
38455
- const version = "3.10.8";
38444
+ const version = "3.10.10";
38456
38445
 
38457
38446
  /* eslint-disable local-rules/sort-imports */
38458
38447