@vuetify/nightly 3.9.2-master.2025-07-23 → 3.9.2-master.2025-07-24

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 (211) hide show
  1. package/CHANGELOG.md +11 -3
  2. package/dist/_component-variables-labs.sass +2 -1
  3. package/dist/json/attributes.json +2563 -2299
  4. package/dist/json/importMap-labs.json +24 -12
  5. package/dist/json/importMap.json +174 -174
  6. package/dist/json/tags.json +81 -0
  7. package/dist/json/web-types.json +5100 -3978
  8. package/dist/vuetify-labs.cjs +751 -15
  9. package/dist/vuetify-labs.css +5171 -4837
  10. package/dist/vuetify-labs.d.ts +6526 -845
  11. package/dist/vuetify-labs.esm.js +752 -16
  12. package/dist/vuetify-labs.esm.js.map +1 -1
  13. package/dist/vuetify-labs.js +751 -15
  14. package/dist/vuetify-labs.min.css +2 -2
  15. package/dist/vuetify.cjs +37 -9
  16. package/dist/vuetify.cjs.map +1 -1
  17. package/dist/vuetify.css +3169 -3169
  18. package/dist/vuetify.d.ts +88 -68
  19. package/dist/vuetify.esm.js +37 -9
  20. package/dist/vuetify.esm.js.map +1 -1
  21. package/dist/vuetify.js +37 -9
  22. package/dist/vuetify.js.map +1 -1
  23. package/dist/vuetify.min.css +2 -2
  24. package/dist/vuetify.min.js +264 -263
  25. package/dist/vuetify.min.js.map +1 -1
  26. package/lib/components/VBottomSheet/VBottomSheet.d.ts +6 -6
  27. package/lib/components/VDialog/VDialog.d.ts +6 -6
  28. package/lib/components/VOverlay/VOverlay.js +1 -0
  29. package/lib/components/VOverlay/VOverlay.js.map +1 -1
  30. package/lib/components/VOverlay/scrollStrategies.d.ts +1 -0
  31. package/lib/components/VOverlay/scrollStrategies.js +6 -4
  32. package/lib/components/VOverlay/scrollStrategies.js.map +1 -1
  33. package/lib/components/VRangeSlider/VRangeSlider.d.ts +13 -0
  34. package/lib/components/VSlider/VSlider.d.ts +13 -0
  35. package/lib/components/VSlider/VSlider.js +3 -1
  36. package/lib/components/VSlider/VSlider.js.map +1 -1
  37. package/lib/components/VSlider/VSliderThumb.d.ts +13 -0
  38. package/lib/components/VSlider/VSliderThumb.js +2 -0
  39. package/lib/components/VSlider/VSliderThumb.js.map +1 -1
  40. package/lib/components/VSlider/slider.d.ts +6 -0
  41. package/lib/components/VSlider/slider.js +2 -0
  42. package/lib/components/VSlider/slider.js.map +1 -1
  43. package/lib/components/index.js +1 -1
  44. package/lib/components/index.js.map +1 -1
  45. package/lib/entry-bundler.js +1 -1
  46. package/lib/framework.d.ts +60 -56
  47. package/lib/framework.js +1 -1
  48. package/lib/iconsets/fa.js +9 -1
  49. package/lib/iconsets/fa.js.map +1 -1
  50. package/lib/iconsets/fa4.js +9 -1
  51. package/lib/iconsets/fa4.js.map +1 -1
  52. package/lib/iconsets/md.js +9 -1
  53. package/lib/iconsets/md.js.map +1 -1
  54. package/lib/iconsets/mdi-svg.js +9 -1
  55. package/lib/iconsets/mdi-svg.js.map +1 -1
  56. package/lib/iconsets/mdi.js +9 -1
  57. package/lib/iconsets/mdi.js.map +1 -1
  58. package/lib/labs/VVideo/VVideo.css +319 -0
  59. package/lib/labs/VVideo/VVideo.d.ts +6932 -0
  60. package/lib/labs/VVideo/VVideo.js +424 -0
  61. package/lib/labs/VVideo/VVideo.js.map +1 -0
  62. package/lib/labs/VVideo/VVideo.sass +301 -0
  63. package/lib/labs/VVideo/VVideoControls.d.ts +3524 -0
  64. package/lib/labs/VVideo/VVideoControls.js +232 -0
  65. package/lib/labs/VVideo/VVideoControls.js.map +1 -0
  66. package/lib/labs/VVideo/VVideoVolume.d.ts +3088 -0
  67. package/lib/labs/VVideo/VVideoVolume.js +90 -0
  68. package/lib/labs/VVideo/VVideoVolume.js.map +1 -0
  69. package/lib/labs/VVideo/_variables.scss +58 -0
  70. package/lib/labs/VVideo/index.d.ts +3 -0
  71. package/lib/labs/VVideo/index.js +4 -0
  72. package/lib/labs/VVideo/index.js.map +1 -0
  73. package/lib/labs/components.d.ts +1 -0
  74. package/lib/labs/components.js +1 -0
  75. package/lib/labs/components.js.map +1 -1
  76. package/lib/locale/af.d.ts +11 -0
  77. package/lib/locale/af.js +11 -0
  78. package/lib/locale/af.js.map +1 -1
  79. package/lib/locale/ar.d.ts +11 -0
  80. package/lib/locale/ar.js +11 -0
  81. package/lib/locale/ar.js.map +1 -1
  82. package/lib/locale/az.d.ts +11 -0
  83. package/lib/locale/az.js +11 -0
  84. package/lib/locale/az.js.map +1 -1
  85. package/lib/locale/bg.d.ts +11 -0
  86. package/lib/locale/bg.js +11 -0
  87. package/lib/locale/bg.js.map +1 -1
  88. package/lib/locale/ca.d.ts +11 -0
  89. package/lib/locale/ca.js +11 -0
  90. package/lib/locale/ca.js.map +1 -1
  91. package/lib/locale/ckb.d.ts +11 -0
  92. package/lib/locale/ckb.js +11 -0
  93. package/lib/locale/ckb.js.map +1 -1
  94. package/lib/locale/cs.d.ts +11 -0
  95. package/lib/locale/cs.js +11 -0
  96. package/lib/locale/cs.js.map +1 -1
  97. package/lib/locale/da.d.ts +11 -0
  98. package/lib/locale/da.js +11 -0
  99. package/lib/locale/da.js.map +1 -1
  100. package/lib/locale/de.d.ts +11 -0
  101. package/lib/locale/de.js +11 -0
  102. package/lib/locale/de.js.map +1 -1
  103. package/lib/locale/el.d.ts +11 -0
  104. package/lib/locale/el.js +11 -0
  105. package/lib/locale/el.js.map +1 -1
  106. package/lib/locale/en.d.ts +11 -0
  107. package/lib/locale/en.js +11 -0
  108. package/lib/locale/en.js.map +1 -1
  109. package/lib/locale/es.d.ts +11 -0
  110. package/lib/locale/es.js +11 -0
  111. package/lib/locale/es.js.map +1 -1
  112. package/lib/locale/et.d.ts +11 -0
  113. package/lib/locale/et.js +11 -0
  114. package/lib/locale/et.js.map +1 -1
  115. package/lib/locale/fa.d.ts +11 -0
  116. package/lib/locale/fa.js +11 -0
  117. package/lib/locale/fa.js.map +1 -1
  118. package/lib/locale/fi.d.ts +11 -0
  119. package/lib/locale/fi.js +11 -0
  120. package/lib/locale/fi.js.map +1 -1
  121. package/lib/locale/fr.d.ts +11 -0
  122. package/lib/locale/fr.js +11 -0
  123. package/lib/locale/fr.js.map +1 -1
  124. package/lib/locale/he.d.ts +11 -0
  125. package/lib/locale/he.js +11 -0
  126. package/lib/locale/he.js.map +1 -1
  127. package/lib/locale/hr.d.ts +11 -0
  128. package/lib/locale/hr.js +11 -0
  129. package/lib/locale/hr.js.map +1 -1
  130. package/lib/locale/hu.d.ts +11 -0
  131. package/lib/locale/hu.js +11 -0
  132. package/lib/locale/hu.js.map +1 -1
  133. package/lib/locale/id.d.ts +11 -0
  134. package/lib/locale/id.js +11 -0
  135. package/lib/locale/id.js.map +1 -1
  136. package/lib/locale/it.d.ts +11 -0
  137. package/lib/locale/it.js +11 -0
  138. package/lib/locale/it.js.map +1 -1
  139. package/lib/locale/ja.d.ts +11 -0
  140. package/lib/locale/ja.js +11 -0
  141. package/lib/locale/ja.js.map +1 -1
  142. package/lib/locale/km.d.ts +11 -0
  143. package/lib/locale/km.js +11 -0
  144. package/lib/locale/km.js.map +1 -1
  145. package/lib/locale/ko.d.ts +11 -0
  146. package/lib/locale/ko.js +11 -0
  147. package/lib/locale/ko.js.map +1 -1
  148. package/lib/locale/lt.d.ts +11 -0
  149. package/lib/locale/lt.js +11 -0
  150. package/lib/locale/lt.js.map +1 -1
  151. package/lib/locale/lv.d.ts +11 -0
  152. package/lib/locale/lv.js +11 -0
  153. package/lib/locale/lv.js.map +1 -1
  154. package/lib/locale/nl.d.ts +11 -0
  155. package/lib/locale/nl.js +11 -0
  156. package/lib/locale/nl.js.map +1 -1
  157. package/lib/locale/no.d.ts +11 -0
  158. package/lib/locale/no.js +11 -0
  159. package/lib/locale/no.js.map +1 -1
  160. package/lib/locale/pl.d.ts +11 -0
  161. package/lib/locale/pl.js +11 -0
  162. package/lib/locale/pl.js.map +1 -1
  163. package/lib/locale/pt.d.ts +11 -0
  164. package/lib/locale/pt.js +11 -0
  165. package/lib/locale/pt.js.map +1 -1
  166. package/lib/locale/ro.d.ts +11 -0
  167. package/lib/locale/ro.js +11 -0
  168. package/lib/locale/ro.js.map +1 -1
  169. package/lib/locale/ru.d.ts +11 -0
  170. package/lib/locale/ru.js +11 -0
  171. package/lib/locale/ru.js.map +1 -1
  172. package/lib/locale/sk.d.ts +11 -0
  173. package/lib/locale/sk.js +11 -0
  174. package/lib/locale/sk.js.map +1 -1
  175. package/lib/locale/sl.d.ts +11 -0
  176. package/lib/locale/sl.js +11 -0
  177. package/lib/locale/sl.js.map +1 -1
  178. package/lib/locale/sr-Cyrl.d.ts +11 -0
  179. package/lib/locale/sr-Cyrl.js +11 -0
  180. package/lib/locale/sr-Cyrl.js.map +1 -1
  181. package/lib/locale/sr-Latn.d.ts +11 -0
  182. package/lib/locale/sr-Latn.js +11 -0
  183. package/lib/locale/sr-Latn.js.map +1 -1
  184. package/lib/locale/sv.d.ts +11 -0
  185. package/lib/locale/sv.js +11 -0
  186. package/lib/locale/sv.js.map +1 -1
  187. package/lib/locale/th.d.ts +11 -0
  188. package/lib/locale/th.js +11 -0
  189. package/lib/locale/th.js.map +1 -1
  190. package/lib/locale/tr.d.ts +11 -0
  191. package/lib/locale/tr.js +11 -0
  192. package/lib/locale/tr.js.map +1 -1
  193. package/lib/locale/uk.d.ts +11 -0
  194. package/lib/locale/uk.js +11 -0
  195. package/lib/locale/uk.js.map +1 -1
  196. package/lib/locale/vi.d.ts +11 -0
  197. package/lib/locale/vi.js +11 -0
  198. package/lib/locale/vi.js.map +1 -1
  199. package/lib/locale/zh-Hans.d.ts +11 -0
  200. package/lib/locale/zh-Hans.js +11 -0
  201. package/lib/locale/zh-Hans.js.map +1 -1
  202. package/lib/locale/zh-Hant.d.ts +11 -0
  203. package/lib/locale/zh-Hant.js +11 -0
  204. package/lib/locale/zh-Hant.js.map +1 -1
  205. package/lib/util/index.d.ts +1 -0
  206. package/lib/util/index.js +1 -0
  207. package/lib/util/index.js.map +1 -1
  208. package/lib/util/timeUtils.d.ts +1 -0
  209. package/lib/util/timeUtils.js +4 -0
  210. package/lib/util/timeUtils.js.map +1 -0
  211. package/package.json +1 -1
