vuetify 3.9.0-beta.0 → 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 (337) hide show
  1. package/dist/_component-variables-labs.sass +1 -0
  2. package/dist/json/attributes.json +3590 -3502
  3. package/dist/json/importMap-labs.json +16 -12
  4. package/dist/json/importMap.json +186 -186
  5. package/dist/json/tags.json +31 -4
  6. package/dist/json/web-types.json +6626 -6392
  7. package/dist/vuetify-labs.cjs +1082 -195
  8. package/dist/vuetify-labs.css +4654 -4339
  9. package/dist/vuetify-labs.d.ts +2027 -493
  10. package/dist/vuetify-labs.esm.js +1082 -196
  11. package/dist/vuetify-labs.esm.js.map +1 -1
  12. package/dist/vuetify-labs.js +1082 -195
  13. package/dist/vuetify-labs.min.css +2 -2
  14. package/dist/vuetify.cjs +663 -170
  15. package/dist/vuetify.cjs.map +1 -1
  16. package/dist/vuetify.css +4744 -4671
  17. package/dist/vuetify.d.ts +1575 -267
  18. package/dist/vuetify.esm.js +663 -171
  19. package/dist/vuetify.esm.js.map +1 -1
  20. package/dist/vuetify.js +663 -170
  21. package/dist/vuetify.js.map +1 -1
  22. package/dist/vuetify.min.css +2 -2
  23. package/dist/vuetify.min.js +1182 -1126
  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/VBtn/VBtn.sass +3 -1
  29. package/lib/components/VCarousel/VCarousel.css +0 -1
  30. package/lib/components/VCarousel/VCarousel.js +1 -0
  31. package/lib/components/VCarousel/VCarousel.js.map +1 -1
  32. package/lib/components/VCarousel/VCarousel.sass +0 -1
  33. package/lib/components/VCombobox/VCombobox.d.ts +39 -14
  34. package/lib/components/VCombobox/VCombobox.js +2 -2
  35. package/lib/components/VCombobox/VCombobox.js.map +1 -1
  36. package/lib/components/VDataIterator/composables/items.d.ts +2 -1
  37. package/lib/components/VDataIterator/composables/items.js.map +1 -1
  38. package/lib/components/VDataTable/VDataTable.css +12 -1
  39. package/lib/components/VDataTable/VDataTable.d.ts +20 -38
  40. package/lib/components/VDataTable/VDataTable.sass +12 -2
  41. package/lib/components/VDataTable/VDataTableColumn.d.ts +9 -3
  42. package/lib/components/VDataTable/VDataTableColumn.js +12 -4
  43. package/lib/components/VDataTable/VDataTableColumn.js.map +1 -1
  44. package/lib/components/VDataTable/VDataTableHeaders.d.ts +0 -13
  45. package/lib/components/VDataTable/VDataTableHeaders.js +10 -9
  46. package/lib/components/VDataTable/VDataTableHeaders.js.map +1 -1
  47. package/lib/components/VDataTable/VDataTableRow.js +2 -0
  48. package/lib/components/VDataTable/VDataTableRow.js.map +1 -1
  49. package/lib/components/VDataTable/VDataTableServer.d.ts +10 -23
  50. package/lib/components/VDataTable/VDataTableVirtual.d.ts +10 -23
  51. package/lib/components/VDataTable/composables/headers.d.ts +22 -14
  52. package/lib/components/VDataTable/composables/headers.js +51 -22
  53. package/lib/components/VDataTable/composables/headers.js.map +1 -1
  54. package/lib/components/VDataTable/composables/sort.js +2 -1
  55. package/lib/components/VDataTable/composables/sort.js.map +1 -1
  56. package/lib/components/VDataTable/types.d.ts +4 -2
  57. package/lib/components/VDataTable/types.js.map +1 -1
  58. package/lib/components/VDatePicker/VDatePicker.js +2 -1
  59. package/lib/components/VDatePicker/VDatePicker.js.map +1 -1
  60. package/lib/components/VDatePicker/VDatePickerControls.css +1 -0
  61. package/lib/components/VDatePicker/VDatePickerControls.sass +1 -0
  62. package/lib/components/VDatePicker/VDatePickerMonth.css +3 -8
  63. package/lib/components/VDatePicker/VDatePickerMonth.js +7 -3
  64. package/lib/components/VDatePicker/VDatePickerMonth.js.map +1 -1
  65. package/lib/components/VDatePicker/VDatePickerMonth.sass +3 -8
  66. package/lib/components/VField/VField.js +2 -10
  67. package/lib/components/VField/VField.js.map +1 -1
  68. package/lib/components/VKbd/VKbd.css +14 -5
  69. package/lib/components/VKbd/VKbd.js.map +1 -1
  70. package/lib/components/VKbd/VKbd.scss +26 -0
  71. package/lib/components/VKbd/_variables.scss +12 -6
  72. package/lib/components/VKbd/index.js.map +1 -1
  73. package/lib/components/VList/VList.d.ts +24 -27
  74. package/lib/components/VList/VList.js +1 -5
  75. package/lib/components/VList/VList.js.map +1 -1
  76. package/lib/components/VList/VListGroup.d.ts +13 -0
  77. package/lib/components/VList/VListGroup.js +2 -1
  78. package/lib/components/VList/VListGroup.js.map +1 -1
  79. package/lib/components/VList/VListItem.d.ts +6 -3
  80. package/lib/components/VList/VListItem.js +1 -1
  81. package/lib/components/VList/VListItem.js.map +1 -1
  82. package/lib/components/VNumberInput/VNumberInput.js +4 -10
  83. package/lib/components/VNumberInput/VNumberInput.js.map +1 -1
  84. package/lib/components/VNumberInput/hold.js +4 -0
  85. package/lib/components/VNumberInput/hold.js.map +1 -1
  86. package/lib/components/VOtpInput/VOtpInput.js +17 -14
  87. package/lib/components/VOtpInput/VOtpInput.js.map +1 -1
  88. package/lib/components/VOverlay/locationStrategies.js +1 -1
  89. package/lib/components/VOverlay/locationStrategies.js.map +1 -1
  90. package/lib/components/VSelect/VSelect.d.ts +58 -22
  91. package/lib/components/VSelect/VSelect.js +2 -2
  92. package/lib/components/VSelect/VSelect.js.map +1 -1
  93. package/lib/components/VTextField/VTextField.js +1 -1
  94. package/lib/components/VTextField/VTextField.js.map +1 -1
  95. package/lib/components/VTimePicker/VTimePicker.css +1 -6
  96. package/lib/components/VTimePicker/VTimePicker.sass +1 -6
  97. package/lib/components/VTimePicker/VTimePickerClock.css +5 -4
  98. package/lib/components/VTimePicker/VTimePickerClock.sass +5 -4
  99. package/lib/components/VTimePicker/VTimePickerControls.css +2 -1
  100. package/lib/components/VTimePicker/VTimePickerControls.sass +2 -3
  101. package/lib/components/VTreeview/VTreeview.d.ts +235 -188
  102. package/lib/components/VTreeview/VTreeview.js +13 -12
  103. package/lib/components/VTreeview/VTreeview.js.map +1 -1
  104. package/lib/components/VTreeview/VTreeviewChildren.d.ts +94 -10
  105. package/lib/components/VTreeview/VTreeviewChildren.js +61 -17
  106. package/lib/components/VTreeview/VTreeviewChildren.js.map +1 -1
  107. package/lib/components/VTreeview/VTreeviewGroup.d.ts +13 -0
  108. package/lib/components/VTreeview/VTreeviewItem.css +57 -0
  109. package/lib/components/VTreeview/VTreeviewItem.d.ts +1334 -97
  110. package/lib/components/VTreeview/VTreeviewItem.js +25 -16
  111. package/lib/components/VTreeview/VTreeviewItem.js.map +1 -1
  112. package/lib/components/VTreeview/VTreeviewItem.sass +60 -0
  113. package/lib/components/VTreeview/_variables.scss +15 -0
  114. package/lib/composables/calendar.d.ts +2 -1
  115. package/lib/composables/calendar.js +8 -8
  116. package/lib/composables/calendar.js.map +1 -1
  117. package/lib/composables/date/adapters/vuetify.js +1 -1
  118. package/lib/composables/date/adapters/vuetify.js.map +1 -1
  119. package/lib/composables/filter.d.ts +1 -0
  120. package/lib/composables/filter.js +1 -1
  121. package/lib/composables/filter.js.map +1 -1
  122. package/lib/composables/hotkey/hotkey-parsing.d.ts +15 -0
  123. package/lib/composables/hotkey/hotkey-parsing.js +154 -0
  124. package/lib/composables/hotkey/hotkey-parsing.js.map +1 -0
  125. package/lib/composables/hotkey/hotkey.d.ts +9 -0
  126. package/lib/composables/{hotkey.js → hotkey/hotkey.js} +31 -39
  127. package/lib/composables/hotkey/hotkey.js.map +1 -0
  128. package/lib/composables/hotkey/index.d.ts +1 -0
  129. package/lib/composables/hotkey/index.js +2 -0
  130. package/lib/composables/hotkey/index.js.map +1 -0
  131. package/lib/composables/hotkey/key-aliases.d.ts +14 -0
  132. package/lib/composables/hotkey/key-aliases.js +38 -0
  133. package/lib/composables/hotkey/key-aliases.js.map +1 -0
  134. package/lib/composables/icons.d.ts +11 -0
  135. package/lib/composables/icons.js.map +1 -1
  136. package/lib/composables/index.d.ts +1 -0
  137. package/lib/composables/index.js +1 -0
  138. package/lib/composables/index.js.map +1 -1
  139. package/lib/composables/list-items.d.ts +14 -1
  140. package/lib/composables/list-items.js +9 -3
  141. package/lib/composables/list-items.js.map +1 -1
  142. package/lib/composables/nested/nested.d.ts +7 -4
  143. package/lib/composables/nested/nested.js +24 -14
  144. package/lib/composables/nested/nested.js.map +1 -1
  145. package/lib/composables/nested/selectStrategies.d.ts +2 -1
  146. package/lib/composables/nested/selectStrategies.js +22 -11
  147. package/lib/composables/nested/selectStrategies.js.map +1 -1
  148. package/lib/composables/virtual.js +1 -1
  149. package/lib/composables/virtual.js.map +1 -1
  150. package/lib/entry-bundler.js +1 -1
  151. package/lib/entry-bundler.js.map +1 -1
  152. package/lib/framework.d.ts +91 -66
  153. package/lib/framework.js +1 -1
  154. package/lib/framework.js.map +1 -1
  155. package/lib/iconsets/fa.js +12 -1
  156. package/lib/iconsets/fa.js.map +1 -1
  157. package/lib/iconsets/fa4.js +12 -1
  158. package/lib/iconsets/fa4.js.map +1 -1
  159. package/lib/iconsets/md.js +12 -1
  160. package/lib/iconsets/md.js.map +1 -1
  161. package/lib/iconsets/mdi-svg.js +12 -1
  162. package/lib/iconsets/mdi-svg.js.map +1 -1
  163. package/lib/iconsets/mdi.js +12 -1
  164. package/lib/iconsets/mdi.js.map +1 -1
  165. package/lib/labs/VCalendar/VCalendar.d.ts +33 -33
  166. package/lib/labs/VCalendar/VCalendar.js +10 -10
  167. package/lib/labs/VCalendar/VCalendar.js.map +1 -1
  168. package/lib/labs/VCalendar/VCalendarDay.d.ts +33 -33
  169. package/lib/labs/VCalendar/VCalendarDay.js +1 -1
  170. package/lib/labs/VCalendar/VCalendarDay.js.map +1 -1
  171. package/lib/labs/VCalendar/VCalendarInterval.d.ts +36 -36
  172. package/lib/labs/VCalendar/VCalendarInterval.js +9 -9
  173. package/lib/labs/VCalendar/VCalendarInterval.js.map +1 -1
  174. package/lib/labs/VCalendar/VCalendarIntervalEvent.d.ts +12 -12
  175. package/lib/labs/VCalendar/VCalendarIntervalEvent.js +1 -1
  176. package/lib/labs/VCalendar/VCalendarIntervalEvent.js.map +1 -1
  177. package/lib/labs/VCalendar/VCalendarMonthDay.d.ts +36 -36
  178. package/lib/labs/VCalendar/VCalendarMonthDay.js +4 -4
  179. package/lib/labs/VCalendar/VCalendarMonthDay.js.map +1 -1
  180. package/lib/labs/VHotkey/VHotkey.css +242 -0
  181. package/lib/labs/VHotkey/VHotkey.d.ts +387 -0
  182. package/lib/labs/VHotkey/VHotkey.js +432 -0
  183. package/lib/labs/VHotkey/VHotkey.js.map +1 -0
  184. package/lib/labs/VHotkey/VHotkey.scss +253 -0
  185. package/lib/labs/VHotkey/_variables.scss +43 -0
  186. package/lib/labs/VHotkey/index.d.ts +1 -0
  187. package/lib/labs/VHotkey/index.js +2 -0
  188. package/lib/labs/VHotkey/index.js.map +1 -0
  189. package/lib/labs/VIconBtn/VIconBtn.js +1 -0
  190. package/lib/labs/VIconBtn/VIconBtn.js.map +1 -1
  191. package/lib/labs/VPicker/VPicker.css +4 -0
  192. package/lib/labs/VPicker/VPicker.sass +4 -0
  193. package/lib/labs/components.d.ts +1 -0
  194. package/lib/labs/components.js +1 -0
  195. package/lib/labs/components.js.map +1 -1
  196. package/lib/locale/af.d.ts +18 -0
  197. package/lib/locale/af.js +18 -0
  198. package/lib/locale/af.js.map +1 -1
  199. package/lib/locale/ar.d.ts +18 -0
  200. package/lib/locale/ar.js +18 -0
  201. package/lib/locale/ar.js.map +1 -1
  202. package/lib/locale/az.d.ts +18 -0
  203. package/lib/locale/az.js +18 -0
  204. package/lib/locale/az.js.map +1 -1
  205. package/lib/locale/bg.d.ts +18 -0
  206. package/lib/locale/bg.js +18 -0
  207. package/lib/locale/bg.js.map +1 -1
  208. package/lib/locale/ca.d.ts +18 -0
  209. package/lib/locale/ca.js +18 -0
  210. package/lib/locale/ca.js.map +1 -1
  211. package/lib/locale/ckb.d.ts +18 -0
  212. package/lib/locale/ckb.js +18 -0
  213. package/lib/locale/ckb.js.map +1 -1
  214. package/lib/locale/cs.d.ts +18 -0
  215. package/lib/locale/cs.js +18 -0
  216. package/lib/locale/cs.js.map +1 -1
  217. package/lib/locale/da.d.ts +18 -0
  218. package/lib/locale/da.js +18 -0
  219. package/lib/locale/da.js.map +1 -1
  220. package/lib/locale/de.d.ts +18 -0
  221. package/lib/locale/de.js +18 -0
  222. package/lib/locale/de.js.map +1 -1
  223. package/lib/locale/el.d.ts +18 -0
  224. package/lib/locale/el.js +18 -0
  225. package/lib/locale/el.js.map +1 -1
  226. package/lib/locale/en.d.ts +18 -0
  227. package/lib/locale/en.js +18 -0
  228. package/lib/locale/en.js.map +1 -1
  229. package/lib/locale/es.d.ts +18 -0
  230. package/lib/locale/es.js +18 -0
  231. package/lib/locale/es.js.map +1 -1
  232. package/lib/locale/et.d.ts +18 -0
  233. package/lib/locale/et.js +18 -0
  234. package/lib/locale/et.js.map +1 -1
  235. package/lib/locale/fa.d.ts +18 -0
  236. package/lib/locale/fa.js +18 -0
  237. package/lib/locale/fa.js.map +1 -1
  238. package/lib/locale/fi.d.ts +18 -0
  239. package/lib/locale/fi.js +18 -0
  240. package/lib/locale/fi.js.map +1 -1
  241. package/lib/locale/fr.d.ts +18 -0
  242. package/lib/locale/fr.js +18 -0
  243. package/lib/locale/fr.js.map +1 -1
  244. package/lib/locale/he.d.ts +18 -0
  245. package/lib/locale/he.js +18 -0
  246. package/lib/locale/he.js.map +1 -1
  247. package/lib/locale/hr.d.ts +18 -0
  248. package/lib/locale/hr.js +18 -0
  249. package/lib/locale/hr.js.map +1 -1
  250. package/lib/locale/hu.d.ts +18 -0
  251. package/lib/locale/hu.js +18 -0
  252. package/lib/locale/hu.js.map +1 -1
  253. package/lib/locale/id.d.ts +18 -0
  254. package/lib/locale/id.js +18 -0
  255. package/lib/locale/id.js.map +1 -1
  256. package/lib/locale/it.d.ts +18 -0
  257. package/lib/locale/it.js +18 -0
  258. package/lib/locale/it.js.map +1 -1
  259. package/lib/locale/ja.d.ts +18 -0
  260. package/lib/locale/ja.js +18 -0
  261. package/lib/locale/ja.js.map +1 -1
  262. package/lib/locale/km.d.ts +18 -0
  263. package/lib/locale/km.js +18 -0
  264. package/lib/locale/km.js.map +1 -1
  265. package/lib/locale/ko.d.ts +18 -0
  266. package/lib/locale/ko.js +18 -0
  267. package/lib/locale/ko.js.map +1 -1
  268. package/lib/locale/lt.d.ts +18 -0
  269. package/lib/locale/lt.js +18 -0
  270. package/lib/locale/lt.js.map +1 -1
  271. package/lib/locale/lv.d.ts +18 -0
  272. package/lib/locale/lv.js +18 -0
  273. package/lib/locale/lv.js.map +1 -1
  274. package/lib/locale/nl.d.ts +18 -0
  275. package/lib/locale/nl.js +18 -0
  276. package/lib/locale/nl.js.map +1 -1
  277. package/lib/locale/no.d.ts +18 -0
  278. package/lib/locale/no.js +18 -0
  279. package/lib/locale/no.js.map +1 -1
  280. package/lib/locale/pl.d.ts +18 -0
  281. package/lib/locale/pl.js +18 -0
  282. package/lib/locale/pl.js.map +1 -1
  283. package/lib/locale/pt.d.ts +18 -0
  284. package/lib/locale/pt.js +18 -0
  285. package/lib/locale/pt.js.map +1 -1
  286. package/lib/locale/ro.d.ts +18 -0
  287. package/lib/locale/ro.js +18 -0
  288. package/lib/locale/ro.js.map +1 -1
  289. package/lib/locale/ru.d.ts +18 -0
  290. package/lib/locale/ru.js +18 -0
  291. package/lib/locale/ru.js.map +1 -1
  292. package/lib/locale/sk.d.ts +18 -0
  293. package/lib/locale/sk.js +18 -0
  294. package/lib/locale/sk.js.map +1 -1
  295. package/lib/locale/sl.d.ts +18 -0
  296. package/lib/locale/sl.js +18 -0
  297. package/lib/locale/sl.js.map +1 -1
  298. package/lib/locale/sr-Cyrl.d.ts +18 -0
  299. package/lib/locale/sr-Cyrl.js +18 -0
  300. package/lib/locale/sr-Cyrl.js.map +1 -1
  301. package/lib/locale/sr-Latn.d.ts +18 -0
  302. package/lib/locale/sr-Latn.js +18 -0
  303. package/lib/locale/sr-Latn.js.map +1 -1
  304. package/lib/locale/sv.d.ts +18 -0
  305. package/lib/locale/sv.js +18 -0
  306. package/lib/locale/sv.js.map +1 -1
  307. package/lib/locale/th.d.ts +18 -0
  308. package/lib/locale/th.js +18 -0
  309. package/lib/locale/th.js.map +1 -1
  310. package/lib/locale/tr.d.ts +18 -0
  311. package/lib/locale/tr.js +18 -0
  312. package/lib/locale/tr.js.map +1 -1
  313. package/lib/locale/uk.d.ts +18 -0
  314. package/lib/locale/uk.js +18 -0
  315. package/lib/locale/uk.js.map +1 -1
  316. package/lib/locale/vi.d.ts +18 -0
  317. package/lib/locale/vi.js +18 -0
  318. package/lib/locale/vi.js.map +1 -1
  319. package/lib/locale/zh-Hans.d.ts +18 -0
  320. package/lib/locale/zh-Hans.js +18 -0
  321. package/lib/locale/zh-Hans.js.map +1 -1
  322. package/lib/locale/zh-Hant.d.ts +18 -0
  323. package/lib/locale/zh-Hant.js +18 -0
  324. package/lib/locale/zh-Hant.js.map +1 -1
  325. package/lib/util/helpers.d.ts +3 -0
  326. package/lib/util/helpers.js +4 -0
  327. package/lib/util/helpers.js.map +1 -1
  328. package/lib/util/indentLines.d.ts +17 -0
  329. package/lib/util/indentLines.js +34 -0
  330. package/lib/util/indentLines.js.map +1 -0
  331. package/lib/util/index.d.ts +1 -0
  332. package/lib/util/index.js +1 -0
  333. package/lib/util/index.js.map +1 -1
  334. package/package.json +2 -2
  335. package/lib/components/VKbd/VKbd.sass +0 -15
  336. package/lib/composables/hotkey.d.ts +0 -9
  337. package/lib/composables/hotkey.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Vuetify v3.9.0-beta.0
