vuetify 3.9.0-beta.1 → 3.9.0

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 (314) hide show
  1. package/dist/_component-variables-labs.sass +1 -0
  2. package/dist/json/attributes.json +3362 -3274
  3. package/dist/json/importMap-labs.json +20 -16
  4. package/dist/json/importMap.json +158 -158
  5. package/dist/json/tags.json +31 -4
  6. package/dist/json/web-types.json +6150 -5916
  7. package/dist/vuetify-labs.cjs +1035 -151
  8. package/dist/vuetify-labs.css +5736 -5417
  9. package/dist/vuetify-labs.d.ts +708 -377
  10. package/dist/vuetify-labs.esm.js +1035 -152
  11. package/dist/vuetify-labs.esm.js.map +1 -1
  12. package/dist/vuetify-labs.js +1035 -151
  13. package/dist/vuetify-labs.min.css +2 -2
  14. package/dist/vuetify.cjs +616 -126
  15. package/dist/vuetify.cjs.map +1 -1
  16. package/dist/vuetify.css +3902 -3825
  17. package/dist/vuetify.d.ts +338 -233
  18. package/dist/vuetify.esm.js +616 -127
  19. package/dist/vuetify.esm.js.map +1 -1
  20. package/dist/vuetify.js +616 -126
  21. package/dist/vuetify.js.map +1 -1
  22. package/dist/vuetify.min.css +2 -2
  23. package/dist/vuetify.min.js +1176 -1120
  24. package/dist/vuetify.min.js.map +1 -1
  25. package/lib/components/VAutocomplete/VAutocomplete.d.ts +39 -14
  26. package/lib/components/VAutocomplete/VAutocomplete.js +2 -2
  27. package/lib/components/VAutocomplete/VAutocomplete.js.map +1 -1
  28. package/lib/components/VCombobox/VCombobox.d.ts +39 -14
  29. package/lib/components/VCombobox/VCombobox.js +2 -2
  30. package/lib/components/VCombobox/VCombobox.js.map +1 -1
  31. package/lib/components/VDataIterator/composables/items.d.ts +2 -1
  32. package/lib/components/VDataIterator/composables/items.js.map +1 -1
  33. package/lib/components/VDataTable/VDataTable.css +12 -1
  34. package/lib/components/VDataTable/VDataTable.d.ts +20 -38
  35. package/lib/components/VDataTable/VDataTable.sass +12 -2
  36. package/lib/components/VDataTable/VDataTableColumn.d.ts +9 -3
  37. package/lib/components/VDataTable/VDataTableColumn.js +12 -4
  38. package/lib/components/VDataTable/VDataTableColumn.js.map +1 -1
  39. package/lib/components/VDataTable/VDataTableHeaders.d.ts +0 -13
  40. package/lib/components/VDataTable/VDataTableHeaders.js +10 -9
  41. package/lib/components/VDataTable/VDataTableHeaders.js.map +1 -1
  42. package/lib/components/VDataTable/VDataTableRow.js +2 -0
  43. package/lib/components/VDataTable/VDataTableRow.js.map +1 -1
  44. package/lib/components/VDataTable/VDataTableServer.d.ts +10 -23
  45. package/lib/components/VDataTable/VDataTableVirtual.d.ts +10 -23
  46. package/lib/components/VDataTable/composables/headers.d.ts +22 -14
  47. package/lib/components/VDataTable/composables/headers.js +51 -22
  48. package/lib/components/VDataTable/composables/headers.js.map +1 -1
  49. package/lib/components/VDataTable/composables/sort.js +2 -1
  50. package/lib/components/VDataTable/composables/sort.js.map +1 -1
  51. package/lib/components/VDataTable/types.d.ts +4 -2
  52. package/lib/components/VDataTable/types.js.map +1 -1
  53. package/lib/components/VDatePicker/VDatePicker.js +2 -1
  54. package/lib/components/VDatePicker/VDatePicker.js.map +1 -1
  55. package/lib/components/VDatePicker/VDatePickerMonth.js +1 -2
  56. package/lib/components/VDatePicker/VDatePickerMonth.js.map +1 -1
  57. package/lib/components/VKbd/VKbd.css +14 -5
  58. package/lib/components/VKbd/VKbd.js.map +1 -1
  59. package/lib/components/VKbd/VKbd.scss +26 -0
  60. package/lib/components/VKbd/_variables.scss +12 -6
  61. package/lib/components/VKbd/index.js.map +1 -1
  62. package/lib/components/VList/VList.d.ts +24 -27
  63. package/lib/components/VList/VList.js +0 -4
  64. package/lib/components/VList/VList.js.map +1 -1
  65. package/lib/components/VList/VListGroup.d.ts +13 -0
  66. package/lib/components/VList/VListGroup.js +2 -1
  67. package/lib/components/VList/VListGroup.js.map +1 -1
  68. package/lib/components/VList/VListItem.d.ts +6 -3
  69. package/lib/components/VList/VListItem.js +1 -1
  70. package/lib/components/VList/VListItem.js.map +1 -1
  71. package/lib/components/VOtpInput/VOtpInput.js +17 -14
  72. package/lib/components/VOtpInput/VOtpInput.js.map +1 -1
  73. package/lib/components/VOverlay/locationStrategies.js +1 -1
  74. package/lib/components/VOverlay/locationStrategies.js.map +1 -1
  75. package/lib/components/VSelect/VSelect.d.ts +58 -22
  76. package/lib/components/VSelect/VSelect.js +2 -2
  77. package/lib/components/VSelect/VSelect.js.map +1 -1
  78. package/lib/components/VTextField/VTextField.js +1 -1
  79. package/lib/components/VTextField/VTextField.js.map +1 -1
  80. package/lib/components/VTreeview/VTreeview.d.ts +235 -188
  81. package/lib/components/VTreeview/VTreeview.js +13 -12
  82. package/lib/components/VTreeview/VTreeview.js.map +1 -1
  83. package/lib/components/VTreeview/VTreeviewChildren.d.ts +81 -10
  84. package/lib/components/VTreeview/VTreeviewChildren.js +50 -11
  85. package/lib/components/VTreeview/VTreeviewChildren.js.map +1 -1
  86. package/lib/components/VTreeview/VTreeviewGroup.d.ts +13 -0
  87. package/lib/components/VTreeview/VTreeviewItem.css +57 -0
  88. package/lib/components/VTreeview/VTreeviewItem.d.ts +137 -103
  89. package/lib/components/VTreeview/VTreeviewItem.js +14 -4
  90. package/lib/components/VTreeview/VTreeviewItem.js.map +1 -1
  91. package/lib/components/VTreeview/VTreeviewItem.sass +60 -0
  92. package/lib/components/VTreeview/_variables.scss +15 -0
  93. package/lib/composables/calendar.d.ts +0 -1
  94. package/lib/composables/calendar.js +6 -10
  95. package/lib/composables/calendar.js.map +1 -1
  96. package/lib/composables/date/adapters/vuetify.js +1 -1
  97. package/lib/composables/date/adapters/vuetify.js.map +1 -1
  98. package/lib/composables/filter.d.ts +1 -0
  99. package/lib/composables/filter.js +1 -1
  100. package/lib/composables/filter.js.map +1 -1
  101. package/lib/composables/hotkey/hotkey-parsing.d.ts +15 -0
  102. package/lib/composables/hotkey/hotkey-parsing.js +154 -0
  103. package/lib/composables/hotkey/hotkey-parsing.js.map +1 -0
  104. package/lib/composables/hotkey/hotkey.d.ts +9 -0
  105. package/lib/composables/{hotkey.js → hotkey/hotkey.js} +31 -39
  106. package/lib/composables/hotkey/hotkey.js.map +1 -0
  107. package/lib/composables/hotkey/index.d.ts +1 -0
  108. package/lib/composables/hotkey/index.js +2 -0
  109. package/lib/composables/hotkey/index.js.map +1 -0
  110. package/lib/composables/hotkey/key-aliases.d.ts +14 -0
  111. package/lib/composables/hotkey/key-aliases.js +38 -0
  112. package/lib/composables/hotkey/key-aliases.js.map +1 -0
  113. package/lib/composables/icons.d.ts +11 -0
  114. package/lib/composables/icons.js.map +1 -1
  115. package/lib/composables/index.d.ts +1 -0
  116. package/lib/composables/index.js +1 -0
  117. package/lib/composables/index.js.map +1 -1
  118. package/lib/composables/list-items.d.ts +14 -1
  119. package/lib/composables/list-items.js +9 -3
  120. package/lib/composables/list-items.js.map +1 -1
  121. package/lib/composables/nested/nested.d.ts +7 -4
  122. package/lib/composables/nested/nested.js +16 -6
  123. package/lib/composables/nested/nested.js.map +1 -1
  124. package/lib/composables/nested/selectStrategies.d.ts +2 -1
  125. package/lib/composables/nested/selectStrategies.js +22 -11
  126. package/lib/composables/nested/selectStrategies.js.map +1 -1
  127. package/lib/composables/virtual.js +1 -1
  128. package/lib/composables/virtual.js.map +1 -1
  129. package/lib/entry-bundler.js +1 -1
  130. package/lib/entry-bundler.js.map +1 -1
  131. package/lib/framework.d.ts +79 -54
  132. package/lib/framework.js +1 -1
  133. package/lib/framework.js.map +1 -1
  134. package/lib/iconsets/fa.js +12 -1
  135. package/lib/iconsets/fa.js.map +1 -1
  136. package/lib/iconsets/fa4.js +12 -1
  137. package/lib/iconsets/fa4.js.map +1 -1
  138. package/lib/iconsets/md.js +12 -1
  139. package/lib/iconsets/md.js.map +1 -1
  140. package/lib/iconsets/mdi-svg.js +12 -1
  141. package/lib/iconsets/mdi-svg.js.map +1 -1
  142. package/lib/iconsets/mdi.js +12 -1
  143. package/lib/iconsets/mdi.js.map +1 -1
  144. package/lib/labs/VCalendar/VCalendar.d.ts +33 -33
  145. package/lib/labs/VCalendar/VCalendar.js +10 -10
  146. package/lib/labs/VCalendar/VCalendar.js.map +1 -1
  147. package/lib/labs/VCalendar/VCalendarDay.d.ts +33 -33
  148. package/lib/labs/VCalendar/VCalendarDay.js +1 -1
  149. package/lib/labs/VCalendar/VCalendarDay.js.map +1 -1
  150. package/lib/labs/VCalendar/VCalendarInterval.d.ts +36 -36
  151. package/lib/labs/VCalendar/VCalendarInterval.js +9 -9
  152. package/lib/labs/VCalendar/VCalendarInterval.js.map +1 -1
  153. package/lib/labs/VCalendar/VCalendarIntervalEvent.d.ts +12 -12
  154. package/lib/labs/VCalendar/VCalendarIntervalEvent.js +1 -1
  155. package/lib/labs/VCalendar/VCalendarIntervalEvent.js.map +1 -1
  156. package/lib/labs/VCalendar/VCalendarMonthDay.d.ts +36 -36
  157. package/lib/labs/VCalendar/VCalendarMonthDay.js +4 -4
  158. package/lib/labs/VCalendar/VCalendarMonthDay.js.map +1 -1
  159. package/lib/labs/VHotkey/VHotkey.css +242 -0
  160. package/lib/labs/VHotkey/VHotkey.d.ts +387 -0
  161. package/lib/labs/VHotkey/VHotkey.js +432 -0
  162. package/lib/labs/VHotkey/VHotkey.js.map +1 -0
  163. package/lib/labs/VHotkey/VHotkey.scss +253 -0
  164. package/lib/labs/VHotkey/_variables.scss +43 -0
  165. package/lib/labs/VHotkey/index.d.ts +1 -0
  166. package/lib/labs/VHotkey/index.js +2 -0
  167. package/lib/labs/VHotkey/index.js.map +1 -0
  168. package/lib/labs/VIconBtn/VIconBtn.js +1 -0
  169. package/lib/labs/VIconBtn/VIconBtn.js.map +1 -1
  170. package/lib/labs/components.d.ts +1 -0
  171. package/lib/labs/components.js +1 -0
  172. package/lib/labs/components.js.map +1 -1
  173. package/lib/locale/af.d.ts +18 -0
  174. package/lib/locale/af.js +18 -0
  175. package/lib/locale/af.js.map +1 -1
  176. package/lib/locale/ar.d.ts +18 -0
  177. package/lib/locale/ar.js +18 -0
  178. package/lib/locale/ar.js.map +1 -1
  179. package/lib/locale/az.d.ts +18 -0
  180. package/lib/locale/az.js +18 -0
  181. package/lib/locale/az.js.map +1 -1
  182. package/lib/locale/bg.d.ts +18 -0
  183. package/lib/locale/bg.js +18 -0
  184. package/lib/locale/bg.js.map +1 -1
  185. package/lib/locale/ca.d.ts +18 -0
  186. package/lib/locale/ca.js +18 -0
  187. package/lib/locale/ca.js.map +1 -1
  188. package/lib/locale/ckb.d.ts +18 -0
  189. package/lib/locale/ckb.js +18 -0
  190. package/lib/locale/ckb.js.map +1 -1
  191. package/lib/locale/cs.d.ts +18 -0
  192. package/lib/locale/cs.js +18 -0
  193. package/lib/locale/cs.js.map +1 -1
  194. package/lib/locale/da.d.ts +18 -0
  195. package/lib/locale/da.js +18 -0
  196. package/lib/locale/da.js.map +1 -1
  197. package/lib/locale/de.d.ts +18 -0
  198. package/lib/locale/de.js +18 -0
  199. package/lib/locale/de.js.map +1 -1
  200. package/lib/locale/el.d.ts +18 -0
  201. package/lib/locale/el.js +18 -0
  202. package/lib/locale/el.js.map +1 -1
  203. package/lib/locale/en.d.ts +18 -0
  204. package/lib/locale/en.js +18 -0
  205. package/lib/locale/en.js.map +1 -1
  206. package/lib/locale/es.d.ts +18 -0
  207. package/lib/locale/es.js +18 -0
  208. package/lib/locale/es.js.map +1 -1
  209. package/lib/locale/et.d.ts +18 -0
  210. package/lib/locale/et.js +18 -0
  211. package/lib/locale/et.js.map +1 -1
  212. package/lib/locale/fa.d.ts +18 -0
  213. package/lib/locale/fa.js +18 -0
  214. package/lib/locale/fa.js.map +1 -1
  215. package/lib/locale/fi.d.ts +18 -0
  216. package/lib/locale/fi.js +18 -0
  217. package/lib/locale/fi.js.map +1 -1
  218. package/lib/locale/fr.d.ts +18 -0
  219. package/lib/locale/fr.js +18 -0
  220. package/lib/locale/fr.js.map +1 -1
  221. package/lib/locale/he.d.ts +18 -0
  222. package/lib/locale/he.js +18 -0
  223. package/lib/locale/he.js.map +1 -1
  224. package/lib/locale/hr.d.ts +18 -0
  225. package/lib/locale/hr.js +18 -0
  226. package/lib/locale/hr.js.map +1 -1
  227. package/lib/locale/hu.d.ts +18 -0
  228. package/lib/locale/hu.js +18 -0
  229. package/lib/locale/hu.js.map +1 -1
  230. package/lib/locale/id.d.ts +18 -0
  231. package/lib/locale/id.js +18 -0
  232. package/lib/locale/id.js.map +1 -1
  233. package/lib/locale/it.d.ts +18 -0
  234. package/lib/locale/it.js +18 -0
  235. package/lib/locale/it.js.map +1 -1
  236. package/lib/locale/ja.d.ts +18 -0
  237. package/lib/locale/ja.js +18 -0
  238. package/lib/locale/ja.js.map +1 -1
  239. package/lib/locale/km.d.ts +18 -0
  240. package/lib/locale/km.js +18 -0
  241. package/lib/locale/km.js.map +1 -1
  242. package/lib/locale/ko.d.ts +18 -0
  243. package/lib/locale/ko.js +18 -0
  244. package/lib/locale/ko.js.map +1 -1
  245. package/lib/locale/lt.d.ts +18 -0
  246. package/lib/locale/lt.js +18 -0
  247. package/lib/locale/lt.js.map +1 -1
  248. package/lib/locale/lv.d.ts +18 -0
  249. package/lib/locale/lv.js +18 -0
  250. package/lib/locale/lv.js.map +1 -1
  251. package/lib/locale/nl.d.ts +18 -0
  252. package/lib/locale/nl.js +18 -0
  253. package/lib/locale/nl.js.map +1 -1
  254. package/lib/locale/no.d.ts +18 -0
  255. package/lib/locale/no.js +18 -0
  256. package/lib/locale/no.js.map +1 -1
  257. package/lib/locale/pl.d.ts +18 -0
  258. package/lib/locale/pl.js +18 -0
  259. package/lib/locale/pl.js.map +1 -1
  260. package/lib/locale/pt.d.ts +18 -0
  261. package/lib/locale/pt.js +18 -0
  262. package/lib/locale/pt.js.map +1 -1
  263. package/lib/locale/ro.d.ts +18 -0
  264. package/lib/locale/ro.js +18 -0
  265. package/lib/locale/ro.js.map +1 -1
  266. package/lib/locale/ru.d.ts +18 -0
  267. package/lib/locale/ru.js +18 -0
  268. package/lib/locale/ru.js.map +1 -1
  269. package/lib/locale/sk.d.ts +18 -0
  270. package/lib/locale/sk.js +18 -0
  271. package/lib/locale/sk.js.map +1 -1
  272. package/lib/locale/sl.d.ts +18 -0
  273. package/lib/locale/sl.js +18 -0
  274. package/lib/locale/sl.js.map +1 -1
  275. package/lib/locale/sr-Cyrl.d.ts +18 -0
  276. package/lib/locale/sr-Cyrl.js +18 -0
  277. package/lib/locale/sr-Cyrl.js.map +1 -1
  278. package/lib/locale/sr-Latn.d.ts +18 -0
  279. package/lib/locale/sr-Latn.js +18 -0
  280. package/lib/locale/sr-Latn.js.map +1 -1
  281. package/lib/locale/sv.d.ts +18 -0
  282. package/lib/locale/sv.js +18 -0
  283. package/lib/locale/sv.js.map +1 -1
  284. package/lib/locale/th.d.ts +18 -0
  285. package/lib/locale/th.js +18 -0
  286. package/lib/locale/th.js.map +1 -1
  287. package/lib/locale/tr.d.ts +18 -0
  288. package/lib/locale/tr.js +18 -0
  289. package/lib/locale/tr.js.map +1 -1
  290. package/lib/locale/uk.d.ts +18 -0
  291. package/lib/locale/uk.js +18 -0
  292. package/lib/locale/uk.js.map +1 -1
  293. package/lib/locale/vi.d.ts +18 -0
  294. package/lib/locale/vi.js +18 -0
  295. package/lib/locale/vi.js.map +1 -1
  296. package/lib/locale/zh-Hans.d.ts +18 -0
  297. package/lib/locale/zh-Hans.js +18 -0
  298. package/lib/locale/zh-Hans.js.map +1 -1
  299. package/lib/locale/zh-Hant.d.ts +18 -0
  300. package/lib/locale/zh-Hant.js +18 -0
  301. package/lib/locale/zh-Hant.js.map +1 -1
  302. package/lib/util/helpers.d.ts +3 -0
  303. package/lib/util/helpers.js +4 -0
  304. package/lib/util/helpers.js.map +1 -1
  305. package/lib/util/indentLines.d.ts +17 -0
  306. package/lib/util/indentLines.js +34 -0
  307. package/lib/util/indentLines.js.map +1 -0
  308. package/lib/util/index.d.ts +1 -0
  309. package/lib/util/index.js +1 -0
  310. package/lib/util/index.js.map +1 -1
  311. package/package.json +2 -2
  312. package/lib/components/VKbd/VKbd.sass +0 -15
  313. package/lib/composables/hotkey.d.ts +0 -9
  314. package/lib/composables/hotkey.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.9.0-beta.1