@@ -1,10 +1,10 @@
1
1
  /*!
2
- * Vuetify v3.9.2-master.2025-07-23
2
+ * Vuetify v3.9.2-master.2025-07-24
3
3
  * Forged by John Leider
4
4
  * Released under the MIT License.
5
5
  */
6
6
 
7
- import { shallowRef, reactive, watchEffect, toRef, capitalize, unref, Fragment, camelize, isVNode, Comment, warn, getCurrentInstance as getCurrentInstance$1, ref, computed, provide, inject as inject$1, defineComponent as defineComponent$1, h, onBeforeUnmount, watch, readonly, onMounted, useId, onDeactivated, onActivated, onScopeDispose, effectScope, toRaw, getCurrentScope, createElementVNode, normalizeStyle, normalizeClass, createVNode, TransitionGroup, Transition, mergeProps, toRefs, toValue, isRef, onBeforeMount, nextTick, withDirectives, vShow, onUpdated, Text, resolveDynamicComponent, toDisplayString, markRaw, Teleport, cloneVNode, createTextVNode, normalizeProps, guardReactiveProps, onUnmounted, onBeforeUpdate, withModifiers, vModelText, resolveComponent, render } from 'vue';
7
+ import { shallowRef, reactive, watchEffect, toRef, capitalize, unref, Fragment, camelize, isVNode, Comment, warn, getCurrentInstance as getCurrentInstance$1, ref, computed, provide, inject as inject$1, defineComponent as defineComponent$1, h, onBeforeUnmount, watch, readonly, onMounted, useId, onDeactivated, onActivated, onScopeDispose, effectScope, toRaw, getCurrentScope, createElementVNode, normalizeStyle, normalizeClass, createVNode, TransitionGroup, Transition, mergeProps, toRefs, toValue, isRef, onBeforeMount, nextTick, withDirectives, vShow, onUpdated, Text, resolveDynamicComponent, toDisplayString, markRaw, Teleport, cloneVNode, createTextVNode, normalizeProps, guardReactiveProps, onUnmounted, onBeforeUpdate, withModifiers, vModelText, resolveDirective, resolveComponent, render } from 'vue';
8
8
 
