@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
package/dist/vuetify.cjs CHANGED
@@ -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
  */
@@ -1836,7 +1836,18 @@
1836
1836
  treeviewExpand: 'mdi-menu-right',
1837
1837
  eyeDropper: 'mdi-eyedropper',
1838
1838
  upload: 'mdi-cloud-upload',
1839
- color: 'mdi-palette'
1839
+ color: 'mdi-palette',
1840
+ command: 'mdi-apple-keyboard-command',
1841
+ ctrl: 'mdi-apple-keyboard-control',
1842
+ space: 'mdi-keyboard-space',
1843
+ shift: 'mdi-apple-keyboard-shift',
1844
+ alt: 'mdi-apple-keyboard-option',
1845
+ enter: 'mdi-keyboard-return',
1846
+ arrowup: 'mdi-arrow-up',
1847
+ arrowdown: 'mdi-arrow-down',
1848
+ arrowleft: 'mdi-arrow-left',
1849
+ arrowright: 'mdi-arrow-right',
1850
+ backspace: 'mdi-backspace'
1840
1851
  };
1841
1852
  const mdi = {
1842
1853
  // Not using mergeProps here, functional components merge props by default (?)
@@ -2632,6 +2643,24 @@
2632
2643
  exclude: 'The {0} character is not allowed',
2633
2644
  notEmpty: 'Please choose at least one value',
2634
2645
  pattern: 'Invalid format'
2646
+ },
2647
+ hotkey: {
2648
+ then: 'then',
2649
+ ctrl: 'Ctrl',
2650
+ command: 'Command',
2651
+ space: 'Space',
2652
+ shift: 'Shift',
2653
+ alt: 'Alt',
2654
+ enter: 'Enter',
2655
+ escape: 'Escape',
2656
+ upArrow: 'Up Arrow',
2657
+ downArrow: 'Down Arrow',
2658
+ leftArrow: 'Left Arrow',
2659
+ rightArrow: 'Right Arrow',
2660
+ backspace: 'Backspace',
2661
+ option: 'Option',
2662
+ plus: 'plus',
2663
+ shortcut: 'Keyboard shortcut: {0}'
2635
2664
  }
2636
2665
  };
2637
2666
 
@@ -9299,9 +9328,9 @@
9299
9328
  }, 'nested');
9300
9329
  const useNested = props => {
9301
9330
  let isUnmounted = false;
9302
- const children = vue.ref(new Map());
9303
- const parents = vue.ref(new Map());
9304
- const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(v), v => [...v.values()]);
9331
+ const children = vue.shallowRef(new Map());
9332
+ const parents = vue.shallowRef(new Map());
9333
+ const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(Array.isArray(v) ? v.map(i => vue.toRaw(i)) : v), v => [...v.values()]);
9305
9334
  const activeStrategy = vue.computed(() => {
9306
9335
  if (typeof props.activeStrategy === 'object') return props.activeStrategy;
9307
9336
  if (typeof props.activeStrategy === 'function') return props.activeStrategy(props.mandatory);
@@ -9355,7 +9384,7 @@
9355
9384
  });
