@vuetify/nightly 3.9.0-beta.0-dev.2025-06-24 → 3.9.0-beta.1-dev.2025-06-28

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 (212) hide show
  1. package/CHANGELOG.md +4 -83
  2. package/dist/_component-variables-labs.sass +1 -0
  3. package/dist/json/attributes.json +2471 -2411
  4. package/dist/json/importMap-labs.json +34 -30
  5. package/dist/json/importMap.json +146 -146
  6. package/dist/json/tags.json +20 -0
  7. package/dist/json/web-types.json +4808 -4642
  8. package/dist/vuetify-labs.cjs +750 -15
  9. package/dist/vuetify-labs.css +5609 -5358
  10. package/dist/vuetify-labs.d.ts +300 -54
  11. package/dist/vuetify-labs.esm.js +750 -16
  12. package/dist/vuetify-labs.esm.js.map +1 -1
  13. package/dist/vuetify-labs.js +750 -15
  14. package/dist/vuetify-labs.min.css +2 -2
  15. package/dist/vuetify.cjs +357 -15
  16. package/dist/vuetify.cjs.map +1 -1
  17. package/dist/vuetify.css +3235 -3226
  18. package/dist/vuetify.d.ts +73 -53
  19. package/dist/vuetify.esm.js +357 -16
  20. package/dist/vuetify.esm.js.map +1 -1
  21. package/dist/vuetify.js +357 -15
  22. package/dist/vuetify.js.map +1 -1
  23. package/dist/vuetify.min.css +2 -2
  24. package/dist/vuetify.min.js +292 -253
  25. package/dist/vuetify.min.js.map +1 -1
  26. package/lib/components/VKbd/VKbd.css +14 -5
  27. package/lib/components/VKbd/VKbd.js.map +1 -1
  28. package/lib/components/VKbd/VKbd.scss +26 -0
  29. package/lib/components/VKbd/_variables.scss +12 -6
  30. package/lib/components/VKbd/index.js.map +1 -1
  31. package/lib/components/VTreeview/VTreeviewChildren.d.ts +13 -0
  32. package/lib/components/VTreeview/VTreeviewChildren.js +2 -1
  33. package/lib/components/VTreeview/VTreeviewChildren.js.map +1 -1
  34. package/lib/components/VTreeview/VTreeviewItem.js +3 -3
  35. package/lib/components/VTreeview/VTreeviewItem.js.map +1 -1
  36. package/lib/composables/hotkey/hotkey-parsing.d.ts +15 -0
  37. package/lib/composables/hotkey/hotkey-parsing.js +154 -0
  38. package/lib/composables/hotkey/hotkey-parsing.js.map +1 -0
  39. package/lib/composables/hotkey/hotkey.d.ts +9 -0
  40. package/lib/composables/{hotkey.js → hotkey/hotkey.js} +31 -39
  41. package/lib/composables/hotkey/hotkey.js.map +1 -0
  42. package/lib/composables/hotkey/index.d.ts +1 -0
  43. package/lib/composables/hotkey/index.js +2 -0
  44. package/lib/composables/hotkey/index.js.map +1 -0
  45. package/lib/composables/hotkey/key-aliases.d.ts +14 -0
  46. package/lib/composables/hotkey/key-aliases.js +38 -0
  47. package/lib/composables/hotkey/key-aliases.js.map +1 -0
  48. package/lib/composables/icons.d.ts +11 -0
  49. package/lib/composables/icons.js.map +1 -1
  50. package/lib/composables/index.d.ts +1 -0
  51. package/lib/composables/index.js +1 -0
  52. package/lib/composables/index.js.map +1 -1
  53. package/lib/composables/nested/nested.js +8 -8
  54. package/lib/composables/nested/nested.js.map +1 -1
  55. package/lib/entry-bundler.js +1 -1
  56. package/lib/framework.d.ts +74 -53
  57. package/lib/framework.js +1 -1
  58. package/lib/iconsets/fa.js +12 -1
  59. package/lib/iconsets/fa.js.map +1 -1
  60. package/lib/iconsets/fa4.js +12 -1
  61. package/lib/iconsets/fa4.js.map +1 -1
  62. package/lib/iconsets/md.js +12 -1
  63. package/lib/iconsets/md.js.map +1 -1
  64. package/lib/iconsets/mdi-svg.js +12 -1
  65. package/lib/iconsets/mdi-svg.js.map +1 -1
  66. package/lib/iconsets/mdi.js +12 -1
  67. package/lib/iconsets/mdi.js.map +1 -1
  68. package/lib/labs/VHotkey/VHotkey.css +242 -0
  69. package/lib/labs/VHotkey/VHotkey.d.ts +387 -0
  70. package/lib/labs/VHotkey/VHotkey.js +432 -0
  71. package/lib/labs/VHotkey/VHotkey.js.map +1 -0
  72. package/lib/labs/VHotkey/VHotkey.scss +253 -0
  73. package/lib/labs/VHotkey/_variables.scss +43 -0
  74. package/lib/labs/VHotkey/index.d.ts +1 -0
  75. package/lib/labs/VHotkey/index.js +2 -0
  76. package/lib/labs/VHotkey/index.js.map +1 -0
  77. package/lib/labs/components.d.ts +1 -0
  78. package/lib/labs/components.js +1 -0
  79. package/lib/labs/components.js.map +1 -1
  80. package/lib/locale/af.d.ts +18 -0
  81. package/lib/locale/af.js +18 -0
  82. package/lib/locale/af.js.map +1 -1
  83. package/lib/locale/ar.d.ts +18 -0
  84. package/lib/locale/ar.js +18 -0
  85. package/lib/locale/ar.js.map +1 -1
  86. package/lib/locale/az.d.ts +18 -0
  87. package/lib/locale/az.js +18 -0
  88. package/lib/locale/az.js.map +1 -1
  89. package/lib/locale/bg.d.ts +18 -0
  90. package/lib/locale/bg.js +18 -0
  91. package/lib/locale/bg.js.map +1 -1
  92. package/lib/locale/ca.d.ts +18 -0
  93. package/lib/locale/ca.js +18 -0
  94. package/lib/locale/ca.js.map +1 -1
  95. package/lib/locale/ckb.d.ts +18 -0
  96. package/lib/locale/ckb.js +18 -0
  97. package/lib/locale/ckb.js.map +1 -1
  98. package/lib/locale/cs.d.ts +18 -0
  99. package/lib/locale/cs.js +18 -0
  100. package/lib/locale/cs.js.map +1 -1
  101. package/lib/locale/da.d.ts +18 -0
  102. package/lib/locale/da.js +18 -0
  103. package/lib/locale/da.js.map +1 -1
  104. package/lib/locale/de.d.ts +18 -0
  105. package/lib/locale/de.js +18 -0
  106. package/lib/locale/de.js.map +1 -1
  107. package/lib/locale/el.d.ts +18 -0
  108. package/lib/locale/el.js +18 -0
  109. package/lib/locale/el.js.map +1 -1
  110. package/lib/locale/en.d.ts +18 -0
  111. package/lib/locale/en.js +18 -0
  112. package/lib/locale/en.js.map +1 -1
  113. package/lib/locale/es.d.ts +18 -0
  114. package/lib/locale/es.js +18 -0
  115. package/lib/locale/es.js.map +1 -1
  116. package/lib/locale/et.d.ts +18 -0
  117. package/lib/locale/et.js +18 -0
  118. package/lib/locale/et.js.map +1 -1
  119. package/lib/locale/fa.d.ts +18 -0
  120. package/lib/locale/fa.js +18 -0
  121. package/lib/locale/fa.js.map +1 -1
  122. package/lib/locale/fi.d.ts +18 -0
  123. package/lib/locale/fi.js +18 -0
  124. package/lib/locale/fi.js.map +1 -1
  125. package/lib/locale/fr.d.ts +18 -0
  126. package/lib/locale/fr.js +18 -0
  127. package/lib/locale/fr.js.map +1 -1
  128. package/lib/locale/he.d.ts +18 -0
  129. package/lib/locale/he.js +18 -0
  130. package/lib/locale/he.js.map +1 -1
  131. package/lib/locale/hr.d.ts +18 -0
  132. package/lib/locale/hr.js +18 -0
  133. package/lib/locale/hr.js.map +1 -1
  134. package/lib/locale/hu.d.ts +18 -0
  135. package/lib/locale/hu.js +18 -0
  136. package/lib/locale/hu.js.map +1 -1
  137. package/lib/locale/id.d.ts +18 -0
  138. package/lib/locale/id.js +18 -0
  139. package/lib/locale/id.js.map +1 -1
  140. package/lib/locale/it.d.ts +18 -0
  141. package/lib/locale/it.js +18 -0
  142. package/lib/locale/it.js.map +1 -1
  143. package/lib/locale/ja.d.ts +18 -0
  144. package/lib/locale/ja.js +18 -0
  145. package/lib/locale/ja.js.map +1 -1
  146. package/lib/locale/km.d.ts +18 -0
  147. package/lib/locale/km.js +18 -0
  148. package/lib/locale/km.js.map +1 -1
  149. package/lib/locale/ko.d.ts +18 -0
  150. package/lib/locale/ko.js +18 -0
  151. package/lib/locale/ko.js.map +1 -1
  152. package/lib/locale/lt.d.ts +18 -0
  153. package/lib/locale/lt.js +18 -0
  154. package/lib/locale/lt.js.map +1 -1
  155. package/lib/locale/lv.d.ts +18 -0
  156. package/lib/locale/lv.js +18 -0
  157. package/lib/locale/lv.js.map +1 -1
  158. package/lib/locale/nl.d.ts +18 -0
  159. package/lib/locale/nl.js +18 -0
  160. package/lib/locale/nl.js.map +1 -1
  161. package/lib/locale/no.d.ts +18 -0
  162. package/lib/locale/no.js +18 -0
  163. package/lib/locale/no.js.map +1 -1
  164. package/lib/locale/pl.d.ts +18 -0
  165. package/lib/locale/pl.js +18 -0
  166. package/lib/locale/pl.js.map +1 -1
  167. package/lib/locale/pt.d.ts +18 -0
  168. package/lib/locale/pt.js +18 -0
  169. package/lib/locale/pt.js.map +1 -1
  170. package/lib/locale/ro.d.ts +18 -0
  171. package/lib/locale/ro.js +18 -0
  172. package/lib/locale/ro.js.map +1 -1
  173. package/lib/locale/ru.d.ts +18 -0
  174. package/lib/locale/ru.js +18 -0
  175. package/lib/locale/ru.js.map +1 -1
  176. package/lib/locale/sk.d.ts +18 -0
  177. package/lib/locale/sk.js +18 -0
  178. package/lib/locale/sk.js.map +1 -1
  179. package/lib/locale/sl.d.ts +18 -0
  180. package/lib/locale/sl.js +18 -0
  181. package/lib/locale/sl.js.map +1 -1
  182. package/lib/locale/sr-Cyrl.d.ts +18 -0
  183. package/lib/locale/sr-Cyrl.js +18 -0
  184. package/lib/locale/sr-Cyrl.js.map +1 -1
  185. package/lib/locale/sr-Latn.d.ts +18 -0
  186. package/lib/locale/sr-Latn.js +18 -0
  187. package/lib/locale/sr-Latn.js.map +1 -1
  188. package/lib/locale/sv.d.ts +18 -0
  189. package/lib/locale/sv.js +18 -0
  190. package/lib/locale/sv.js.map +1 -1
  191. package/lib/locale/th.d.ts +18 -0
  192. package/lib/locale/th.js +18 -0
  193. package/lib/locale/th.js.map +1 -1
  194. package/lib/locale/tr.d.ts +18 -0
  195. package/lib/locale/tr.js +18 -0
  196. package/lib/locale/tr.js.map +1 -1
  197. package/lib/locale/uk.d.ts +18 -0
  198. package/lib/locale/uk.js +18 -0
  199. package/lib/locale/uk.js.map +1 -1
  200. package/lib/locale/vi.d.ts +18 -0
  201. package/lib/locale/vi.js +18 -0
  202. package/lib/locale/vi.js.map +1 -1
  203. package/lib/locale/zh-Hans.d.ts +18 -0
  204. package/lib/locale/zh-Hans.js +18 -0
  205. package/lib/locale/zh-Hans.js.map +1 -1
  206. package/lib/locale/zh-Hant.d.ts +18 -0
  207. package/lib/locale/zh-Hant.js +18 -0
  208. package/lib/locale/zh-Hant.js.map +1 -1
  209. package/package.json +1 -1
  210. package/lib/components/VKbd/VKbd.sass +0 -15
  211. package/lib/composables/hotkey.d.ts +0 -9
  212. package/lib/composables/hotkey.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.9.0-beta.0-dev.2025-06-24