2
+ * Vuetify v3.9.0
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
@@ -550,6 +550,10 @@
550
550
  return child.type !== vue.Fragment || ensureValidVNode(child.children);
551
551
  }) ? vnodes : null;
552
552
  }
553
+ function renderSlot(slot, props, fallback) {
554
+ // TODO: check if slot returns elements: #18308
555
+ return slot?.(props) ?? fallback?.(props);
556
+ }
553
557
  function defer(timeout, cb) {
554
558
  if (!IN_BROWSER || timeout === 0) {
555
559
  cb();
@@ -1624,6 +1628,40 @@
1624
1628
  return ['scroll', 'auto'].includes(style.overflowY);
1625
1629
  }
1626
1630
 
1631
+ // Types
1632
+
1633
+ function getIndentLines(_ref) {
1634
+ let {
1635
+ depth,
1636
+ isLast,
1637
+ isLastGroup,
1638
+ leafLinks,
1639
+ separateRoots,
1640
+ parentIndentLines,
1641
+ variant
1642
+ } = _ref;
1643
+ if (!parentIndentLines || !depth) {
1644
+ return {
1645
+ leaf: undefined,
1646
+ node: undefined,
1647
+ children: parentIndentLines
1648
+ };
1649
+ }
1650
+ if (variant === 'simple') {
1651
+ return {
1652
+ leaf: [...parentIndentLines, 'line'],
1653
+ node: [...parentIndentLines, 'line'],
1654
+ children: [...parentIndentLines, 'line']
1655
+ };
1656
+ }
1657
+ const isLastLeaf = isLast && (!isLastGroup || separateRoots || depth > 1);
1658
+ return {
1659
+ leaf: [...parentIndentLines, isLastLeaf ? 'last-leaf' : 'leaf', ...(leafLinks ? ['leaf-link'] : [])],
1660
+ node: [...parentIndentLines, isLastLeaf ? 'last-leaf' : 'leaf'],
1661
+ children: [...parentIndentLines, isLastLeaf ? 'none' : 'line']
1662
+ };
1663
+ }
1664
+
1627
1665
  function isFixedPosition(el) {
1628
1666
  while (el) {
1629
1667
  if (window.getComputedStyle(el).position === 'fixed') {
@@ -2145,6 +2183,24 @@
2145
2183
  exclude: 'The {0} character is not allowed',
2146
2184
  notEmpty: 'Please choose at least one value',
2147
2185
  pattern: 'Invalid format'
2186
+ },
2187
+ hotkey: {
2188
+ then: 'then',
2189
+ ctrl: 'Ctrl',
2190
+ command: 'Command',
2191
+ space: 'Space',
2192
+ shift: 'Shift',
2193
+ alt: 'Alt',
2194
+ enter: 'Enter',
2195
+ escape: 'Escape',
2196
+ upArrow: 'Up Arrow',
2197
+ downArrow: 'Down Arrow',
2198
+ leftArrow: 'Left Arrow',
2199
+ rightArrow: 'Right Arrow',
2200
+ backspace: 'Backspace',
2201
+ option: 'Option',
2202
+ plus: 'plus',
2203
+ shortcut: 'Keyboard shortcut: {0}'
2148
2204
  }
2149
2205
  };
2150
2206
 
@@ -4655,7 +4711,18 @@
4655
4711
  treeviewExpand: 'mdi-menu-right',
4656
4712
  eyeDropper: 'mdi-eyedropper',
4657
4713
  upload: 'mdi-cloud-upload',
4658
- color: 'mdi-palette'
4714
+ color: 'mdi-palette',
4715
+ command: 'mdi-apple-keyboard-command',
4716
+ ctrl: 'mdi-apple-keyboard-control',
4717
+ space: 'mdi-keyboard-space',
4718
+ shift: 'mdi-apple-keyboard-shift',
4719
+ alt: 'mdi-apple-keyboard-option',
4720
+ enter: 'mdi-keyboard-return',
4721
+ arrowup: 'mdi-arrow-up',
4722
+ arrowdown: 'mdi-arrow-down',
4723
+ arrowleft: 'mdi-arrow-left',
4724
+ arrowright: 'mdi-arrow-right',
4725
+ backspace: 'mdi-backspace'
4659
4726
  };
4660
4727
  const mdi = {
4661
4728
  // Not using mergeProps here, functional components merge props by default (?)
@@ -8797,7 +8864,7 @@
8797
8864
  selected.set(id, value ? 'on' : 'off');
8798
8865
  return selected;
8799
8866
  },
8800
- in: (v, children, parents) => {
8867
+ in: (v, children, parents, disabled) => {
8801
8868
  const map = new Map();
8802
8869
  for (const id of v || []) {
8803
8870
  strategy.select({
@@ -8805,7 +8872,8 @@
8805
8872
  value: true,
8806
8873
  selected: map,
8807
8874
  children,
8808
- parents
8875
+ parents,
8876
+ disabled
8809
8877
  });
8810
8878
  }
8811
8879
  return map;
@@ -8837,9 +8905,9 @@
8837
8905
  selected: singleSelected
8838
8906
  });
8839
8907
  },
8840
- in: (v, children, parents) => {
8908
+ in: (v, children, parents, disabled) => {
8841
8909
  if (v?.length) {
8842
- return parentStrategy.in(v.slice(0, 1), children, parents);
8910
+ return parentStrategy.in(v.slice(0, 1), children, parents, disabled);
8843
8911
  }
8844
8912
  return new Map();
8845
8913
  },
@@ -8905,23 +8973,32 @@
8905
8973
  value,
8906
8974
  selected,
8907
8975
  children,
8908
- parents
8976
+ parents,
8977
+ disabled
8909
8978
  } = _ref6;
8910
8979
  id = vue.toRaw(id);
8911
8980
  const original = new Map(selected);
8912
8981
  const items = [id];
8913
8982
  while (items.length) {
8914
8983
  const item = items.shift();
8915
- selected.set(vue.toRaw(item), value ? 'on' : 'off');
8984
+ if (!disabled.has(item)) {
8985
+ selected.set(vue.toRaw(item), value ? 'on' : 'off');
8986
+ }
8916
8987
  if (children.has(item)) {
8917
8988
  items.push(...children.get(item));
8918
8989
  }
8919
8990
  }
8920
8991
  let parent = vue.toRaw(parents.get(id));
8921
8992
  while (parent) {
8922
- const childrenIds = children.get(parent);
8923
- const everySelected = childrenIds.every(cid => selected.get(vue.toRaw(cid)) === 'on');
8924
- const noneSelected = childrenIds.every(cid => !selected.has(vue.toRaw(cid)) || selected.get(vue.toRaw(cid)) === 'off');
8993
+ let everySelected = true;
8994
+ let noneSelected = true;
8995
+ for (const child of children.get(parent)) {
8996
+ const cid = vue.toRaw(child);
8997
+ if (disabled.has(cid)) continue;
8998
+ if (selected.get(cid) !== 'on') everySelected = false;
8999
+ if (selected.has(cid) && selected.get(cid) !== 'off') noneSelected = false;
9000
+ if (!everySelected && !noneSelected) break;
9001
+ }
8925
9002
  selected.set(parent, everySelected ? 'on' : noneSelected ? 'off' : 'indeterminate');
8926
9003
  parent = vue.toRaw(parents.get(parent));
8927
9004
  }
@@ -8938,7 +9015,7 @@
8938
9015
  }
8939
9016
  return selected;
8940
9017
  },
8941
- in: (v, children, parents) => {
9018
+ in: (v, children, parents, disabled) => {
8942
9019
  let map = new Map();
8943
9020
  for (const id of v || []) {
8944
9021
  map = strategy.select({
@@ -8946,7 +9023,8 @@
8946
9023
  value: true,
8947
9024
  selected: map,
8948
9025
  children,
8949
- parents
9026
+ parents,
9027
+ disabled
8950
9028
  });
8951
9029
  }
8952
9030
  return map;
@@ -8993,8 +9071,9 @@
8993
9071
  root: {
8994
9072
  register: () => null,
8995
9073
  unregister: () => null,
8996
- parents: vue.ref(new Map()),
8997
9074
  children: vue.ref(new Map()),
9075
+ parents: vue.ref(new Map()),
9076
+ disabled: vue.ref(new Set()),
8998
9077
  open: () => null,
8999
9078
  openOnSelect: () => null,
9000
9079
  activate: () => null,
@@ -9021,9 +9100,10 @@
9021
9100
  }, 'nested');
9022
9101
  const useNested = props => {
9023
9102
  let isUnmounted = false;
9024
- const children = vue.ref(new Map());
9025
- const parents = vue.ref(new Map());
9026
- const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(v), v => [...v.values()]);
9103
+ const children = vue.shallowRef(new Map());
9104
+ const parents = vue.shallowRef(new Map());
9105
+ const disabled = vue.shallowRef(new Set());
9106
+ const opened = useProxiedModel(props, 'opened', props.opened, v => new Set(Array.isArray(v) ? v.map(i => vue.toRaw(i)) : v), v => [...v.values()]);
9027
9107
  const activeStrategy = vue.computed(() => {
9028
9108
  if (typeof props.activeStrategy === 'object') return props.activeStrategy;
9029
9109
  if (typeof props.activeStrategy === 'function') return props.activeStrategy(props.mandatory);
@@ -9071,13 +9151,13 @@
9071
9151
  }
9072
9152
  });
9073
9153
  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));
9074
- 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));
9154
+ 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));
9075
9155
  vue.onBeforeUnmount(() => {
9076
9156
  isUnmounted = true;
9077
9157
  });
9078
9158
  function getPath(id) {
9079
9159
  const path = [];
9080
- let parent = id;
9160
+ let parent = vue.toRaw(id);
9081
9161
  while (parent != null) {
9082
9162
  path.unshift(parent);
9083
9163
  parent = parents.value.get(parent);
@@ -9101,7 +9181,7 @@
9101
9181
  }
9102
9182
  return arr;
9103
9183
  }),