2
+ * Vuetify v3.9.0
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
@@ -546,6 +546,10 @@ function ensureValidVNode(vnodes) {
546
546
  return child.type !== Fragment || ensureValidVNode(child.children);
547
547
  }) ? vnodes : null;
548
548
  }
549
+ function renderSlot(slot, props, fallback) {
550
+ // TODO: check if slot returns elements: #18308
551
+ return slot?.(props) ?? fallback?.(props);
552
+ }
549
553
  function defer(timeout, cb) {
550
554
  if (!IN_BROWSER || timeout === 0) {
551
555
  cb();
@@ -1620,6 +1624,40 @@ function isPotentiallyScrollable(el) {
1620
1624
  return ['scroll', 'auto'].includes(style.overflowY);
1621
1625
  }
1622
1626
 
1627
+ // Types
1628
+
1629
+ function getIndentLines(_ref) {
1630
+ let {
1631
+ depth,
1632
+ isLast,
1633
+ isLastGroup,
1634
+ leafLinks,
1635
+ separateRoots,
1636
+ parentIndentLines,
1637
+ variant
1638
+ } = _ref;
1639
+ if (!parentIndentLines || !depth) {
1640
+ return {
1641
+ leaf: undefined,
1642
+ node: undefined,
1643
+ children: parentIndentLines
1644
+ };
1645
+ }
1646
+ if (variant === 'simple') {
1647
+ return {
1648
+ leaf: [...parentIndentLines, 'line'],
1649
+ node: [...parentIndentLines, 'line'],
1650
+ children: [...parentIndentLines, 'line']
1651
+ };
1652
+ }
1653
+ const isLastLeaf = isLast && (!isLastGroup || separateRoots || depth > 1);
1654
+ return {
1655
+ leaf: [...parentIndentLines, isLastLeaf ? 'last-leaf' : 'leaf', ...(leafLinks ? ['leaf-link'] : [])],
1656
+ node: [...parentIndentLines, isLastLeaf ? 'last-leaf' : 'leaf'],
1657
+ children: [...parentIndentLines, isLastLeaf ? 'none' : 'line']
1658
+ };
1659
+ }
1660
+
1623
1661
  function isFixedPosition(el) {
1624
1662
  while (el) {
1625
1663
  if (window.getComputedStyle(el).position === 'fixed') {
@@ -2141,6 +2179,24 @@ var en = {
2141
2179
  exclude: 'The {0} character is not allowed',
2142
2180
  notEmpty: 'Please choose at least one value',
2143
2181
  pattern: 'Invalid format'
2182
+ },
2183
+ hotkey: {
2184
+ then: 'then',
2185
+ ctrl: 'Ctrl',
2186
+ command: 'Command',
2187
+ space: 'Space',
2188
+ shift: 'Shift',
2189
+ alt: 'Alt',
2190
+ enter: 'Enter',
2191
+ escape: 'Escape',
2192
+ upArrow: 'Up Arrow',
2193
+ downArrow: 'Down Arrow',
2194
+ leftArrow: 'Left Arrow',
2195
+ rightArrow: 'Right Arrow',
2196
+ backspace: 'Backspace',
2197
+ option: 'Option',
2198
+ plus: 'plus',
2199
+ shortcut: 'Keyboard shortcut: {0}'
2144
2200
  }
2145
2201
  };
2146
2202
 
@@ -4651,7 +4707,18 @@ const aliases = {
4651
4707
  treeviewExpand: 'mdi-menu-right',
4652
4708
  eyeDropper: 'mdi-eyedropper',
4653
4709
  upload: 'mdi-cloud-upload',
4654
- color: 'mdi-palette'
4710
+ color: 'mdi-palette',
4711
+ command: 'mdi-apple-keyboard-command',
4712
+ ctrl: 'mdi-apple-keyboard-control',
4713
+ space: 'mdi-keyboard-space',
4714
+ shift: 'mdi-apple-keyboard-shift',
4715
+ alt: 'mdi-apple-keyboard-option',
4716
+ enter: 'mdi-keyboard-return',
4717
+ arrowup: 'mdi-arrow-up',
4718
+ arrowdown: 'mdi-arrow-down',
4719
+ arrowleft: 'mdi-arrow-left',
4720
+ arrowright: 'mdi-arrow-right',
4721
+ backspace: 'mdi-backspace'
4655
4722
  };
4656
4723
  const mdi = {
4657
4724
  // Not using mergeProps here, functional components merge props by default (?)
@@ -8793,7 +8860,7 @@ const independentSelectStrategy = mandatory => {
8793
8860
  selected.set(id, value ? 'on' : 'off');
8794
8861
  return selected;
8795
8862
  },
8796
- in: (v, children, parents) => {
8863
+ in: (v, children, parents, disabled) => {
8797
8864
  const map = new Map();
8798
8865
  for (const id of v || []) {
8799
8866
  strategy.select({
@@ -8801,7 +8868,8 @@ const independentSelectStrategy = mandatory => {
8801
8868
  value: true,
8802
8869
  selected: map,
8803
8870
  children,
8804
- parents
8871
+ parents,
8872
+ disabled
8805
8873
  });
8806
8874
  }
8807
8875
  return map;
@@ -8833,9 +8901,9 @@ const independentSingleSelectStrategy = mandatory => {
8833
8901
  selected: singleSelected
8834
8902
  });
8835
8903
  },
8836
- in: (v, children, parents) => {
8904
+ in: (v, children, parents, disabled) => {
8837
8905
  if (v?.length) {
8838
- return parentStrategy.in(v.slice(0, 1), children, parents);
8906
+ return parentStrategy.in(v.slice(0, 1), children, parents, disabled);
8839
8907
  }
8840
8908
  return new Map();
8841
8909
  },
@@ -8901,23 +8969,32 @@ const classicSelectStrategy = mandatory => {
8901
8969
  value,
8902
8970
  selected,
8903
8971
  children,
8904
- parents
8972
+ parents,
8973
+ disabled
8905
8974
  } = _ref6;
8906
8975
  id = toRaw(id);
8907
8976
  const original = new Map(selected);
8908
8977
  const items = [id];
8909
8978
  while (items.length) {
8910
8979
  const item = items.shift();
8911
- selected.set(toRaw(item), value ? 'on' : 'off');
8980
+ if (!disabled.has(item)) {
8981
+ selected.set(toRaw(item), value ? 'on' : 'off');
8982
+ }
8912
8983
  if (children.has(item)) {
8913
8984
  items.push(...children.get(item));
8914
8985
  }
8915
8986
  }
8916
8987
  let parent = toRaw(parents.get(id));
8917
8988
  while (parent) {
8918
- const childrenIds = children.get(parent);
8919
- const everySelected = childrenIds.every(cid => selected.get(toRaw(cid)) === 'on');
8920
- const noneSelected = childrenIds.every(cid => !selected.has(toRaw(cid)) || selected.get(toRaw(cid)) === 'off');
8989
+ let everySelected = true;
8990
+ let noneSelected = true;
8991
+ for (const child of children.get(parent)) {
8992
+ const cid = toRaw(child);
8993
+ if (disabled.has(cid)) continue;
8994
+ if (selected.get(cid) !== 'on') everySelected = false;
8995
+ if (selected.has(cid) && selected.get(cid) !== 'off') noneSelected = false;
8996
+ if (!everySelected && !noneSelected) break;
8997
+ }
8921
8998
  selected.set(parent, everySelected ? 'on' : noneSelected ? 'off' : 'indeterminate');
8922
8999
  parent = toRaw(parents.get(parent));
8923
9000
  }
@@ -8934,7 +9011,7 @@ const classicSelectStrategy = mandatory => {
8934
9011
  }
8935
9012
  return selected;
8936
9013
  },
8937
- in: (v, children, parents) => {
9014
+ in: (v, children, parents, disabled) => {
8938
9015
  let map = new Map();
8939
9016
  for (const id of v || []) {
8940
9017
  map = strategy.select({
@@ -8942,7 +9019,8 @@ const classicSelectStrategy = mandatory => {
8942
9019
  value: true,
8943
9020
  selected: map,
8944
9021
  children,
8945
- parents
9022
+ parents,
9023
+ disabled
8946
9024
  });
8947
9025
  }
8948
9026
  return map;
@@ -8989,8 +9067,9 @@ const emptyNested = {
8989
9067
  root: {
8990
9068
  register: () => null,
8991
9069
  unregister: () => null,
8992
- parents: ref(new Map()),
8993
9070
  children: ref(new Map()),
9071
+ parents: ref(new Map()),
9072
+ disabled: ref(new Set()),
8994
9073
  open: () => null,
8995
9074
  openOnSelect: () => null,
8996
9075
  activate: () => null,
@@ -9019,6 +9098,7 @@ const useNested = props => {
9019
9098
  let isUnmounted = false;
9020
9099
  const children = shallowRef(new Map());
9021
9100
  const parents = shallowRef(new Map());
9101
+ const disabled = shallowRef(new Set());
9022
9102
  const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(Array.isArray(v) ? v.map(i => toRaw(i)) : v), v => [...v.values()]);
9023
9103
  const activeStrategy = computed(() => {
9024
9104
  if (typeof props.activeStrategy === 'object') return props.activeStrategy;
@@ -9067,7 +9147,7 @@ const useNested = props => {
9067
9147
  }
9068
9148
  });
9069
9149
  const activated = useProxiedModel(props, 'activated', props.activated, v => activeStrategy.value.in(v, children.value, parents.value), v => activeStrategy.value.out(v, children.value, parents.value));
9070
- const selected = useProxiedModel(props, 'selected', props.selected, v => selectStrategy.value.in(v, children.value, parents.value), v => selectStrategy.value.out(v, children.value, parents.value));
9150
+ const selected = useProxiedModel(props, 'selected', props.selected, v => selectStrategy.value.in(v, children.value, parents.value, disabled.value), v => selectStrategy.value.out(v, children.value, parents.value));
9071
9151
  onBeforeUnmount(() => {
9072
9152
  isUnmounted = true;
9073
9153
  });
@@ -9097,7 +9177,7 @@ const useNested = props => {
9097
9177
  }
9098
9178
  return arr;
9099
9179
  }),
9100
- register: (id, parentId, isGroup) => {
9180
+ register: (id, parentId, isDisabled, isGroup) => {
9101
9181
  if (nodeIds.has(id)) {
9102
9182
  const path = getPath(id).map(String).join(' -> ');
9103
9183
  const newPath = getPath(parentId).concat(id).map(String).join(' -> ');
@@ -9107,6 +9187,7 @@ const useNested = props => {
9107
9187
  nodeIds.add(id);
9108
9188
  }
9109
9189
  parentId && id !== parentId && parents.value.set(id, parentId);
9190
+ isDisabled && disabled.value.add(id);
9110
9191
  isGroup && children.value.set(id, []);
9111
9192
  if (parentId != null) {
9112
9193
  children.value.set(parentId, [...(children.value.get(parentId) || []), id]);
@@ -9116,6 +9197,7 @@ const useNested = props => {
9116
9197
  if (isUnmounted) return;
9117
9198
  nodeIds.delete(id);
9118
9199
  children.value.delete(id);
9200
+ disabled.value.delete(id);
9119
9201
  const parent = parents.value.get(id);
9120
9202
  if (parent) {
9121
9203
  const list = children.value.get(parent) ?? [];
@@ -9165,6 +9247,7 @@ const useNested = props => {
9165
9247
  selected: new Map(selected.value),
9166
9248
  children: children.value,
9167
9249
  parents: parents.value,
9250
+ disabled: disabled.value,
9168
9251
  event
9169
9252
  });
9170
9253
  newSelected && (selected.value = newSelected);
@@ -9207,13 +9290,14 @@ const useNested = props => {
9207
9290
  },
9208
9291
  children,
9209
9292
  parents,
9293
+ disabled,
9210
9294
  getPath
9211
9295
  }
9212
9296
  };
9213
9297
  provide(VNestedSymbol, nested);
9214
9298
  return nested.root;
9215
9299
  };
9216
- const useNestedItem = (id, isGroup) => {
9300
+ const useNestedItem = (id, isDisabled, isGroup) => {
9217
9301
  const parent = inject$1(VNestedSymbol, emptyNested);
9218
9302
  const uidSymbol = Symbol('nested item');
9219
9303
  const computedId = computed(() => toRaw(toValue(id)) ?? uidSymbol);
@@ -9233,10 +9317,14 @@ const useNestedItem = (id, isGroup) => {
9233
9317
  isGroupActivator: parent.isGroupActivator
9234
9318
  };
9235
9319
  onBeforeMount(() => {
9236
- !parent.isGroupActivator && parent.root.register(computedId.value, parent.id.value, isGroup);
9320
+ if (!parent.isGroupActivator) {
9321
+ parent.root.register(computedId.value, parent.id.value, toValue(isDisabled), isGroup);
9322
+ }
9237
9323
  });
9238
9324
  onBeforeUnmount(() => {
9239
- !parent.isGroupActivator && parent.root.unregister(computedId.value);
9325
+ if (!parent.isGroupActivator) {
9326
+ parent.root.unregister(computedId.value);
9327
+ }
9240
9328
  });
9241
9329
  isGroup && provide(VNestedSymbol, item);
9242
9330
  return item;
@@ -9268,6 +9356,7 @@ const makeVListGroupProps = propsFactory({
9268
9356
  type: IconValue,
9269
9357
  default: '$collapse'
9270
9358
  },
9359
+ disabled: Boolean,
9271
9360
  expandIcon: {
9272
9361
  type: IconValue,
9273
9362
  default: '$expand'
@@ -9293,7 +9382,7 @@ const VListGroup = genericComponent()({
9293
9382
  isOpen,
9294
9383
  open,
9295
9384
  id: _id
9296
- } = useNestedItem(() => props.value, true);
9385
+ } = useNestedItem(() => props.value, () => props.disabled, true);
9297
9386
  const id = computed(() => `v-list-group--id-${String(props.rawId ?? _id.value)}`);
9298
9387
  const list = useList();
9299
9388
  const {
@@ -9463,7 +9552,7 @@ const VListItem = genericComponent()({
9463
9552
  parent,
9464
9553
  openOnSelect,
9465
9554
  id: uid
9466
- } = useNestedItem(id, false);
9555
+ } = useNestedItem(id, () => props.disabled, false);
9467
9556
  const list = useList();
9468
9557
  const isActive = computed(() => props.active !== false && (props.active || link.isActive?.value || (root.activatable.value ? isActivated.value : isSelected.value)));
9469
9558
  const isLink = toRef(() => props.link !== false && link.isLink.value);
@@ -9815,6 +9904,10 @@ const makeItemsProps = propsFactory({
9815
9904
  type: [Boolean, String, Array, Function],
9816
9905
  default: 'props'
9817
9906
  },
9907
+ itemType: {
9908
+ type: [Boolean, String, Array, Function],
9909
+ default: 'type'
9910
+ },
9818
9911
  returnObject: Boolean,
9819
9912
  valueComparator: Function
9820
9913
  }, 'list-items');
@@ -9822,6 +9915,7 @@ function transformItem$3(props, item) {
9822
9915
  const title = getPropertyFromItem(item, props.itemTitle, item);
9823
9916
  const value = getPropertyFromItem(item, props.itemValue, title);
9824
9917
  const children = getPropertyFromItem(item, props.itemChildren);
9918
+ const type = getPropertyFromItem(item, props.itemType, 'item');
9825
9919
  const itemProps = props.itemProps === true ? typeof item === 'object' && item != null && !Array.isArray(item) ? 'children' in item ? omit(item, ['children']) : item : undefined : getPropertyFromItem(item, props.itemProps);
9826
9920
  const _props = {
9827
9921
  title,
@@ -9829,15 +9923,16 @@ function transformItem$3(props, item) {
9829
9923
  ...itemProps
9830
9924
  };
9831
9925
  return {
9926
+ type,
9832
9927
  title: String(_props.title ?? ''),
9833
9928
  value: _props.value,
9834
9929
  props: _props,
9835
- children: Array.isArray(children) ? transformItems$3(props, children) : undefined,
9930
+ children: type === 'item' && Array.isArray(children) ? transformItems$3(props, children) : undefined,
9836
9931
  raw: item
9837
9932
  };
9838
9933
  }
9839
9934
  function transformItems$3(props, items) {
9840
- const _props = pick(props, ['itemTitle', 'itemValue', 'itemChildren', 'itemProps', 'returnObject', 'valueComparator']);
9935
+ const _props = pick(props, ['itemTitle', 'itemValue', 'itemChildren', 'itemProps', 'itemType', 'returnObject', 'valueComparator']);
9841
9936
  const array = [];
9842
9937
  for (const item of items) {
9843
9938
  array.push(transformItem$3(_props, item));
@@ -9879,7 +9974,7 @@ function useItems(props) {
9879
9974
  const _returnObject = props.returnObject;
9880
9975
  const hasValueComparator = !!props.valueComparator;
9881
9976
  const valueComparator = props.valueComparator || deepEqual;
9882
- const _props = pick(props, ['itemTitle', 'itemValue', 'itemChildren', 'itemProps', 'returnObject', 'valueComparator']);
9977
+ const _props = pick(props, ['itemTitle', 'itemValue', 'itemChildren', 'itemProps', 'itemType', 'returnObject', 'valueComparator']);
9883
9978
  const returnValue = [];
9884
9979
  main: for (const v of value) {
9885
9980
  // When the model value is null, return an InternalItem
@@ -9999,10 +10094,6 @@ const makeVListProps = propsFactory({
9999
10094
  ...makeDensityProps(),
10000
10095
  ...makeDimensionProps(),
10001
10096
  ...makeElevationProps(),
10002
- itemType: {
10003
- type: String,
10004
- default: 'type'
10005
- },
10006
10097
  ...makeItemsProps(),
10007
10098
  ...makeRoundedProps(),
10008
10099
  ...makeTagProps(),
@@ -10423,7 +10514,7 @@ function connectedLocationStrategy(data, props, contentStyles) {
10423
10514
  });
10424
10515
  if (flipped.isFull) {
10425
10516
  const values = flipped.values();
10426
- if (deepEqual(values.at(-1), values.at(-3))) {
10517
+ if (deepEqual(values.at(-1), values.at(-3)) && !deepEqual(values.at(-1), values.at(-2))) {
10427
10518
  // Flipping is causing a container resize loop
10428
10519
  return;
10429
10520
  }
@@ -12273,7 +12364,7 @@ const VTextField = genericComponent()({
12273
12364
  if (!isFocused.value) focus();
12274
12365
  nextTick(() => {
12275
12366
  if (inputRef.value !== document.activeElement) {
12276
- inputRef.value?.focus();
12367
+ nextTick(() => inputRef.value?.focus());
12277
12368
  }
12278
12369
  });
12279
12370
  }
@@ -12612,7 +12703,7 @@ function useVirtual(props, items) {
12612
12703
  raf = requestAnimationFrame(_calculateVisibleItems);
12613
12704
  }
12614
12705
  function _calculateVisibleItems() {
12615
- if (!containerRef.value || !viewportHeight.value) return;
12706
+ if (!containerRef.value || !viewportHeight.value || !itemHeight.value) return;
12616
12707
  const scrollTop = lastScrollTop - markerOffset;
12617
12708
  const direction = Math.sign(scrollVelocity);
12618
12709
  const startPx = Math.max(0, scrollTop - BUFFER_PX);
@@ -13221,7 +13312,7 @@ const VSelect = genericComponent()({
13221
13312
  key: item.value,
13222
13313
  onClick: () => select(item, null)
13223
13314
  });
13224
- if (item.raw.type === 'divider') {
13315
+ if (item.type === 'divider') {
13225
13316
  return slots.divider?.({
13226
13317
  props: item.raw,
13227
13318
  index
@@ -13229,7 +13320,7 @@ const VSelect = genericComponent()({
13229
13320
  "key": `divider-${index}`
13230
13321
  }), null);
13231
13322
  }
13232
- if (item.raw.type === 'subheader') {
13323
+ if (item.type === 'subheader') {
13233
13324
  return slots.subheader?.({
13234
13325
  props: item.raw,
13235
13326
  index
@@ -13397,7 +13488,7 @@ function filterItems(items, query, options) {
13397
13488
  let match = -1;
13398
13489
  if ((query || customFiltersLength > 0) && !options?.noFilter) {
13399
13490
  if (typeof item === 'object') {
13400
- if (['divider', 'subheader'].includes(item.raw?.type)) {
13491
+ if (item.type === 'divider' || item.type === 'subheader') {
13401
13492
  continue;
13402
13493
  }
13403
13494
  const filterKeys = keys || Object.keys(transformed);
@@ -13839,7 +13930,7 @@ const VAutocomplete = genericComponent()({
13839
13930
  active: highlightFirst.value && index === 0 ? true : undefined,
13840
13931
  onClick: () => select(item, null)
13841
13932
  });
13842
- if (item.raw.type === 'divider') {
13933
+ if (item.type === 'divider') {
13843
13934
  return slots.divider?.({
13844
13935
  props: item.raw,
13845
13936
  index
@@ -13847,7 +13938,7 @@ const VAutocomplete = genericComponent()({
13847
13938
  "key": `divider-${index}`
13848
13939
  }), null);
13849
13940
  }
13850
- if (item.raw.type === 'subheader') {
13941
+ if (item.type === 'subheader') {
13851
13942
  return slots.subheader?.({
13852
13943
  props: item.raw,
13853
13944
  index
@@ -17495,7 +17586,7 @@ function format(value, formatString, locale, formats) {
17495
17586
  case 'fullDate':
17496
17587
  options = {
17497
17588
  year: 'numeric',
17498
- month: 'long',
17589
+ month: 'short',
17499
17590
  day: 'numeric'
17500
17591
  };
17501
17592
  break;
@@ -18073,6 +18164,317 @@ function useDate() {
18073
18164
  return createInstance(options, locale);
18074
18165
  }
18075
18166
 
18167
+ /**
18168
+ * Centralized key alias mapping for consistent key normalization across the hotkey system.
18169
+ *
18170
+ * This maps various user-friendly aliases to canonical key names that match
18171
+ * KeyboardEvent.key values (in lowercase) where possible.
18172
+ */
18173
+ const keyAliasMap = {
18174
+ // Modifier aliases (from vue-use, other libraries, and current implementation)
18175
+ control: 'ctrl',
18176
+ command: 'cmd',
18177
+ option: 'alt',
18178
+ // Arrow key aliases (common abbreviations)
18179
+ up: 'arrowup',
18180
+ down: 'arrowdown',
18181
+ left: 'arrowleft',
18182
+ right: 'arrowright',
18183
+ // Other common key aliases
18184
+ esc: 'escape',
18185
+ spacebar: ' ',
18186
+ space: ' ',
18187
+ return: 'enter',
18188
+ del: 'delete',
18189
+ // Symbol aliases (existing from hotkey-parsing.ts)
18190
+ minus: '-',
18191
+ hyphen: '-'
18192
+ };
18193
+
18194
+ /**
18195
+ * Normalizes a key string to its canonical form using the alias map.
18196
+ *
18197
+ * @param key - The key string to normalize
18198
+ * @returns The canonical key name in lowercase
18199
+ */
18200
+ function normalizeKey(key) {
18201
+ const lowerKey = key.toLowerCase();
18202
+ return keyAliasMap[lowerKey] || lowerKey;
18203
+ }
18204
+
18205
+ // Utilities
18206
+
18207
+ /**
18208
+ * Splits a single combination string into individual key parts.
18209
+ *
18210
+ * A combination is a set of keys that must be pressed simultaneously.
18211
+ * e.g. `ctrl+k`, `shift--`
18212
+ */
18213
+ function splitKeyCombination(combination) {
18214
+ let isInternal = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
18215
+ if (!combination) {
18216
+ if (!isInternal) consoleWarn('Invalid hotkey combination: empty string provided');
18217
+ return [];
18218
+ }
18219
+
18220
+ // --- VALIDATION ---
18221
+ const startsWithPlusOrUnderscore = combination.startsWith('+') || combination.startsWith('_');
18222
+ const hasInvalidLeadingSeparator =
18223
+ // Starts with a single '+' or '_' followed by a non-separator character (e.g. '+a', '_a')
18224
+ startsWithPlusOrUnderscore && !(combination.startsWith('++') || combination.startsWith('__'));
18225
+ const hasInvalidStructure =
18226
+ // Invalid leading separator patterns
18227
+ combination.length > 1 && hasInvalidLeadingSeparator ||
18228
+ // Disallow literal + or _ keys (they require shift)
18229
+ combination.includes('++') || combination.includes('__') || combination === '+' || combination === '_' ||
18230
+ // Ends with a separator that is not part of a doubled literal
18231
+ combination.length > 1 && (combination.endsWith('+') || combination.endsWith('_')) && combination.at(-2) !== combination.at(-1) ||
18232
+ // Stand-alone doubled separators (dangling)
18233
+ combination === '++' || combination === '--' || combination === '__';
18234
+ if (hasInvalidStructure) {
18235
+ if (!isInternal) consoleWarn(`Invalid hotkey combination: "${combination}" has invalid structure`);
18236
+ return [];
18237
+ }
18238
+ const keys = [];
18239
+ let buffer = '';
18240
+ const flushBuffer = () => {
18241
+ if (buffer) {
18242
+ keys.push(normalizeKey(buffer));
18243
+ buffer = '';
18244
+ }
18245
+ };
18246
+ for (let i = 0; i < combination.length; i++) {
18247
+ const char = combination[i];
18248
+ const nextChar = combination[i + 1];
18249
+ if (char === '+' || char === '_' || char === '-') {
18250
+ if (char === nextChar) {
18251
+ flushBuffer();
18252
+ keys.push(char);
18253
+ i++;
18254
+ } else if (char === '+' || char === '_') {
18255
+ flushBuffer();
18256
+ } else {
18257
+ buffer += char;
18258
+ }
18259
+ } else {
18260
+ buffer += char;
18261
+ }
18262
+ }
18263
+ flushBuffer();
18264
+
18265
+ // Within a combination, `-` is only valid as a literal key (e.g., `ctrl+-`).
18266
+ // `-` cannot be part of a longer key name within a combination.
18267
+ const hasInvalidMinus = keys.some(key => key.length > 1 && key.includes('-') && key !== '--');
18268
+ if (hasInvalidMinus) {
18269
+ if (!isInternal) consoleWarn(`Invalid hotkey combination: "${combination}" has invalid structure`);
18270
+ return [];
18271
+ }
18272
+ if (keys.length === 0 && combination) {
18273
+ return [normalizeKey(combination)];
18274
+ }
18275
+ return keys;
18276
+ }
18277
+
18278
+ /**
18279
+ * Splits a hotkey string into its constituent combination groups.
18280
+ *
18281
+ * A sequence is a series of combinations that must be pressed in order.
18282
+ * e.g. `a-b`, `ctrl+k-p`
18283
+ */
18284
+ function splitKeySequence(str) {
18285
+ if (!str) {
18286
+ consoleWarn('Invalid hotkey sequence: empty string provided');
18287
+ return [];
18288
+ }
18289
+
18290
+ // A sequence is invalid if it starts or ends with a separator,
18291
+ // unless it is part of a combination (e.g., `shift+-`).
18292
+ const hasInvalidStart = str.startsWith('-') && !['---', '--+'].includes(str);
18293
+ const hasInvalidEnd = str.endsWith('-') && !str.endsWith('+-') && !str.endsWith('_-') && str !== '-' && str !== '---';
18294
+ if (hasInvalidStart || hasInvalidEnd) {
18295
+ consoleWarn(`Invalid hotkey sequence: "${str}" contains invalid combinations`);
18296
+ return [];
18297
+ }
18298
+ const result = [];
18299
+ let buffer = '';
18300
+ let i = 0;
18301
+ while (i < str.length) {
18302
+ const char = str[i];
18303
+ if (char === '-') {
18304
+ // Determine if this hyphen is part of the current combination
18305
+ const prevChar = str[i - 1];
18306
+ const prevPrevChar = i > 1 ? str[i - 2] : undefined;
18307
+ const precededBySinglePlusOrUnderscore = (prevChar === '+' || prevChar === '_') && prevPrevChar !== '+';
18308
+ if (precededBySinglePlusOrUnderscore) {
18309
+ // Treat as part of the combination (e.g., 'ctrl+-')
18310
+ buffer += char;
18311
+ i++;
18312
+ } else {
18313
+ // Treat as sequence separator
18314
+ if (buffer) {
18315
+ result.push(buffer);
18316
+ buffer = '';
18317
+ } else {
18318
+ // Empty buffer means we have a literal '-' key
18319
+ result.push('-');
18320
+ }
18321
+ i++;
18322
+ }
18323
+ } else {
18324
+ buffer += char;
18325
+ i++;
18326
+ }
18327
+ }
18328
+
18329
+ // Add final buffer if it exists
18330
+ if (buffer) {
18331
+ result.push(buffer);
18332
+ }
18333
+
18334
+ // Collapse runs of '-' so that every second '-' is removed
18335
+ const collapsed = [];
18336
+ let minusCount = 0;
18337
+ for (const part of result) {
18338
+ if (part === '-') {
18339
+ if (minusCount % 2 === 0) collapsed.push('-');
18340
+ minusCount++;
18341
+ } else {
18342
+ minusCount = 0;
18343
+ collapsed.push(part);
18344
+ }
18345
+ }
18346
+
18347
+ // Validate that each part of the sequence is a valid combination
18348
+ const areAllValid = collapsed.every(s => splitKeyCombination(s, true).length > 0);
18349
+ if (!areAllValid) {
18350
+ consoleWarn(`Invalid hotkey sequence: "${str}" contains invalid combinations`);
18351
+ return [];
18352
+ }
18353
+ return collapsed;
18354
+ }
18355
+
18356
+ // Composables
18357
+
18358
+ // Types
18359
+
18360
+ function useHotkey(keys, callback) {
18361
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
18362
+ if (!IN_BROWSER) return function () {};
18363
+ const {
18364
+ event = 'keydown',
18365
+ inputs = false,
18366
+ preventDefault = true,
18367
+ sequenceTimeout = 1000
18368
+ } = options;
18369
+ const isMac = navigator?.userAgent?.includes('Macintosh') ?? false;
18370
+ let timeout = 0;
18371
+ let keyGroups;
18372
+ let isSequence = false;
18373
+ let groupIndex = 0;
18374
+ function clearTimer() {
18375
+ if (!timeout) return;
18376
+ clearTimeout(timeout);
18377
+ timeout = 0;
18378
+ }
18379
+ function isInputFocused() {
18380
+ if (toValue(inputs)) return false;
18381
+ const activeElement = document.activeElement;
18382
+ return activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA' || activeElement.isContentEditable || activeElement.contentEditable === 'true');
18383
+ }
18384
+ function resetSequence() {
18385
+ groupIndex = 0;
18386
+ clearTimer();
18387
+ }
18388
+ function handler(e) {
18389
+ const group = keyGroups[groupIndex];
18390
+ if (!group || isInputFocused()) return;
18391
+ if (!matchesKeyGroup(e, group)) {
18392
+ if (isSequence) resetSequence();
18393
+ return;
18394
+ }
18395
+ if (toValue(preventDefault)) e.preventDefault();
18396
+ if (!isSequence) {
18397
+ callback(e);
18398
+ return;
18399
+ }
18400
+ clearTimer();
18401
+ groupIndex++;
18402
+ if (groupIndex === keyGroups.length) {
18403
+ callback(e);
18404
+ resetSequence();
18405
+ return;
18406
+ }
18407
+ timeout = window.setTimeout(resetSequence, toValue(sequenceTimeout));
18408
+ }
18409
+ function cleanup() {
18410
+ window.removeEventListener(toValue(event), handler);
18411
+ clearTimer();
18412
+ }
18413
+ watch(() => toValue(keys), function (unrefKeys) {
18414
+ cleanup();
18415
+ if (unrefKeys) {
18416
+ const groups = splitKeySequence(unrefKeys.toLowerCase());
18417
+ isSequence = groups.length > 1;
18418
+ keyGroups = groups;
18419
+ resetSequence();
18420
+ window.addEventListener(toValue(event), handler);
18421
+ }
18422
+ }, {
18423
+ immediate: true
18424
+ });
18425
+
18426
+ // Watch for changes in the event type to re-register the listener
18427
+ watch(() => toValue(event), function (newEvent, oldEvent) {
18428
+ if (oldEvent && keyGroups && keyGroups.length > 0) {
18429
+ window.removeEventListener(oldEvent, handler);
18430
+ window.addEventListener(newEvent, handler);
18431
+ }
18432
+ });
18433
+ try {
18434
+ getCurrentInstance('useHotkey');
18435
+ onBeforeUnmount(cleanup);
18436
+ } catch {
18437
+ // Not in Vue setup context
18438
+ }
18439
+ function parseKeyGroup(group) {
18440
+ const MODIFIERS = ['ctrl', 'shift', 'alt', 'meta', 'cmd'];
18441
+
18442
+ // Use the shared combination splitting logic
18443
+ const parts = splitKeyCombination(group.toLowerCase());
18444
+
18445
+ // If the combination is invalid, return empty result
18446
+ if (parts.length === 0) {
18447
+ return {
18448
+ modifiers: Object.fromEntries(MODIFIERS.map(m => [m, false])),
18449
+ actualKey: undefined
18450
+ };
18451
+ }
18452
+ const modifiers = Object.fromEntries(MODIFIERS.map(m => [m, false]));
18453
+ let actualKey;
18454
+ for (const part of parts) {
18455
+ if (MODIFIERS.includes(part)) {
18456
+ modifiers[part] = true;
18457
+ } else {
18458
+ actualKey = part;
18459
+ }
18460
+ }
18461
+ return {
18462
+ modifiers,
18463
+ actualKey
18464
+ };
18465
+ }
18466
+ function matchesKeyGroup(e, group) {
18467
+ const {
18468
+ modifiers,
18469
+ actualKey
18470
+ } = parseKeyGroup(group);
18471
+ const expectCtrl = modifiers.ctrl || !isMac && (modifiers.cmd || modifiers.meta);
18472
+ const expectMeta = isMac && (modifiers.cmd || modifiers.meta);
18473
+ return e.ctrlKey === expectCtrl && e.metaKey === expectMeta && e.shiftKey === modifiers.shift && e.altKey === modifiers.alt && e.key.toLowerCase() === actualKey?.toLowerCase();
18474
+ }
18475
+ return cleanup;
18476
+ }
18477
+
18076
18478
  // Types
18077
18479
 
18078
18480
  const makeVColorPickerProps = propsFactory({
@@ -18619,7 +19021,7 @@ const VCombobox = genericComponent()({
18619
19021
  active: highlightFirst.value && index === 0 ? true : undefined,
18620
19022
  onClick: () => select(item, null)
18621
19023
  });
18622
- if (item.raw.type === 'divider') {
19024
+ if (item.type === 'divider') {
18623
19025
  return slots.divider?.({
18624
19026
  props: item.raw,
18625
19027
  index
@@ -18627,7 +19029,7 @@ const VCombobox = genericComponent()({
18627
19029
  "key": `divider-${index}`
18628
19030
  }), null);
18629
19031
  }
18630
- if (item.raw.type === 'subheader') {
19032
+ if (item.type === 'subheader') {
18631
19033
  return slots.subheader?.({
18632
19034
  props: item.raw,
18633
19035
  index
@@ -19501,7 +19903,8 @@ function sortItems(items, sortByItems, locale, options) {
19501
19903
 
19502
19904
  // Dates should be compared numerically
19503
19905
  if (sortA instanceof Date && sortB instanceof Date) {
19504
- return sortA.getTime() - sortB.getTime();
19906
+ sortA = sortA.getTime();
19907
+ sortB = sortB.getTime();
19505
19908
  }
19506
19909
  [sortA, sortB] = [sortA, sortB].map(s => s != null ? s.toString().toLocaleLowerCase() : s);
19507
19910
  if (sortA !== sortB) {
@@ -20210,10 +20613,15 @@ const VDataTableColumn = defineFunctionalComponent({
20210
20613
  type: String,
20211
20614
  default: 'start'
20212
20615
  },
20213
- fixed: Boolean,
20616
+ fixed: {
20617
+ type: [Boolean, String],
20618
+ default: false
20619
+ },
20214
20620
  fixedOffset: [Number, String],
20621
+ fixedEndOffset: [Number, String],
20215
20622
  height: [Number, String],
20216
20623
  lastFixed: Boolean,
20624
+ firstFixedEnd: Boolean,
20217
20625
  noPadding: Boolean,
20218
20626
  tag: String,
20219
20627
  width: [Number, String],
@@ -20224,11 +20632,13 @@ const VDataTableColumn = defineFunctionalComponent({
20224
20632
  slots
20225
20633
  } = _ref;
20226
20634
  const Tag = props.tag ?? 'td';
20635
+ const fixedSide = typeof props.fixed === 'string' ? props.fixed : props.fixed ? 'start' : 'none';
20227
20636
  return createVNode(Tag, {
20228
- "tabindex": "0",
20229
20637
  "class": normalizeClass(['v-data-table__td', {
20230
- 'v-data-table-column--fixed': props.fixed,
20638
+ 'v-data-table-column--fixed': fixedSide === 'start',
20639
+ 'v-data-table-column--fixed-end': fixedSide === 'end',
20231
20640
  'v-data-table-column--last-fixed': props.lastFixed,
20641
+ 'v-data-table-column--first-fixed-end': props.firstFixedEnd,
20232
20642
  'v-data-table-column--no-padding': props.noPadding,
20233
20643
  'v-data-table-column--nowrap': props.nowrap
20234
20644
  }, `v-data-table-column--align-${props.align}`]),
@@ -20236,7 +20646,8 @@ const VDataTableColumn = defineFunctionalComponent({
20236
20646
  height: convertToUnit(props.height),
20237
20647
  width: convertToUnit(props.width),
20238
20648
  maxWidth: convertToUnit(props.maxWidth),
20239
- left: convertToUnit(props.fixedOffset || null)
20649
+ left: fixedSide === 'start' ? convertToUnit(props.fixedOffset || null) : undefined,
20650
+ right: fixedSide === 'end' ? convertToUnit(props.fixedEndOffset || null) : undefined
20240
20651
  }
20241
20652
  }, {
20242
20653
  default: () => [slots.default?.()]
@@ -20333,20 +20744,28 @@ function getDepth(item) {
20333
20744
  }
20334
20745
  function parseFixedColumns(items) {
20335
20746
  let seenFixed = false;
20336
- function setFixed(item) {
20337
- let parentFixed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
20747
+ function setFixed(item, side) {
20748
+ let parentFixedSide = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'none';
20338
20749
  if (!item) return;
20339
- if (parentFixed) {
20340
- item.fixed = true;
20750
+ if (parentFixedSide !== 'none') {
20751
+ item.fixed = parentFixedSide;
20341
20752
  }
20342
- if (item.fixed) {
20343
- if (item.children) {
20344
- for (let i = item.children.length - 1; i >= 0; i--) {
20345
- setFixed(item.children[i], true);
20753
+
20754
+ // normalize to simplify logic below
20755
+ if (item.fixed === true) {
20756
+ item.fixed = 'start';
20757
+ }
20758
+ const orderedChildren = side === 'start' ? item.children?.toReversed() : item.children;
20759
+ if (item.fixed === side) {
20760
+ if (orderedChildren) {
20761
+ for (const child of orderedChildren) {
20762
+ setFixed(child, side, side);
20346
20763
  }
20347
20764
  } else {
20348
- if (!seenFixed) {
20765
+ if (!seenFixed && side === 'start') {
20349
20766
  item.lastFixed = true;
20767
+ } else if (!seenFixed && side === 'end') {
20768
+ item.firstFixedEnd = true;
20350
20769
  } else if (isNaN(Number(item.width))) {
20351
20770
  consoleError(`Multiple fixed columns should have a static width (key: ${item.key})`);
20352
20771
  } else {
@@ -20355,36 +20774,57 @@ function parseFixedColumns(items) {
20355
20774
  seenFixed = true;
20356
20775
  }
20357
20776
  } else {
20358
- if (item.children) {
20359
- for (let i = item.children.length - 1; i >= 0; i--) {
20360
- setFixed(item.children[i]);
20777
+ if (orderedChildren) {
20778
+ for (const child of orderedChildren) {
20779
+ setFixed(child, side);
20361
20780
  }
20362
20781
  } else {
20363
20782
  seenFixed = false;
20364
20783
  }
20365
20784
  }
20366
20785
  }
20367
- for (let i = items.length - 1; i >= 0; i--) {
20368
- setFixed(items[i]);
20786
+ for (const item of items.toReversed()) {
20787
+ setFixed(item, 'start');
20788
+ }
20789
+ for (const item of items) {
20790
+ setFixed(item, 'end');
20369
20791
  }
20370
20792
  function setFixedOffset(item) {
20371
- let fixedOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
20372
- if (!item) return fixedOffset;
20793
+ let offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
20794
+ if (!item) return offset;
20373
20795
  if (item.children) {
20374
- item.fixedOffset = fixedOffset;
20796
+ item.fixedOffset = offset;
20375
20797
  for (const child of item.children) {
20376
- fixedOffset = setFixedOffset(child, fixedOffset);
20798
+ offset = setFixedOffset(child, offset);
20377
20799
  }
20378
- } else if (item.fixed) {
20379
- item.fixedOffset = fixedOffset;
20380
- fixedOffset += parseFloat(item.width || '0') || 0;
20800
+ } else if (item.fixed && item.fixed !== 'end') {
20801
+ item.fixedOffset = offset;
20802
+ offset += parseFloat(item.width || '0') || 0;
20381
20803
  }
20382
- return fixedOffset;
20804
+ return offset;
20383
20805
  }
20384
20806
  let fixedOffset = 0;
20385
20807
  for (const item of items) {
20386
20808
  fixedOffset = setFixedOffset(item, fixedOffset);
20387
20809
  }
20810
+ function setFixedEndOffset(item) {
20811
+ let offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
20812
+ if (!item) return offset;
20813
+ if (item.children) {
20814
+ item.fixedEndOffset = offset;
20815
+ for (const child of item.children) {
20816
+ offset = setFixedEndOffset(child, offset);
20817
+ }
20818
+ } else if (item.fixed === 'end') {
20819
+ item.fixedEndOffset = offset;
20820
+ offset += parseFloat(item.width || '0') || 0;
20821
+ }
20822
+ return offset;
20823
+ }
20824
+ let fixedEndOffset = 0;
20825
+ for (const item of items.toReversed()) {
20826
+ fixedEndOffset = setFixedEndOffset(item, fixedEndOffset);
20827
+ }
20388
20828
  }
20389
20829
  function parse(items, maxDepth) {
20390
20830
  const headers = [];
@@ -20517,7 +20957,6 @@ const makeVDataTableHeadersProps = propsFactory({
20517
20957
  color: String,
20518
20958
  disableSort: Boolean,
20519
20959
  fixedHeader: Boolean,
20520
- lastFixed: Boolean,
20521
20960
  multiSort: Boolean,
20522
20961
  sortAscIcon: {
20523
20962
  type: IconValue,
@@ -20564,11 +21003,12 @@ const VDataTableHeaders = genericComponent()({
20564
21003
  loaderClasses
20565
21004
  } = useLoader(props);
20566
21005
  function getFixedStyles(column, y) {
20567
- if (!(props.sticky || props.fixedHeader) && !(column.fixed || column.lastFixed)) return undefined;
21006
+ if (!(props.sticky || props.fixedHeader) && !column.fixed) return undefined;
21007
+ const fixedSide = typeof column.fixed === 'string' ? column.fixed : column.fixed ? 'start' : 'none';
20568
21008
  return {
20569
21009
  position: 'sticky',
20570
- left: column.fixed || column.lastFixed ? convertToUnit(column.fixedOffset) : undefined,
20571
- right: column.lastFixed ? convertToUnit(column.fixedOffset ?? 0) : undefined,
21010
+ left: fixedSide === 'start' ? convertToUnit(column.fixedOffset) : undefined,
21011
+ right: fixedSide === 'end' ? convertToUnit(column.fixedEndOffset) : undefined,
20572
21012
  top: props.sticky || props.fixedHeader ? `calc(var(--v-table-header-height) * ${y})` : undefined
20573
21013
  };
20574
21014
  }
@@ -20628,14 +21068,15 @@ const VDataTableHeaders = genericComponent()({
20628
21068
  },
20629
21069
  "colspan": column.colspan,
20630
21070
  "rowspan": column.rowspan,
20631
- "onClick": column.sortable ? () => toggleSort(column) : undefined,
20632
21071
  "fixed": column.fixed,
20633
21072
  "nowrap": column.nowrap,
20634
21073
  "lastFixed": column.lastFixed,
20635
- "noPadding": noPadding
20636
- }, headerProps, {
20637
- "onKeydown": event => column.sortable && handleEnterKeyPress(event, column)
20638
- }), {
21074
+ "firstFixedEnd": column.firstFixedEnd,
21075
+ "noPadding": noPadding,
21076
+ "tabindex": column.sortable ? 0 : undefined,
21077
+ "onClick": column.sortable ? () => toggleSort(column) : undefined,
21078
+ "onKeydown": column.sortable ? event => handleEnterKeyPress(event, column) : undefined
21079
+ }, headerProps), {
20639
21080
  default: () => {
20640
21081
  const columnSlotName = `header.${column.key}`;
20641
21082
  const columnSlotProps = {
@@ -20911,7 +21352,9 @@ const VDataTableRow = genericComponent()({
20911
21352
  },
20912
21353
  "fixed": column.fixed,
20913
21354
  "fixedOffset": column.fixedOffset,
21355
+ "fixedEndOffset": column.fixedEndOffset,
20914
21356
  "lastFixed": column.lastFixed,
21357
+ "firstFixedEnd": column.firstFixedEnd,
20915
21358
  "maxWidth": !mobile.value ? column.maxWidth : undefined,
20916
21359
  "noPadding": column.key === 'data-table-select' || column.key === 'data-table-expand',
20917
21360
  "nowrap": column.nowrap,
@@ -22321,13 +22764,9 @@ function useCalendar(props) {
22321
22764
  const date = adapter.setYear(adapter.startOfMonth(adapter.date()), adapter.getYear(year.value));
22322
22765
  return adapter.setMonth(date, value);
22323
22766
  }, v => adapter.getMonth(v));
22324
- const weekDays = computed(() => {
22325
- const firstDayOfWeek = adapter.toJsDate(adapter.startOfWeek(adapter.date(), props.firstDayOfWeek)).getDay();
22326
- return props.weekdays.map(day => (day + firstDayOfWeek) % 7);
22327
- });
22328
22767
  const weekdayLabels = computed(() => {
22329
- const labels = adapter.getWeekdays(props.firstDayOfWeek, props.weekdayFormat);
22330
- return weekDays.value.map(day => labels[day]);
22768
+ const firstDayOfWeek = adapter.toJsDate(adapter.startOfWeek(adapter.date(), props.firstDayOfWeek)).getDay();
22769
+ return adapter.getWeekdays(props.firstDayOfWeek, props.weekdayFormat).filter((_, i) => props.weekdays.includes((i + firstDayOfWeek) % 7));
22331
22770
  });
22332
22771
  const weeksInMonth = computed(() => {
22333
22772
  const weeks = adapter.getWeekArray(month.value, props.firstDayOfWeek);
@@ -22351,13 +22790,14 @@ function useCalendar(props) {
22351
22790
  });
22352
22791
  function genDays(days, today) {
22353
22792
  return days.filter(date => {
22354
- return weekDays.value.includes(adapter.toJsDate(date).getDay());
22793
+ return props.weekdays.includes(adapter.toJsDate(date).getDay());
22355
22794
  }).map((date, index) => {
22356
22795
  const isoDate = adapter.toISO(date);
22357
22796
  const isAdjacent = !adapter.isSameMonth(date, month.value);
22358
22797
  const isStart = adapter.isSameDay(date, adapter.startOfMonth(month.value));
22359
22798
  const isEnd = adapter.isSameDay(date, adapter.endOfMonth(month.value));
22360
22799
  const isSame = adapter.isSameDay(date, month.value);
22800
+ const weekdaysCount = props.weekdays.length;
22361
22801
  return {
22362
22802
  date,
22363
22803
  formatted: adapter.format(date, 'keyboardDate'),
@@ -22369,8 +22809,8 @@ function useCalendar(props) {
22369
22809
  isSelected: model.value.some(value => adapter.isSameDay(date, value)),
22370
22810
  isStart,
22371
22811
  isToday: adapter.isSameDay(date, today),
22372
- isWeekEnd: index % 7 === 6,
22373
- isWeekStart: index % 7 === 0,
22812
+ isWeekEnd: index % weekdaysCount === weekdaysCount - 1,
22813
+ isWeekStart: index % weekdaysCount === 0,
22374
22814
  isoDate,
22375
22815
  localized: adapter.format(date, 'dayOfMonth'),
22376
22816
  month: adapter.getMonth(date),
@@ -22417,7 +22857,6 @@ function useCalendar(props) {
22417
22857
  genDays,
22418
22858
  model,
22419
22859
  weeksInMonth,
22420
- weekDays,
22421
22860
  weekdayLabels,
22422
22861
  weekNumbers
22423
22862
  };
@@ -22458,7 +22897,6 @@ const VDatePickerMonth = genericComponent()({
22458
22897
  daysInMonth,
22459
22898
  model,
22460
22899
  weekNumbers,
22461
- weekDays,
22462
22900
  weekdayLabels
22463
22901
  } = useCalendar(props);
22464
22902
  const adapter = useDate();
@@ -22533,7 +22971,7 @@ const VDatePickerMonth = genericComponent()({
22533
22971
  useRender(() => createElementVNode("div", {
22534
22972
  "class": "v-date-picker-month",
22535
22973
  "style": {
22536
- '--v-date-picker-days-in-week': weekDays.value.length
22974
+ '--v-date-picker-days-in-week': props.weekdays.length
22537
22975
  }
22538
22976
  }, [props.showWeek && createElementVNode("div", {
22539
22977
  "key": "weeks",
@@ -22933,7 +23371,8 @@ const VDatePicker = genericComponent()({
22933
23371
  }
22934
23372
  function allowedMonths(month) {
22935
23373
  if (typeof props.allowedDates === 'function') {
22936
- const startOfMonth = adapter.parseISO(`${year.value}-${month + 1}-01`);
23374
+ const monthTwoDigits = String(month + 1).padStart(2, '0');
23375
+ const startOfMonth = adapter.parseISO(`${year.value}-${monthTwoDigits}-01`);
22937
23376
  return isAllowedInRange(startOfMonth, adapter.endOfMonth(startOfMonth));
22938
23377
  }
22939
23378
  if (Array.isArray(props.allowedDates) && props.allowedDates.length) {
@@ -25704,19 +26143,21 @@ const VOtpInput = genericComponent()({
25704
26143
  const contentRef = ref();
25705
26144
  const inputRef = ref([]);
25706
26145
  const current = computed(() => inputRef.value[focusIndex.value]);
25707
- const intersectScope = effectScope();
25708
- intersectScope.run(() => {
25709
- const {
25710
- intersectionRef,
25711
- isIntersecting
25712
- } = useIntersectionObserver();
25713
- watch(isIntersecting, v => {
25714
- if (!v) return;
25715
- intersectionRef.value?.focus();
25716
- intersectScope.stop();
25717
- });
25718
- watchEffect(() => {
25719
- intersectionRef.value = inputRef.value[0];
26146
+ useToggleScope(() => props.autofocus, () => {
26147
+ const intersectScope = effectScope();
26148
+ intersectScope.run(() => {
26149
+ const {
26150
+ intersectionRef,
26151
+ isIntersecting
26152
+ } = useIntersectionObserver();
26153
+ watchEffect(() => {
26154
+ intersectionRef.value = inputRef.value[0];
26155
+ });
26156
+ watch(isIntersecting, v => {
26157
+ if (!v) return;
26158
+ intersectionRef.value?.focus();
26159
+ intersectScope.stop();
26160
+ });
25720
26161
  });
25721
26162
  });
25722
26163
  function onInput() {
@@ -29727,6 +30168,8 @@ const VTreeviewSymbol = Symbol.for('vuetify:v-treeview');
29727
30168
 
29728
30169
  const makeVTreeviewItemProps = propsFactory({
29729
30170
  loading: Boolean,
30171
+ hideActions: Boolean,
30172
+ indentLines: Array,
29730
30173
  toggleIcon: IconValue,
29731
30174
  ...makeVListItemProps({
29732
30175
  slim: true
@@ -29763,11 +30206,11 @@ const VTreeviewItem = genericComponent()({
29763
30206
  }
29764
30207
  useRender(() => {
29765
30208
  const listItemProps = VListItem.filterProps(props);
29766
- const hasPrepend = slots.prepend || props.toggleIcon;
30209
+ const hasPrepend = slots.prepend || props.toggleIcon || props.indentLines;
29767
30210
  return createVNode(VListItem, mergeProps({
29768
30211
  "ref": vListItemRef
29769
30212
  }, listItemProps, {
29770
- "active": vListItemRef.value?.isActivated,
30213
+ "active": vListItemRef.value?.isActivated || undefined,
29771
30214
  "class": ['v-treeview-item', {
29772
30215
  'v-treeview-item--activatable-group-activator': isActivatableGroupActivator.value,
29773
30216
  'v-treeview-item--filtered': isFiltered.value
@@ -29777,7 +30220,15 @@ const VTreeviewItem = genericComponent()({
29777
30220
  }), {
29778
30221
  ...slots,
29779
30222
  prepend: hasPrepend ? slotProps => {
29780
- return createElementVNode(Fragment, null, [createVNode(VListItemAction, {
30223
+ return createElementVNode(Fragment, null, [props.indentLines && props.indentLines.length > 0 ? createElementVNode("div", {
30224
+ "key": "indent-lines",
30225
+ "class": "v-treeview-indent-lines",
30226
+ "style": {
30227
+ '--v-indent-parts': props.indentLines.length
30228
+ }
30229
+ }, [props.indentLines.map(type => createElementVNode("div", {
30230
+ "class": normalizeClass(`v-treeview-indent-line v-treeview-indent-line--${type}`)
30231
+ }, null))]) : '', !props.hideActions && createVNode(VListItemAction, {
29781
30232
  "start": true
29782
30233
  }, {
29783
30234
  default: () => [props.toggleIcon ? createVNode(VBtn, {
@@ -29829,10 +30280,15 @@ const makeVTreeviewChildrenProps = propsFactory({
29829
30280
  selectedColor: String,
29830
30281
  selectStrategy: [String, Function, Object],
29831
30282
  index: Number,
30283
+ isLastGroup: Boolean,
30284
+ separateRoots: Boolean,
30285
+ parentIndentLines: Array,
30286
+ indentLinesVariant: String,
29832
30287
  path: {
29833
30288
  type: Array,
29834
30289
  default: () => []
29835
30290
  },
30291
+ ...pick(makeVTreeviewItemProps(), ['hideActions']),
29836
30292
  ...makeDensityProps()
29837
30293
  }, 'VTreeviewChildren');
29838
30294
  const VTreeviewChildren = genericComponent()({
@@ -29861,19 +30317,32 @@ const VTreeviewChildren = genericComponent()({
29861
30317
  select(isSelected);
29862
30318
  }
29863
30319
  }
29864
- return () => slots.default?.() ?? props.items?.map((item, index) => {
30320
+ return () => slots.default?.() ?? props.items?.map((item, index, items) => {
29865
30321
  const {
29866
30322
  children,
29867
30323
  props: itemProps
29868
30324
  } = item;
29869
30325
  const loading = isLoading.has(item.value);
30326
+ const nextItemHasChildren = !!items.at(index + 1)?.children;
30327
+ const depth = props.path?.length ?? 0;
30328
+ const isLast = items.length - 1 === index;
29870
30329
  const treeItemProps = {
29871
30330
  index,
29872
- depth: props.path?.length ?? 0,
30331
+ depth,
29873
30332
  isFirst: index === 0,
29874
- isLast: props.items ? props.items.length - 1 === index : false,
29875
- path: [...props.path, index]
30333
+ isLast,
30334
+ path: [...props.path, index],
30335
+ hideAction: props.hideActions
29876
30336
  };
30337
+ const indentLines = getIndentLines({
30338
+ depth,
30339
+ isLast,
30340
+ isLastGroup: props.isLastGroup,
30341
+ leafLinks: !props.hideActions,
30342
+ separateRoots: props.separateRoots,
30343
+ parentIndentLines: props.parentIndentLines,
30344
+ variant: props.indentLinesVariant
30345
+ });
29877
30346
  const slotsWithItem = {
29878
30347
  prepend: slotProps => createElementVNode(Fragment, null, [props.selectable && (!children || children && !['leaf', 'single-leaf'].includes(props.selectStrategy)) && createElementVNode("div", null, [createVNode(VCheckboxBtn, {
29879
30348
  "key": item.value,
@@ -29939,21 +30408,40 @@ const VTreeviewChildren = genericComponent()({
29939
30408
  return createVNode(VTreeviewItem, mergeProps({
29940
30409
  "ref": el => activatorItems.value[index] = el
29941
30410
  }, listItemProps, {
30411
+ "hideActions": props.hideActions,
30412
+ "indentLines": indentLines.node,
29942
30413
  "value": props.returnObject ? item.raw : itemProps.value,
29943
30414
  "loading": loading
29944
30415
  }), slotsWithItem);
29945
30416
  },
29946
30417
  default: () => createVNode(VTreeviewChildren, mergeProps(treeviewChildrenProps, {
29947
30418
  "items": children,
30419
+ "indentLinesVariant": props.indentLinesVariant,
30420
+ "parentIndentLines": indentLines.children,
30421
+ "isLastGroup": nextItemHasChildren,
29948
30422
  "returnObject": props.returnObject
29949
30423
  }), slots)
29950
- }) : slots.item?.({
30424
+ }) : renderSlot(slots.item, {
29951
30425
  props: itemProps,
29952
30426
  item: item.raw,
29953
30427
  internalItem: item
29954
- }) ?? createVNode(VTreeviewItem, mergeProps(itemProps, {
29955
- "value": props.returnObject ? toRaw(item.raw) : itemProps.value
29956
- }), slotsWithItem);
30428
+ }, () => {
30429
+ if (item.type === 'divider') {
30430
+ return renderSlot(slots.divider, {
30431
+ props: item.raw
30432
+ }, () => createVNode(VDivider, item.props, null));
30433
+ }
30434
+ if (item.type === 'subheader') {
30435
+ return renderSlot(slots.subheader, {
30436
+ props: item.raw
30437
+ }, () => createVNode(VListSubheader, item.props, null));
30438
+ }
30439
+ return createVNode(VTreeviewItem, mergeProps(itemProps, {
30440
+ "hideActions": props.hideActions,
30441
+ "indentLines": indentLines.leaf,
30442
+ "value": props.returnObject ? toRaw(item.raw) : itemProps.value
30443
+ }), slotsWithItem);
30444
+ });
29957
30445
  });
29958
30446
  }
29959
30447
  });
@@ -29969,20 +30457,18 @@ function flatten(items) {
29969
30457
  const makeVTreeviewProps = propsFactory({
29970
30458
  fluid: Boolean,
29971
30459
  openAll: Boolean,
30460
+ indentLines: [Boolean, String],
29972
30461
  search: String,
29973
30462
  ...makeFilterProps({
29974
30463
  filterKeys: ['title']
29975
30464
  }),
29976
- ...omit(makeVTreeviewChildrenProps(), ['index', 'path']),
30465
+ ...omit(makeVTreeviewChildrenProps(), ['index', 'path', 'indentLinesVariant', 'parentIndentLines', 'isLastGroup']),
29977
30466
  ...omit(makeVListProps({
29978
30467
  collapseIcon: '$treeviewCollapse',
29979
30468
  expandIcon: '$treeviewExpand',
29980
30469
  slim: true
29981
- }), ['itemType', 'nav', 'openStrategy']),
29982
- modelValue: {
29983
- type: Array,
29984
- default: () => []
29985
- }
30470
+ }), ['nav', 'openStrategy']),
30471
+ modelValue: Array
29986
30472
  }, 'VTreeview');
29987
30473
  const VTreeview = genericComponent()({
29988
30474
  name: 'VTreeview',
@@ -29997,7 +30483,8 @@ const VTreeview = genericComponent()({
29997
30483
  },
29998
30484
  setup(props, _ref) {
29999
30485
  let {
30000
- slots
30486
+ slots,
30487
+ emit
30001
30488
  } = _ref;
30002
30489
  const {
30003
30490
  items
@@ -30006,13 +30493,12 @@ const VTreeview = genericComponent()({
30006
30493
  const baseColor = toRef(() => props.baseColor);
30007
30494
  const color = toRef(() => props.color);
30008
30495
  const activated = useProxiedModel(props, 'activated');
30009
- const model = useProxiedModel(props, 'modelValue');
30010
- const _selected = useProxiedModel(props, 'selected', props.modelValue);
30496
+ const _selected = useProxiedModel(props, 'selected');
30011
30497
  const selected = computed({
30012
- get: () => _selected.value,
30498
+ get: () => props.modelValue ?? _selected.value,
30013
30499
  set(val) {
30014
30500
  _selected.value = val;
30015
- model.value = val;
30501
+ emit('update:modelValue', val);
30016
30502
  }
30017
30503
  });
30018
30504
  const vListRef = ref();
@@ -30078,6 +30564,7 @@ const VTreeview = genericComponent()({
30078
30564
  useRender(() => {
30079
30565
  const listProps = VList.filterProps(props);
30080
30566
  const treeviewChildrenProps = VTreeviewChildren.filterProps(props);
30567
+ const indentLinesVariant = typeof props.indentLines === 'boolean' ? 'default' : props.indentLines;
30081
30568
  return createVNode(VList, mergeProps({
30082
30569
  "ref": vListRef
30083
30570
  }, listProps, {
@@ -30095,7 +30582,9 @@ const VTreeview = genericComponent()({
30095
30582
  default: () => [createVNode(VTreeviewChildren, mergeProps(treeviewChildrenProps, {
30096
30583
  "density": props.density,
30097
30584
  "returnObject": props.returnObject,
30098
- "items": items.value
30585
+ "items": items.value,
30586
+ "parentIndentLines": props.indentLines ? [] : undefined,
30587
+ "indentLinesVariant": indentLinesVariant
30099
30588
  }), slots)]
30100
30589
  });
30101
30590
  });
@@ -30184,7 +30673,7 @@ const VCalendarIntervalEvent = genericComponent()({
30184
30673
  }
30185
30674
  };
30186
30675
  useRender(() => {
30187
- return createElementVNode("div", null, [slots.intervalEvent?.({
30676
+ return createElementVNode("div", null, [slots['interval-event']?.({
30188
30677
  height: calcHeight().height,
30189
30678
  margin: calcHeight().margin,
30190
30679
  eventClass: 'v-calendar-internal-event',
@@ -30281,13 +30770,13 @@ const VCalendarInterval = genericComponent()({
30281
30770
  "style": normalizeStyle(`height: ${convertToUnit(props.intervalHeight)}`)
30282
30771
  }, [createElementVNode("div", mergeProps({
30283
30772
  "class": "v-calendar-day__row-label"
30284
- }, getPrefixedEventHandlers(attrs, ':time', () => props)), [slots.intervalTitle?.({
30773
+ }, getPrefixedEventHandlers(attrs, ':time', () => props)), [slots['interval-title']?.({
30285
30774
  interval: interval.value
30286
30775
  }) ?? (props.index ? props.intervalFormat ? typeof props.intervalFormat === 'string' ? adapter.format(interval.value.start, 'hours12h') : props.intervalFormat(interval.value) : interval.value.label : '12 AM')]), createElementVNode("div", {
30287
30776
  "class": "v-calendar-day__row-hairline"
30288
30777
  }, null), createElementVNode("div", mergeProps({
30289
30778
  "class": ['v-calendar-day__row-content', interval.value.events.some(e => !e.last) ? 'v-calendar-day__row-content-through' : '']
30290
- }, getPrefixedEventHandlers(attrs, ':interval', () => interval.value)), [slots.intervalBody?.({
30779
+ }, getPrefixedEventHandlers(attrs, ':interval', () => interval.value)), [slots['interval-body']?.({
30291
30780
  interval: interval.value
30292
30781
  }) ?? createElementVNode("div", null, [interval.value.events?.map(event => createVNode(VCalendarIntervalEvent, mergeProps({
30293
30782
  "event": event,
@@ -30296,8 +30785,8 @@ const VCalendarInterval = genericComponent()({
30296
30785
  "intervalDuration": props.intervalDuration,
30297
30786
  "intervalHeight": props.intervalHeight
30298
30787
  }, attrs), {
30299
- ...(slots.intervalEvent ? {
30300
- intervalEvent: _ref2 => {
30788
+ ...(slots['interval-event'] ? {
30789
+ 'interval-event': _ref2 => {
30301
30790
  let {
30302
30791
  height,
30303
30792
  margin,
@@ -30305,7 +30794,7 @@ const VCalendarInterval = genericComponent()({
30305
30794
  event,
30306
30795
  interval
30307
30796
  } = _ref2;
30308
- return slots.intervalEvent?.({
30797
+ return slots['interval-event']?.({
30309
30798
  height,
30310
30799
  margin,
30311
30800
  eventClass,
@@ -30319,7 +30808,7 @@ const VCalendarInterval = genericComponent()({
30319
30808
  "style": normalizeStyle(`height: ${convertToUnit(props.intervalHeight)}`)
30320
30809
  }, [createElementVNode("div", mergeProps({
30321
30810
  "class": ['v-calendar-day__row-content', interval.value.events.some(e => !e.last) ? 'v-calendar-day__row-content-through' : '']
30322
- }, getPrefixedEventHandlers(attrs, ':interval', () => interval.value)), [slots.intervalBody?.({
30811
+ }, getPrefixedEventHandlers(attrs, ':interval', () => interval.value)), [slots['interval-body']?.({
30323
30812
  interval: interval.value
30324
30813
  }) ?? interval.value.events?.map(event => createVNode(VCalendarIntervalEvent, mergeProps({
30325
30814
  "event": event,
@@ -30328,8 +30817,8 @@ const VCalendarInterval = genericComponent()({
30328
30817
  "intervalDuration": props.intervalDuration,
30329
30818
  "intervalHeight": props.intervalHeight
30330
30819
  }, attrs), {
30331
- ...(slots.intervalEvent ? {
30332
- intervalEvent: _ref3 => {
30820
+ ...(slots['interval-event'] ? {
30821
+ 'interval-event': _ref3 => {
30333
30822
  let {
30334
30823
  height,
30335
30824
  margin,
@@ -30337,7 +30826,7 @@ const VCalendarInterval = genericComponent()({
30337
30826
  event,
30338
30827
  interval
30339
30828
  } = _ref3;
30340
- return slots.intervalEvent?.({
30829
+ return slots['interval-event']?.({
30341
30830
  height,
30342
30831
  margin,
30343
30832
  eventClass,
@@ -30392,7 +30881,7 @@ const VCalendarDay = genericComponent()({
30392
30881
  }), null)])]), intervals.value.map((_, index) => slots.interval?.(calendarIntervalProps) ?? createVNode(VCalendarInterval, mergeProps({
30393
30882
  "index": index
30394
30883
  }, calendarIntervalProps, attrs, getPrefixedEventHandlers(attrs, ':interval', () => calendarIntervalProps)), {
30395
- ...pick(slots, ['intervalBody', 'intervalEvent', 'intervalTitle'])
30884
+ ...pick(slots, ['interval-body', 'interval-event', 'interval-title'])
30396
30885
  }))]);
30397
30886
  });
30398
30887
  return {
@@ -30536,7 +31025,7 @@ const VCalendarMonthDay = genericComponent()({
30536
31025
  }, getPrefixedEventHandlers(attrs, ':day', () => props)), [!props.day?.isHidden ? createElementVNode("div", {
30537
31026
  "key": "title",
30538
31027
  "class": "v-calendar-weekly__day-label"
30539
- }, [slots.dayTitle?.({
31028
+ }, [slots['day-title']?.({
30540
31029
  title: props.title
30541
31030
  }) ?? createVNode(VBtn, mergeProps({
30542
31031
  "class": props.day?.isToday ? 'v-calendar-weekly__day-label__today' : undefined,
@@ -30549,12 +31038,12 @@ const VCalendarMonthDay = genericComponent()({
30549
31038
  }, getPrefixedEventHandlers(attrs, ':date', () => props)), null)]) : undefined, !props.day?.isHidden ? createElementVNode("div", {
30550
31039
  "key": "content",
30551
31040
  "class": "v-calendar-weekly__day-content"
30552
- }, [slots.dayBody?.({
31041
+ }, [slots['day-body']?.({
30553
31042
  day: props.day,
30554
31043
  events: props.events
30555
31044
  }) ?? createElementVNode("div", null, [createElementVNode("div", {
30556
31045
  "class": "v-calendar-weekly__day-alldayevents-container"
30557
- }, [props.events?.filter(event => event.allDay).map(event => slots.dayEvent ? slots.dayEvent({
31046
+ }, [props.events?.filter(event => event.allDay).map(event => slots['day-event'] ? slots['day-event']({
30558
31047
  day: props.day,
30559
31048
  allDay: true,
30560
31049
  event
@@ -30564,7 +31053,7 @@ const VCalendarMonthDay = genericComponent()({
30564
31053
  "allDay": true
30565
31054
  }, attrs), null))]), createElementVNode("div", {
30566
31055
  "class": "v-calendar-weekly__day-events-container"
30567
- }, [props.events?.filter(event => !event.allDay).map(event => slots.dayEvent ? slots.dayEvent({
31056
+ }, [props.events?.filter(event => !event.allDay).map(event => slots['day-event'] ? slots['day-event']({
30568
31057
  day: props.day,
30569
31058
  event,
30570
31059
  allDay: false
@@ -30609,9 +31098,8 @@ const VCalendar = genericComponent()({
30609
31098
  model,
30610
31099
  displayValue,
30611
31100
  weekNumbers,
30612
- weekDays
31101
+ weekdayLabels
30613
31102
  } = useCalendar(props);
30614
- const dayNames = adapter.getWeekdays();
30615
31103
  function onClickNext() {
30616
31104
  if (props.viewMode === 'month') {
30617
31105
  model.value = [adapter.addMonths(displayValue.value, 1)];
@@ -30649,6 +31137,7 @@ const VCalendar = genericComponent()({
30649
31137
  useRender(() => {
30650
31138
  const calendarDayProps = VCalendarDay.filterProps(props);
30651
31139
  const calendarHeaderProps = VCalendarHeader.filterProps(props);
31140
+ const weekdaysCount = daysInWeek.value.length;
30652
31141
  return createElementVNode("div", {
30653
31142
  "class": normalizeClass(['v-calendar', {
30654
31143
  'v-calendar-monthly': props.viewMode === 'month',
@@ -30670,25 +31159,25 @@ const VCalendar = genericComponent()({
30670
31159
  }), {
30671
31160
  title: slots.title
30672
31161
  }))]), createElementVNode("div", {
30673
- "class": normalizeClass(['v-calendar__container', `days__${weekDays.value.length}`])
31162
+ "class": normalizeClass(['v-calendar__container', `days__${weekdaysCount}`])
30674
31163
  }, [props.viewMode === 'month' && !props.hideDayHeader && createElementVNode("div", {
30675
- "class": normalizeClass(['v-calendar-weekly__head', `days__${weekDays.value.length}`, ...(!props.hideWeekNumber ? ['v-calendar-weekly__head-weeknumbers'] : [])]),
31164
+ "class": normalizeClass(['v-calendar-weekly__head', `days__${weekdaysCount}`, ...(!props.hideWeekNumber ? ['v-calendar-weekly__head-weeknumbers'] : [])]),
30676
31165
  "key": "calendarWeeklyHead"
30677
31166
  }, [!props.hideWeekNumber ? createElementVNode("div", {
30678
31167
  "key": "weekNumber0",
30679
31168
  "class": "v-calendar-weekly__head-weeknumber"
30680
- }, null) : '', weekDays.value.map(weekday => createElementVNode("div", {
31169
+ }, null) : '', weekdayLabels.value.map(weekday => createElementVNode("div", {
30681
31170
  "class": normalizeClass(`v-calendar-weekly__head-weekday${!props.hideWeekNumber ? '-with-weeknumber' : ''}`)
30682
- }, [dayNames[weekday]]))]), props.viewMode === 'month' && createElementVNode("div", {
31171
+ }, [weekday]))]), props.viewMode === 'month' && createElementVNode("div", {
30683
31172
  "key": "VCalendarMonth",
30684
- "class": normalizeClass(['v-calendar-month__days', `days${!props.hideWeekNumber ? '-with-weeknumbers' : ''}__${weekDays.value.length}`, ...(!props.hideWeekNumber ? ['v-calendar-month__weeknumbers'] : [])])
30685
- }, [chunkArray(daysInMonth.value, weekDays.value.length).map((week, wi) => [!props.hideWeekNumber ? createElementVNode("div", mergeProps({
31173
+ "class": normalizeClass(['v-calendar-month__days', `days${!props.hideWeekNumber ? '-with-weeknumbers' : ''}__${weekdaysCount}`, ...(!props.hideWeekNumber ? ['v-calendar-month__weeknumbers'] : [])])
31174
+ }, [chunkArray(daysInMonth.value, weekdaysCount).map((week, wi) => [!props.hideWeekNumber ? createElementVNode("div", mergeProps({
30686
31175
  "class": "v-calendar-month__weeknumber"
30687
31176
  }, getPrefixedEventHandlers(attrs, ':weekNumber', () => ({
30688
31177
  weekNumber: weekNumbers.value[wi],
30689
31178
  week
30690
31179
  }))), [weekNumbers.value[wi]]) : '', week.map(day => createVNode(VCalendarMonthDay, mergeProps({
30691
- "key": day.date.getTime()
31180
+ "key": adapter.toJsDate(day.date).getTime()
30692
31181
  }, calendarDayProps, {
30693
31182
  "day": day,
30694
31183
  "title": adapter.format(day.date, 'dayOfMonth'),
@@ -30705,7 +31194,7 @@ const VCalendar = genericComponent()({
30705
31194
  "dayIndex": i,
30706
31195
  "events": props.events?.filter(e => adapter.isSameDay(e.start, day.date) || adapter.isSameDay(e.end, day.date))
30707
31196
  }, attrs), {
30708
- ...pick(slots, ['interval', 'intervalBody', 'intervalEvent', 'intervalTitle'])
31197
+ ...pick(slots, ['interval', 'interval-body', 'interval-event', 'interval-title'])
30709
31198
  })), props.viewMode === 'day' && (slots['day-interval'] ? slots['day-interval']({
30710
31199
  day: genDays([displayValue.value], adapter.date())[0],
30711
31200
  dayIndex: 0,
@@ -31620,6 +32109,7 @@ const VIconBtn = genericComponent()({
31620
32109
  opacity: props.opacity
31621
32110
  };
31622
32111
  return createVNode(props.tag, {
32112
+ "type": props.tag === 'button' ? 'button' : undefined,
31623
32113
  "class": normalizeClass([{
31624
32114
  'v-icon-btn': true,
31625
32115
  'v-icon-btn--active': isActive.value,
@@ -32278,6 +32768,398 @@ const VPullToRefresh = genericComponent()({
32278
32768
  }
32279
32769
  });
32280
32770
 
32771
+ // Types
32772
+
32773
+ // Display mode types for different visual representations
32774
+
32775
+ // Extended variant type that includes our custom 'contained' variant
32776
+
32777
+ // Key display tuple: [mode, content] where content is string or IconValue
32778
+
32779
+ // Key tuple: [mode, content] where content is string or IconValue
32780
+
32781
+ function processKey(config, requestedMode, isMac) {
32782
+ const keyCfg = isMac && config.mac ? config.mac : config.default;
32783
+
32784
+ // 1. Resolve the safest display mode for the current platform
32785
+ const mode = (() => {
32786
+ // Non-Mac platforms rarely use icons – prefer text
32787
+ if (requestedMode === 'icon' && !isMac) return 'text';
32788
+
32789
+ // If the requested mode lacks an asset, fall back to text
32790
+ if (requestedMode === 'icon' && !keyCfg.icon) return 'text';
32791
+ if (requestedMode === 'symbol' && !keyCfg.symbol) return 'text';
32792
+ return requestedMode;
32793
+ })();
32794
+
32795
+ // 2. Pick value for the chosen mode, defaulting to text representation
32796
+ let value = keyCfg[mode] ?? keyCfg.text;
32797
+
32798
+ // 3. Guard against icon tokens leaking into text mode (e.g. "$ctrl")
32799
+ if (mode === 'text' && typeof value === 'string' && value.startsWith('$') && !value.startsWith('$vuetify.')) {
32800
+ value = value.slice(1).toUpperCase(); // "$ctrl" → "CTRL"
32801
+ }
32802
+ return mode === 'icon' ? ['icon', value] : [mode, value];
32803
+ }
32804
+ const hotkeyMap = {
32805
+ ctrl: {
32806
+ mac: {
32807
+ symbol: '⌃',
32808
+ icon: '$ctrl',
32809
+ text: '$vuetify.hotkey.ctrl'
32810
+ },
32811
+ default: {
32812
+ text: 'Ctrl'
32813
+ }
32814
+ },
32815
+ meta: {
32816
+ mac: {
32817
+ symbol: '⌘',
32818
+ icon: '$command',
32819
+ text: '$vuetify.hotkey.command'
32820
+ },
32821
+ default: {
32822
+ text: 'Ctrl'
32823
+ }
32824
+ },
32825
+ cmd: {
32826
+ mac: {
32827
+ symbol: '⌘',
32828
+ icon: '$command',
32829
+ text: '$vuetify.hotkey.command'
32830
+ },
32831
+ default: {
32832
+ text: 'Ctrl'
32833
+ }
32834
+ },
32835
+ shift: {
32836
+ mac: {
32837
+ symbol: '⇧',
32838
+ icon: '$shift',
32839
+ text: '$vuetify.hotkey.shift'
32840
+ },
32841
+ default: {
32842
+ text: 'Shift'
32843
+ }
32844
+ },
32845
+ alt: {
32846
+ mac: {
32847
+ symbol: '⌥',
32848
+ icon: '$alt',
32849
+ text: '$vuetify.hotkey.option'
32850
+ },
32851
+ default: {
32852
+ text: 'Alt'
32853
+ }
32854
+ },
32855
+ enter: {
32856
+ default: {
32857
+ symbol: '↵',
32858
+ icon: '$enter',
32859
+ text: '$vuetify.hotkey.enter'
32860
+ }
32861
+ },
32862
+ arrowup: {
32863
+ default: {
32864
+ symbol: '↑',
32865
+ icon: '$arrowup',
32866
+ text: '$vuetify.hotkey.upArrow'
32867
+ }
32868
+ },
32869
+ arrowdown: {
32870
+ default: {
32871
+ symbol: '↓',
32872
+ icon: '$arrowdown',
32873
+ text: '$vuetify.hotkey.downArrow'
32874
+ }
32875
+ },
32876
+ arrowleft: {
32877
+ default: {
32878
+ symbol: '←',
32879
+ icon: '$arrowleft',
32880
+ text: '$vuetify.hotkey.leftArrow'
32881
+ }
32882
+ },
32883
+ arrowright: {
32884
+ default: {
32885
+ symbol: '→',
32886
+ icon: '$arrowright',
32887
+ text: '$vuetify.hotkey.rightArrow'
32888
+ }
32889
+ },
32890
+ backspace: {
32891
+ default: {
32892
+ symbol: '⌫',
32893
+ icon: '$backspace',
32894
+ text: '$vuetify.hotkey.backspace'
32895
+ }
32896
+ },
32897
+ escape: {
32898
+ default: {
32899
+ text: '$vuetify.hotkey.escape'
32900
+ }
32901
+ },
32902
+ ' ': {
32903
+ mac: {
32904
+ symbol: '␣',
32905
+ icon: '$space',
32906
+ text: '$vuetify.hotkey.space'
32907
+ },
32908
+ default: {
32909
+ text: '$vuetify.hotkey.space'
32910
+ }
32911
+ },
32912
+ '-': {
32913
+ default: {
32914
+ text: '-'
32915
+ }
32916
+ }
32917
+ };
32918
+
32919
+ // Create custom variant props that extend the base variant props with our 'contained' option
32920
+ const makeVHotkeyVariantProps = propsFactory({
32921
+ variant: {
32922
+ type: String,
32923
+ default: 'elevated',
32924
+ validator: v => ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain', 'contained'].includes(v)
32925
+ }
32926
+ }, 'VHotkeyVariant');
32927
+ const makeVHotkeyProps = propsFactory({
32928
+ // String representing keyboard shortcuts (e.g., "ctrl+k", "meta+shift+p")
32929
+ keys: String,
32930
+ // How to display keys: 'symbol' uses special characters (⌘, ⌃), 'icon' uses SVG icons, 'text' uses words
32931
+ displayMode: {
32932
+ type: String,
32933
+ default: 'icon'
32934
+ },
32935
+ // Custom key mapping configuration. Users can import and modify the exported hotkeyMap as needed
32936
+ keyMap: {
32937
+ type: Object,
32938
+ default: () => hotkeyMap
32939
+ },
32940
+ platform: {
32941
+ type: String,
32942
+ default: 'auto'
32943
+ },
32944
+ inline: Boolean,
32945
+ disabled: Boolean,
32946
+ prefix: String,
32947
+ suffix: String,
32948
+ ...makeComponentProps(),
32949
+ ...makeThemeProps(),
32950
+ ...makeBorderProps(),
32951
+ ...makeRoundedProps(),
32952
+ ...makeElevationProps(),
32953
+ ...makeVHotkeyVariantProps(),
32954
+ color: String
32955
+ }, 'VHotkey');
32956
+ class Delineator {
32957
+ constructor(delineator) {
32958
+ if (['and', 'then'].includes(delineator)) this.val = delineator;else {
32959
+ throw new Error('Not a valid delineator');
32960
+ }
32961
+ }
32962
+ isEqual(d) {
32963
+ return this.val === d.val;
32964
+ }
32965
+ }
32966
+ function isDelineator(value) {
32967
+ return value instanceof Delineator;
32968
+ }
32969
+ function isString(value) {
32970
+ return typeof value === 'string';
32971
+ }
32972
+ function getKeyText(keyMap, key, isMac) {
32973
+ const lowerKey = key.toLowerCase();
32974
+ if (lowerKey in keyMap) {
32975
+ const result = processKey(keyMap[lowerKey], 'text', isMac);
32976
+ return typeof result[1] === 'string' ? result[1] : String(result[1]);
32977
+ }
32978
+ return key.toUpperCase();
32979
+ }
32980
+ function applyDisplayModeToKey(keyMap, mode, key, isMac) {
32981
+ const lowerKey = key.toLowerCase();
32982
+ if (lowerKey in keyMap) {
32983
+ const result = processKey(keyMap[lowerKey], mode, isMac);
32984
+ if (result[0] === 'text' && typeof result[1] === 'string' && result[1].startsWith('$') && !result[1].startsWith('$vuetify.')) {
32985
+ return ['text', result[1].replace('$', '').toUpperCase(), key];
32986
+ }
32987
+ return [...result, key];
32988
+ }
32989
+ return ['text', key.toUpperCase(), key];
32990
+ }
32991
+ const VHotkey = genericComponent()({
32992
+ name: 'VHotkey',
32993
+ props: makeVHotkeyProps(),
32994
+ setup(props) {
32995
+ const {
32996
+ t
32997
+ } = useLocale();
32998
+ const {
32999
+ themeClasses
33000
+ } = provideTheme(props);
33001
+ const {
33002
+ rtlClasses
33003
+ } = useRtl();
33004
+ const {
33005
+ borderClasses
33006
+ } = useBorder(props);
33007
+ const {
33008
+ roundedClasses
33009
+ } = useRounded(props);
33010
+ const {
33011
+ elevationClasses
33012
+ } = useElevation(props);
33013
+ const isContainedVariant = computed(() => props.variant === 'contained');
33014
+ const effectiveVariantProps = computed(() => ({
33015
+ ...props,
33016
+ variant: isContainedVariant.value ? 'elevated' : props.variant
33017
+ }));
33018
+ const {
33019
+ colorClasses,
33020
+ colorStyles,
33021
+ variantClasses
33022
+ } = useVariant(effectiveVariantProps);
33023
+ const isMac = computed(() => props.platform === 'auto' ? typeof navigator !== 'undefined' && /macintosh/i.test(navigator.userAgent) : props.platform === 'mac');
33024
+ const effectiveDisplayMode = computed(() => props.displayMode);
33025
+ const AND_DELINEATOR = new Delineator('and'); // For + separators
33026
+ const THEN_DELINEATOR = new Delineator('then'); // For - separators
33027
+
33028
+ const effectiveKeyMap = computed(() => props.keyMap);
33029
+ const keyCombinations = computed(() => {
33030
+ if (!props.keys) return [];
33031
+
33032
+ // Split by spaces to handle multiple key combinations
33033
+ // Example: "ctrl+k meta+p" -> ["ctrl+k", "meta+p"]
33034
+ return props.keys.split(' ').map(combination => {
33035
+ // Use the shared sequence splitting logic
33036
+ const sequenceGroups = splitKeySequence(combination);
33037
+
33038
+ // Process each sequence group
33039
+ return sequenceGroups.flatMap((group, groupIndex) => {
33040
+ // Use the shared key combination splitting logic
33041
+ const keyParts = splitKeyCombination(group);
33042
+ const parts = keyParts.reduce((acc, part, index) => {
33043
+ if (index !== 0) {
33044
+ // Add AND delineator between keys
33045
+ return [...acc, AND_DELINEATOR, part];
33046
+ }
33047
+ return [...acc, part];
33048
+ }, []);
33049
+
33050
+ // Add THEN delineator between sequence groups
33051
+ const result = parts.map(key => {
33052
+ if (isString(key)) {
33053
+ return applyDisplayModeToKey(effectiveKeyMap.value, effectiveDisplayMode.value, key, isMac.value);
33054
+ }
33055
+ return key;
33056
+ });
33057
+
33058
+ // Add sequence separator if not the last group
33059
+ if (groupIndex < sequenceGroups.length - 1) {
33060
+ result.push(THEN_DELINEATOR);
33061
+ }
33062
+ return result;
33063
+ });
33064
+ });
33065
+ });
33066
+ const accessibleLabel = computed(() => {
33067
+ if (!props.keys) return '';
33068
+
33069
+ // Convert the parsed key combinations into readable text
33070
+ const readableShortcuts = keyCombinations.value.map(combination => {
33071
+ const readableParts = [];
33072
+ for (const key of combination) {
33073
+ if (isDelineator(key)) {
33074
+ if (AND_DELINEATOR.isEqual(key)) {
33075
+ readableParts.push(t('$vuetify.hotkey.plus'));
33076
+ } else if (THEN_DELINEATOR.isEqual(key)) {
33077
+ readableParts.push(t('$vuetify.hotkey.then'));
33078
+ }
33079
+ } else {
33080
+ // Always use text representation for screen readers
33081
+ const textKey = key[0] === 'icon' || key[0] === 'symbol' ? applyDisplayModeToKey(mergeDeep(hotkeyMap, props.keyMap), 'text', String(key[1]), isMac.value)[1] : key[1];
33082
+ readableParts.push(translateKey(textKey));
33083
+ }
33084
+ }
33085
+ return readableParts.join(' ');
33086
+ });
33087
+ const shortcutText = readableShortcuts.join(', ');
33088
+ return t('$vuetify.hotkey.shortcut', shortcutText);
33089
+ });
33090
+ function translateKey(key) {
33091
+ return key.startsWith('$vuetify.') ? t(key) : key;
33092
+ }
33093
+ function getKeyTooltip(key) {
33094
+ if (effectiveDisplayMode.value === 'text') return undefined;
33095
+ const textKey = getKeyText(effectiveKeyMap.value, String(key[2]), isMac.value);
33096
+ return translateKey(textKey);
33097
+ }
33098
+ function renderKey(key, keyIndex, isContained) {
33099
+ const KeyComponent = isContained ? 'kbd' : VKbd;
33100
+ const keyClasses = ['v-hotkey__key', `v-hotkey__key-${key[0]}`, ...(isContained ? ['v-hotkey__key--nested'] : [borderClasses.value, roundedClasses.value, elevationClasses.value, colorClasses.value])];
33101
+ return createVNode(KeyComponent, {
33102
+ "key": keyIndex,
33103
+ "class": normalizeClass(keyClasses),
33104
+ "style": normalizeStyle(isContained ? undefined : colorStyles.value),
33105
+ "aria-hidden": "true",
33106
+ "title": getKeyTooltip(key)
33107
+ }, {
33108
+ default: () => [key[0] === 'icon' ? createVNode(VIcon, {
33109
+ "icon": key[1],
33110
+ "aria-hidden": "true"
33111
+ }, null) : translateKey(key[1])]
33112
+ });
33113
+ }
33114
+ function renderDivider(key, keyIndex) {
33115
+ return createElementVNode("span", {
33116
+ "key": keyIndex,
33117
+ "class": "v-hotkey__divider",
33118
+ "aria-hidden": "true"
33119
+ }, [AND_DELINEATOR.isEqual(key) ? '+' : t('$vuetify.hotkey.then')]);
33120
+ }
33121
+ useRender(() => createElementVNode("div", {
33122
+ "class": normalizeClass(['v-hotkey', {
33123
+ 'v-hotkey--disabled': props.disabled,
33124
+ 'v-hotkey--inline': props.inline,
33125
+ 'v-hotkey--contained': isContainedVariant.value
33126
+ }, themeClasses.value, rtlClasses.value, variantClasses.value, props.class]),
33127
+ "style": normalizeStyle(props.style),
33128
+ "role": "img",
33129
+ "aria-label": accessibleLabel.value
33130
+ }, [isContainedVariant.value ? createVNode(VKbd, {
33131
+ "key": "contained",
33132
+ "class": normalizeClass(['v-hotkey__contained-wrapper', borderClasses.value, roundedClasses.value, elevationClasses.value, colorClasses.value]),
33133
+ "style": normalizeStyle(colorStyles.value),
33134
+ "aria-hidden": "true"
33135
+ }, {
33136
+ default: () => [props.prefix && createElementVNode("span", {
33137
+ "key": "contained-prefix",
33138
+ "class": "v-hotkey__prefix"
33139
+ }, [props.prefix]), keyCombinations.value.map((combination, comboIndex) => createElementVNode("span", {
33140
+ "class": "v-hotkey__combination",
33141
+ "key": comboIndex
33142
+ }, [combination.map((key, keyIndex) => isDelineator(key) ? renderDivider(key, keyIndex) : renderKey(key, keyIndex, true)), comboIndex < keyCombinations.value.length - 1 && createElementVNode("span", {
33143
+ "aria-hidden": "true"
33144
+ }, [createTextVNode("\xA0")])])), props.suffix && createElementVNode("span", {
33145
+ "key": "contained-suffix",
33146
+ "class": "v-hotkey__suffix"
33147
+ }, [props.suffix])]
33148
+ }) : createElementVNode(Fragment, null, [props.prefix && createElementVNode("span", {
33149
+ "key": "prefix",
33150
+ "class": "v-hotkey__prefix"
33151
+ }, [props.prefix]), keyCombinations.value.map((combination, comboIndex) => createElementVNode("span", {
33152
+ "class": "v-hotkey__combination",
33153
+ "key": comboIndex
33154
+ }, [combination.map((key, keyIndex) => isDelineator(key) ? renderDivider(key, keyIndex) : renderKey(key, keyIndex, false)), comboIndex < keyCombinations.value.length - 1 && createElementVNode("span", {
33155
+ "aria-hidden": "true"
33156
+ }, [createTextVNode("\xA0")])])), props.suffix && createElementVNode("span", {
33157
+ "key": "suffix",
33158
+ "class": "v-hotkey__suffix"
33159
+ }, [props.suffix])])]));
33160
+ }
33161
+ });
33162
+
32281
33163
  var components = /*#__PURE__*/Object.freeze({
32282
33164
  __proto__: null,
32283
33165
  VAlert: VAlert,
@@ -32366,6 +33248,7 @@ var components = /*#__PURE__*/Object.freeze({
32366
33248
  VFileUploadItem: VFileUploadItem,
32367
33249
  VFooter: VFooter,
32368
33250
  VForm: VForm,
33251
+ VHotkey: VHotkey,
32369
33252
  VHover: VHover,
32370
33253
  VIcon: VIcon,
32371
33254
  VIconBtn: VIconBtn,
@@ -32789,7 +33672,7 @@ function createVuetify$1() {
32789
33672
  };
32790
33673
  });
32791
33674
  }
32792
- const version$1 = "3.9.0-beta.1";
33675
+ const version$1 = "3.9.0";
32793
33676
  createVuetify$1.version = version$1;
32794
33677
 
32795
33678
  // Vue's inject() can only be used in setup
@@ -33087,7 +33970,7 @@ var index = /*#__PURE__*/Object.freeze({
33087
33970
 
33088
33971
  /* eslint-disable local-rules/sort-imports */
33089
33972
 
33090
- const version = "3.9.0-beta.1";
33973
+ const version = "3.9.0";
33091
33974
 
33092
33975
  /* eslint-disable local-rules/sort-imports */
33093
33976
 
@@ -33100,5 +33983,5 @@ const createVuetify = function () {
33100
33983
  });
33101
33984
  };
33102
33985
 
33103
- export { index as blueprints, components, createVuetify, directives, useDate, useDefaults, useDisplay, useGoTo, useLayout, useLocale, useRtl, useTheme, version };
33986
+ export { index as blueprints, components, createVuetify, directives, useDate, useDefaults, useDisplay, useGoTo, useHotkey, useLayout, useLocale, useRtl, useTheme, version };
33104
33987
  //# sourceMappingURL=vuetify-labs.esm.js.map