2
+ * Vuetify v3.9.0-beta.1-dev.2025-06-28
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
@@ -1832,7 +1832,18 @@ const aliases = {
1832
1832
  treeviewExpand: 'mdi-menu-right',
1833
1833
  eyeDropper: 'mdi-eyedropper',
1834
1834
  upload: 'mdi-cloud-upload',
1835
- color: 'mdi-palette'
1835
+ color: 'mdi-palette',
1836
+ command: 'mdi-apple-keyboard-command',
1837
+ ctrl: 'mdi-apple-keyboard-control',
1838
+ space: 'mdi-keyboard-space',
1839
+ shift: 'mdi-apple-keyboard-shift',
1840
+ alt: 'mdi-apple-keyboard-option',
1841
+ enter: 'mdi-keyboard-return',
1842
+ arrowup: 'mdi-arrow-up',
1843
+ arrowdown: 'mdi-arrow-down',
1844
+ arrowleft: 'mdi-arrow-left',
1845
+ arrowright: 'mdi-arrow-right',
1846
+ backspace: 'mdi-backspace'
1836
1847
  };
1837
1848
  const mdi = {
1838
1849
  // Not using mergeProps here, functional components merge props by default (?)
@@ -2628,6 +2639,24 @@ var en = {
2628
2639
  exclude: 'The {0} character is not allowed',
2629
2640
  notEmpty: 'Please choose at least one value',
2630
2641
  pattern: 'Invalid format'
2642
+ },
2643
+ hotkey: {
2644
+ then: 'then',
2645
+ ctrl: 'Ctrl',
2646
+ command: 'Command',
2647
+ space: 'Space',
2648
+ shift: 'Shift',
2649
+ alt: 'Alt',
2650
+ enter: 'Enter',
2651
+ escape: 'Escape',
2652
+ upArrow: 'Up Arrow',
2653
+ downArrow: 'Down Arrow',
2654
+ leftArrow: 'Left Arrow',
2655
+ rightArrow: 'Right Arrow',
2656
+ backspace: 'Backspace',
2657
+ option: 'Option',
2658
+ plus: 'plus',
2659
+ shortcut: 'Keyboard shortcut: {0}'
2631
2660
  }
2632
2661
  };