9356
9385
  function getPath(id) {
9357
9386
  const path = [];
9358
- let parent = id;
9387
+ let parent = vue.toRaw(id);
9359
9388
  while (parent != null) {
9360
9389
  path.unshift(parent);
9361
9390
  parent = parents.value.get(parent);
@@ -9498,7 +9527,7 @@
9498
9527
  const useNestedItem = (id, isGroup) => {
9499
9528
  const parent = vue.inject(VNestedSymbol, emptyNested);
9500
9529
  const uidSymbol = Symbol('nested item');
9501
- const computedId = vue.computed(() => vue.toValue(id) ?? uidSymbol);
9530
+ const computedId = vue.computed(() => vue.toRaw(vue.toValue(id)) ?? uidSymbol);
9502
9531
  const item = {
9503
9532
  ...parent,
9504
9533
  id: computedId,
@@ -9507,10 +9536,10 @@
9507
9536
  isOpen: vue.computed(() => parent.root.opened.value.has(computedId.value)),
9508
9537
  parent: vue.computed(() => parent.root.parents.value.get(computedId.value)),
9509
9538
  activate: (activated, e) => parent.root.activate(computedId.value, activated, e),
9510
- isActivated: vue.computed(() => parent.root.activated.value.has(vue.toRaw(computedId.value))),
9539
+ isActivated: vue.computed(() => parent.root.activated.value.has(computedId.value)),
9511
9540
  select: (selected, e) => parent.root.select(computedId.value, selected, e),
9512
- isSelected: vue.computed(() => parent.root.selected.value.get(vue.toRaw(computedId.value)) === 'on'),
9513
- isIndeterminate: vue.computed(() => parent.root.selected.value.get(vue.toRaw(computedId.value)) === 'indeterminate'),
9541
+ isSelected: vue.computed(() => parent.root.selected.value.get(computedId.value) === 'on'),
9542
+ isIndeterminate: vue.computed(() => parent.root.selected.value.get(computedId.value) === 'indeterminate'),
9514
9543
  isLeaf: vue.computed(() => !parent.root.children.value.get(computedId.value)),
9515
9544
  isGroupActivator: parent.isGroupActivator
9516
9545
  };
@@ -18355,6 +18384,317 @@
18355
18384
  return createInstance(options, locale);
18356
18385
  }
18357
18386
 
18387
+ /**
18388
+ * Centralized key alias mapping for consistent key normalization across the hotkey system.
18389
+ *
18390
+ * This maps various user-friendly aliases to canonical key names that match
18391
+ * KeyboardEvent.key values (in lowercase) where possible.
18392
+ */
18393
+ const keyAliasMap = {
18394
+ // Modifier aliases (from vue-use, other libraries, and current implementation)
18395
+ control: 'ctrl',
18396
+ command: 'cmd',
18397
+ option: 'alt',
18398
+ // Arrow key aliases (common abbreviations)
18399
+ up: 'arrowup',
18400
+ down: 'arrowdown',
18401
+ left: 'arrowleft',
18402
+ right: 'arrowright',
18403
+ // Other common key aliases
18404
+ esc: 'escape',
18405
+ spacebar: ' ',
18406
+ space: ' ',
18407
+ return: 'enter',
18408
+ del: 'delete',
18409
+ // Symbol aliases (existing from hotkey-parsing.ts)
18410
+ minus: '-',
18411
+ hyphen: '-'
18412
+ };
18413
+
18414
+ /**
18415
+ * Normalizes a key string to its canonical form using the alias map.
18416
+ *
18417
+ * @param key - The key string to normalize
18418
+ * @returns The canonical key name in lowercase
18419
+ */
18420
+ function normalizeKey(key) {
18421
+ const lowerKey = key.toLowerCase();
18422
+ return keyAliasMap[lowerKey] || lowerKey;
18423
+ }
18424
+
18425
+ // Utilities
18426
+
18427
+ /**
18428
+ * Splits a single combination string into individual key parts.
18429
+ *
18430
+ * A combination is a set of keys that must be pressed simultaneously.
18431
+ * e.g. `ctrl+k`, `shift--`
18432
+ */
18433
+ function splitKeyCombination(combination) {
18434
+ let isInternal = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
18435
+ if (!combination) {
18436
+ if (!isInternal) consoleWarn('Invalid hotkey combination: empty string provided');
18437
+ return [];
18438
+ }
18439
+
18440
+ // --- VALIDATION ---
18441
+ const startsWithPlusOrUnderscore = combination.startsWith('+') || combination.startsWith('_');
18442
+ const hasInvalidLeadingSeparator =
18443
+ // Starts with a single '+' or '_' followed by a non-separator character (e.g. '+a', '_a')
18444
+ startsWithPlusOrUnderscore && !(combination.startsWith('++') || combination.startsWith('__'));
18445
+ const hasInvalidStructure =
18446
+ // Invalid leading separator patterns
18447
+ combination.length > 1 && hasInvalidLeadingSeparator ||
18448
+ // Disallow literal + or _ keys (they require shift)
18449
+ combination.includes('++') || combination.includes('__') || combination === '+' || combination === '_' ||
18450
+ // Ends with a separator that is not part of a doubled literal
18451
+ combination.length > 1 && (combination.endsWith('+') || combination.endsWith('_')) && combination.at(-2) !== combination.at(-1) ||
18452
+ // Stand-alone doubled separators (dangling)
18453
+ combination === '++' || combination === '--' || combination === '__';
18454
+ if (hasInvalidStructure) {
18455
+ if (!isInternal) consoleWarn(`Invalid hotkey combination: "${combination}" has invalid structure`);
18456
+ return [];
18457
+ }
18458
+ const keys = [];
18459
+ let buffer = '';
18460
+ const flushBuffer = () => {
18461
+ if (buffer) {
18462
+ keys.push(normalizeKey(buffer));
18463
+ buffer = '';
18464
+ }
18465
+ };
18466
+ for (let i = 0; i < combination.length; i++) {
18467
+ const char = combination[i];
18468
+ const nextChar = combination[i + 1];
18469
+ if (char === '+' || char === '_' || char === '-') {
18470
+ if (char === nextChar) {
18471
+ flushBuffer();
18472
+ keys.push(char);
18473
+ i++;
18474
+ } else if (char === '+' || char === '_') {
18475
+ flushBuffer();
18476
+ } else {
18477
+ buffer += char;
18478
+ }
18479
+ } else {
18480
+ buffer += char;
18481
+ }
18482
+ }
18483
+ flushBuffer();
18484
+
18485
+ // Within a combination, `-` is only valid as a literal key (e.g., `ctrl+-`).
18486
+ // `-` cannot be part of a longer key name within a combination.
18487
+ const hasInvalidMinus = keys.some(key => key.length > 1 && key.includes('-') && key !== '--');
18488
+ if (hasInvalidMinus) {
18489
+ if (!isInternal) consoleWarn(`Invalid hotkey combination: "${combination}" has invalid structure`);
18490
+ return [];
18491
+ }
18492
+ if (keys.length === 0 && combination) {
18493
+ return [normalizeKey(combination)];
18494
+ }
18495
+ return keys;
18496
+ }
18497
+
18498
+ /**
18499
+ * Splits a hotkey string into its constituent combination groups.
18500
+ *
18501
+ * A sequence is a series of combinations that must be pressed in order.
18502
+ * e.g. `a-b`, `ctrl+k-p`
18503
+ */
18504
+ function splitKeySequence(str) {
18505
+ if (!str) {
18506
+ consoleWarn('Invalid hotkey sequence: empty string provided');
18507
+ return [];
18508
+ }
18509
+
18510
+ // A sequence is invalid if it starts or ends with a separator,
18511
+ // unless it is part of a combination (e.g., `shift+-`).
18512
+ const hasInvalidStart = str.startsWith('-') && !['---', '--+'].includes(str);
18513
+ const hasInvalidEnd = str.endsWith('-') && !str.endsWith('+-') && !str.endsWith('_-') && str !== '-' && str !== '---';
18514
+ if (hasInvalidStart || hasInvalidEnd) {
18515
+ consoleWarn(`Invalid hotkey sequence: "${str}" contains invalid combinations`);
18516
+ return [];
18517
+ }
18518
+ const result = [];
18519
+ let buffer = '';
18520
+ let i = 0;
18521
+ while (i < str.length) {
18522
+ const char = str[i];
18523
+ if (char === '-') {
18524
+ // Determine if this hyphen is part of the current combination
18525
+ const prevChar = str[i - 1];
18526
+ const prevPrevChar = i > 1 ? str[i - 2] : undefined;
18527
+ const precededBySinglePlusOrUnderscore = (prevChar === '+' || prevChar === '_') && prevPrevChar !== '+';
18528
+ if (precededBySinglePlusOrUnderscore) {
18529
+ // Treat as part of the combination (e.g., 'ctrl+-')
18530
+ buffer += char;
18531
+ i++;
18532
+ } else {
18533
+ // Treat as sequence separator
18534
+ if (buffer) {
18535
+ result.push(buffer);
18536
+ buffer = '';
18537
+ } else {
18538
+ // Empty buffer means we have a literal '-' key
18539
+ result.push('-');
18540
+ }
18541
+ i++;
18542
+ }
18543
+ } else {
18544
+ buffer += char;
18545
+ i++;
18546
+ }
18547
+ }
18548
+
18549
+ // Add final buffer if it exists
18550
+ if (buffer) {
18551
+ result.push(buffer);
18552
+ }
18553
+
18554
+ // Collapse runs of '-' so that every second '-' is removed
18555
+ const collapsed = [];
18556
+ let minusCount = 0;
18557
+ for (const part of result) {
18558
+ if (part === '-') {
18559
+ if (minusCount % 2 === 0) collapsed.push('-');
18560
+ minusCount++;
18561
+ } else {
18562
+ minusCount = 0;
18563
+ collapsed.push(part);
18564
+ }
18565
+ }
18566
+
18567
+ // Validate that each part of the sequence is a valid combination
18568
+ const areAllValid = collapsed.every(s => splitKeyCombination(s, true).length > 0);
18569
+ if (!areAllValid) {
18570
+ consoleWarn(`Invalid hotkey sequence: "${str}" contains invalid combinations`);
18571
+ return [];
18572
+ }
18573
+ return collapsed;
18574
+ }
18575
+
18576
+ // Composables
18577
+
18578
+ // Types
18579
+
18580
+ function useHotkey(keys, callback) {
18581
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
18582
+ if (!IN_BROWSER) return function () {};
18583
+ const {
18584
+ event = 'keydown',
18585
+ inputs = false,
18586
+ preventDefault = true,
18587
+ sequenceTimeout = 1000
18588
+ } = options;
18589
+ const isMac = navigator?.userAgent?.includes('Macintosh') ?? false;
18590
+ let timeout = 0;
18591
+ let keyGroups;
18592
+ let isSequence = false;
18593
+ let groupIndex = 0;
18594
+ function clearTimer() {
18595
+ if (!timeout) return;
18596
+ clearTimeout(timeout);
18597
+ timeout = 0;
18598
+ }
18599
+ function isInputFocused() {
18600
+ if (vue.toValue(inputs)) return false;
18601
+ const activeElement = document.activeElement;
18602
+ return activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA' || activeElement.isContentEditable || activeElement.contentEditable === 'true');
18603
+ }
18604
+ function resetSequence() {
18605
+ groupIndex = 0;
18606
+ clearTimer();
18607
+ }
18608
+ function handler(e) {
18609
+ const group = keyGroups[groupIndex];
18610
+ if (!group || isInputFocused()) return;
18611
+ if (!matchesKeyGroup(e, group)) {
18612
+ if (isSequence) resetSequence();
18613
+ return;
18614
+ }
18615
+ if (vue.toValue(preventDefault)) e.preventDefault();
18616
+ if (!isSequence) {
18617
+ callback(e);
18618
+ return;
18619
+ }
18620
+ clearTimer();
18621
+ groupIndex++;
18622
+ if (groupIndex === keyGroups.length) {
18623
+ callback(e);
18624
+ resetSequence();
18625
+ return;
18626
+ }
18627
+ timeout = window.setTimeout(resetSequence, vue.toValue(sequenceTimeout));
18628
+ }
18629
+ function cleanup() {
18630
+ window.removeEventListener(vue.toValue(event), handler);
18631
+ clearTimer();
18632
+ }
18633
+ vue.watch(() => vue.toValue(keys), function (unrefKeys) {
18634
+ cleanup();
18635
+ if (unrefKeys) {
18636
+ const groups = splitKeySequence(unrefKeys.toLowerCase());
18637
+ isSequence = groups.length > 1;
18638
+ keyGroups = groups;
18639
+ resetSequence();
18640
+ window.addEventListener(vue.toValue(event), handler);
18641
+ }
18642
+ }, {
18643
+ immediate: true
18644
+ });
18645
+
18646
+ // Watch for changes in the event type to re-register the listener
18647
+ vue.watch(() => vue.toValue(event), function (newEvent, oldEvent) {
18648
+ if (oldEvent && keyGroups && keyGroups.length > 0) {
18649
+ window.removeEventListener(oldEvent, handler);
18650
+ window.addEventListener(newEvent, handler);
18651
+ }
18652
+ });
18653
+ try {
18654
+ getCurrentInstance('useHotkey');
18655
+ vue.onBeforeUnmount(cleanup);
18656
+ } catch {
18657
+ // Not in Vue setup context
18658
+ }
18659
+ function parseKeyGroup(group) {
18660
+ const MODIFIERS = ['ctrl', 'shift', 'alt', 'meta', 'cmd'];
18661
+
18662
+ // Use the shared combination splitting logic
18663
+ const parts = splitKeyCombination(group.toLowerCase());
18664
+
18665
+ // If the combination is invalid, return empty result
18666
+ if (parts.length === 0) {
18667
+ return {
18668
+ modifiers: Object.fromEntries(MODIFIERS.map(m => [m, false])),
18669
+ actualKey: undefined
18670
+ };
18671
+ }
18672
+ const modifiers = Object.fromEntries(MODIFIERS.map(m => [m, false]));
18673
+ let actualKey;
18674
+ for (const part of parts) {
18675
+ if (MODIFIERS.includes(part)) {
18676
+ modifiers[part] = true;
18677
+ } else {
18678
+ actualKey = part;
18679
+ }
18680
+ }
18681
+ return {
18682
+ modifiers,
18683
+ actualKey
18684
+ };
18685
+ }
18686
+ function matchesKeyGroup(e, group) {
18687
+ const {
18688
+ modifiers,
18689
+ actualKey
18690
+ } = parseKeyGroup(group);
18691
+ const expectCtrl = modifiers.ctrl || !isMac && (modifiers.cmd || modifiers.meta);
18692
+ const expectMeta = isMac && (modifiers.cmd || modifiers.meta);
18693
+ return e.ctrlKey === expectCtrl && e.metaKey === expectMeta && e.shiftKey === modifiers.shift && e.altKey === modifiers.alt && e.key.toLowerCase() === actualKey?.toLowerCase();
18694
+ }
18695
+ return cleanup;
18696
+ }
18697
+
18358
18698
  // Types
18359
18699
 
18360
18700
  const makeVColorPickerProps = propsFactory({
@@ -30044,7 +30384,7 @@
30044
30384
  emit('toggleExpand', e);
30045
30385
  }
30046
30386
  useRender(() => {
30047
- const listItemProps = omit(VListItem.filterProps(props), ['onClick']);
30387
+ const listItemProps = VListItem.filterProps(props);
30048
30388
  const hasPrepend = slots.prepend || props.toggleIcon;
30049
30389
  return vue.createVNode(VListItem, vue.mergeProps({
30050
30390
  "ref": vListItemRef
@@ -30055,7 +30395,7 @@
30055
30395
  'v-treeview-item--filtered': isFiltered.value
30056
30396
  }, props.class],
30057
30397
  "ripple": false,
30058
- "onClick": props.onClick ?? activateGroupActivator
30398
+ "onClick": activateGroupActivator
30059
30399
  }), {
30060
30400
  ...slots,
30061
30401
  prepend: hasPrepend ? slotProps => {
@@ -30106,6 +30446,7 @@
30106
30446
  falseIcon: IconValue,
30107
30447
  trueIcon: IconValue,
30108
30448
  returnObject: Boolean,
30449
+ activatable: Boolean,
30109
30450
  selectable: Boolean,
30110
30451
  selectedColor: String,
30111
30452
  selectStrategy: [String, Function, Object],
@@ -30125,7 +30466,7 @@
30125
30466
  } = _ref;
30126
30467
  const isLoading = vue.reactive(new Set());
30127
30468
  const activatorItems = vue.ref([]);
30128
- const isClickOnOpen = vue.computed(() => !props.disabled && (props.openOnClick != null ? props.openOnClick : props.selectable));
30469
+ const isClickOnOpen = vue.computed(() => !props.disabled && (props.openOnClick != null ? props.openOnClick : props.selectable && !props.activatable));
30129
30470
  async function checkChildren(item) {
30130
30471
  try {
30131
30472
  if (!props.items?.length || !props.loadChildren) return;
@@ -30896,7 +31237,7 @@
30896
31237
  };
30897
31238
  });
30898
31239
  }
30899
- const version$1 = "3.9.0-beta.0-dev.2025-06-24";
31240
+ const version$1 = "3.9.0-beta.1-dev.2025-06-28";
30900
31241
  createVuetify$1.version = version$1;
30901
31242
 
30902
31243
  // Vue's inject() can only be used in setup
@@ -30921,7 +31262,7 @@
30921
31262
  ...options
30922
31263
  });
30923
31264
  };
30924
- const version = "3.9.0-beta.0-dev.2025-06-24";
31265
+ const version = "3.9.0-beta.1-dev.2025-06-28";
30925
31266
  createVuetify.version = version;
30926
31267
 
30927
31268
  exports.blueprints = index;
@@ -30932,6 +31273,7 @@
30932
31273
  exports.useDefaults = useDefaults;
30933
31274
  exports.useDisplay = useDisplay;
30934
31275
  exports.useGoTo = useGoTo;
31276
+ exports.useHotkey = useHotkey;
30935
31277
  exports.useLayout = useLayout;
30936
31278
  exports.useLocale = useLocale;
30937
31279
  exports.useRtl = useRtl;