9
9
  // Types
10
10
  // eslint-disable-line vue/prefer-import-from-vue
@@ -1656,6 +1656,10 @@ function useRender(render) {
1656
1656
  vm.render = render;
1657
1657
  }
1658
1658
 
1659
+ function formatTime(seconds) {
1660
+ return [Math.floor(seconds % 60), Math.floor(seconds / 60 % 60), Math.floor(seconds / 60 / 60 % 60)].filter((x, i) => i < 2 || x > 0).reverse().map(String).map((x, i) => i > 0 ? x.padStart(2, '0') : x).join(':');
1661
+ }
1662
+
1659
1663
  // Utilities
1660
1664
 
1661
1665
  // Types
@@ -2176,6 +2180,17 @@ var en = {
2176
2180
  option: 'Option',
2177
2181
  plus: 'plus',
2178
2182
  shortcut: 'Keyboard shortcut: {0}'
2183
+ },
2184
+ video: {
2185
+ play: 'Play',
2186
+ pause: 'Pause',
2187
+ seek: 'Seek',
2188
+ volume: 'Volume',
2189
+ showVolume: 'Show volume control',
2190
+ mute: 'Mute',
2191
+ unmute: 'Unmute',
2192
+ enterFullscreen: 'Full screen',
2193
+ exitFullscreen: 'Exit full screen'
2179
2194
  }
2180
2195
  };
2181
2196
 