9104
- register: (id, parentId, isGroup) => {
9184
+ register: (id, parentId, isDisabled, isGroup) => {
9105
9185
  if (nodeIds.has(id)) {
9106
9186
  const path = getPath(id).map(String).join(' -> ');
9107
9187
  const newPath = getPath(parentId).concat(id).map(String).join(' -> ');
@@ -9111,6 +9191,7 @@
9111
9191
  nodeIds.add(id);
9112
9192
  }
9113
9193
  parentId && id !== parentId && parents.value.set(id, parentId);
9194
+ isDisabled && disabled.value.add(id);
9114
9195
  isGroup && children.value.set(id, []);
9115
9196
  if (parentId != null) {
9116
9197
  children.value.set(parentId, [...(children.value.get(parentId) || []), id]);
@@ -9120,6 +9201,7 @@
9120
9201
  if (isUnmounted) return;
9121
9202
  nodeIds.delete(id);
9122
9203
  children.value.delete(id);
9204
+ disabled.value.delete(id);
9123
9205
  const parent = parents.value.get(id);
9124
9206
  if (parent) {
9125
9207
  const list = children.value.get(parent) ?? [];
@@ -9169,6 +9251,7 @@
9169
9251
  selected: new Map(selected.value),
9170
9252
  children: children.value,
9171
9253
  parents: parents.value,
9254
+ disabled: disabled.value,
9172
9255
  event
9173
9256
  });
9174
9257
  newSelected && (selected.value = newSelected);
@@ -9211,16 +9294,17 @@
9211
9294
  },
9212
9295
  children,
9213
9296
  parents,
9297
+ disabled,
9214
9298
  getPath
9215
9299
  }
9216
9300
  };
9217
9301
  vue.provide(VNestedSymbol, nested);
9218
9302
  return nested.root;
9219
9303
  };
9220
- const useNestedItem = (id, isGroup) => {
9304
+ const useNestedItem = (id, isDisabled, isGroup) => {
9221
9305
  const parent = vue.inject(VNestedSymbol, emptyNested);
9222
9306
  const uidSymbol = Symbol('nested item');
9223
- const computedId = vue.computed(() => vue.toValue(id) ?? uidSymbol);
9307
+ const computedId = vue.computed(() => vue.toRaw(vue.toValue(id)) ?? uidSymbol);
9224
9308
  const item = {
9225
9309
  ...parent,
9226
9310
  id: computedId,
@@ -9229,18 +9313,22 @@
9229
9313
  isOpen: vue.computed(() => parent.root.opened.value.has(computedId.value)),
9230
9314
  parent: vue.computed(() => parent.root.parents.value.get(computedId.value)),
9231
9315
  activate: (activated, e) => parent.root.activate(computedId.value, activated, e),
9232
- isActivated: vue.computed(() => parent.root.activated.value.has(vue.toRaw(computedId.value))),
9316
+ isActivated: vue.computed(() => parent.root.activated.value.has(computedId.value)),
9233
9317
  select: (selected, e) => parent.root.select(computedId.value, selected, e),
9234
- isSelected: vue.computed(() => parent.root.selected.value.get(vue.toRaw(computedId.value)) === 'on'),
9235
- isIndeterminate: vue.computed(() => parent.root.selected.value.get(vue.toRaw(computedId.value)) === 'indeterminate'),
9318
+ isSelected: vue.computed(() => parent.root.selected.value.get(computedId.value) === 'on'),
9319
+ isIndeterminate: vue.computed(() => parent.root.selected.value.get(computedId.value) === 'indeterminate'),
9236
9320
  isLeaf: vue.computed(() => !parent.root.children.value.get(computedId.value)),
9237
9321
  isGroupActivator: parent.isGroupActivator
9238
9322
  };
9239
9323
  vue.onBeforeMount(() => {
9240
- !parent.isGroupActivator && parent.root.register(computedId.value, parent.id.value, isGroup);
9324
+ if (!parent.isGroupActivator) {
9325
+ parent.root.register(computedId.value, parent.id.value, vue.toValue(isDisabled), isGroup);
9326
+ }
9241
9327
  });
9242
9328
  vue.onBeforeUnmount(() => {
9243
- !parent.isGroupActivator && parent.root.unregister(computedId.value);
9329
+ if (!parent.isGroupActivator) {
9330
+ parent.root.unregister(computedId.value);
9331
+ }
9244
9332
  });
9245
9333
  isGroup && vue.provide(VNestedSymbol, item);
9246
9334
  return item;
@@ -9272,6 +9360,7 @@
9272
9360
  type: IconValue,
9273
9361
  default: '$collapse'
9274
9362
  },
9363
+ disabled: Boolean,
9275
9364
  expandIcon: {
9276
9365
  type: IconValue,
9277
9366
  default: '$expand'
@@ -9297,7 +9386,7 @@
9297
9386
  isOpen,
9298
9387
  open,
9299
9388
  id: _id
9300
- } = useNestedItem(() => props.value, true);
9389
+ } = useNestedItem(() => props.value, () => props.disabled, true);
9301
9390
  const id = vue.computed(() => `v-list-group--id-${String(props.rawId ?? _id.value)}`);
9302
9391
  const list = useList();
9303
9392
  const {
@@ -9467,7 +9556,7 @@
9467
9556
  parent,
9468
9557
  openOnSelect,
9469
9558
  id: uid
9470
- } = useNestedItem(id, false);
9559
+ } = useNestedItem(id, () => props.disabled, false);
9471
9560
  const list = useList();
9472
9561
  const isActive = vue.computed(() => props.active !== false && (props.active || link.isActive?.value || (root.activatable.value ? isActivated.value : isSelected.value)));
9473
9562
  const isLink = vue.toRef(() => props.link !== false && link.isLink.value);
@@ -9819,6 +9908,10 @@
9819
9908
  type: [Boolean, String, Array, Function],
9820
9909
  default: 'props'
9821
9910
  },
9911
+ itemType: {
9912
+ type: [Boolean, String, Array, Function],
9913
+ default: 'type'
9914
+ },
9822
9915
  returnObject: Boolean,
9823
9916
  valueComparator: Function
9824
9917
  }, 'list-items');
@@ -9826,6 +9919,7 @@
9826
9919
  const title = getPropertyFromItem(item, props.itemTitle, item);
9827
9920
  const value = getPropertyFromItem(item, props.itemValue, title);
9828
9921
  const children = getPropertyFromItem(item, props.itemChildren);
9922
+ const type = getPropertyFromItem(item, props.itemType, 'item');
9829
9923
  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);
9830
9924
  const _props = {
9831
9925
  title,
@@ -9833,15 +9927,16 @@
9833
9927
  ...itemProps
9834
9928
  };
9835
9929
  return {
9930
+ type,
9836
9931
  title: String(_props.title ?? ''),
9837
9932
  value: _props.value,
9838
9933
  props: _props,
9839
- children: Array.isArray(children) ? transformItems$3(props, children) : undefined,
9934
+ children: type === 'item' && Array.isArray(children) ? transformItems$3(props, children) : undefined,
9840
9935
  raw: item
9841
9936
  };
9842
9937
  }