2633
2662
 
@@ -9295,9 +9324,9 @@ const makeNestedProps = propsFactory({
9295
9324
  }, 'nested');
9296
9325
  const useNested = props => {
9297
9326
  let isUnmounted = false;
9298
- const children = ref(new Map());
9299
- const parents = ref(new Map());
9300
- const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(v), v => [...v.values()]);
9327
+ const children = shallowRef(new Map());
9328
+ const parents = shallowRef(new Map());
9329
+ const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(Array.isArray(v) ? v.map(i => toRaw(i)) : v), v => [...v.values()]);
9301
9330
  const activeStrategy = computed(() => {
9302
9331
  if (typeof props.activeStrategy === 'object') return props.activeStrategy;
9303
9332
  if (typeof props.activeStrategy === 'function') return props.activeStrategy(props.mandatory);
@@ -9351,7 +9380,7 @@ const useNested = props => {
9351
9380
  });
9352
9381
  function getPath(id) {
9353
9382
  const path = [];
9354
- let parent = id;
9383
+ let parent = toRaw(id);
9355
9384
  while (parent != null) {
9356
9385
  path.unshift(parent);
9357
9386
  parent = parents.value.get(parent);
@@ -9494,7 +9523,7 @@ const useNested = props => {
9494
9523
  const useNestedItem = (id, isGroup) => {
9495
9524
  const parent = inject$1(VNestedSymbol, emptyNested);
9496
9525
  const uidSymbol = Symbol('nested item');
9497
- const computedId = computed(() => toValue(id) ?? uidSymbol);
9526
+ const computedId = computed(() => toRaw(toValue(id)) ?? uidSymbol);
9498
9527
  const item = {
9499
9528
  ...parent,
9500
9529
  id: computedId,
@@ -9503,10 +9532,10 @@ const useNestedItem = (id, isGroup) => {
9503
9532
  isOpen: computed(() => parent.root.opened.value.has(computedId.value)),
9504
9533
  parent: computed(() => parent.root.parents.value.get(computedId.value)),
9505
9534
  activate: (activated, e) => parent.root.activate(computedId.value, activated, e),
9506
- isActivated: computed(() => parent.root.activated.value.has(toRaw(computedId.value))),
9535
+ isActivated: computed(() => parent.root.activated.value.has(computedId.value)),
9507
9536
  select: (selected, e) => parent.root.select(computedId.value, selected, e),
9508
- isSelected: computed(() => parent.root.selected.value.get(toRaw(computedId.value)) === 'on'),
9509
- isIndeterminate: computed(() => parent.root.selected.value.get(toRaw(computedId.value)) === 'indeterminate'),
9537
+ isSelected: computed(() => parent.root.selected.value.get(computedId.value) === 'on'),
9538
+ isIndeterminate: computed(() => parent.root.selected.value.get(computedId.value) === 'indeterminate'),
9510
9539
  isLeaf: computed(() => !parent.root.children.value.get(computedId.value)),
9511
9540
  isGroupActivator: parent.isGroupActivator
9512
9541
  };
@@ -18351,6 +18380,317 @@ function useDate() {
18351
18380
  return createInstance(options, locale);
18352
18381
  }
18353
18382
 
18383
+ /**
18384
+ * Centralized key alias mapping for consistent key normalization across the hotkey system.
18385
+ *
18386
+ * This maps various user-friendly aliases to canonical key names that match
18387
+ * KeyboardEvent.key values (in lowercase) where possible.
18388
+ */
18389
+ const keyAliasMap = {
18390
+ // Modifier aliases (from vue-use, other libraries, and current implementation)
18391
+ control: 'ctrl',
18392
+ command: 'cmd',
18393
+ option: 'alt',
18394
+ // Arrow key aliases (common abbreviations)
18395
+ up: 'arrowup',
18396
+ down: 'arrowdown',
18397
+ left: 'arrowleft',
18398
+ right: 'arrowright',
18399
+ // Other common key aliases
18400
+ esc: 'escape',
18401
+ spacebar: ' ',
18402
+ space: ' ',
18403
+ return: 'enter',
18404
+ del: 'delete',
18405
+ // Symbol aliases (existing from hotkey-parsing.ts)
18406
+ minus: '-',
18407
+ hyphen: '-'
18408
+ };
18409
+
18410
+ /**
18411
+ * Normalizes a key string to its canonical form using the alias map.
18412
+ *
18413
+ * @param key - The key string to normalize
18414
+ * @returns The canonical key name in lowercase
18415
+ */
18416
+ function normalizeKey(key) {
18417
+ const lowerKey = key.toLowerCase();
18418
+ return keyAliasMap[lowerKey] || lowerKey;
18419
+ }
18420
+
18421
+ // Utilities
18422
+
18423
+ /**
18424
+ * Splits a single combination string into individual key parts.
18425
+ *
18426
+ * A combination is a set of keys that must be pressed simultaneously.
18427
+ * e.g. `ctrl+k`, `shift--`
18428
+ */
18429
+ function splitKeyCombination(combination) {
18430
+ let isInternal = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
18431
+ if (!combination) {
18432
+ if (!isInternal) consoleWarn('Invalid hotkey combination: empty string provided');
18433
+ return [];
18434
+ }
18435
+
18436
+ // --- VALIDATION ---
18437
+ const startsWithPlusOrUnderscore = combination.startsWith('+') || combination.startsWith('_');
18438
+ const hasInvalidLeadingSeparator =
18439
+ // Starts with a single '+' or '_' followed by a non-separator character (e.g. '+a', '_a')
18440
+ startsWithPlusOrUnderscore && !(combination.startsWith('++') || combination.startsWith('__'));
18441
+ const hasInvalidStructure =
18442
+ // Invalid leading separator patterns
18443
+ combination.length > 1 && hasInvalidLeadingSeparator ||
18444
+ // Disallow literal + or _ keys (they require shift)
18445
+ combination.includes('++') || combination.includes('__') || combination === '+' || combination === '_' ||
18446
+ // Ends with a separator that is not part of a doubled literal
18447
+ combination.length > 1 && (combination.endsWith('+') || combination.endsWith('_')) && combination.at(-2) !== combination.at(-1) ||
18448
+ // Stand-alone doubled separators (dangling)
18449
+ combination === '++' || combination === '--' || combination === '__';
18450
+ if (hasInvalidStructure) {
18451
+ if (!isInternal) consoleWarn(`Invalid hotkey combination: "${combination}" has invalid structure`);
18452
+ return [];
18453
+ }
18454
+ const keys = [];
18455
+ let buffer = '';
18456
+ const flushBuffer = () => {
18457
+ if (buffer) {
18458
+ keys.push(normalizeKey(buffer));
18459
+ buffer = '';
18460
+ }
18461
+ };
18462
+ for (let i = 0; i < combination.length; i++) {
18463
+ const char = combination[i];
18464
+ const nextChar = combination[i + 1];
18465
+ if (char === '+' || char === '_' || char === '-') {
18466
+ if (char === nextChar) {
18467
+ flushBuffer();
18468
+ keys.push(char);
18469
+ i++;
18470
+ } else if (char === '+' || char === '_') {
18471
+ flushBuffer();
18472
+ } else {
18473
+ buffer += char;
18474
+ }
18475
+ } else {
18476
+ buffer += char;
18477
+ }
18478
+ }
18479
+ flushBuffer();
18480
+
18481
+ // Within a combination, `-` is only valid as a literal key (e.g., `ctrl+-`).
18482
+ // `-` cannot be part of a longer key name within a combination.
18483
+ const hasInvalidMinus = keys.some(key => key.length > 1 && key.includes('-') && key !== '--');
18484
+ if (hasInvalidMinus) {
18485
+ if (!isInternal) consoleWarn(`Invalid hotkey combination: "${combination}" has invalid structure`);
18486
+ return [];
18487
+ }
18488
+ if (keys.length === 0 && combination) {
18489
+ return [normalizeKey(combination)];
18490
+ }
18491
+ return keys;
18492
+ }
18493
+
18494
+ /**
18495
+ * Splits a hotkey string into its constituent combination groups.
18496
+ *
18497
+ * A sequence is a series of combinations that must be pressed in order.
18498
+ * e.g. `a-b`, `ctrl+k-p`
18499
+ */
18500
+ function splitKeySequence(str) {
18501
+ if (!str) {
18502
+ consoleWarn('Invalid hotkey sequence: empty string provided');
18503
+ return [];
18504
+ }
18505
+
18506
+ // A sequence is invalid if it starts or ends with a separator,
18507
+ // unless it is part of a combination (e.g., `shift+-`).
18508
+ const hasInvalidStart = str.startsWith('-') && !['---', '--+'].includes(str);
18509
+ const hasInvalidEnd = str.endsWith('-') && !str.endsWith('+-') && !str.endsWith('_-') && str !== '-' && str !== '---';
18510
+ if (hasInvalidStart || hasInvalidEnd) {
18511
+ consoleWarn(`Invalid hotkey sequence: "${str}" contains invalid combinations`);
18512
+ return [];
18513
+ }
18514
+ const result = [];
18515
+ let buffer = '';
18516
+ let i = 0;
18517
+ while (i < str.length) {
18518
+ const char = str[i];
18519
+ if (char === '-') {
18520
+ // Determine if this hyphen is part of the current combination
18521
+ const prevChar = str[i - 1];
18522
+ const prevPrevChar = i > 1 ? str[i - 2] : undefined;
18523
+ const precededBySinglePlusOrUnderscore = (prevChar === '+' || prevChar === '_') && prevPrevChar !== '+';
18524
+ if (precededBySinglePlusOrUnderscore) {
18525
+ // Treat as part of the combination (e.g., 'ctrl+-')
18526
+ buffer += char;
18527
+ i++;
18528
+ } else {
18529
+ // Treat as sequence separator
18530
+ if (buffer) {
18531
+ result.push(buffer);
18532
+ buffer = '';
18533
+ } else {
18534
+ // Empty buffer means we have a literal '-' key
18535
+ result.push('-');
18536
+ }
18537
+ i++;
18538
+ }
18539
+ } else {
18540
+ buffer += char;
18541
+ i++;
18542
+ }
18543
+ }
18544
+
18545
+ // Add final buffer if it exists
18546
+ if (buffer) {
18547
+ result.push(buffer);
18548
+ }
18549
+
18550
+ // Collapse runs of '-' so that every second '-' is removed
18551
+ const collapsed = [];
18552
+ let minusCount = 0;
18553
+ for (const part of result) {
18554
+ if (part === '-') {
18555
+ if (minusCount % 2 === 0) collapsed.push('-');
18556
+ minusCount++;
18557
+ } else {
18558
+ minusCount = 0;
18559
+ collapsed.push(part);
18560
+ }
18561
+ }
18562
+
18563
+ // Validate that each part of the sequence is a valid combination
18564
+ const areAllValid = collapsed.every(s => splitKeyCombination(s, true).length > 0);
18565
+ if (!areAllValid) {
18566
+ consoleWarn(`Invalid hotkey sequence: "${str}" contains invalid combinations`);
18567
+ return [];
18568
+ }
18569
+ return collapsed;
18570
+ }
18571
+
18572
+ // Composables
18573
+
18574
+ // Types
18575
+
18576
+ function useHotkey(keys, callback) {
18577
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
18578
+ if (!IN_BROWSER) return function () {};
18579
+ const {
18580
+ event = 'keydown',
18581
+ inputs = false,
18582
+ preventDefault = true,
18583
+ sequenceTimeout = 1000
18584
+ } = options;
18585
+ const isMac = navigator?.userAgent?.includes('Macintosh') ?? false;
18586
+ let timeout = 0;
18587
+ let keyGroups;
18588
+ let isSequence = false;
18589
+ let groupIndex = 0;
18590
+ function clearTimer() {
18591
+ if (!timeout) return;
18592
+ clearTimeout(timeout);
18593
+ timeout = 0;
18594
+ }
18595
+ function isInputFocused() {
18596
+ if (toValue(inputs)) return false;
18597
+ const activeElement = document.activeElement;
18598
+ return activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA' || activeElement.isContentEditable || activeElement.contentEditable === 'true');
18599
+ }
18600
+ function resetSequence() {
18601
+ groupIndex = 0;
18602
+ clearTimer();
18603
+ }
18604
+ function handler(e) {
18605
+ const group = keyGroups[groupIndex];
18606
+ if (!group || isInputFocused()) return;
18607
+ if (!matchesKeyGroup(e, group)) {
18608
+ if (isSequence) resetSequence();
18609
+ return;
18610
+ }
18611
+ if (toValue(preventDefault)) e.preventDefault();
18612
+ if (!isSequence) {
18613
+ callback(e);
18614
+ return;
18615
+ }
18616
+ clearTimer();
18617
+ groupIndex++;
18618
+ if (groupIndex === keyGroups.length) {
18619
+ callback(e);
18620
+ resetSequence();
18621
+ return;
18622
+ }
18623
+ timeout = window.setTimeout(resetSequence, toValue(sequenceTimeout));
18624
+ }
18625
+ function cleanup() {
18626
+ window.removeEventListener(toValue(event), handler);
18627
+ clearTimer();
18628
+ }
18629
+ watch(() => toValue(keys), function (unrefKeys) {
18630
+ cleanup();
18631
+ if (unrefKeys) {
18632
+ const groups = splitKeySequence(unrefKeys.toLowerCase());
18633
+ isSequence = groups.length > 1;
18634
+ keyGroups = groups;
18635
+ resetSequence();
18636
+ window.addEventListener(toValue(event), handler);
18637
+ }
18638
+ }, {
18639
+ immediate: true
18640
+ });
18641
+
18642
+ // Watch for changes in the event type to re-register the listener
18643
+ watch(() => toValue(event), function (newEvent, oldEvent) {
18644
+ if (oldEvent && keyGroups && keyGroups.length > 0) {
18645
+ window.removeEventListener(oldEvent, handler);
18646
+ window.addEventListener(newEvent, handler);
18647
+ }
18648
+ });
18649
+ try {
18650
+ getCurrentInstance('useHotkey');
18651
+ onBeforeUnmount(cleanup);
18652
+ } catch {
18653
+ // Not in Vue setup context
18654
+ }
18655
+ function parseKeyGroup(group) {
18656
+ const MODIFIERS = ['ctrl', 'shift', 'alt', 'meta', 'cmd'];
18657
+
18658
+ // Use the shared combination splitting logic
18659
+ const parts = splitKeyCombination(group.toLowerCase());
18660
+
18661
+ // If the combination is invalid, return empty result
18662
+ if (parts.length === 0) {
18663
+ return {
18664
+ modifiers: Object.fromEntries(MODIFIERS.map(m => [m, false])),
18665
+ actualKey: undefined
18666
+ };
18667
+ }
18668
+ const modifiers = Object.fromEntries(MODIFIERS.map(m => [m, false]));
18669
+ let actualKey;
18670
+ for (const part of parts) {
18671
+ if (MODIFIERS.includes(part)) {
18672
+ modifiers[part] = true;
18673
+ } else {
18674
+ actualKey = part;
18675
+ }
18676
+ }
18677
+ return {
18678
+ modifiers,
18679
+ actualKey
18680
+ };
18681
+ }
18682
+ function matchesKeyGroup(e, group) {
18683
+ const {
18684
+ modifiers,
18685
+ actualKey
18686
+ } = parseKeyGroup(group);
18687
+ const expectCtrl = modifiers.ctrl || !isMac && (modifiers.cmd || modifiers.meta);
18688
+ const expectMeta = isMac && (modifiers.cmd || modifiers.meta);
18689
+ return e.ctrlKey === expectCtrl && e.metaKey === expectMeta && e.shiftKey === modifiers.shift && e.altKey === modifiers.alt && e.key.toLowerCase() === actualKey?.toLowerCase();
18690
+ }
18691
+ return cleanup;
18692
+ }
18693
+
18354
18694
  // Types
18355
18695
 
18356
18696
  const makeVColorPickerProps = propsFactory({
@@ -30040,7 +30380,7 @@ const VTreeviewItem = genericComponent()({
30040
30380
  emit('toggleExpand', e);
30041
30381
  }
30042
30382
  useRender(() => {
30043
- const listItemProps = omit(VListItem.filterProps(props), ['onClick']);
30383
+ const listItemProps = VListItem.filterProps(props);
30044
30384
  const hasPrepend = slots.prepend || props.toggleIcon;
30045
30385
  return createVNode(VListItem, mergeProps({
30046
30386
  "ref": vListItemRef
@@ -30051,7 +30391,7 @@ const VTreeviewItem = genericComponent()({
30051
30391
  'v-treeview-item--filtered': isFiltered.value
30052
30392
  }, props.class],
30053
30393
  "ripple": false,
30054
- "onClick": props.onClick ?? activateGroupActivator
30394
+ "onClick": activateGroupActivator
30055
30395
  }), {
30056
30396
  ...slots,
30057
30397
  prepend: hasPrepend ? slotProps => {
@@ -30102,6 +30442,7 @@ const makeVTreeviewChildrenProps = propsFactory({
30102
30442
  falseIcon: IconValue,
30103
30443
  trueIcon: IconValue,
30104
30444
  returnObject: Boolean,
30445
+ activatable: Boolean,
30105
30446
  selectable: Boolean,
30106
30447
  selectedColor: String,
30107
30448
  selectStrategy: [String, Function, Object],
@@ -30121,7 +30462,7 @@ const VTreeviewChildren = genericComponent()({
30121
30462
  } = _ref;
30122
30463
  const isLoading = reactive(new Set());
30123
30464
  const activatorItems = ref([]);
30124
- const isClickOnOpen = computed(() => !props.disabled && (props.openOnClick != null ? props.openOnClick : props.selectable));
30465
+ const isClickOnOpen = computed(() => !props.disabled && (props.openOnClick != null ? props.openOnClick : props.selectable && !props.activatable));
30125
30466
  async function checkChildren(item) {
30126
30467
  try {
30127
30468
  if (!props.items?.length || !props.loadChildren) return;
@@ -30892,7 +31233,7 @@ function createVuetify$1() {
30892
31233
  };
30893
31234
  });
30894
31235
  }
30895
- const version$1 = "3.9.0-beta.0-dev.2025-06-24";
31236
+ const version$1 = "3.9.0-beta.1-dev.2025-06-28";
30896
31237
  createVuetify$1.version = version$1;
30897
31238
 
30898
31239
  // Vue's inject() can only be used in setup
@@ -30917,8 +31258,8 @@ const createVuetify = function () {
30917
31258
  ...options
30918
31259
  });
30919
31260
  };
30920
- const version = "3.9.0-beta.0-dev.2025-06-24";
31261
+ const version = "3.9.0-beta.1-dev.2025-06-28";
30921
31262
  createVuetify.version = version;
30922
31263
 
30923
- export { index as blueprints, components, createVuetify, directives, useDate, useDefaults, useDisplay, useGoTo, useLayout, useLocale, useRtl, useTheme, version };
31264
+ export { index as blueprints, components, createVuetify, directives, useDate, useDefaults, useDisplay, useGoTo, useHotkey, useLayout, useLocale, useRtl, useTheme, version };
30924
31265
  //# sourceMappingURL=vuetify.esm.js.map