@@ -4258,7 +4273,7 @@ function useDensity(props) {
4258
4273
 
4259
4274
  // Types
4260
4275
 
4261
- const allowedVariants$2 = ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain'];
4276
+ const allowedVariants$4 = ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain'];
4262
4277
  function genOverlays(isClickable, name) {
4263
4278
  return createElementVNode(Fragment, null, [isClickable && createElementVNode("span", {
4264
4279
  "key": "overlay",
@@ -4273,7 +4288,7 @@ const makeVariantProps = propsFactory({
4273
4288
  variant: {
4274
4289
  type: String,
4275
4290
  default: 'elevated',
4276
- validator: v => allowedVariants$2.includes(v)
4291
+ validator: v => allowedVariants$4.includes(v)
4277
4292
  }
4278
4293
  }, 'variant');
4279
4294
  function useVariant(props) {
@@ -4697,7 +4712,15 @@ const aliases = {
4697
4712
  arrowdown: 'mdi-arrow-down',
4698
4713
  arrowleft: 'mdi-arrow-left',
4699
4714
  arrowright: 'mdi-arrow-right',
4700
- backspace: 'mdi-backspace'
4715
+ backspace: 'mdi-backspace',
4716
+ play: 'mdi-play',
4717
+ pause: 'mdi-pause',
4718
+ fullscreen: 'mdi-fullscreen',
4719
+ fullscreenExit: 'mdi-fullscreen-exit',
4720
+ volumeHigh: 'mdi-volume-high',
4721
+ volumeMedium: 'mdi-volume-medium',
4722
+ volumeLow: 'mdi-volume-low',
4723
+ volumeOff: 'mdi-volume-variant-off'
4701
4724
  };
4702
4725
  const mdi = {
4703
4726
  // Not using mergeProps here, functional components merge props by default (?)
@@ -10827,11 +10850,12 @@ function closeScrollStrategy(data) {
10827
10850
  function onScroll(e) {
10828
10851
  data.isActive.value = false;
10829
10852
  }
10830
- bindScroll(data.targetEl.value ?? data.contentEl.value, onScroll);
10853
+ bindScroll(data.target.value ?? data.contentEl.value, onScroll);
10831
10854
  }
10832
10855
  function blockScrollStrategy(data, props) {
10833
10856
  const offsetParent = data.root.value?.offsetParent;
10834
- const scrollElements = [...new Set([...getScrollParents(data.targetEl.value, props.contained ? offsetParent : undefined), ...getScrollParents(data.contentEl.value, props.contained ? offsetParent : undefined)])].filter(el => !el.classList.contains('v-overlay-scroll-blocked'));
10857
+ const target = Array.isArray(data.target.value) ? document.elementFromPoint(...data.target.value) : data.target.value;
10858
+ const scrollElements = [...new Set([...getScrollParents(target, props.contained ? offsetParent : undefined), ...getScrollParents(data.contentEl.value, props.contained ? offsetParent : undefined)])].filter(el => !el.classList.contains('v-overlay-scroll-blocked'));
10835
10859
  const scrollbarWidth = window.innerWidth - document.documentElement.offsetWidth;
10836
10860
  const scrollableParent = (el => hasScrollbar(el) && el)(offsetParent || document.documentElement);
10837
10861
  if (scrollableParent) {
@@ -10878,7 +10902,7 @@ function repositionScrollStrategy(data, props, scope) {
10878
10902
  }
10879
10903
  ric = (typeof requestIdleCallback === 'undefined' ? cb => cb() : requestIdleCallback)(() => {
10880
10904
  scope.run(() => {
10881
- bindScroll(data.targetEl.value ?? data.contentEl.value, e => {
10905
+ bindScroll(data.target.value ?? data.contentEl.value, e => {
10882
10906
  if (slow) {
10883
10907
  // If the position calculation is slow,
10884
10908
  // defer updates until scrolling is finished.
@@ -10903,7 +10927,8 @@ function repositionScrollStrategy(data, props, scope) {
10903
10927
  }
10904
10928
 
10905
10929
  /** @private */
10906
- function bindScroll(el, onScroll) {
10930
+ function bindScroll(target, onScroll) {
10931
+ const el = Array.isArray(target) ? document.elementFromPoint(...target) : target;
10907
10932
  const scrollElements = [document, ...getScrollParents(el)];
10908
10933
  scrollElements.forEach(el => {
10909
10934
  el.addEventListener('scroll', onScroll, {
@@ -11585,6 +11610,7 @@ const VOverlay = genericComponent()({
11585
11610
  root,
11586
11611
  contentEl,
11587
11612
  targetEl,
11613
+ target,
11588
11614
  isActive,
11589
11615
  updateLocation
11590
11616
  });
@@ -11980,7 +12006,7 @@ const VFieldLabel = genericComponent()({
11980
12006
 
11981
12007
  // Types
11982
12008
 
11983
- const allowedVariants$1 = ['underlined', 'outlined', 'filled', 'solo', 'solo-inverted', 'solo-filled', 'plain'];
12009
+ const allowedVariants$3 = ['underlined', 'outlined', 'filled', 'solo', 'solo-inverted', 'solo-filled', 'plain'];
11984
12010
  const makeVFieldProps = propsFactory({
11985
12011
  appendInnerIcon: IconValue,
11986
12012
  bgColor: String,
@@ -12014,7 +12040,7 @@ const makeVFieldProps = propsFactory({
12014
12040
  variant: {
12015
12041
  type: String,
12016
12042
  default: 'filled',
12017
- validator: v => allowedVariants$1.includes(v)
12043
+ validator: v => allowedVariants$3.includes(v)
12018
12044
  },
12019
12045
  'onClick:clear': EventProp(),
12020
12046
  'onClick:appendInner': EventProp(),
@@ -16176,6 +16202,7 @@ const makeSliderProps = propsFactory({
16176
16202
  validator: v => ['vertical', 'horizontal'].includes(v)
16177
16203
  },
16178
16204
  reverse: Boolean,
16205
+ noKeyboard: Boolean,
16179
16206
  ...makeRoundedProps(),
16180
16207
  ...makeElevationProps({
16181
16208
  elevation: 2
@@ -16379,6 +16406,7 @@ const useSlider = _ref => {
16379
16406
  min,
16380
16407
  max,
16381
16408
  mousePressed,
16409
+ noKeyboard: toRef(() => props.noKeyboard),
16382
16410
  numTicks,
16383
16411
  onSliderMousedown,
16384
16412
  onSliderTouchstart,
@@ -16431,6 +16459,7 @@ const makeVSliderThumbProps = propsFactory({
16431
16459
  default: true
16432
16460
  },
16433
16461
  name: String,
16462
+ noKeyboard: Boolean,
16434
16463
  ...makeComponentProps()
16435
16464
  }, 'VSliderThumb');
16436
16465
  const VSliderThumb = genericComponent()({
@@ -16493,6 +16522,7 @@ const VSliderThumb = genericComponent()({
16493
16522
  if (step.value) return [1, 2, 3];else return [1, 5, 10];
16494
16523
  });
16495
16524
  function parseKeydown(e, value) {
16525
+ if (props.noKeyboard) return;
16496
16526
  if (!relevantKeys.includes(e.key)) return;
16497
16527
  e.preventDefault();
16498
16528
  const _step = step.value || 0.1;
@@ -16728,7 +16758,8 @@ const VSlider = genericComponent()({
16728
16758
  trackContainerRef,
16729
16759
  position,
16730
16760
  hasLabels,
16731
- readonly
16761
+ readonly,
16762
+ noKeyboard
16732
16763
  } = useSlider({
16733
16764
  props,
16734
16765
  steps,
@@ -16804,6 +16835,7 @@ const VSlider = genericComponent()({
16804
16835
  "ref": thumbContainerRef,
16805
16836
  "aria-describedby": messagesId.value,
16806
16837
  "focused": isFocused.value,
16838
+ "noKeyboard": noKeyboard.value,
16807
16839
  "min": min.value,
16808
16840
  "max": max.value,
16809
16841
  "modelValue": model.value,
@@ -23880,7 +23912,7 @@ const VExpansionPanel = genericComponent()({
23880
23912
 
23881
23913
  // Types
23882
23914
 
23883
- const allowedVariants = ['default', 'accordion', 'inset', 'popout'];
23915
+ const allowedVariants$2 = ['default', 'accordion', 'inset', 'popout'];
23884
23916
  const makeVExpansionPanelsProps = propsFactory({
23885
23917
  flat: Boolean,
23886
23918
  ...makeGroupProps(),
@@ -23891,7 +23923,7 @@ const makeVExpansionPanelsProps = propsFactory({
23891
23923
  variant: {
23892
23924
  type: String,
23893
23925
  default: 'default',
23894
- validator: v => allowedVariants.includes(v)
23926
+ validator: v => allowedVariants$2.includes(v)
23895
23927
  }
23896
23928
  }, 'VExpansionPanels');
23897
23929
  const VExpansionPanels = genericComponent()({
@@ -33182,6 +33214,707 @@ const VHotkey = genericComponent()({
33182
33214
  }
33183
33215
  });
33184
33216
 
33217
+ // Types
33218
+
33219
+ const makeVVideoVolumeProps = propsFactory({
33220
+ inline: Boolean,
33221
+ label: String,
33222
+ direction: {
33223
+ type: String,
33224
+ default: 'vertical'
33225
+ },
33226
+ modelValue: {
33227
+ type: Number,
33228
+ default: 0
33229
+ },
33230
+ menuProps: Object,
33231
+ sliderProps: Object,
33232
+ onClick: EventProp(),
33233
+ ...makeComponentProps()
33234
+ }, 'VVideoVolume');
33235
+ const VVideoVolume = genericComponent()({
33236
+ name: 'VVideoVolume',
33237
+ props: makeVVideoVolumeProps(),
33238
+ emits: {
33239
+ 'update:modelValue': val => true
33240
+ },
33241
+ setup(props, _ref) {
33242
+ let {
33243
+ attrs
33244
+ } = _ref;
33245
+ const {
33246
+ t
33247
+ } = useLocale();
33248
+ const volume = useProxiedModel(props, 'modelValue');
33249
+ const volumeIcon = toRef(() => volume.value > 70 ? '$volumeHigh' : volume.value > 40 ? '$volumeMedium' : volume.value > 10 ? '$volumeLow' : '$volumeOff');
33250
+ const containerRef = ref();
33251
+ useRender(() => {
33252
+ const sliderDefaults = {
33253
+ hideDetails: true,
33254
+ step: 5,
33255
+ thumbSize: 16
33256
+ };
33257
+ return createElementVNode("div", {
33258
+ "class": normalizeClass(['v-video-volume', {
33259
+ 'v-video-volume--inline': props.inline
33260
+ }, props.class]),
33261
+ "style": normalizeStyle(props.style),
33262
+ "ref": containerRef
33263
+ }, [withDirectives(createVNode(VIconBtn, mergeProps({
33264
+ "icon": volumeIcon.value,
33265
+ "aria-label": props.label,
33266
+ "onClick": props.onClick
33267
+ }, attrs), {
33268
+ default: () => [createVNode(VIcon, null, null), !props.inline && createVNode(VMenu, {
33269
+ "offset": "8",
33270
+ "activator": "parent",
33271
+ "attach": containerRef.value,
33272
+ "location": props.menuProps?.location ?? 'top center',
33273
+ "closeOnContentClick": false
33274
+ }, {
33275
+ default: () => [createElementVNode("div", {
33276
+ "class": normalizeClass(['v-video-volume__menu', `v-video-volume__menu--${props.direction}`])
33277
+ }, [createVNode(VSlider, mergeProps({
33278
+ "direction": props.direction,
33279
+ "aria-label": t('$vuetify.video.volume'),
33280
+ "modelValue": volume.value,
33281
+ "onUpdate:modelValue": v => volume.value = v
33282
+ }, sliderDefaults, props.sliderProps), null)])]
33283
+ })]
33284
+ }), [[resolveDirective("tooltip"), props.label, 'top']]), props.inline && createVNode(VSlider, mergeProps({
33285
+ "class": "v-video-volume-inline__slider",
33286
+ "minWidth": "50",
33287
+ "aria-label": t('$vuetify.video.volume'),
33288
+ "modelValue": volume.value,
33289
+ "onUpdate:modelValue": v => volume.value = v,
33290
+ "onKeydown": e => {
33291
+ e.stopPropagation();
33292
+ }
33293
+ }, sliderDefaults, props.sliderProps), null)]);
33294
+ });
33295
+ }
33296
+ });
33297
+
33298
+ // Types
33299
+
33300
+ const allowedVariants$1 = ['hidden', 'default', 'tube', 'mini'];
33301
+ const makeVVideoControlsProps = propsFactory({
33302
+ color: String,
33303
+ backgroundColor: String,
33304
+ trackColor: String,
33305
+ playing: Boolean,
33306
+ hidePlay: Boolean,
33307
+ hideVolume: Boolean,
33308
+ hideFullscreen: Boolean,
33309
+ fullscreen: Boolean,
33310
+ floating: Boolean,
33311
+ splitTime: Boolean,
33312
+ pills: Boolean,
33313
+ detached: Boolean,
33314
+ progress: {
33315
+ type: Number,
33316
+ default: 0
33317
+ },
33318
+ duration: {
33319
+ type: Number,
33320
+ default: 0
33321
+ },
33322
+ volume: [Number, String],
33323
+ variant: {
33324
+ type: String,
33325
+ default: 'default',
33326
+ validator: v => allowedVariants$1.includes(v)
33327
+ },
33328
+ volumeProps: Object,
33329
+ ...makeDensityProps(),
33330
+ ...makeElevationProps(),
33331
+ ...makeThemeProps()
33332
+ }, 'VVideoControls');
33333
+ const VVideoControls = genericComponent()({
33334
+ name: 'VVideoControls',
33335
+ props: makeVVideoControlsProps(),
33336
+ emits: {
33337
+ 'update:playing': val => true,
33338
+ 'update:progress': val => true,
33339
+ 'update:volume': val => true,
33340
+ skip: val => true,
33341
+ 'click:fullscreen': () => true
33342
+ },
33343
+ setup(props, _ref) {
33344
+ let {
33345
+ emit,
33346
+ slots
33347
+ } = _ref;
33348
+ const {
33349
+ t
33350
+ } = useLocale();
33351
+ const {
33352
+ themeClasses
33353
+ } = provideTheme(props);
33354
+ const {
33355
+ densityClasses
33356
+ } = useDensity(props);
33357
+ const {
33358
+ elevationClasses
33359
+ } = useElevation(props);
33360
+ const {
33361
+ backgroundColorClasses,
33362
+ backgroundColorStyles
33363
+ } = useBackgroundColor(() => {
33364
+ const fallbackBackground = props.detached ? 'surface' : undefined;
33365
+ return props.backgroundColor ?? fallbackBackground;
33366
+ });
33367
+ const playing = useProxiedModel(props, 'playing');
33368
+ const progress = useProxiedModel(props, 'progress');
33369
+ const volume = useProxiedModel(props, 'volume', 0, v => Number(v ?? 0));
33370
+ const lastVolume = shallowRef();
33371
+ const currentTime = computed(() => {
33372
+ const secondsElapsed = Math.round(props.progress / 100 * props.duration);
33373
+ return {
33374
+ elapsed: formatTime(secondsElapsed),
33375
+ remaining: formatTime(props.duration - secondsElapsed),
33376
+ total: formatTime(props.duration)
33377
+ };
33378
+ });
33379
+ const labels = computed(() => {
33380
+ const playIconLocaleKey = playing.value ? 'pause' : 'play';
33381
+ const volumeIconLocaleKey = props.volumeProps?.inline ? volume.value ? 'mute' : 'unmute' : 'showVolume';
33382
+ const fullscreenIconLocaleKey = props.fullscreen ? 'exitFullscreen' : 'enterFullscreen';
33383
+ return {
33384
+ seek: t('$vuetify.video.seek'),
33385
+ volume: t('$vuetify.video.volume'),
33386
+ playAction: t(`$vuetify.video.${playIconLocaleKey}`),
33387
+ volumeAction: t(`$vuetify.video.${volumeIconLocaleKey}`),
33388
+ fullscreenAction: t(`$vuetify.video.${fullscreenIconLocaleKey}`)
33389
+ };
33390
+ });
33391
+ function play() {
33392
+ playing.value = true;
33393
+ }
33394
+ function pause() {
33395
+ playing.value = false;
33396
+ }
33397
+ function skipTo(v) {
33398
+ progress.value = v;
33399
+ }
33400
+ function toggleMuted() {
33401
+ if (volume.value) {
33402
+ lastVolume.value = volume.value;
33403
+ volume.value = 0;
33404
+ } else {
33405
+ volume.value = lastVolume.value ?? 100;
33406
+ }
33407
+ }
33408
+ function toggleFullscreen() {
33409
+ emit('click:fullscreen');
33410
+ }
33411
+ useRender(() => {
33412
+ const sizes = props.pills ? [42, 36, 30] : [32, 28, 24];
33413
+ const innerDefaults = {
33414
+ VIconBtn: {
33415
+ size: props.density === 'compact' ? sizes[2] : props.density === 'comfortable' ? sizes[1] : sizes[0],
33416
+ iconSize: props.density === 'compact' ? 20 : props.density === 'comfortable' ? 24 : 26,
33417
+ variant: 'text',
33418
+ color: props.color
33419
+ },
33420
+ VSlider: {
33421
+ thumbSize: props.variant === 'tube' ? 10 : 16,
33422
+ hideDetails: true
33423
+ }
33424
+ };
33425
+ const regularBtnSize = innerDefaults.VIconBtn.size;
33426
+ const playBtnSize = props.pills ? regularBtnSize + 8 : regularBtnSize;
33427
+ const pillClasses = ['v-video-control__pill', props.pills ? elevationClasses.value : []];
33428
+ const slotProps = {
33429
+ play,
33430
+ pause,
33431
+ playing: playing.value,
33432
+ progress: progress.value,
33433
+ currentTime: currentTime.value,
33434
+ skipTo,
33435
+ volume,
33436
+ toggleMuted,
33437
+ fullscreen: props.fullscreen,
33438
+ toggleFullscreen,
33439
+ labels: labels.value
33440
+ };
33441
+ return createElementVNode("div", {
33442
+ "class": normalizeClass(['v-video-controls', `v-video-controls--variant-${props.variant}`, {
33443
+ 'v-video-controls--pills': props.pills
33444
+ }, {
33445
+ 'v-video-controls--detached': props.detached
33446
+ }, {
33447
+ 'v-video-controls--floating': props.floating
33448
+ }, {
33449
+ 'v-video-controls--split-time': props.splitTime
33450
+ }, backgroundColorClasses.value, props.detached && !props.pills ? elevationClasses.value : [], densityClasses.value, themeClasses.value]),
33451
+ "style": normalizeStyle([backgroundColorStyles.value, {
33452
+ '--v-video-controls-pill-height': `${regularBtnSize}px`
33453
+ }])
33454
+ }, [createVNode(VDefaultsProvider, {
33455
+ "defaults": innerDefaults
33456
+ }, {
33457
+ default: () => [slots.default?.(slotProps) ?? createElementVNode(Fragment, null, [props.variant !== 'mini' && createElementVNode(Fragment, null, [!props.hidePlay && createElementVNode("div", {
33458
+ "class": normalizeClass([pillClasses, 'v-video__action-play'])
33459
+ }, [withDirectives(createVNode(VIconBtn, {
33460
+ "icon": playing.value ? '$pause' : '$play',
33461
+ "size": playBtnSize,
33462
+ "aria-label": labels.value.playAction,
33463
+ "onClick": () => playing.value = !playing.value
33464
+ }, null), [[resolveDirective("tooltip"), labels.value.playAction, 'top']])]), slots.prepend && createElementVNode("div", {
33465
+ "class": normalizeClass(pillClasses)
33466
+ }, [slots.prepend(slotProps)]), props.splitTime ? createElementVNode("span", {
33467
+ "class": normalizeClass([pillClasses, 'v-video__time'])
33468
+ }, [currentTime.value.elapsed]) : props.variant !== 'default' ? createElementVNode("span", {
33469
+ "class": normalizeClass([pillClasses, 'v-video__time'])
33470
+ }, [currentTime.value.elapsed, createTextVNode(" / "), currentTime.value.total]) : '', createVNode(VSlider, {
33471
+ "modelValue": props.progress,
33472
+ "noKeyboard": true,
33473
+ "color": props.trackColor ?? props.color,
33474
+ "trackColor": props.variant === 'tube' ? 'white' : undefined,
33475
+ "class": "v-video__track",
33476
+ "thumbLabel": "always",
33477
+ "aria-label": labels.value.seek,
33478
+ "onUpdate:modelValue": skipTo
33479
+ }, {
33480
+ 'thumb-label': () => currentTime.value.elapsed
33481
+ }), props.variant === 'tube' && createVNode(VSpacer, null, null), props.splitTime ? createElementVNode("span", {
33482
+ "class": normalizeClass([pillClasses, 'v-video__time'])
33483
+ }, [currentTime.value.remaining]) : '']), props.variant === 'mini' && createElementVNode(Fragment, null, [createVNode(VSpacer, null, null), slots.prepend && createElementVNode("div", {
33484
+ "class": normalizeClass(pillClasses)
33485
+ }, [slots.prepend(slotProps)]), !props.hidePlay && createElementVNode("div", {
33486
+ "class": normalizeClass([pillClasses, 'v-video__action-play'])
33487
+ }, [withDirectives(createVNode(VIconBtn, {
33488
+ "icon": playing.value ? '$pause' : '$play',
33489
+ "size": playBtnSize,
33490
+ "aria-label": labels.value.playAction,
33491
+ "onClick": () => playing.value = !playing.value
33492
+ }, null), [[resolveDirective("tooltip"), labels.value.playAction, 'top']])])]), (!props.hideVolume || !props.hideFullscreen || slots.append) && createElementVNode("div", {
33493
+ "class": normalizeClass(pillClasses)
33494
+ }, [!props.hideVolume && createVNode(VVideoVolume, mergeProps({
33495
+ "key": "volume-control",
33496
+ "sliderProps": {
33497
+ color: props.color
33498
+ },
33499
+ "modelValue": volume.value,
33500
+ "label": labels.value.volumeAction,
33501
+ "onUpdate:modelValue": v => volume.value = v,
33502
+ "onClick": () => props.volumeProps?.inline && toggleMuted()
33503
+ }, props.volumeProps), null), slots.append?.(slotProps), !props.hideFullscreen && withDirectives(createVNode(VIconBtn, {
33504
+ "icon": props.fullscreen ? '$fullscreenExit' : '$fullscreen',
33505
+ "aria-label": labels.value.fullscreenAction,
33506
+ "onClick": toggleFullscreen
33507
+ }, null), [[resolveDirective("tooltip"), labels.value.fullscreenAction, 'top']])]), props.variant === 'mini' && createVNode(VSpacer, null, null)])]
33508
+ })]);
33509
+ });
33510
+ return {
33511
+ toggleMuted
33512
+ };
33513
+ }
33514
+ });
33515
+
33516
+ // Types
33517
+
33518
+ const allowedVariants = ['background', 'player'];
33519
+ const makeVVideoProps = propsFactory({
33520
+ autoplay: Boolean,
33521
+ muted: Boolean,
33522
+ eager: Boolean,
33523
+ src: String,
33524
+ type: String,
33525
+ // e.g. video/mp4
33526
+ image: String,
33527
+ hideOverlay: Boolean,
33528
+ noFullscreen: Boolean,
33529
+ startAt: [Number, String],
33530
+ variant: {
33531
+ type: String,
33532
+ default: 'player',
33533
+ validator: v => allowedVariants.includes(v)
33534
+ },
33535
+ controlsTransition: {
33536
+ type: [Boolean, String, Object],
33537
+ component: VFadeTransition
33538
+ },
33539
+ controlsVariant: {
33540
+ type: String,
33541
+ default: 'default'
33542
+ },
33543
+ controlsProps: {
33544
+ type: Object
33545
+ },
33546
+ rounded: [Boolean, Number, String, Array],
33547
+ ...makeComponentProps(),
33548
+ ...makeDensityProps(),
33549
+ ...makeDimensionProps(),
33550
+ ...makeThemeProps(),
33551
+ ...omit(makeVVideoControlsProps(), ['fullscreen', 'variant'])
33552
+ }, 'VVideo');
33553
+ const VVideo = genericComponent()({
33554
+ name: 'VVideo',
33555
+ inheritAttrs: false,
33556
+ props: makeVVideoProps(),
33557
+ emits: {
33558
+ loaded: element => true,
33559
+ 'update:playing': val => true,
33560
+ 'update:progress': val => true,
33561
+ 'update:volume': val => true
33562
+ },
33563
+ setup(props, _ref) {
33564
+ let {
33565
+ attrs,
33566
+ emit,
33567
+ slots
33568
+ } = _ref;
33569
+ const {
33570
+ themeClasses
33571
+ } = provideTheme(props);
33572
+ const {
33573
+ densityClasses
33574
+ } = useDensity(props);
33575
+ const {
33576
+ dimensionStyles
33577
+ } = useDimension(props);
33578
+ const {
33579
+ elevationClasses
33580
+ } = useElevation(props);
33581
+ const {
33582
+ ssr
33583
+ } = useDisplay();
33584
+ const roundedForContainer = toRef(() => Array.isArray(props.rounded) ? props.rounded[0] : props.rounded);
33585
+ const roundedForControls = toRef(() => Array.isArray(props.rounded) ? props.rounded.at(-1) : props.rounded ?? false);
33586
+ const {
33587
+ roundedClasses: roundedContainerClasses
33588
+ } = useRounded(roundedForContainer);
33589
+ const {
33590
+ roundedClasses: roundedControlsClasses
33591
+ } = useRounded(roundedForControls);
33592
+ const containerRef = ref();
33593
+ const videoRef = ref();
33594
+ const controlsRef = ref();
33595
+ const playing = useProxiedModel(props, 'playing');
33596
+ const progress = useProxiedModel(props, 'progress');
33597
+ const volume = useProxiedModel(props, 'volume', 0, v => Number(v ?? 0));
33598
+ const fullscreen = shallowRef(false);
33599
+ const waiting = shallowRef(false);
33600
+ const triggered = shallowRef(false);
33601
+ const startAfterLoad = shallowRef(false);
33602
+ const state = shallowRef(props.autoplay ? 'loading' : 'idle');
33603
+ const duration = shallowRef(0);
33604
+ const fullscreenEnabled = toRef(() => !props.noFullscreen && !String(attrs.controlsList ?? '').includes('nofullscreen'));
33605
+ function onTimeupdate() {
33606
+ const {
33607
+ currentTime,
33608
+ duration
33609
+ } = videoRef.value;
33610
+ progress.value = duration === 0 ? 0 : 100 * currentTime / duration;
33611
+ }
33612
+ async function onTriggered() {
33613
+ await nextTick();
33614
+ if (!videoRef.value) return;
33615
+ videoRef.value.addEventListener('timeupdate', onTimeupdate);
33616
+ videoRef.value.volume = volume.value / 100;
33617
+ if (state.value !== 'loaded') {
33618
+ state.value = 'loading';
33619
+ }
33620
+ }
33621
+ function onVideoLoaded() {
33622
+ state.value = 'loaded';
33623
+ duration.value = videoRef.value.duration;
33624
+ const startTime = Number(props.startAt ?? 0);
33625
+ if (startTime && startTime <= duration.value) {
33626
+ videoRef.value.currentTime = startTime;
33627
+ progress.value = duration.value === 0 ? 0 : 100 * startTime / duration.value;
33628
+ }
33629
+ if (startAfterLoad.value) {
33630
+ setTimeout(() => playing.value = true, 100);
33631
+ }
33632
+ emit('loaded', videoRef.value);
33633
+ }
33634
+ function onClick() {
33635
+ if (state.value !== 'loaded') {
33636
+ triggered.value = true;
33637
+ startAfterLoad.value = !startAfterLoad.value;
33638
+ }
33639
+ }
33640
+ function onKeydown(e) {
33641
+ if (!videoRef.value || e.ctrlKey) return;
33642
+ if (e.key.startsWith('Arrow')) {
33643
+ e.preventDefault();
33644
+ }
33645
+ switch (true) {
33646
+ case e.key === ' ':
33647
+ {
33648
+ if (!['A', 'BUTTON'].includes(e.target?.tagName)) {
33649
+ e.preventDefault();
33650
+ playing.value = !playing.value;
33651
+ }
33652
+ break;
33653
+ }
33654
+ case e.key === 'ArrowRight':
33655
+ {
33656
+ const step = 10 * (e.shiftKey ? 6 : 1);
33657
+ videoRef.value.currentTime = Math.min(videoRef.value.currentTime + step, duration.value);
33658
+ // TODO: show skip indicator
33659
+ break;
33660
+ }
33661
+ case e.key === 'ArrowLeft':
33662
+ {
33663
+ const step = 10 * (e.shiftKey ? 6 : 1);
33664
+ videoRef.value.currentTime = Math.max(videoRef.value.currentTime - step, 0);
33665
+ // TODO: show skip indicator
33666
+ break;
33667
+ }
33668
+ case createRange(10).map(String).includes(e.key):
33669
+ {
33670
+ skipTo(Number(e.key) * 10);
33671
+ break;
33672
+ }
33673
+ case e.key === 'ArrowUp':
33674
+ {
33675
+ volume.value = Math.min(volume.value + 10, 100);
33676
+ // TODO: show volume change indicator
33677
+ break;
33678
+ }
33679
+ case e.key === 'ArrowDown':
33680
+ {
33681
+ volume.value = Math.max(volume.value - 10, 0);
33682
+ // TODO: show volume change indicator
33683
+ break;
33684
+ }
33685
+ case e.key === 'm':
33686
+ {
33687
+ controlsRef.value?.toggleMuted();
33688
+ break;
33689
+ }
33690
+ case e.key === 'f':
33691
+ {
33692
+ toggleFullscreen();
33693
+ break;
33694
+ }
33695
+ }
33696
+ }
33697
+ function skipTo(v) {
33698
+ if (!videoRef.value) return;
33699
+ progress.value = v;
33700
+ videoRef.value.currentTime = duration.value * v / 100;
33701
+ }
33702
+ watch(() => props.src, v => {
33703
+ progress.value = 0;
33704
+ });
33705
+ watch(playing, v => {
33706
+ if (!videoRef.value) return;
33707
+ if (v) {
33708
+ videoRef.value.play();
33709
+ } else {
33710
+ videoRef.value.pause();
33711
+ }
33712
+ });
33713
+ watch(volume, v => {
33714
+ if (!videoRef.value) return;
33715
+ videoRef.value.volume = v / 100;
33716
+ });
33717
+ watch(triggered, () => onTriggered(), {
33718
+ once: true
33719
+ });
33720
+ watch(() => props.eager, v => v && (triggered.value = true), {
33721
+ immediate: true
33722
+ });
33723
+ onMounted(() => {
33724
+ if (props.autoplay && !ssr) {
33725
+ triggered.value = true;
33726
+ startAfterLoad.value = true;
33727
+ }
33728
+ });
33729
+ onBeforeUnmount(() => {
33730
+ videoRef.value?.removeEventListener('timeupdate', onTimeupdate);
33731
+ });
33732
+ function focusSlider() {
33733
+ const container = videoRef.value?.closest('.v-video');
33734
+ const innerSlider = container?.querySelector('[role="slider"]');
33735
+ innerSlider?.focus();
33736
+ }
33737
+ function fullscreenExitShortcut(e) {
33738
+ if (['ESC', 'f'].includes(e.key)) {
33739
+ toggleFullscreen();
33740
+ document.body.removeEventListener('keydown', fullscreenExitShortcut);
33741
+ }
33742
+ }
33743
+ async function toggleFullscreen() {
33744
+ if (!fullscreenEnabled.value || !document.fullscreenEnabled) {
33745
+ return;
33746
+ }
33747
+ if (document.fullscreenElement) {
33748
+ document.exitFullscreen();
33749
+ onFullscreenExit();
33750
+ } else {
33751
+ await containerRef.value?.requestFullscreen();
33752
+ document.body.addEventListener('keydown', fullscreenExitShortcut);
33753
+ document.addEventListener('fullscreenchange', onFullscreenExit);
33754
+ fullscreen.value = true;
33755
+ }
33756
+ }
33757
+ function onFullscreenExit() {
33758
+ // event fires with a delay after requestFullscreen(), ignore first run
33759
+ if (document.fullscreenElement) return;
33760
+ focusSlider();
33761
+ fullscreen.value = false;
33762
+ document.body.removeEventListener('keydown', fullscreenExitShortcut);
33763
+ document.removeEventListener('fullscreenchange', onFullscreenExit);
33764
+ }
33765
+ function onVideoClick(e) {
33766
+ e.preventDefault();
33767
+ if (state.value === 'loaded') {
33768
+ playing.value = !playing.value;
33769
+ focusSlider();
33770
+ }
33771
+ }
33772
+ function onDoubleClick(e) {
33773
+ e.preventDefault();
33774
+ toggleFullscreen();
33775
+ }
33776
+ let lastTap = 0;
33777
+ function onTouchend(e) {
33778
+ const now = performance.now();
33779
+ if (now - lastTap < 500) {
33780
+ e.preventDefault();
33781
+ toggleFullscreen();
33782
+ } else {
33783
+ lastTap = now;
33784
+ }
33785
+ }
33786
+ useRender(() => {
33787
+ const showControls = state.value === 'loaded' && props.variant === 'player' && props.controlsVariant !== 'hidden';
33788
+ const posterTransition = props.variant === 'background' ? 'poster-fade-out' : 'fade-transition';
33789
+ const overlayProps = {
33790
+ contained: true,
33791
+ persistent: true,
33792
+ contentClass: 'v-video__overlay-fill'
33793
+ };
33794
+ const controlsProps = {
33795
+ ...VVideoControls.filterProps(omit(props, ['variant', 'rounded', 'hideVolume'])),
33796
+ rounded: Array.isArray(props.rounded) ? props.rounded.at(-1) : props.rounded,
33797
+ fullscreen: fullscreen.value,
33798
+ hideVolume: props.hideVolume || props.muted,
33799
+ hideFullscreen: props.hideFullscreen || !fullscreenEnabled.value,
33800
+ density: props.density,
33801
+ variant: props.controlsVariant,
33802
+ playing: playing.value,
33803
+ progress: progress.value,
33804
+ duration: duration.value,
33805
+ volume: volume.value,
33806
+ ...props.controlsProps
33807
+ };
33808
+ const controlsEventHandlers = {
33809
+ onSkip: v => skipTo(v),
33810
+ 'onClick:fullscreen': () => toggleFullscreen(),
33811
+ 'onUpdate:playing': v => playing.value = v,
33812
+ 'onUpdate:progress': v => skipTo(v),
33813
+ 'onUpdate:volume': v => volume.value = v,
33814
+ onClick: e => e.stopPropagation()
33815
+ };
33816
+ const controlslist = [attrs.controlslist, props.noFullscreen ? 'nofullscreen' : ''].filter(Boolean).join(' ');
33817
+ const loadingIndicator = createVNode(VProgressCircular, {
33818
+ "indeterminate": true,
33819
+ "color": props.color,
33820
+ "width": "3",
33821
+ "size": Math.min(100, Number(props.height) / 2 || 50)
33822
+ }, null);
33823
+ const overlayPlayIcon = createVNode(VIconBtn, {
33824
+ "icon": "$play",
33825
+ "size": "80",
33826
+ "color": "#fff",
33827
+ "variant": "outlined",
33828
+ "iconSize": "50",
33829
+ "class": "v-video__center-icon"
33830
+ }, null);
33831
+ return createElementVNode("div", {
33832
+ "ref": containerRef,
33833
+ "class": normalizeClass(['v-video', `v-video--variant-${props.variant}`, `v-video--${state.value}`, {
33834
+ 'v-video--playing': playing.value
33835
+ }, themeClasses.value, densityClasses.value, roundedContainerClasses.value, props.class]),
33836
+ "style": normalizeStyle([props.variant === 'background' ? [] : pick(dimensionStyles.value, ['width', 'min-width', 'max-width']), props.style]),
33837
+ "onKeydown": onKeydown,
33838
+ "onClick": onClick
33839
+ }, [createElementVNode("div", {
33840
+ "class": normalizeClass(['v-video__content', elevationClasses.value]),
33841
+ "style": normalizeStyle([props.variant === 'background' ? [] : dimensionStyles.value])
33842
+ }, [(props.eager || triggered.value) && createElementVNode("video", mergeProps({
33843
+ "key": "video-element",
33844
+ "class": ['v-video__video', roundedContainerClasses.value]
33845
+ }, omit(attrs, ['controlslist', 'class', 'style']), {
33846
+ "controlslist": controlslist,
33847
+ "autoplay": props.autoplay,
33848
+ "muted": props.muted,
33849
+ "playsinline": true,
33850
+ "ref": videoRef,
33851
+ "onLoadeddata": onVideoLoaded,
33852
+ "onPlay": () => playing.value = true,
33853
+ "onPause": () => playing.value = false,
33854
+ "onWaiting": () => waiting.value = true,
33855
+ "onPlaying": () => waiting.value = false,
33856
+ "onClick": onVideoClick,
33857
+ "onDblclick": onDoubleClick,
33858
+ "onTouchend": onTouchend
33859
+ }), [slots.sources?.() ?? createElementVNode("source", {
33860
+ "src": props.src,
33861
+ "type": props.type
33862
+ }, null)]), props.variant === 'player' && !props.hideOverlay && createVNode(VOverlay, mergeProps({
33863
+ "key": "pause-overlay",
33864
+ "modelValue": state.value === 'loaded',
33865
+ "opacity": "0"
33866
+ }, overlayProps), {
33867
+ default: () => [createVNode(VSpacer, null, null), createVNode(MaybeTransition, {
33868
+ "name": "fade-transition"
33869
+ }, {
33870
+ default: () => [!playing.value && overlayPlayIcon]
33871
+ }), createVNode(VSpacer, null, null)]
33872
+ }), props.variant === 'player' && !!slots.header ? createElementVNode("div", {
33873
+ "key": "header",
33874
+ "class": "v-video__header"
33875
+ }, [slots.header()]) : '', createVNode(VOverlay, mergeProps({
33876
+ "key": "poster-overlay",
33877
+ "modelValue": state.value !== 'loaded',
33878
+ "transition": posterTransition
33879
+ }, overlayProps), {
33880
+ default: () => [createVNode(VImg, {
33881
+ "cover": true,
33882
+ "src": props.image
33883
+ }, {
33884
+ default: () => [createElementVNode("div", {
33885
+ "class": normalizeClass(['v-video__overlay-fill', ...roundedContainerClasses.value])
33886
+ }, [overlayPlayIcon])]
33887
+ })]
33888
+ }), createVNode(VOverlay, mergeProps({
33889
+ "key": "loading-overlay",
33890
+ "modelValue": state.value === 'loading' || waiting.value,
33891
+ "opacity": ".1"
33892
+ }, overlayProps), {
33893
+ default: () => [loadingIndicator]
33894
+ })]), createVNode(MaybeTransition, {
33895
+ "key": "actions",
33896
+ "transition": props.controlsTransition
33897
+ }, {
33898
+ default: () => [showControls && createVNode(VVideoControls, mergeProps({
33899
+ "ref": controlsRef,
33900
+ "class": roundedControlsClasses.value
33901
+ }, controlsProps, controlsEventHandlers), {
33902
+ default: slots.controls,
33903
+ prepend: slots.prepend,
33904
+ append: slots.append
33905
+ })]
33906
+ })]);
33907
+ });
33908
+ return {
33909
+ video: videoRef,
33910
+ ...forwardRefs({
33911
+ skipTo,
33912
+ toggleFullscreen
33913
+ }, controlsRef)
33914
+ };
33915
+ }
33916
+ });
33917
+
33185
33918
  var components = /*#__PURE__*/Object.freeze({
33186
33919
  __proto__: null,
33187
33920
  VAlert: VAlert,
@@ -33372,6 +34105,9 @@ var components = /*#__PURE__*/Object.freeze({
33372
34105
  VTreeviewGroup: VTreeviewGroup,
33373
34106
  VTreeviewItem: VTreeviewItem,
33374
34107
  VValidation: VValidation,
34108
+ VVideo: VVideo,
34109
+ VVideoControls: VVideoControls,
34110
+ VVideoVolume: VVideoVolume,
33375
34111
  VVirtualScroll: VVirtualScroll,
33376
34112
  VWindow: VWindow,
33377
34113
  VWindowItem: VWindowItem
@@ -33694,7 +34430,7 @@ function createVuetify$1() {
33694
34430
  };
33695
34431
  });
33696
34432
  }
33697
- const version$1 = "3.9.2-master.2025-07-23";
34433
+ const version$1 = "3.9.2-master.2025-07-24";
33698
34434
  createVuetify$1.version = version$1;
33699
34435
 
33700
34436
  // Vue's inject() can only be used in setup
@@ -33992,7 +34728,7 @@ var index = /*#__PURE__*/Object.freeze({
33992
34728
 
33993
34729
  /* eslint-disable local-rules/sort-imports */
33994
34730
 
33995
- const version = "3.9.2-master.2025-07-23";
34731
+ const version = "3.9.2-master.2025-07-24";
33996
34732
 
33997
34733
  /* eslint-disable local-rules/sort-imports */
33998
34734