9843
9938
  function transformItems$3(props, items) {
9844
- const _props = pick(props, ['itemTitle', 'itemValue', 'itemChildren', 'itemProps', 'returnObject', 'valueComparator']);
9939
+ const _props = pick(props, ['itemTitle', 'itemValue', 'itemChildren', 'itemProps', 'itemType', 'returnObject', 'valueComparator']);
9845
9940
  const array = [];
9846
9941
  for (const item of items) {
9847
9942
  array.push(transformItem$3(_props, item));
@@ -9883,7 +9978,7 @@
9883
9978
  const _returnObject = props.returnObject;
9884
9979
  const hasValueComparator = !!props.valueComparator;
9885
9980
  const valueComparator = props.valueComparator || deepEqual;
9886
- const _props = pick(props, ['itemTitle', 'itemValue', 'itemChildren', 'itemProps', 'returnObject', 'valueComparator']);
9981
+ const _props = pick(props, ['itemTitle', 'itemValue', 'itemChildren', 'itemProps', 'itemType', 'returnObject', 'valueComparator']);
9887
9982
  const returnValue = [];
9888
9983
  main: for (const v of value) {
9889
9984
  // When the model value is null, return an InternalItem
@@ -9945,7 +10040,7 @@
9945
10040
  function transformItem$2(props, item) {
9946
10041
  const type = getPropertyFromItem(item, props.itemType, 'item');
9947
10042
  const title = isPrimitive(item) ? item : getPropertyFromItem(item, props.itemTitle);
9948
- const value = getPropertyFromItem(item, props.itemValue, undefined);
10043
+ const value = isPrimitive(item) ? item : getPropertyFromItem(item, props.itemValue, undefined);
9949
10044
  const children = getPropertyFromItem(item, props.itemChildren);
9950
10045
  const itemProps = props.itemProps === true ? omit(item, ['children']) : getPropertyFromItem(item, props.itemProps);
9951
10046
  const _props = {
@@ -10003,10 +10098,6 @@
10003
10098
  ...makeDensityProps(),
10004
10099
  ...makeDimensionProps(),
10005
10100
  ...makeElevationProps(),
10006
- itemType: {
10007
- type: String,
10008
- default: 'type'
10009
- },
10010
10101
  ...makeItemsProps(),
10011
10102
  ...makeRoundedProps(),
10012
10103
  ...makeTagProps(),
@@ -10427,7 +10518,7 @@
10427
10518
  });
10428
10519
  if (flipped.isFull) {
10429
10520
  const values = flipped.values();
10430
- if (deepEqual(values.at(-1), values.at(-3))) {
10521
+ if (deepEqual(values.at(-1), values.at(-3)) && !deepEqual(values.at(-1), values.at(-2))) {
10431
10522
  // Flipping is causing a container resize loop
10432
10523
  return;
10433
10524
  }
@@ -12097,11 +12188,7 @@
12097
12188
  default: slots.loader
12098
12189
  }), hasPrepend && vue.createElementVNode("div", {
12099
12190
  "key": "prepend",
12100
- "class": "v-field__prepend-inner",
12101
- "onMousedown": e => {
12102
- e.preventDefault();
12103
- e.stopPropagation();
12104
- }
12191
+ "class": "v-field__prepend-inner"
12105
12192
  }, [props.prependInnerIcon && vue.createVNode(InputIcon, {
12106
12193
  "key": "prepend-icon",
12107
12194
  "name": "prependInner",
@@ -12170,11 +12257,7 @@
12170
12257
  })]), [[vue.vShow, props.dirty]])]
12171
12258
  }), hasAppend && vue.createElementVNode("div", {
12172
12259
  "key": "append",
12173
- "class": "v-field__append-inner",
12174
- "onMousedown": e => {
12175
- e.preventDefault();
12176
- e.stopPropagation();
12177
- }
12260
+ "class": "v-field__append-inner"
12178
12261
  }, [slots['append-inner']?.(slotProps.value), props.appendInnerIcon && vue.createVNode(InputIcon, {
12179
12262
  "key": "append-icon",
12180
12263
  "name": "appendInner",
@@ -12285,7 +12368,7 @@
12285
12368
  if (!isFocused.value) focus();
12286
12369
  vue.nextTick(() => {
12287
12370
  if (inputRef.value !== document.activeElement) {
12288
- inputRef.value?.focus();
12371
+ vue.nextTick(() => inputRef.value?.focus());
12289
12372
  }
12290
12373
  });
12291
12374
  }
@@ -12624,7 +12707,7 @@
12624
12707
  raf = requestAnimationFrame(_calculateVisibleItems);
12625
12708
  }
12626
12709
  function _calculateVisibleItems() {
12627
- if (!containerRef.value || !viewportHeight.value) return;
12710
+ if (!containerRef.value || !viewportHeight.value || !itemHeight.value) return;
12628
12711
  const scrollTop = lastScrollTop - markerOffset;
12629
12712
  const direction = Math.sign(scrollVelocity);
12630
12713
  const startPx = Math.max(0, scrollTop - BUFFER_PX);
@@ -13233,7 +13316,7 @@
13233
13316
  key: item.value,
13234
13317
  onClick: () => select(item, null)
13235
13318
  });
13236
- if (item.raw.type === 'divider') {
13319
+ if (item.type === 'divider') {
13237
13320
  return slots.divider?.({
13238
13321
  props: item.raw,
13239
13322
  index
@@ -13241,7 +13324,7 @@
13241
13324
  "key": `divider-${index}`
13242
13325
  }), null);
13243
13326
  }
13244
- if (item.raw.type === 'subheader') {
13327
+ if (item.type === 'subheader') {
13245
13328
  return slots.subheader?.({
13246
13329
  props: item.raw,
13247
13330
  index
@@ -13409,7 +13492,7 @@
13409
13492
  let match = -1;
13410
13493
  if ((query || customFiltersLength > 0) && !options?.noFilter) {
13411
13494
  if (typeof item === 'object') {
13412
- if (['divider', 'subheader'].includes(item.raw?.type)) {
13495
+ if (item.type === 'divider' || item.type === 'subheader') {
13413
13496
  continue;
13414
13497
  }
13415
13498
  const filterKeys = keys || Object.keys(transformed);
@@ -13851,7 +13934,7 @@
13851
13934
  active: highlightFirst.value && index === 0 ? true : undefined,
13852
13935
  onClick: () => select(item, null)
13853
13936
  });
13854
- if (item.raw.type === 'divider') {
13937
+ if (item.type === 'divider') {
13855
13938
  return slots.divider?.({
13856
13939
  props: item.raw,
13857
13940
  index
@@ -13859,7 +13942,7 @@
13859
13942
  "key": `divider-${index}`
13860
13943
  }), null);
13861
13944
  }
13862
- if (item.raw.type === 'subheader') {
13945
+ if (item.type === 'subheader') {
13863
13946
  return slots.subheader?.({
13864
13947
  props: item.raw,
13865
13948
  index
@@ -15420,6 +15503,7 @@
15420
15503
  }) : vue.createVNode(VBtn, vue.mergeProps(item, props), null);
15421
15504
  })]
15422
15505
  })]), props.progress && vue.createVNode(VProgressLinear, {
15506
+ "absolute": true,
15423
15507
  "class": "v-carousel__progress",
15424
15508
  "color": typeof props.progress === 'string' ? props.progress : undefined,
15425
15509
  "modelValue": (group.getItemIndex(model.value) + 1) / group.items.value.length * 100
@@ -17506,7 +17590,7 @@
17506
17590
  case 'fullDate':
17507
17591
  options = {
17508
17592
  year: 'numeric',
17509
- month: 'long',
17593
+ month: 'short',
17510
17594
  day: 'numeric'
17511
17595
  };
17512
17596
  break;
@@ -18084,6 +18168,317 @@
18084
18168
  return createInstance(options, locale);
18085
18169
  }
18086
18170
 
18171
+ /**
18172
+ * Centralized key alias mapping for consistent key normalization across the hotkey system.
18173
+ *
18174
+ * This maps various user-friendly aliases to canonical key names that match
18175
+ * KeyboardEvent.key values (in lowercase) where possible.
18176
+ */
18177
+ const keyAliasMap = {
18178
+ // Modifier aliases (from vue-use, other libraries, and current implementation)
18179
+ control: 'ctrl',
18180
+ command: 'cmd',
18181
+ option: 'alt',
18182
+ // Arrow key aliases (common abbreviations)
18183
+ up: 'arrowup',
18184
+ down: 'arrowdown',
18185
+ left: 'arrowleft',
18186
+ right: 'arrowright',
18187
+ // Other common key aliases
18188
+ esc: 'escape',
18189
+ spacebar: ' ',
18190
+ space: ' ',
18191
+ return: 'enter',
18192
+ del: 'delete',
18193
+ // Symbol aliases (existing from hotkey-parsing.ts)
18194
+ minus: '-',
18195
+ hyphen: '-'
18196
+ };
18197
+
18198
+ /**
18199
+ * Normalizes a key string to its canonical form using the alias map.
18200
+ *
18201
+ * @param key - The key string to normalize
18202
+ * @returns The canonical key name in lowercase
18203
+ */
18204
+ function normalizeKey(key) {
18205
+ const lowerKey = key.toLowerCase();
18206
+ return keyAliasMap[lowerKey] || lowerKey;
18207
+ }
18208
+
18209
+ // Utilities
18210
+
18211
+ /**
18212
+ * Splits a single combination string into individual key parts.
18213
+ *
18214
+ * A combination is a set of keys that must be pressed simultaneously.
18215
+ * e.g. `ctrl+k`, `shift--`
18216
+ */
18217
+ function splitKeyCombination(combination) {
18218
+ let isInternal = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
18219
+ if (!combination) {
18220
+ if (!isInternal) consoleWarn('Invalid hotkey combination: empty string provided');
18221
+ return [];
18222
+ }
18223
+
18224
+ // --- VALIDATION ---
18225
+ const startsWithPlusOrUnderscore = combination.startsWith('+') || combination.startsWith('_');
18226
+ const hasInvalidLeadingSeparator =
18227
+ // Starts with a single '+' or '_' followed by a non-separator character (e.g. '+a', '_a')
18228
+ startsWithPlusOrUnderscore && !(combination.startsWith('++') || combination.startsWith('__'));
18229
+ const hasInvalidStructure =
18230
+ // Invalid leading separator patterns
18231
+ combination.length > 1 && hasInvalidLeadingSeparator ||
18232
+ // Disallow literal + or _ keys (they require shift)
18233
+ combination.includes('++') || combination.includes('__') || combination === '+' || combination === '_' ||
18234
+ // Ends with a separator that is not part of a doubled literal
18235
+ combination.length > 1 && (combination.endsWith('+') || combination.endsWith('_')) && combination.at(-2) !== combination.at(-1) ||
18236
+ // Stand-alone doubled separators (dangling)
18237
+ combination === '++' || combination === '--' || combination === '__';
18238
+ if (hasInvalidStructure) {
18239
+ if (!isInternal) consoleWarn(`Invalid hotkey combination: "${combination}" has invalid structure`);
18240
+ return [];
18241
+ }
18242
+ const keys = [];
18243
+ let buffer = '';
18244
+ const flushBuffer = () => {
18245
+ if (buffer) {
18246
+ keys.push(normalizeKey(buffer));
18247
+ buffer = '';
18248
+ }
18249
+ };
18250
+ for (let i = 0; i < combination.length; i++) {
18251
+ const char = combination[i];
18252
+ const nextChar = combination[i + 1];
18253
+ if (char === '+' || char === '_' || char === '-') {
18254
+ if (char === nextChar) {
18255
+ flushBuffer();
18256
+ keys.push(char);
18257
+ i++;
18258
+ } else if (char === '+' || char === '_') {
18259
+ flushBuffer();
18260
+ } else {
18261
+ buffer += char;
18262
+ }
18263
+ } else {
18264
+ buffer += char;
18265
+ }
18266
+ }
18267
+ flushBuffer();
18268
+
18269
+ // Within a combination, `-` is only valid as a literal key (e.g., `ctrl+-`).
18270
+ // `-` cannot be part of a longer key name within a combination.
18271
+ const hasInvalidMinus = keys.some(key => key.length > 1 && key.includes('-') && key !== '--');
18272
+ if (hasInvalidMinus) {
18273
+ if (!isInternal) consoleWarn(`Invalid hotkey combination: "${combination}" has invalid structure`);
18274
+ return [];
18275
+ }
18276
+ if (keys.length === 0 && combination) {
18277
+ return [normalizeKey(combination)];
18278
+ }
18279
+ return keys;
18280
+ }
18281
+
18282
+ /**
18283
+ * Splits a hotkey string into its constituent combination groups.
18284
+ *
18285
+ * A sequence is a series of combinations that must be pressed in order.
18286
+ * e.g. `a-b`, `ctrl+k-p`
18287
+ */
18288
+ function splitKeySequence(str) {
18289
+ if (!str) {
18290
+ consoleWarn('Invalid hotkey sequence: empty string provided');
18291
+ return [];
18292
+ }
18293
+
18294
+ // A sequence is invalid if it starts or ends with a separator,
18295
+ // unless it is part of a combination (e.g., `shift+-`).
18296
+ const hasInvalidStart = str.startsWith('-') && !['---', '--+'].includes(str);
18297
+ const hasInvalidEnd = str.endsWith('-') && !str.endsWith('+-') && !str.endsWith('_-') && str !== '-' && str !== '---';
18298
+ if (hasInvalidStart || hasInvalidEnd) {
18299
+ consoleWarn(`Invalid hotkey sequence: "${str}" contains invalid combinations`);
18300
+ return [];
18301
+ }
18302
+ const result = [];
18303
+ let buffer = '';
18304
+ let i = 0;
18305
+ while (i < str.length) {
18306
+ const char = str[i];
18307
+ if (char === '-') {
18308
+ // Determine if this hyphen is part of the current combination
18309
+ const prevChar = str[i - 1];
18310
+ const prevPrevChar = i > 1 ? str[i - 2] : undefined;
18311
+ const precededBySinglePlusOrUnderscore = (prevChar === '+' || prevChar === '_') && prevPrevChar !== '+';
18312
+ if (precededBySinglePlusOrUnderscore) {
18313
+ // Treat as part of the combination (e.g., 'ctrl+-')
18314
+ buffer += char;
18315
+ i++;
18316
+ } else {
18317
+ // Treat as sequence separator
18318
+ if (buffer) {
18319
+ result.push(buffer);
18320
+ buffer = '';
18321
+ } else {
18322
+ // Empty buffer means we have a literal '-' key
18323
+ result.push('-');
18324
+ }
18325
+ i++;
18326
+ }
18327
+ } else {
18328
+ buffer += char;
18329
+ i++;
18330
+ }
18331
+ }
18332
+
18333
+ // Add final buffer if it exists
18334
+ if (buffer) {
18335
+ result.push(buffer);
18336
+ }
18337
+
18338
+ // Collapse runs of '-' so that every second '-' is removed
18339
+ const collapsed = [];
18340
+ let minusCount = 0;
18341
+ for (const part of result) {
18342
+ if (part === '-') {
18343
+ if (minusCount % 2 === 0) collapsed.push('-');
18344
+ minusCount++;
18345
+ } else {
18346
+ minusCount = 0;
18347
+ collapsed.push(part);
18348
+ }
18349
+ }
18350
+
18351
+ // Validate that each part of the sequence is a valid combination
18352
+ const areAllValid = collapsed.every(s => splitKeyCombination(s, true).length > 0);
18353
+ if (!areAllValid) {
18354
+ consoleWarn(`Invalid hotkey sequence: "${str}" contains invalid combinations`);
18355
+ return [];
18356
+ }
18357
+ return collapsed;
18358
+ }
18359
+
18360
+ // Composables
18361
+
18362
+ // Types
18363
+
18364
+ function useHotkey(keys, callback) {
18365
+ let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
18366
+ if (!IN_BROWSER) return function () {};
18367
+ const {
18368
+ event = 'keydown',
18369
+ inputs = false,
18370
+ preventDefault = true,
18371
+ sequenceTimeout = 1000
18372
+ } = options;
18373
+ const isMac = navigator?.userAgent?.includes('Macintosh') ?? false;
18374
+ let timeout = 0;
18375
+ let keyGroups;
18376
+ let isSequence = false;
18377
+ let groupIndex = 0;
18378
+ function clearTimer() {
18379
+ if (!timeout) return;
18380
+ clearTimeout(timeout);
18381
+ timeout = 0;
18382
+ }
18383
+ function isInputFocused() {
18384
+ if (vue.toValue(inputs)) return false;
18385
+ const activeElement = document.activeElement;
18386
+ return activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA' || activeElement.isContentEditable || activeElement.contentEditable === 'true');
18387
+ }
18388
+ function resetSequence() {
18389
+ groupIndex = 0;
18390
+ clearTimer();
18391
+ }
18392
+ function handler(e) {
18393
+ const group = keyGroups[groupIndex];
18394
+ if (!group || isInputFocused()) return;
18395
+ if (!matchesKeyGroup(e, group)) {
18396
+ if (isSequence) resetSequence();
18397
+ return;
18398
+ }
18399
+ if (vue.toValue(preventDefault)) e.preventDefault();
18400
+ if (!isSequence) {
18401
+ callback(e);
18402
+ return;
18403
+ }
18404
+ clearTimer();
18405
+ groupIndex++;
18406
+ if (groupIndex === keyGroups.length) {
18407
+ callback(e);
18408
+ resetSequence();
18409
+ return;
18410
+ }
18411
+ timeout = window.setTimeout(resetSequence, vue.toValue(sequenceTimeout));
18412
+ }
18413
+ function cleanup() {
18414
+ window.removeEventListener(vue.toValue(event), handler);
18415
+ clearTimer();
18416
+ }
18417
+ vue.watch(() => vue.toValue(keys), function (unrefKeys) {
18418
+ cleanup();
18419
+ if (unrefKeys) {
18420
+ const groups = splitKeySequence(unrefKeys.toLowerCase());
18421
+ isSequence = groups.length > 1;
18422
+ keyGroups = groups;
18423
+ resetSequence();
18424
+ window.addEventListener(vue.toValue(event), handler);
18425
+ }
18426
+ }, {
18427
+ immediate: true
18428
+ });
18429
+
18430
+ // Watch for changes in the event type to re-register the listener
18431
+ vue.watch(() => vue.toValue(event), function (newEvent, oldEvent) {
18432
+ if (oldEvent && keyGroups && keyGroups.length > 0) {
18433
+ window.removeEventListener(oldEvent, handler);
18434
+ window.addEventListener(newEvent, handler);
18435
+ }
18436
+ });
18437
+ try {
18438
+ getCurrentInstance('useHotkey');
18439
+ vue.onBeforeUnmount(cleanup);
18440
+ } catch {
18441
+ // Not in Vue setup context
18442
+ }
18443
+ function parseKeyGroup(group) {
18444
+ const MODIFIERS = ['ctrl', 'shift', 'alt', 'meta', 'cmd'];
18445
+
18446
+ // Use the shared combination splitting logic
18447
+ const parts = splitKeyCombination(group.toLowerCase());
18448
+
18449
+ // If the combination is invalid, return empty result
18450
+ if (parts.length === 0) {
18451
+ return {
18452
+ modifiers: Object.fromEntries(MODIFIERS.map(m => [m, false])),
18453
+ actualKey: undefined
18454
+ };
18455
+ }
18456
+ const modifiers = Object.fromEntries(MODIFIERS.map(m => [m, false]));
18457
+ let actualKey;
18458
+ for (const part of parts) {
18459
+ if (MODIFIERS.includes(part)) {
18460
+ modifiers[part] = true;
18461
+ } else {
18462
+ actualKey = part;
18463
+ }
18464
+ }
18465
+ return {
18466
+ modifiers,
18467
+ actualKey
18468
+ };
18469
+ }
18470
+ function matchesKeyGroup(e, group) {
18471
+ const {
18472
+ modifiers,
18473
+ actualKey
18474
+ } = parseKeyGroup(group);
18475
+ const expectCtrl = modifiers.ctrl || !isMac && (modifiers.cmd || modifiers.meta);
18476
+ const expectMeta = isMac && (modifiers.cmd || modifiers.meta);
18477
+ return e.ctrlKey === expectCtrl && e.metaKey === expectMeta && e.shiftKey === modifiers.shift && e.altKey === modifiers.alt && e.key.toLowerCase() === actualKey?.toLowerCase();
18478
+ }
18479
+ return cleanup;
18480
+ }
18481
+
18087
18482
  // Types
18088
18483
 
18089
18484
  const makeVColorPickerProps = propsFactory({
@@ -18630,7 +19025,7 @@
18630
19025
  active: highlightFirst.value && index === 0 ? true : undefined,
18631
19026
  onClick: () => select(item, null)
18632
19027
  });
18633
- if (item.raw.type === 'divider') {
19028
+ if (item.type === 'divider') {
18634
19029
  return slots.divider?.({
18635
19030
  props: item.raw,
18636
19031
  index
@@ -18638,7 +19033,7 @@
18638
19033
  "key": `divider-${index}`
18639
19034
  }), null);
18640
19035
  }
18641
- if (item.raw.type === 'subheader') {
19036
+ if (item.type === 'subheader') {
18642
19037
  return slots.subheader?.({
18643
19038
  props: item.raw,
18644
19039
  index
@@ -19512,7 +19907,8 @@
19512
19907
 
19513
19908
  // Dates should be compared numerically
19514
19909
  if (sortA instanceof Date && sortB instanceof Date) {
19515
- return sortA.getTime() - sortB.getTime();
19910
+ sortA = sortA.getTime();
19911
+ sortB = sortB.getTime();
19516
19912
  }
19517
19913
  [sortA, sortB] = [sortA, sortB].map(s => s != null ? s.toString().toLocaleLowerCase() : s);
19518
19914
  if (sortA !== sortB) {
@@ -20221,10 +20617,15 @@
20221
20617
  type: String,
20222
20618
  default: 'start'
20223
20619
  },
20224
- fixed: Boolean,
20620
+ fixed: {
20621
+ type: [Boolean, String],
20622
+ default: false
20623
+ },
20225
20624
  fixedOffset: [Number, String],
20625
+ fixedEndOffset: [Number, String],
20226
20626
  height: [Number, String],
20227
20627
  lastFixed: Boolean,
20628
+ firstFixedEnd: Boolean,
20228
20629
  noPadding: Boolean,
20229
20630
  tag: String,
20230
20631
  width: [Number, String],
@@ -20235,11 +20636,13 @@
20235
20636
  slots
20236
20637
  } = _ref;
20237
20638
  const Tag = props.tag ?? 'td';
20639
+ const fixedSide = typeof props.fixed === 'string' ? props.fixed : props.fixed ? 'start' : 'none';
20238
20640
  return vue.createVNode(Tag, {
20239
- "tabindex": "0",
20240
20641
  "class": vue.normalizeClass(['v-data-table__td', {
20241
- 'v-data-table-column--fixed': props.fixed,
20642
+ 'v-data-table-column--fixed': fixedSide === 'start',
20643
+ 'v-data-table-column--fixed-end': fixedSide === 'end',
20242
20644
  'v-data-table-column--last-fixed': props.lastFixed,
20645
+ 'v-data-table-column--first-fixed-end': props.firstFixedEnd,
20243
20646
  'v-data-table-column--no-padding': props.noPadding,
20244
20647
  'v-data-table-column--nowrap': props.nowrap
20245
20648
  }, `v-data-table-column--align-${props.align}`]),
@@ -20247,7 +20650,8 @@
20247
20650
  height: convertToUnit(props.height),
20248
20651
  width: convertToUnit(props.width),
20249
20652
  maxWidth: convertToUnit(props.maxWidth),
20250
- left: convertToUnit(props.fixedOffset || null)
20653
+ left: fixedSide === 'start' ? convertToUnit(props.fixedOffset || null) : undefined,
20654
+ right: fixedSide === 'end' ? convertToUnit(props.fixedEndOffset || null) : undefined
20251
20655
  }
20252
20656
  }, {
20253
20657
  default: () => [slots.default?.()]
@@ -20344,20 +20748,28 @@
20344
20748
  }
20345
20749
  function parseFixedColumns(items) {
20346
20750
  let seenFixed = false;
20347
- function setFixed(item) {
20348
- let parentFixed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
20751
+ function setFixed(item, side) {
20752
+ let parentFixedSide = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'none';
20349
20753
  if (!item) return;
20350
- if (parentFixed) {
20351
- item.fixed = true;
20754
+ if (parentFixedSide !== 'none') {
20755
+ item.fixed = parentFixedSide;
20352
20756
  }
20353
- if (item.fixed) {
20354
- if (item.children) {
20355
- for (let i = item.children.length - 1; i >= 0; i--) {
20356
- setFixed(item.children[i], true);
20757
+
20758
+ // normalize to simplify logic below
20759
+ if (item.fixed === true) {
20760
+ item.fixed = 'start';
20761
+ }
20762
+ const orderedChildren = side === 'start' ? item.children?.toReversed() : item.children;
20763
+ if (item.fixed === side) {
20764
+ if (orderedChildren) {
20765
+ for (const child of orderedChildren) {
20766
+ setFixed(child, side, side);
20357
20767
  }
20358
20768
  } else {
20359
- if (!seenFixed) {
20769
+ if (!seenFixed && side === 'start') {
20360
20770
  item.lastFixed = true;
20771
+ } else if (!seenFixed && side === 'end') {
20772
+ item.firstFixedEnd = true;
20361
20773
  } else if (isNaN(Number(item.width))) {
20362
20774
  consoleError(`Multiple fixed columns should have a static width (key: ${item.key})`);
20363
20775
  } else {
@@ -20366,36 +20778,57 @@
20366
20778
  seenFixed = true;
20367
20779
  }
20368
20780
  } else {
20369
- if (item.children) {
20370
- for (let i = item.children.length - 1; i >= 0; i--) {
20371
- setFixed(item.children[i]);
20781
+ if (orderedChildren) {
20782
+ for (const child of orderedChildren) {
20783
+ setFixed(child, side);
20372
20784
  }
20373
20785
  } else {
20374
20786
  seenFixed = false;
20375
20787
  }
20376
20788
  }
20377
20789
  }
20378
- for (let i = items.length - 1; i >= 0; i--) {
20379
- setFixed(items[i]);
20790
+ for (const item of items.toReversed()) {
20791
+ setFixed(item, 'start');
20792
+ }
20793
+ for (const item of items) {
20794
+ setFixed(item, 'end');
20380
20795
  }
20381
20796
  function setFixedOffset(item) {
20382
- let fixedOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
20383
- if (!item) return fixedOffset;
20797
+ let offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
20798
+ if (!item) return offset;
20384
20799
  if (item.children) {
20385
- item.fixedOffset = fixedOffset;
20800
+ item.fixedOffset = offset;
20386
20801
  for (const child of item.children) {
20387
- fixedOffset = setFixedOffset(child, fixedOffset);
20802
+ offset = setFixedOffset(child, offset);
20388
20803
  }
20389
- } else if (item.fixed) {
20390
- item.fixedOffset = fixedOffset;
20391
- fixedOffset += parseFloat(item.width || '0') || 0;
20804
+ } else if (item.fixed && item.fixed !== 'end') {
20805
+ item.fixedOffset = offset;
20806
+ offset += parseFloat(item.width || '0') || 0;
20392
20807
  }
20393
- return fixedOffset;
20808
+ return offset;
20394
20809
  }
20395
20810
  let fixedOffset = 0;
20396
20811
  for (const item of items) {
20397
20812
  fixedOffset = setFixedOffset(item, fixedOffset);
20398
20813
  }
20814
+ function setFixedEndOffset(item) {
20815
+ let offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
20816
+ if (!item) return offset;
20817
+ if (item.children) {
20818
+ item.fixedEndOffset = offset;
20819
+ for (const child of item.children) {
20820
+ offset = setFixedEndOffset(child, offset);
20821
+ }
20822
+ } else if (item.fixed === 'end') {
20823
+ item.fixedEndOffset = offset;
20824
+ offset += parseFloat(item.width || '0') || 0;
20825
+ }
20826
+ return offset;
20827
+ }
20828
+ let fixedEndOffset = 0;
20829
+ for (const item of items.toReversed()) {
20830
+ fixedEndOffset = setFixedEndOffset(item, fixedEndOffset);
20831
+ }
20399
20832
  }
20400
20833
  function parse(items, maxDepth) {
20401
20834
  const headers = [];
@@ -20528,7 +20961,6 @@
20528
20961
  color: String,
20529
20962
  disableSort: Boolean,
20530
20963
  fixedHeader: Boolean,
20531
- lastFixed: Boolean,
20532
20964
  multiSort: Boolean,
20533
20965
  sortAscIcon: {
20534
20966
  type: IconValue,
@@ -20575,11 +21007,12 @@
20575
21007
  loaderClasses
20576
21008
  } = useLoader(props);
20577
21009
  function getFixedStyles(column, y) {
20578
- if (!(props.sticky || props.fixedHeader) && !(column.fixed || column.lastFixed)) return undefined;
21010
+ if (!(props.sticky || props.fixedHeader) && !column.fixed) return undefined;
21011
+ const fixedSide = typeof column.fixed === 'string' ? column.fixed : column.fixed ? 'start' : 'none';
20579
21012
  return {
20580
21013
  position: 'sticky',
20581
- left: column.fixed || column.lastFixed ? convertToUnit(column.fixedOffset) : undefined,
20582
- right: column.lastFixed ? convertToUnit(column.fixedOffset ?? 0) : undefined,
21014
+ left: fixedSide === 'start' ? convertToUnit(column.fixedOffset) : undefined,
21015
+ right: fixedSide === 'end' ? convertToUnit(column.fixedEndOffset) : undefined,
20583
21016
  top: props.sticky || props.fixedHeader ? `calc(var(--v-table-header-height) * ${y})` : undefined
20584
21017
  };
20585
21018
  }
@@ -20639,14 +21072,15 @@
20639
21072
  },
20640
21073
  "colspan": column.colspan,
20641
21074
  "rowspan": column.rowspan,
20642
- "onClick": column.sortable ? () => toggleSort(column) : undefined,
20643
21075
  "fixed": column.fixed,
20644
21076
  "nowrap": column.nowrap,
20645
21077
  "lastFixed": column.lastFixed,
20646
- "noPadding": noPadding
20647
- }, headerProps, {
20648
- "onKeydown": event => column.sortable && handleEnterKeyPress(event, column)
20649
- }), {
21078
+ "firstFixedEnd": column.firstFixedEnd,
21079
+ "noPadding": noPadding,
21080
+ "tabindex": column.sortable ? 0 : undefined,
21081
+ "onClick": column.sortable ? () => toggleSort(column) : undefined,
21082
+ "onKeydown": column.sortable ? event => handleEnterKeyPress(event, column) : undefined
21083
+ }, headerProps), {
20650
21084
  default: () => {
20651
21085
  const columnSlotName = `header.${column.key}`;
20652
21086
  const columnSlotProps = {
@@ -20922,7 +21356,9 @@
20922
21356
  },
20923
21357
  "fixed": column.fixed,
20924
21358
  "fixedOffset": column.fixedOffset,
21359
+ "fixedEndOffset": column.fixedEndOffset,
20925
21360
  "lastFixed": column.lastFixed,
21361
+ "firstFixedEnd": column.firstFixedEnd,
20926
21362
  "maxWidth": !mobile.value ? column.maxWidth : undefined,
20927
21363
  "noPadding": column.key === 'data-table-select' || column.key === 'data-table-expand',
20928
21364
  "nowrap": column.nowrap,
@@ -22332,10 +22768,9 @@
22332
22768
  const date = adapter.setYear(adapter.startOfMonth(adapter.date()), adapter.getYear(year.value));
22333
22769
  return adapter.setMonth(date, value);
22334
22770
  }, v => adapter.getMonth(v));
22335
- const weekDays = vue.computed(() => {
22771
+ const weekdayLabels = vue.computed(() => {
22336
22772
  const firstDayOfWeek = adapter.toJsDate(adapter.startOfWeek(adapter.date(), props.firstDayOfWeek)).getDay();
22337
- // Always generate all days, regardless of props.weekdays
22338
- return [0, 1, 2, 3, 4, 5, 6].map(day => (day + firstDayOfWeek) % 7);
22773
+ return adapter.getWeekdays(props.firstDayOfWeek, props.weekdayFormat).filter((_, i) => props.weekdays.includes((i + firstDayOfWeek) % 7));
22339
22774
  });
22340
22775
  const weeksInMonth = vue.computed(() => {
22341
22776
  const weeks = adapter.getWeekArray(month.value, props.firstDayOfWeek);
@@ -22359,13 +22794,14 @@
22359
22794
  });
22360
22795
  function genDays(days, today) {
22361
22796
  return days.filter(date => {
22362
- return weekDays.value.includes(adapter.toJsDate(date).getDay());
22797
+ return props.weekdays.includes(adapter.toJsDate(date).getDay());
22363
22798
  }).map((date, index) => {
22364
22799
  const isoDate = adapter.toISO(date);
22365
22800
  const isAdjacent = !adapter.isSameMonth(date, month.value);
22366
22801
  const isStart = adapter.isSameDay(date, adapter.startOfMonth(month.value));
22367
22802
  const isEnd = adapter.isSameDay(date, adapter.endOfMonth(month.value));
22368
22803
  const isSame = adapter.isSameDay(date, month.value);
22804
+ const weekdaysCount = props.weekdays.length;
22369
22805
  return {
22370
22806
  date,
22371
22807
  formatted: adapter.format(date, 'keyboardDate'),
@@ -22377,8 +22813,8 @@
22377
22813
  isSelected: model.value.some(value => adapter.isSameDay(date, value)),
22378
22814
  isStart,
22379
22815
  isToday: adapter.isSameDay(date, today),
22380
- isWeekEnd: index % 7 === 6,
22381
- isWeekStart: index % 7 === 0,
22816
+ isWeekEnd: index % weekdaysCount === weekdaysCount - 1,
22817
+ isWeekStart: index % weekdaysCount === 0,
22382
22818
  isoDate,
22383
22819
  localized: adapter.format(date, 'dayOfMonth'),
22384
22820
  month: adapter.getMonth(date),
@@ -22416,7 +22852,7 @@
22416
22852
  if (typeof props.allowedDates === 'function') {
22417
22853
  return !props.allowedDates(date);
22418
22854
  }
22419
- return !props.weekdays.includes(adapter.toJsDate(date).getDay());
22855
+ return false;
22420
22856
  }
22421
22857
  return {
22422
22858
  displayValue,
@@ -22425,7 +22861,7 @@
22425
22861
  genDays,
22426
22862
  model,
22427
22863
  weeksInMonth,
22428
- weekDays,
22864
+ weekdayLabels,
22429
22865
  weekNumbers
22430
22866
  };
22431
22867
  }
@@ -22464,7 +22900,8 @@
22464
22900
  const {
22465
22901
  daysInMonth,
22466
22902
  model,
22467
- weekNumbers
22903
+ weekNumbers,
22904
+ weekdayLabels
22468
22905
  } = useCalendar(props);
22469
22906
  const adapter = useDate();
22470
22907
  const rangeStart = vue.shallowRef();
@@ -22536,7 +22973,10 @@
22536
22973
  }
22537
22974
  }
22538
22975
  useRender(() => vue.createElementVNode("div", {
22539
- "class": "v-date-picker-month"
22976
+ "class": "v-date-picker-month",
22977
+ "style": {
22978
+ '--v-date-picker-days-in-week': props.weekdays.length
22979
+ }
22540
22980
  }, [props.showWeek && vue.createElementVNode("div", {
22541
22981
  "key": "weeks",
22542
22982
  "class": "v-date-picker-month__weeks"
@@ -22552,7 +22992,7 @@
22552
22992
  "ref": daysRef,
22553
22993
  "key": daysInMonth.value[0].date?.toString(),
22554
22994
  "class": "v-date-picker-month__days"
22555
- }, [!props.hideWeekdays && adapter.getWeekdays(props.firstDayOfWeek, props.weekdayFormat).map(weekDay => vue.createElementVNode("div", {
22995
+ }, [!props.hideWeekdays && weekdayLabels.value.map(weekDay => vue.createElementVNode("div", {
22556
22996
  "class": vue.normalizeClass(['v-date-picker-month__day', 'v-date-picker-month__weekday'])
22557
22997
  }, [weekDay])), daysInMonth.value.map((item, i) => {
22558
22998
  const slotProps = {
@@ -22935,7 +23375,8 @@
22935
23375
  }
22936
23376
  function allowedMonths(month) {
22937
23377
  if (typeof props.allowedDates === 'function') {
22938
- const startOfMonth = adapter.parseISO(`${year.value}-${month + 1}-01`);
23378
+ const monthTwoDigits = String(month + 1).padStart(2, '0');
23379
+ const startOfMonth = adapter.parseISO(`${year.value}-${monthTwoDigits}-01`);
22939
23380
  return isAllowedInRange(startOfMonth, adapter.endOfMonth(startOfMonth));
22940
23381
  }
22941
23382
  if (Array.isArray(props.allowedDates) && props.allowedDates.length) {
@@ -25232,6 +25673,8 @@
25232
25673
  function holdStart(value) {
25233
25674
  holdStop();
25234
25675
  tick(value);
25676
+ window.addEventListener('pointerup', holdStop);
25677
+ document.addEventListener('blur', holdStop);
25235
25678
  timeout = window.setTimeout(() => {
25236
25679
  interval = window.setInterval(() => tick(value), HOLD_REPEAT);
25237
25680
  }, HOLD_DELAY);
@@ -25239,6 +25682,8 @@
25239
25682
  function holdStop() {
25240
25683
  window.clearTimeout(timeout);
25241
25684
  window.clearInterval(interval);
25685
+ window.removeEventListener('pointerup', holdStop);
25686
+ document.removeEventListener('blur', holdStop);
25242
25687
  }
25243
25688
  function tick(value) {
25244
25689
  toggleUpDown(value === 'up');
@@ -25374,7 +25819,7 @@
25374
25819
  onClick: onControlClick,
25375
25820
  onPointerup: onControlMouseup,
25376
25821
  onPointerdown: onUpControlMousedown,
25377
- onPointercancel: onControlPointerCancel
25822
+ onPointercancel: onControlMouseup
25378
25823
  }
25379
25824
  };
25380
25825
  const decrementSlotProps = {
@@ -25382,7 +25827,7 @@
25382
25827
  onClick: onControlClick,
25383
25828
  onPointerup: onControlMouseup,
25384
25829
  onPointerdown: onDownControlMousedown,
25385
- onPointercancel: onControlPointerCancel
25830
+ onPointercancel: onControlMouseup
25386
25831
  }
25387
25832
  };
25388
25833
  vue.watch(() => props.precision, () => formatInputValue());
@@ -25463,7 +25908,6 @@
25463
25908
  const el = e.currentTarget;
25464
25909
  el?.releasePointerCapture(e.pointerId);
25465
25910
  e.preventDefault();
25466
- e.stopPropagation();
25467
25911
  holdStop();
25468
25912
  }
25469
25913
  function onUpControlMousedown(e) {
@@ -25480,11 +25924,6 @@
25480
25924
  e.stopPropagation();
25481
25925
  holdStart('down');
25482
25926
  }
25483
- function onControlPointerCancel(e) {
25484
- const el = e.currentTarget;
25485
- el?.releasePointerCapture(e.pointerId);
25486
- holdStop();
25487
- }
25488
25927
  function clampModel() {
25489
25928
  if (controlsDisabled.value) return;
25490
25929
  if (!vTextFieldRef.value) return;
@@ -25531,7 +25970,7 @@
25531
25970
  "onClick": onControlClick,
25532
25971
  "onPointerdown": onUpControlMousedown,
25533
25972
  "onPointerup": onControlMouseup,
25534
- "onPointercancel": onControlPointerCancel,
25973
+ "onPointercancel": onControlMouseup,
25535
25974
  "size": controlNodeSize.value,
25536
25975
  "tabindex": "-1"
25537
25976
  }, null) : vue.createVNode(VDefaultsProvider, {
@@ -25561,7 +26000,7 @@
25561
26000
  "onClick": onControlClick,
25562
26001
  "onPointerdown": onDownControlMousedown,
25563
26002
  "onPointerup": onControlMouseup,
25564
- "onPointercancel": onControlPointerCancel,
26003
+ "onPointercancel": onControlMouseup,
25565
26004
  "size": controlNodeSize.value,
25566
26005
  "tabindex": "-1"
25567
26006
  }, null) : vue.createVNode(VDefaultsProvider, {
@@ -25708,19 +26147,21 @@
25708
26147
  const contentRef = vue.ref();
25709
26148
  const inputRef = vue.ref([]);
25710
26149
  const current = vue.computed(() => inputRef.value[focusIndex.value]);
25711
- const intersectScope = vue.effectScope();
25712
- intersectScope.run(() => {
25713
- const {
25714
- intersectionRef,
25715
- isIntersecting
25716
- } = useIntersectionObserver();
25717
- vue.watch(isIntersecting, v => {
25718
- if (!v) return;
25719
- intersectionRef.value?.focus();
25720
- intersectScope.stop();
25721
- });
25722
- vue.watchEffect(() => {
25723
- intersectionRef.value = inputRef.value[0];
26150
+ useToggleScope(() => props.autofocus, () => {
26151
+ const intersectScope = vue.effectScope();
26152
+ intersectScope.run(() => {
26153
+ const {
26154
+ intersectionRef,
26155
+ isIntersecting
26156
+ } = useIntersectionObserver();
26157
+ vue.watchEffect(() => {
26158
+ intersectionRef.value = inputRef.value[0];
26159
+ });
26160
+ vue.watch(isIntersecting, v => {
26161
+ if (!v) return;
26162
+ intersectionRef.value?.focus();
26163
+ intersectScope.stop();
26164
+ });
25724
26165
  });
25725
26166
  });
25726
26167
  function onInput() {
@@ -29731,6 +30172,8 @@
29731
30172
 
29732
30173
  const makeVTreeviewItemProps = propsFactory({
29733
30174
  loading: Boolean,
30175
+ hideActions: Boolean,
30176
+ indentLines: Array,
29734
30177
  toggleIcon: IconValue,
29735
30178
  ...makeVListItemProps({
29736
30179
  slim: true
@@ -29766,23 +30209,31 @@
29766
30209
  emit('toggleExpand', e);
29767
30210
  }
29768
30211
  useRender(() => {
29769
- const listItemProps = omit(VListItem.filterProps(props), ['onClick']);
29770
- const hasPrepend = slots.prepend || props.toggleIcon;
30212
+ const listItemProps = VListItem.filterProps(props);
30213
+ const hasPrepend = slots.prepend || props.toggleIcon || props.indentLines;
29771
30214
  return vue.createVNode(VListItem, vue.mergeProps({
29772
30215
  "ref": vListItemRef
29773
30216
  }, listItemProps, {
29774
- "active": vListItemRef.value?.isActivated,
30217
+ "active": vListItemRef.value?.isActivated || undefined,
29775
30218
  "class": ['v-treeview-item', {
29776
30219
  'v-treeview-item--activatable-group-activator': isActivatableGroupActivator.value,
29777
30220
  'v-treeview-item--filtered': isFiltered.value
29778
30221
  }, props.class],
29779
30222
  "ripple": false,
29780
- "onClick": props.onClick ?? activateGroupActivator
30223
+ "onClick": activateGroupActivator
29781
30224
  }), {
29782
30225
  ...slots,
29783
30226
  prepend: hasPrepend ? slotProps => {
29784
- return vue.createElementVNode(vue.Fragment, null, [vue.createVNode(VListItemAction, {
29785
- "start": false
30227
+ return vue.createElementVNode(vue.Fragment, null, [props.indentLines && props.indentLines.length > 0 ? vue.createElementVNode("div", {
30228
+ "key": "indent-lines",
30229
+ "class": "v-treeview-indent-lines",
30230
+ "style": {
30231
+ '--v-indent-parts': props.indentLines.length
30232
+ }
30233
+ }, [props.indentLines.map(type => vue.createElementVNode("div", {
30234
+ "class": vue.normalizeClass(`v-treeview-indent-line v-treeview-indent-line--${type}`)
30235
+ }, null))]) : '', !props.hideActions && vue.createVNode(VListItemAction, {
30236
+ "start": true
29786
30237
  }, {
29787
30238
  default: () => [props.toggleIcon ? vue.createVNode(VBtn, {
29788
30239
  "density": "compact",
@@ -29791,13 +30242,11 @@
29791
30242
  "variant": "text",
29792
30243
  "onClick": onClickAction
29793
30244
  }, {
29794
- loader() {
29795
- return vue.createVNode(VProgressCircular, {
29796
- "indeterminate": "disable-shrink",
29797
- "size": "20",
29798
- "width": "2"
29799
- }, null);
29800
- }
30245
+ loader: () => vue.createVNode(VProgressCircular, {
30246
+ "indeterminate": "disable-shrink",
30247
+ "size": "20",
30248
+ "width": "2"
30249
+ }, null)
29801
30250
  }) : vue.createElementVNode("div", {
29802
30251
  "class": "v-treeview-item__level"
29803
30252
  }, null)]
@@ -29805,7 +30254,7 @@
29805
30254
  } : undefined
29806
30255
  });
29807
30256
  });
29808
- return {};
30257
+ return forwardRefs({}, vListItemRef);
29809
30258
  }
29810
30259
  });
29811
30260
 
@@ -29830,14 +30279,20 @@
29830
30279
  falseIcon: IconValue,
29831
30280
  trueIcon: IconValue,
29832
30281
  returnObject: Boolean,
30282
+ activatable: Boolean,
29833
30283
  selectable: Boolean,
29834
30284
  selectedColor: String,
29835
30285
  selectStrategy: [String, Function, Object],
29836
30286
  index: Number,
30287
+ isLastGroup: Boolean,
30288
+ separateRoots: Boolean,
30289
+ parentIndentLines: Array,
30290
+ indentLinesVariant: String,
29837
30291
  path: {
29838
30292
  type: Array,
29839
30293
  default: () => []
29840
30294
  },
30295
+ ...pick(makeVTreeviewItemProps(), ['hideActions']),
29841
30296
  ...makeDensityProps()
29842
30297
  }, 'VTreeviewChildren');
29843
30298
  const VTreeviewChildren = genericComponent()({
@@ -29848,7 +30303,8 @@
29848
30303
  slots
29849
30304
  } = _ref;
29850
30305
  const isLoading = vue.reactive(new Set());
29851
- const isClickOnOpen = vue.computed(() => !props.disabled && (props.openOnClick != null ? props.openOnClick : props.selectable));
30306
+ const activatorItems = vue.ref([]);
30307
+ const isClickOnOpen = vue.computed(() => !props.disabled && (props.openOnClick != null ? props.openOnClick : props.selectable && !props.activatable));
29852
30308
  async function checkChildren(item) {
29853
30309
  try {
29854
30310
  if (!props.items?.length || !props.loadChildren) return;
@@ -29862,22 +30318,35 @@
29862
30318
  }
29863
30319
  function selectItem(select, isSelected) {
29864
30320
  if (props.selectable) {
29865
- select(!isSelected);
30321
+ select(isSelected);
29866
30322
  }
29867
30323
  }
29868
- return () => slots.default?.() ?? props.items?.map((item, index) => {
30324
+ return () => slots.default?.() ?? props.items?.map((item, index, items) => {
29869
30325
  const {
29870
30326
  children,
29871
30327
  props: itemProps
29872
30328
  } = item;
29873
30329
  const loading = isLoading.has(item.value);
30330
+ const nextItemHasChildren = !!items.at(index + 1)?.children;
30331
+ const depth = props.path?.length ?? 0;
30332
+ const isLast = items.length - 1 === index;
29874
30333
  const treeItemProps = {
29875
30334
  index,
29876
- depth: props.path?.length ?? 0,
30335
+ depth,
29877
30336
  isFirst: index === 0,
29878
- isLast: props.items ? props.items.length - 1 === index : false,
29879
- path: [...props.path, index]
30337
+ isLast,
30338
+ path: [...props.path, index],
30339
+ hideAction: props.hideActions
29880
30340
  };
30341
+ const indentLines = getIndentLines({
30342
+ depth,
30343
+ isLast,
30344
+ isLastGroup: props.isLastGroup,
30345
+ leafLinks: !props.hideActions,
30346
+ separateRoots: props.separateRoots,
30347
+ parentIndentLines: props.parentIndentLines,
30348
+ variant: props.indentLinesVariant
30349
+ });
29881
30350
  const slotsWithItem = {
29882
30351
  prepend: slotProps => vue.createElementVNode(vue.Fragment, null, [props.selectable && (!children || children && !['leaf', 'single-leaf'].includes(props.selectStrategy)) && vue.createElementVNode("div", null, [vue.createVNode(VCheckboxBtn, {
29883
30352
  "key": item.value,
@@ -29890,7 +30359,8 @@
29890
30359
  "indeterminateIcon": props.indeterminateIcon,
29891
30360
  "falseIcon": props.falseIcon,
29892
30361
  "trueIcon": props.trueIcon,
29893
- "onClick": vue.withModifiers(() => selectItem(slotProps.select, slotProps.isSelected), ['stop']),
30362
+ "onUpdate:modelValue": v => selectItem(slotProps.select, v),
30363
+ "onClick": e => e.stopPropagation(),
29894
30364
  "onKeydown": e => {
29895
30365
  if (!['Enter', 'Space'].includes(e.key)) return;
29896
30366
  e.stopPropagation();
@@ -29937,24 +30407,45 @@
29937
30407
  ...activatorProps,
29938
30408
  value: itemProps?.value,
29939
30409
  onToggleExpand: [() => checkChildren(item), activatorProps.onClick],
29940
- onClick: isClickOnOpen.value ? [() => checkChildren(item), activatorProps.onClick] : undefined
30410
+ onClick: isClickOnOpen.value ? [() => checkChildren(item), activatorProps.onClick] : () => selectItem(activatorItems.value[index]?.select, !activatorItems.value[index]?.isSelected)
29941
30411
  };
29942
- return vue.createVNode(VTreeviewItem, vue.mergeProps(listItemProps, {
30412
+ return vue.createVNode(VTreeviewItem, vue.mergeProps({
30413
+ "ref": el => activatorItems.value[index] = el
30414
+ }, listItemProps, {
30415
+ "hideActions": props.hideActions,
30416
+ "indentLines": indentLines.node,
29943
30417
  "value": props.returnObject ? item.raw : itemProps.value,
29944
30418
  "loading": loading
29945
30419
  }), slotsWithItem);
29946
30420
  },
29947
30421
  default: () => vue.createVNode(VTreeviewChildren, vue.mergeProps(treeviewChildrenProps, {
29948
30422
  "items": children,
30423
+ "indentLinesVariant": props.indentLinesVariant,
30424
+ "parentIndentLines": indentLines.children,
30425
+ "isLastGroup": nextItemHasChildren,
29949
30426
  "returnObject": props.returnObject
29950
30427
  }), slots)
29951
- }) : slots.item?.({
30428
+ }) : renderSlot(slots.item, {
29952
30429
  props: itemProps,
29953
30430
  item: item.raw,
29954
30431
  internalItem: item
29955
- }) ?? vue.createVNode(VTreeviewItem, vue.mergeProps(itemProps, {
29956
- "value": props.returnObject ? vue.toRaw(item.raw) : itemProps.value
29957
- }), slotsWithItem);
30432
+ }, () => {
30433
+ if (item.type === 'divider') {
30434
+ return renderSlot(slots.divider, {
30435
+ props: item.raw
30436
+ }, () => vue.createVNode(VDivider, item.props, null));
30437
+ }
30438
+ if (item.type === 'subheader') {
30439
+ return renderSlot(slots.subheader, {
30440
+ props: item.raw
30441
+ }, () => vue.createVNode(VListSubheader, item.props, null));
30442
+ }
30443
+ return vue.createVNode(VTreeviewItem, vue.mergeProps(itemProps, {
30444
+ "hideActions": props.hideActions,
30445
+ "indentLines": indentLines.leaf,
30446
+ "value": props.returnObject ? vue.toRaw(item.raw) : itemProps.value
30447
+ }), slotsWithItem);
30448
+ });
29958
30449
  });
29959
30450
  }
29960
30451
  });
@@ -29970,20 +30461,18 @@
29970
30461
  const makeVTreeviewProps = propsFactory({
29971
30462
  fluid: Boolean,
29972
30463
  openAll: Boolean,
30464
+ indentLines: [Boolean, String],
29973
30465
  search: String,
29974
30466
  ...makeFilterProps({
29975
30467
  filterKeys: ['title']
29976
30468
  }),
29977
- ...omit(makeVTreeviewChildrenProps(), ['index', 'path']),
30469
+ ...omit(makeVTreeviewChildrenProps(), ['index', 'path', 'indentLinesVariant', 'parentIndentLines', 'isLastGroup']),
29978
30470
  ...omit(makeVListProps({
29979
30471
  collapseIcon: '$treeviewCollapse',
29980
30472
  expandIcon: '$treeviewExpand',
29981
30473
  slim: true
29982
- }), ['itemType', 'nav', 'openStrategy']),
29983
- modelValue: {
29984
- type: Array,
29985
- default: () => []
29986
- }
30474
+ }), ['nav', 'openStrategy']),
30475
+ modelValue: Array
29987
30476
  }, 'VTreeview');
29988
30477
  const VTreeview = genericComponent()({
29989
30478
  name: 'VTreeview',
@@ -29998,7 +30487,8 @@
29998
30487
  },
29999
30488
  setup(props, _ref) {
30000
30489
  let {
30001
- slots
30490
+ slots,
30491
+ emit
30002
30492
  } = _ref;
30003
30493
  const {
30004
30494
  items
@@ -30007,13 +30497,12 @@
30007
30497
  const baseColor = vue.toRef(() => props.baseColor);
30008
30498
  const color = vue.toRef(() => props.color);
30009
30499
  const activated = useProxiedModel(props, 'activated');
30010
- const model = useProxiedModel(props, 'modelValue');
30011
- const _selected = useProxiedModel(props, 'selected', props.modelValue);
30500
+ const _selected = useProxiedModel(props, 'selected');
30012
30501
  const selected = vue.computed({
30013
- get: () => _selected.value,
30502
+ get: () => props.modelValue ?? _selected.value,
30014
30503
  set(val) {
30015
30504
  _selected.value = val;
30016
- model.value = val;
30505
+ emit('update:modelValue', val);
30017
30506
  }
30018
30507
  });
30019
30508
  const vListRef = vue.ref();
@@ -30079,6 +30568,7 @@
30079
30568
  useRender(() => {
30080
30569
  const listProps = VList.filterProps(props);
30081
30570
  const treeviewChildrenProps = VTreeviewChildren.filterProps(props);
30571
+ const indentLinesVariant = typeof props.indentLines === 'boolean' ? 'default' : props.indentLines;
30082
30572
  return vue.createVNode(VList, vue.mergeProps({
30083
30573
  "ref": vListRef
30084
30574
  }, listProps, {
@@ -30096,7 +30586,9 @@
30096
30586
  default: () => [vue.createVNode(VTreeviewChildren, vue.mergeProps(treeviewChildrenProps, {
30097
30587
  "density": props.density,
30098
30588
  "returnObject": props.returnObject,
30099
- "items": items.value
30589
+ "items": items.value,
30590
+ "parentIndentLines": props.indentLines ? [] : undefined,
30591
+ "indentLinesVariant": indentLinesVariant
30100
30592
  }), slots)]
30101
30593
  });
30102
30594
  });
@@ -30185,7 +30677,7 @@
30185
30677
  }
30186
30678
  };
30187
30679
  useRender(() => {
30188
- return vue.createElementVNode("div", null, [slots.intervalEvent?.({
30680
+ return vue.createElementVNode("div", null, [slots['interval-event']?.({
30189
30681
  height: calcHeight().height,
30190
30682
  margin: calcHeight().margin,
30191
30683
  eventClass: 'v-calendar-internal-event',
@@ -30282,13 +30774,13 @@
30282
30774
  "style": vue.normalizeStyle(`height: ${convertToUnit(props.intervalHeight)}`)
30283
30775
  }, [vue.createElementVNode("div", vue.mergeProps({
30284
30776
  "class": "v-calendar-day__row-label"
30285
- }, getPrefixedEventHandlers(attrs, ':time', () => props)), [slots.intervalTitle?.({
30777
+ }, getPrefixedEventHandlers(attrs, ':time', () => props)), [slots['interval-title']?.({
30286
30778
  interval: interval.value
30287
30779
  }) ?? (props.index ? props.intervalFormat ? typeof props.intervalFormat === 'string' ? adapter.format(interval.value.start, 'hours12h') : props.intervalFormat(interval.value) : interval.value.label : '12 AM')]), vue.createElementVNode("div", {
30288
30780
  "class": "v-calendar-day__row-hairline"
30289
30781
  }, null), vue.createElementVNode("div", vue.mergeProps({
30290
30782
  "class": ['v-calendar-day__row-content', interval.value.events.some(e => !e.last) ? 'v-calendar-day__row-content-through' : '']
30291
- }, getPrefixedEventHandlers(attrs, ':interval', () => interval.value)), [slots.intervalBody?.({
30783
+ }, getPrefixedEventHandlers(attrs, ':interval', () => interval.value)), [slots['interval-body']?.({
30292
30784
  interval: interval.value
30293
30785
  }) ?? vue.createElementVNode("div", null, [interval.value.events?.map(event => vue.createVNode(VCalendarIntervalEvent, vue.mergeProps({
30294
30786
  "event": event,
@@ -30297,8 +30789,8 @@
30297
30789
  "intervalDuration": props.intervalDuration,
30298
30790
  "intervalHeight": props.intervalHeight
30299
30791
  }, attrs), {
30300
- ...(slots.intervalEvent ? {
30301
- intervalEvent: _ref2 => {
30792
+ ...(slots['interval-event'] ? {
30793
+ 'interval-event': _ref2 => {
30302
30794
  let {
30303
30795
  height,
30304
30796
  margin,
@@ -30306,7 +30798,7 @@
30306
30798
  event,
30307
30799
  interval
30308
30800
  } = _ref2;
30309
- return slots.intervalEvent?.({
30801
+ return slots['interval-event']?.({
30310
30802
  height,
30311
30803
  margin,
30312
30804
  eventClass,
@@ -30320,7 +30812,7 @@
30320
30812
  "style": vue.normalizeStyle(`height: ${convertToUnit(props.intervalHeight)}`)
30321
30813
  }, [vue.createElementVNode("div", vue.mergeProps({
30322
30814
  "class": ['v-calendar-day__row-content', interval.value.events.some(e => !e.last) ? 'v-calendar-day__row-content-through' : '']
30323
- }, getPrefixedEventHandlers(attrs, ':interval', () => interval.value)), [slots.intervalBody?.({
30815
+ }, getPrefixedEventHandlers(attrs, ':interval', () => interval.value)), [slots['interval-body']?.({
30324
30816
  interval: interval.value
30325
30817
  }) ?? interval.value.events?.map(event => vue.createVNode(VCalendarIntervalEvent, vue.mergeProps({
30326
30818
  "event": event,
@@ -30329,8 +30821,8 @@
30329
30821
  "intervalDuration": props.intervalDuration,
30330
30822
  "intervalHeight": props.intervalHeight
30331
30823
  }, attrs), {
30332
- ...(slots.intervalEvent ? {
30333
- intervalEvent: _ref3 => {
30824
+ ...(slots['interval-event'] ? {
30825
+ 'interval-event': _ref3 => {
30334
30826
  let {
30335
30827
  height,
30336
30828
  margin,
@@ -30338,7 +30830,7 @@
30338
30830
  event,
30339
30831
  interval
30340
30832
  } = _ref3;
30341
- return slots.intervalEvent?.({
30833
+ return slots['interval-event']?.({
30342
30834
  height,
30343
30835
  margin,
30344
30836
  eventClass,
@@ -30393,7 +30885,7 @@
30393
30885
  }), null)])]), intervals.value.map((_, index) => slots.interval?.(calendarIntervalProps) ?? vue.createVNode(VCalendarInterval, vue.mergeProps({
30394
30886
  "index": index
30395
30887
  }, calendarIntervalProps, attrs, getPrefixedEventHandlers(attrs, ':interval', () => calendarIntervalProps)), {
30396
- ...pick(slots, ['intervalBody', 'intervalEvent', 'intervalTitle'])
30888
+ ...pick(slots, ['interval-body', 'interval-event', 'interval-title'])
30397
30889
  }))]);
30398
30890
  });
30399
30891
  return {
@@ -30537,7 +31029,7 @@
30537
31029
  }, getPrefixedEventHandlers(attrs, ':day', () => props)), [!props.day?.isHidden ? vue.createElementVNode("div", {
30538
31030
  "key": "title",
30539
31031
  "class": "v-calendar-weekly__day-label"
30540
- }, [slots.dayTitle?.({
31032
+ }, [slots['day-title']?.({
30541
31033
  title: props.title
30542
31034
  }) ?? vue.createVNode(VBtn, vue.mergeProps({
30543
31035
  "class": props.day?.isToday ? 'v-calendar-weekly__day-label__today' : undefined,
@@ -30550,12 +31042,12 @@
30550
31042
  }, getPrefixedEventHandlers(attrs, ':date', () => props)), null)]) : undefined, !props.day?.isHidden ? vue.createElementVNode("div", {
30551
31043
  "key": "content",
30552
31044
  "class": "v-calendar-weekly__day-content"
30553
- }, [slots.dayBody?.({
31045
+ }, [slots['day-body']?.({
30554
31046
  day: props.day,
30555
31047
  events: props.events
30556
31048
  }) ?? vue.createElementVNode("div", null, [vue.createElementVNode("div", {
30557
31049
  "class": "v-calendar-weekly__day-alldayevents-container"
30558
- }, [props.events?.filter(event => event.allDay).map(event => slots.dayEvent ? slots.dayEvent({
31050
+ }, [props.events?.filter(event => event.allDay).map(event => slots['day-event'] ? slots['day-event']({
30559
31051
  day: props.day,
30560
31052
  allDay: true,
30561
31053
  event
@@ -30565,7 +31057,7 @@
30565
31057
  "allDay": true
30566
31058
  }, attrs), null))]), vue.createElementVNode("div", {
30567
31059
  "class": "v-calendar-weekly__day-events-container"
30568
- }, [props.events?.filter(event => !event.allDay).map(event => slots.dayEvent ? slots.dayEvent({
31060
+ }, [props.events?.filter(event => !event.allDay).map(event => slots['day-event'] ? slots['day-event']({
30569
31061
  day: props.day,
30570
31062
  event,
30571
31063
  allDay: false
@@ -30610,9 +31102,8 @@
30610
31102
  model,
30611
31103
  displayValue,
30612
31104
  weekNumbers,
30613
- weekDays
31105
+ weekdayLabels
30614
31106
  } = useCalendar(props);
30615
- const dayNames = adapter.getWeekdays();
30616
31107
  function onClickNext() {
30617
31108
  if (props.viewMode === 'month') {
30618
31109
  model.value = [adapter.addMonths(displayValue.value, 1)];
@@ -30650,6 +31141,7 @@
30650
31141
  useRender(() => {
30651
31142
  const calendarDayProps = VCalendarDay.filterProps(props);
30652
31143
  const calendarHeaderProps = VCalendarHeader.filterProps(props);
31144
+ const weekdaysCount = daysInWeek.value.length;
30653
31145
  return vue.createElementVNode("div", {
30654
31146
  "class": vue.normalizeClass(['v-calendar', {
30655
31147
  'v-calendar-monthly': props.viewMode === 'month',
@@ -30671,25 +31163,25 @@
30671
31163
  }), {
30672
31164
  title: slots.title
30673
31165
  }))]), vue.createElementVNode("div", {
30674
- "class": vue.normalizeClass(['v-calendar__container', `days__${weekDays.value.length}`])
31166
+ "class": vue.normalizeClass(['v-calendar__container', `days__${weekdaysCount}`])
30675
31167
  }, [props.viewMode === 'month' && !props.hideDayHeader && vue.createElementVNode("div", {
30676
- "class": vue.normalizeClass(['v-calendar-weekly__head', `days__${weekDays.value.length}`, ...(!props.hideWeekNumber ? ['v-calendar-weekly__head-weeknumbers'] : [])]),
31168
+ "class": vue.normalizeClass(['v-calendar-weekly__head', `days__${weekdaysCount}`, ...(!props.hideWeekNumber ? ['v-calendar-weekly__head-weeknumbers'] : [])]),
30677
31169
  "key": "calendarWeeklyHead"
30678
31170
  }, [!props.hideWeekNumber ? vue.createElementVNode("div", {
30679
31171
  "key": "weekNumber0",
30680
31172
  "class": "v-calendar-weekly__head-weeknumber"
30681
- }, null) : '', weekDays.value.map(weekday => vue.createElementVNode("div", {
31173
+ }, null) : '', weekdayLabels.value.map(weekday => vue.createElementVNode("div", {
30682
31174
  "class": vue.normalizeClass(`v-calendar-weekly__head-weekday${!props.hideWeekNumber ? '-with-weeknumber' : ''}`)
30683
- }, [dayNames[weekday]]))]), props.viewMode === 'month' && vue.createElementVNode("div", {
31175
+ }, [weekday]))]), props.viewMode === 'month' && vue.createElementVNode("div", {
30684
31176
  "key": "VCalendarMonth",
30685
- "class": vue.normalizeClass(['v-calendar-month__days', `days${!props.hideWeekNumber ? '-with-weeknumbers' : ''}__${weekDays.value.length}`, ...(!props.hideWeekNumber ? ['v-calendar-month__weeknumbers'] : [])])
30686
- }, [chunkArray(daysInMonth.value, weekDays.value.length).map((week, wi) => [!props.hideWeekNumber ? vue.createElementVNode("div", vue.mergeProps({
31177
+ "class": vue.normalizeClass(['v-calendar-month__days', `days${!props.hideWeekNumber ? '-with-weeknumbers' : ''}__${weekdaysCount}`, ...(!props.hideWeekNumber ? ['v-calendar-month__weeknumbers'] : [])])
31178
+ }, [chunkArray(daysInMonth.value, weekdaysCount).map((week, wi) => [!props.hideWeekNumber ? vue.createElementVNode("div", vue.mergeProps({
30687
31179
  "class": "v-calendar-month__weeknumber"
30688
31180
  }, getPrefixedEventHandlers(attrs, ':weekNumber', () => ({
30689
31181
  weekNumber: weekNumbers.value[wi],
30690
31182
  week
30691
31183
  }))), [weekNumbers.value[wi]]) : '', week.map(day => vue.createVNode(VCalendarMonthDay, vue.mergeProps({
30692
- "key": day.date.getTime()
31184
+ "key": adapter.toJsDate(day.date).getTime()
30693
31185
  }, calendarDayProps, {
30694
31186
  "day": day,
30695
31187
  "title": adapter.format(day.date, 'dayOfMonth'),
@@ -30706,7 +31198,7 @@
30706
31198
  "dayIndex": i,
30707
31199
  "events": props.events?.filter(e => adapter.isSameDay(e.start, day.date) || adapter.isSameDay(e.end, day.date))
30708
31200
  }, attrs), {
30709
- ...pick(slots, ['interval', 'intervalBody', 'intervalEvent', 'intervalTitle'])
31201
+ ...pick(slots, ['interval', 'interval-body', 'interval-event', 'interval-title'])
30710
31202
  })), props.viewMode === 'day' && (slots['day-interval'] ? slots['day-interval']({
30711
31203
  day: genDays([displayValue.value], adapter.date())[0],
30712
31204
  dayIndex: 0,
@@ -31621,6 +32113,7 @@
31621
32113
  opacity: props.opacity
31622
32114
  };
31623
32115
  return vue.createVNode(props.tag, {
32116
+ "type": props.tag === 'button' ? 'button' : undefined,
31624
32117
  "class": vue.normalizeClass([{
31625
32118
  'v-icon-btn': true,
31626
32119
  'v-icon-btn--active': isActive.value,
@@ -32279,6 +32772,398 @@
32279
32772
  }
32280
32773
  });
32281
32774
 
32775
+ // Types
32776
+
32777
+ // Display mode types for different visual representations
32778
+
32779
+ // Extended variant type that includes our custom 'contained' variant
32780
+
32781
+ // Key display tuple: [mode, content] where content is string or IconValue
32782
+
32783
+ // Key tuple: [mode, content] where content is string or IconValue
32784
+
32785
+ function processKey(config, requestedMode, isMac) {
32786
+ const keyCfg = isMac && config.mac ? config.mac : config.default;
32787
+
32788
+ // 1. Resolve the safest display mode for the current platform
32789
+ const mode = (() => {
32790
+ // Non-Mac platforms rarely use icons – prefer text
32791
+ if (requestedMode === 'icon' && !isMac) return 'text';
32792
+
32793
+ // If the requested mode lacks an asset, fall back to text
32794
+ if (requestedMode === 'icon' && !keyCfg.icon) return 'text';
32795
+ if (requestedMode === 'symbol' && !keyCfg.symbol) return 'text';
32796
+ return requestedMode;
32797
+ })();
32798
+
32799
+ // 2. Pick value for the chosen mode, defaulting to text representation
32800
+ let value = keyCfg[mode] ?? keyCfg.text;
32801
+
32802
+ // 3. Guard against icon tokens leaking into text mode (e.g. "$ctrl")
32803
+ if (mode === 'text' && typeof value === 'string' && value.startsWith('$') && !value.startsWith('$vuetify.')) {
32804
+ value = value.slice(1).toUpperCase(); // "$ctrl" → "CTRL"
32805
+ }
32806
+ return mode === 'icon' ? ['icon', value] : [mode, value];
32807
+ }
32808
+ const hotkeyMap = {
32809
+ ctrl: {
32810
+ mac: {
32811
+ symbol: '⌃',
32812
+ icon: '$ctrl',
32813
+ text: '$vuetify.hotkey.ctrl'
32814
+ },
32815
+ default: {
32816
+ text: 'Ctrl'
32817
+ }
32818
+ },
32819
+ meta: {
32820
+ mac: {
32821
+ symbol: '⌘',
32822
+ icon: '$command',
32823
+ text: '$vuetify.hotkey.command'
32824
+ },
32825
+ default: {
32826
+ text: 'Ctrl'
32827
+ }
32828
+ },
32829
+ cmd: {
32830
+ mac: {
32831
+ symbol: '⌘',
32832
+ icon: '$command',
32833
+ text: '$vuetify.hotkey.command'
32834
+ },
32835
+ default: {
32836
+ text: 'Ctrl'
32837
+ }
32838
+ },
32839
+ shift: {
32840
+ mac: {
32841
+ symbol: '⇧',
32842
+ icon: '$shift',
32843
+ text: '$vuetify.hotkey.shift'
32844
+ },
32845
+ default: {
32846
+ text: 'Shift'
32847
+ }
32848
+ },
32849
+ alt: {
32850
+ mac: {
32851
+ symbol: '⌥',
32852
+ icon: '$alt',
32853
+ text: '$vuetify.hotkey.option'
32854
+ },
32855
+ default: {
32856
+ text: 'Alt'
32857
+ }
32858
+ },
32859
+ enter: {
32860
+ default: {
32861
+ symbol: '↵',
32862
+ icon: '$enter',
32863
+ text: '$vuetify.hotkey.enter'
32864
+ }
32865
+ },
32866
+ arrowup: {
32867
+ default: {
32868
+ symbol: '↑',
32869
+ icon: '$arrowup',
32870
+ text: '$vuetify.hotkey.upArrow'
32871
+ }
32872
+ },
32873
+ arrowdown: {
32874
+ default: {
32875
+ symbol: '↓',
32876
+ icon: '$arrowdown',
32877
+ text: '$vuetify.hotkey.downArrow'
32878
+ }
32879
+ },
32880
+ arrowleft: {
32881
+ default: {
32882
+ symbol: '←',
32883
+ icon: '$arrowleft',
32884
+ text: '$vuetify.hotkey.leftArrow'
32885
+ }
32886
+ },
32887
+ arrowright: {
32888
+ default: {
32889
+ symbol: '→',
32890
+ icon: '$arrowright',
32891
+ text: '$vuetify.hotkey.rightArrow'
32892
+ }
32893
+ },
32894
+ backspace: {
32895
+ default: {
32896
+ symbol: '⌫',
32897
+ icon: '$backspace',
32898
+ text: '$vuetify.hotkey.backspace'
32899
+ }
32900
+ },
32901
+ escape: {
32902
+ default: {
32903
+ text: '$vuetify.hotkey.escape'
32904
+ }
32905
+ },
32906
+ ' ': {
32907
+ mac: {
32908
+ symbol: '␣',
32909
+ icon: '$space',
32910
+ text: '$vuetify.hotkey.space'
32911
+ },
32912
+ default: {
32913
+ text: '$vuetify.hotkey.space'
32914
+ }
32915
+ },
32916
+ '-': {
32917
+ default: {
32918
+ text: '-'
32919
+ }
32920
+ }
32921
+ };
32922
+
32923
+ // Create custom variant props that extend the base variant props with our 'contained' option
32924
+ const makeVHotkeyVariantProps = propsFactory({
32925
+ variant: {
32926
+ type: String,
32927
+ default: 'elevated',
32928
+ validator: v => ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain', 'contained'].includes(v)
32929
+ }
32930
+ }, 'VHotkeyVariant');
32931
+ const makeVHotkeyProps = propsFactory({
32932
+ // String representing keyboard shortcuts (e.g., "ctrl+k", "meta+shift+p")
32933
+ keys: String,
32934
+ // How to display keys: 'symbol' uses special characters (⌘, ⌃), 'icon' uses SVG icons, 'text' uses words
32935
+ displayMode: {
32936
+ type: String,
32937
+ default: 'icon'
32938
+ },
32939
+ // Custom key mapping configuration. Users can import and modify the exported hotkeyMap as needed
32940
+ keyMap: {
32941
+ type: Object,
32942
+ default: () => hotkeyMap
32943
+ },
32944
+ platform: {
32945
+ type: String,
32946
+ default: 'auto'
32947
+ },
32948
+ inline: Boolean,
32949
+ disabled: Boolean,
32950
+ prefix: String,
32951
+ suffix: String,
32952
+ ...makeComponentProps(),
32953
+ ...makeThemeProps(),
32954
+ ...makeBorderProps(),
32955
+ ...makeRoundedProps(),
32956
+ ...makeElevationProps(),
32957
+ ...makeVHotkeyVariantProps(),
32958
+ color: String
32959
+ }, 'VHotkey');
32960
+ class Delineator {
32961
+ constructor(delineator) {
32962
+ if (['and', 'then'].includes(delineator)) this.val = delineator;else {
32963
+ throw new Error('Not a valid delineator');
32964
+ }
32965
+ }
32966
+ isEqual(d) {
32967
+ return this.val === d.val;
32968
+ }
32969
+ }
32970
+ function isDelineator(value) {
32971
+ return value instanceof Delineator;
32972
+ }
32973
+ function isString(value) {
32974
+ return typeof value === 'string';
32975
+ }
32976
+ function getKeyText(keyMap, key, isMac) {
32977
+ const lowerKey = key.toLowerCase();
32978
+ if (lowerKey in keyMap) {
32979
+ const result = processKey(keyMap[lowerKey], 'text', isMac);
32980
+ return typeof result[1] === 'string' ? result[1] : String(result[1]);
32981
+ }
32982
+ return key.toUpperCase();
32983
+ }
32984
+ function applyDisplayModeToKey(keyMap, mode, key, isMac) {
32985
+ const lowerKey = key.toLowerCase();
32986
+ if (lowerKey in keyMap) {
32987
+ const result = processKey(keyMap[lowerKey], mode, isMac);
32988
+ if (result[0] === 'text' && typeof result[1] === 'string' && result[1].startsWith('$') && !result[1].startsWith('$vuetify.')) {
32989
+ return ['text', result[1].replace('$', '').toUpperCase(), key];
32990
+ }
32991
+ return [...result, key];
32992
+ }
32993
+ return ['text', key.toUpperCase(), key];
32994
+ }
32995
+ const VHotkey = genericComponent()({
32996
+ name: 'VHotkey',
32997
+ props: makeVHotkeyProps(),
32998
+ setup(props) {
32999
+ const {
33000
+ t
33001
+ } = useLocale();
33002
+ const {
33003
+ themeClasses
33004
+ } = provideTheme(props);
33005
+ const {
33006
+ rtlClasses
33007
+ } = useRtl();
33008
+ const {
33009
+ borderClasses
33010
+ } = useBorder(props);
33011
+ const {
33012
+ roundedClasses
33013
+ } = useRounded(props);
33014
+ const {
33015
+ elevationClasses
33016
+ } = useElevation(props);
33017
+ const isContainedVariant = vue.computed(() => props.variant === 'contained');
33018
+ const effectiveVariantProps = vue.computed(() => ({
33019
+ ...props,
33020
+ variant: isContainedVariant.value ? 'elevated' : props.variant
33021
+ }));
33022
+ const {
33023
+ colorClasses,
33024
+ colorStyles,
33025
+ variantClasses
33026
+ } = useVariant(effectiveVariantProps);
33027
+ const isMac = vue.computed(() => props.platform === 'auto' ? typeof navigator !== 'undefined' && /macintosh/i.test(navigator.userAgent) : props.platform === 'mac');
33028
+ const effectiveDisplayMode = vue.computed(() => props.displayMode);
33029
+ const AND_DELINEATOR = new Delineator('and'); // For + separators
33030
+ const THEN_DELINEATOR = new Delineator('then'); // For - separators
33031
+
33032
+ const effectiveKeyMap = vue.computed(() => props.keyMap);
33033
+ const keyCombinations = vue.computed(() => {
33034
+ if (!props.keys) return [];
33035
+
33036
+ // Split by spaces to handle multiple key combinations
33037
+ // Example: "ctrl+k meta+p" -> ["ctrl+k", "meta+p"]
33038
+ return props.keys.split(' ').map(combination => {
33039
+ // Use the shared sequence splitting logic
33040
+ const sequenceGroups = splitKeySequence(combination);
33041
+
33042
+ // Process each sequence group
33043
+ return sequenceGroups.flatMap((group, groupIndex) => {
33044
+ // Use the shared key combination splitting logic
33045
+ const keyParts = splitKeyCombination(group);
33046
+ const parts = keyParts.reduce((acc, part, index) => {
33047
+ if (index !== 0) {
33048
+ // Add AND delineator between keys
33049
+ return [...acc, AND_DELINEATOR, part];
33050
+ }
33051
+ return [...acc, part];
33052
+ }, []);
33053
+
33054
+ // Add THEN delineator between sequence groups
33055
+ const result = parts.map(key => {
33056
+ if (isString(key)) {
33057
+ return applyDisplayModeToKey(effectiveKeyMap.value, effectiveDisplayMode.value, key, isMac.value);
33058
+ }
33059
+ return key;
33060
+ });
33061
+
33062
+ // Add sequence separator if not the last group
33063
+ if (groupIndex < sequenceGroups.length - 1) {
33064
+ result.push(THEN_DELINEATOR);
33065
+ }
33066
+ return result;
33067
+ });
33068
+ });
33069
+ });
33070
+ const accessibleLabel = vue.computed(() => {
33071
+ if (!props.keys) return '';
33072
+
33073
+ // Convert the parsed key combinations into readable text
33074
+ const readableShortcuts = keyCombinations.value.map(combination => {
33075
+ const readableParts = [];
33076
+ for (const key of combination) {
33077
+ if (isDelineator(key)) {
33078
+ if (AND_DELINEATOR.isEqual(key)) {
33079
+ readableParts.push(t('$vuetify.hotkey.plus'));
33080
+ } else if (THEN_DELINEATOR.isEqual(key)) {
33081
+ readableParts.push(t('$vuetify.hotkey.then'));
33082
+ }
33083
+ } else {
33084
+ // Always use text representation for screen readers
33085
+ const textKey = key[0] === 'icon' || key[0] === 'symbol' ? applyDisplayModeToKey(mergeDeep(hotkeyMap, props.keyMap), 'text', String(key[1]), isMac.value)[1] : key[1];
33086
+ readableParts.push(translateKey(textKey));
33087
+ }
33088
+ }
33089
+ return readableParts.join(' ');
33090
+ });
33091
+ const shortcutText = readableShortcuts.join(', ');
33092
+ return t('$vuetify.hotkey.shortcut', shortcutText);
33093
+ });
33094
+ function translateKey(key) {
33095
+ return key.startsWith('$vuetify.') ? t(key) : key;
33096
+ }
33097
+ function getKeyTooltip(key) {
33098
+ if (effectiveDisplayMode.value === 'text') return undefined;
33099
+ const textKey = getKeyText(effectiveKeyMap.value, String(key[2]), isMac.value);
33100
+ return translateKey(textKey);
33101
+ }
33102
+ function renderKey(key, keyIndex, isContained) {
33103
+ const KeyComponent = isContained ? 'kbd' : VKbd;
33104
+ const keyClasses = ['v-hotkey__key', `v-hotkey__key-${key[0]}`, ...(isContained ? ['v-hotkey__key--nested'] : [borderClasses.value, roundedClasses.value, elevationClasses.value, colorClasses.value])];
33105
+ return vue.createVNode(KeyComponent, {
33106
+ "key": keyIndex,
33107
+ "class": vue.normalizeClass(keyClasses),
33108
+ "style": vue.normalizeStyle(isContained ? undefined : colorStyles.value),
33109
+ "aria-hidden": "true",
33110
+ "title": getKeyTooltip(key)
33111
+ }, {
33112
+ default: () => [key[0] === 'icon' ? vue.createVNode(VIcon, {
33113
+ "icon": key[1],
33114
+ "aria-hidden": "true"
33115
+ }, null) : translateKey(key[1])]
33116
+ });
33117
+ }
33118
+ function renderDivider(key, keyIndex) {
33119
+ return vue.createElementVNode("span", {
33120
+ "key": keyIndex,
33121
+ "class": "v-hotkey__divider",
33122
+ "aria-hidden": "true"
33123
+ }, [AND_DELINEATOR.isEqual(key) ? '+' : t('$vuetify.hotkey.then')]);
33124
+ }
33125
+ useRender(() => vue.createElementVNode("div", {
33126
+ "class": vue.normalizeClass(['v-hotkey', {
33127
+ 'v-hotkey--disabled': props.disabled,
33128
+ 'v-hotkey--inline': props.inline,
33129
+ 'v-hotkey--contained': isContainedVariant.value
33130
+ }, themeClasses.value, rtlClasses.value, variantClasses.value, props.class]),
33131
+ "style": vue.normalizeStyle(props.style),
33132
+ "role": "img",
33133
+ "aria-label": accessibleLabel.value
33134
+ }, [isContainedVariant.value ? vue.createVNode(VKbd, {
33135
+ "key": "contained",
33136
+ "class": vue.normalizeClass(['v-hotkey__contained-wrapper', borderClasses.value, roundedClasses.value, elevationClasses.value, colorClasses.value]),
33137
+ "style": vue.normalizeStyle(colorStyles.value),
33138
+ "aria-hidden": "true"
33139
+ }, {
33140
+ default: () => [props.prefix && vue.createElementVNode("span", {
33141
+ "key": "contained-prefix",
33142
+ "class": "v-hotkey__prefix"
33143
+ }, [props.prefix]), keyCombinations.value.map((combination, comboIndex) => vue.createElementVNode("span", {
33144
+ "class": "v-hotkey__combination",
33145
+ "key": comboIndex
33146
+ }, [combination.map((key, keyIndex) => isDelineator(key) ? renderDivider(key, keyIndex) : renderKey(key, keyIndex, true)), comboIndex < keyCombinations.value.length - 1 && vue.createElementVNode("span", {
33147
+ "aria-hidden": "true"
33148
+ }, [vue.createTextVNode("\xA0")])])), props.suffix && vue.createElementVNode("span", {
33149
+ "key": "contained-suffix",
33150
+ "class": "v-hotkey__suffix"
33151
+ }, [props.suffix])]
33152
+ }) : vue.createElementVNode(vue.Fragment, null, [props.prefix && vue.createElementVNode("span", {
33153
+ "key": "prefix",
33154
+ "class": "v-hotkey__prefix"
33155
+ }, [props.prefix]), keyCombinations.value.map((combination, comboIndex) => vue.createElementVNode("span", {
33156
+ "class": "v-hotkey__combination",
33157
+ "key": comboIndex
33158
+ }, [combination.map((key, keyIndex) => isDelineator(key) ? renderDivider(key, keyIndex) : renderKey(key, keyIndex, false)), comboIndex < keyCombinations.value.length - 1 && vue.createElementVNode("span", {
33159
+ "aria-hidden": "true"
33160
+ }, [vue.createTextVNode("\xA0")])])), props.suffix && vue.createElementVNode("span", {
33161
+ "key": "suffix",
33162
+ "class": "v-hotkey__suffix"
33163
+ }, [props.suffix])])]));
33164
+ }
33165
+ });
33166
+
32282
33167
  var components = /*#__PURE__*/Object.freeze({
32283
33168
  __proto__: null,
32284
33169
  VAlert: VAlert,
@@ -32367,6 +33252,7 @@
32367
33252
  VFileUploadItem: VFileUploadItem,
32368
33253
  VFooter: VFooter,
32369
33254
  VForm: VForm,
33255
+ VHotkey: VHotkey,
32370
33256
  VHover: VHover,
32371
33257
  VIcon: VIcon,
32372
33258
  VIconBtn: VIconBtn,
@@ -32790,7 +33676,7 @@
32790
33676
  };
32791
33677
  });
32792
33678
  }
32793
- const version$1 = "3.9.0-beta.0";
33679
+ const version$1 = "3.9.0";
32794
33680
  createVuetify$1.version = version$1;
32795
33681
 
32796
33682
  // Vue's inject() can only be used in setup
@@ -33088,7 +33974,7 @@
33088
33974
 
33089
33975
  /* eslint-disable local-rules/sort-imports */
33090
33976
 
33091
- const version = "3.9.0-beta.0";
33977
+ const version = "3.9.0";
33092
33978
 
33093
33979
  /* eslint-disable local-rules/sort-imports */
33094
33980
 
@@ -33109,6 +33995,7 @@
33109
33995
  exports.useDefaults = useDefaults;
33110
33996
  exports.useDisplay = useDisplay;
33111
33997
  exports.useGoTo = useGoTo;
33998
+ exports.useHotkey = useHotkey;
33112
33999
  exports.useLayout = useLayout;
33113
34000
  exports.useLocale = useLocale;
33114
34001
  exports.useRtl = useRtl;