@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,5 +1,5 @@
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
  */
@@ -1660,6 +1660,10 @@
1660
1660
  vm.render = render;
1661
1661
  }
1662
1662
 
1663
+ function formatTime(seconds) {
1664
+ 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(':');
1665
+ }
1666
+
1663
1667
  // Utilities
1664
1668
 
1665
1669
  // Types
@@ -2180,6 +2184,17 @@
2180
2184
  option: 'Option',
2181
2185
  plus: 'plus',
2182
2186
  shortcut: 'Keyboard shortcut: {0}'
2187
+ },
2188
+ video: {
2189
+ play: 'Play',
2190
+ pause: 'Pause',
2191
+ seek: 'Seek',
2192
+ volume: 'Volume',
2193
+ showVolume: 'Show volume control',
2194
+ mute: 'Mute',
2195
+ unmute: 'Unmute',
2196
+ enterFullscreen: 'Full screen',
2197
+ exitFullscreen: 'Exit full screen'
2183
2198
  }
2184
2199
  };
2185
2200
 
@@ -4262,7 +4277,7 @@
4262
4277
 
4263
4278
  // Types
4264
4279
 
4265
- const allowedVariants$2 = ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain'];
4280
+ const allowedVariants$4 = ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain'];
4266
4281
  function genOverlays(isClickable, name) {
4267
4282
  return vue.createElementVNode(vue.Fragment, null, [isClickable && vue.createElementVNode("span", {
4268
4283
  "key": "overlay",
@@ -4277,7 +4292,7 @@
4277
4292
  variant: {
4278
4293
  type: String,
4279
4294
  default: 'elevated',
4280
- validator: v => allowedVariants$2.includes(v)
4295
+ validator: v => allowedVariants$4.includes(v)
4281
4296
  }
4282
4297
  }, 'variant');
4283
4298
  function useVariant(props) {
@@ -4701,7 +4716,15 @@
4701
4716
  arrowdown: 'mdi-arrow-down',
4702
4717
  arrowleft: 'mdi-arrow-left',
4703
4718
  arrowright: 'mdi-arrow-right',
4704
- backspace: 'mdi-backspace'
4719
+ backspace: 'mdi-backspace',
4720
+ play: 'mdi-play',
4721
+ pause: 'mdi-pause',
4722
+ fullscreen: 'mdi-fullscreen',
4723
+ fullscreenExit: 'mdi-fullscreen-exit',
4724
+ volumeHigh: 'mdi-volume-high',
4725
+ volumeMedium: 'mdi-volume-medium',
4726
+ volumeLow: 'mdi-volume-low',
4727
+ volumeOff: 'mdi-volume-variant-off'
4705
4728
  };
4706
4729
  const mdi = {
4707
4730
  // Not using mergeProps here, functional components merge props by default (?)
@@ -10831,11 +10854,12 @@
10831
10854
  function onScroll(e) {
10832
10855
  data.isActive.value = false;
10833
10856
  }
10834
- bindScroll(data.targetEl.value ?? data.contentEl.value, onScroll);
10857
+ bindScroll(data.target.value ?? data.contentEl.value, onScroll);
10835
10858
  }
10836
10859
  function blockScrollStrategy(data, props) {
10837
10860
  const offsetParent = data.root.value?.offsetParent;
10838
- 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'));
10861
+ const target = Array.isArray(data.target.value) ? document.elementFromPoint(...data.target.value) : data.target.value;
10862
+ 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'));
10839
10863
  const scrollbarWidth = window.innerWidth - document.documentElement.offsetWidth;
10840
10864
  const scrollableParent = (el => hasScrollbar(el) && el)(offsetParent || document.documentElement);
10841
10865
  if (scrollableParent) {
@@ -10882,7 +10906,7 @@
10882
10906
  }
10883
10907
  ric = (typeof requestIdleCallback === 'undefined' ? cb => cb() : requestIdleCallback)(() => {
10884
10908
  scope.run(() => {
10885
- bindScroll(data.targetEl.value ?? data.contentEl.value, e => {
10909
+ bindScroll(data.target.value ?? data.contentEl.value, e => {
10886
10910
  if (slow) {
10887
10911
  // If the position calculation is slow,
10888
10912
  // defer updates until scrolling is finished.
@@ -10907,7 +10931,8 @@
10907
10931
  }
10908
10932
 
10909
10933
  /** @private */
10910
- function bindScroll(el, onScroll) {
10934
+ function bindScroll(target, onScroll) {
10935
+ const el = Array.isArray(target) ? document.elementFromPoint(...target) : target;
10911
10936
  const scrollElements = [document, ...getScrollParents(el)];
10912
10937
  scrollElements.forEach(el => {
10913
10938
  el.addEventListener('scroll', onScroll, {
@@ -11589,6 +11614,7 @@
11589
11614
  root,
11590
11615
  contentEl,
11591
11616
  targetEl,
11617
+ target,
11592
11618
  isActive,
11593
11619
  updateLocation
11594
11620
  });
@@ -11984,7 +12010,7 @@
11984
12010
 
11985
12011
  // Types
11986
12012
 
11987
- const allowedVariants$1 = ['underlined', 'outlined', 'filled', 'solo', 'solo-inverted', 'solo-filled', 'plain'];
12013
+ const allowedVariants$3 = ['underlined', 'outlined', 'filled', 'solo', 'solo-inverted', 'solo-filled', 'plain'];
11988
12014
  const makeVFieldProps = propsFactory({
11989
12015
  appendInnerIcon: IconValue,
11990
12016
  bgColor: String,
@@ -12018,7 +12044,7 @@
12018
12044
  variant: {
12019
12045
  type: String,
12020
12046
  default: 'filled',
12021
- validator: v => allowedVariants$1.includes(v)
12047
+ validator: v => allowedVariants$3.includes(v)
12022
12048
  },
12023
12049
  'onClick:clear': EventProp(),
12024
12050
  'onClick:appendInner': EventProp(),
@@ -16180,6 +16206,7 @@
16180
16206
  validator: v => ['vertical', 'horizontal'].includes(v)
16181
16207
  },
16182
16208
  reverse: Boolean,
16209
+ noKeyboard: Boolean,
16183
16210
  ...makeRoundedProps(),
16184
16211
  ...makeElevationProps({
16185
16212
  elevation: 2
@@ -16383,6 +16410,7 @@
16383
16410
  min,
16384
16411
  max,
16385
16412
  mousePressed,
16413
+ noKeyboard: vue.toRef(() => props.noKeyboard),
16386
16414
  numTicks,
16387
16415
  onSliderMousedown,
16388
16416
  onSliderTouchstart,
@@ -16435,6 +16463,7 @@
16435
16463
  default: true
16436
16464
  },
16437
16465
  name: String,
16466
+ noKeyboard: Boolean,
16438
16467
  ...makeComponentProps()
16439
16468
  }, 'VSliderThumb');
16440
16469
  const VSliderThumb = genericComponent()({
@@ -16497,6 +16526,7 @@
16497
16526
  if (step.value) return [1, 2, 3];else return [1, 5, 10];
16498
16527
  });
16499
16528
  function parseKeydown(e, value) {
16529
+ if (props.noKeyboard) return;
16500
16530
  if (!relevantKeys.includes(e.key)) return;
16501
16531
  e.preventDefault();
16502
16532
  const _step = step.value || 0.1;
@@ -16732,7 +16762,8 @@
16732
16762
  trackContainerRef,
16733
16763
  position,
16734
16764
  hasLabels,
16735
- readonly
16765
+ readonly,
16766
+ noKeyboard
16736
16767
  } = useSlider({
16737
16768
  props,
16738
16769
  steps,
@@ -16808,6 +16839,7 @@
16808
16839
  "ref": thumbContainerRef,
16809
16840
  "aria-describedby": messagesId.value,
16810
16841
  "focused": isFocused.value,
16842
+ "noKeyboard": noKeyboard.value,
16811
16843
  "min": min.value,
16812
16844
  "max": max.value,
16813
16845
  "modelValue": model.value,
@@ -23884,7 +23916,7 @@
23884
23916
 
23885
23917
  // Types
23886
23918
 
23887
- const allowedVariants = ['default', 'accordion', 'inset', 'popout'];
23919
+ const allowedVariants$2 = ['default', 'accordion', 'inset', 'popout'];
23888
23920
  const makeVExpansionPanelsProps = propsFactory({
23889
23921
  flat: Boolean,
23890
23922
  ...makeGroupProps(),
@@ -23895,7 +23927,7 @@
23895
23927
  variant: {
23896
23928
  type: String,
23897
23929
  default: 'default',
23898
- validator: v => allowedVariants.includes(v)
23930
+ validator: v => allowedVariants$2.includes(v)
23899
23931
  }
23900
23932
  }, 'VExpansionPanels');
23901
23933
  const VExpansionPanels = genericComponent()({
@@ -33186,6 +33218,707 @@
33186
33218
  }
33187
33219
  });
33188
33220
 
33221
+ // Types
33222
+
33223
+ const makeVVideoVolumeProps = propsFactory({
33224
+ inline: Boolean,
33225
+ label: String,
33226
+ direction: {
33227
+ type: String,
33228
+ default: 'vertical'
33229
+ },
33230
+ modelValue: {
33231
+ type: Number,
33232
+ default: 0
33233
+ },
33234
+ menuProps: Object,
33235
+ sliderProps: Object,
33236
+ onClick: EventProp(),
33237
+ ...makeComponentProps()
33238
+ }, 'VVideoVolume');
33239
+ const VVideoVolume = genericComponent()({
33240
+ name: 'VVideoVolume',
33241
+ props: makeVVideoVolumeProps(),
33242
+ emits: {
33243
+ 'update:modelValue': val => true
33244
+ },
33245
+ setup(props, _ref) {
33246
+ let {
33247
+ attrs
33248
+ } = _ref;
33249
+ const {
33250
+ t
33251
+ } = useLocale();
33252
+ const volume = useProxiedModel(props, 'modelValue');
33253
+ const volumeIcon = vue.toRef(() => volume.value > 70 ? '$volumeHigh' : volume.value > 40 ? '$volumeMedium' : volume.value > 10 ? '$volumeLow' : '$volumeOff');
33254
+ const containerRef = vue.ref();
33255
+ useRender(() => {
33256
+ const sliderDefaults = {
33257
+ hideDetails: true,
33258
+ step: 5,
33259
+ thumbSize: 16
33260
+ };
33261
+ return vue.createElementVNode("div", {
33262
+ "class": vue.normalizeClass(['v-video-volume', {
33263
+ 'v-video-volume--inline': props.inline
33264
+ }, props.class]),
33265
+ "style": vue.normalizeStyle(props.style),
33266
+ "ref": containerRef
33267
+ }, [vue.withDirectives(vue.createVNode(VIconBtn, vue.mergeProps({
33268
+ "icon": volumeIcon.value,
33269
+ "aria-label": props.label,
33270
+ "onClick": props.onClick
33271
+ }, attrs), {
33272
+ default: () => [vue.createVNode(VIcon, null, null), !props.inline && vue.createVNode(VMenu, {
33273
+ "offset": "8",
33274
+ "activator": "parent",
33275
+ "attach": containerRef.value,
33276
+ "location": props.menuProps?.location ?? 'top center',
33277
+ "closeOnContentClick": false
33278
+ }, {
33279
+ default: () => [vue.createElementVNode("div", {
33280
+ "class": vue.normalizeClass(['v-video-volume__menu', `v-video-volume__menu--${props.direction}`])
33281
+ }, [vue.createVNode(VSlider, vue.mergeProps({
33282
+ "direction": props.direction,
33283
+ "aria-label": t('$vuetify.video.volume'),
33284
+ "modelValue": volume.value,
33285
+ "onUpdate:modelValue": v => volume.value = v
33286
+ }, sliderDefaults, props.sliderProps), null)])]
33287
+ })]
33288
+ }), [[vue.resolveDirective("tooltip"), props.label, 'top']]), props.inline && vue.createVNode(VSlider, vue.mergeProps({
33289
+ "class": "v-video-volume-inline__slider",
33290
+ "minWidth": "50",
33291
+ "aria-label": t('$vuetify.video.volume'),
33292
+ "modelValue": volume.value,
33293
+ "onUpdate:modelValue": v => volume.value = v,
33294
+ "onKeydown": e => {
33295
+ e.stopPropagation();
33296
+ }
33297
+ }, sliderDefaults, props.sliderProps), null)]);
33298
+ });
33299
+ }
33300
+ });
33301
+
33302
+ // Types
33303
+
33304
+ const allowedVariants$1 = ['hidden', 'default', 'tube', 'mini'];
33305
+ const makeVVideoControlsProps = propsFactory({
33306
+ color: String,
33307
+ backgroundColor: String,
33308
+ trackColor: String,
33309
+ playing: Boolean,
33310
+ hidePlay: Boolean,
33311
+ hideVolume: Boolean,
33312
+ hideFullscreen: Boolean,
33313
+ fullscreen: Boolean,
33314
+ floating: Boolean,
33315
+ splitTime: Boolean,
33316
+ pills: Boolean,
33317
+ detached: Boolean,
33318
+ progress: {
33319
+ type: Number,
33320
+ default: 0
33321
+ },
33322
+ duration: {
33323
+ type: Number,
33324
+ default: 0
33325
+ },
33326
+ volume: [Number, String],
33327
+ variant: {
33328
+ type: String,
33329
+ default: 'default',
33330
+ validator: v => allowedVariants$1.includes(v)
33331
+ },
33332
+ volumeProps: Object,
33333
+ ...makeDensityProps(),
33334
+ ...makeElevationProps(),
33335
+ ...makeThemeProps()
33336
+ }, 'VVideoControls');
33337
+ const VVideoControls = genericComponent()({
33338
+ name: 'VVideoControls',
33339
+ props: makeVVideoControlsProps(),
33340
+ emits: {
33341
+ 'update:playing': val => true,
33342
+ 'update:progress': val => true,
33343
+ 'update:volume': val => true,
33344
+ skip: val => true,
33345
+ 'click:fullscreen': () => true
33346
+ },
33347
+ setup(props, _ref) {
33348
+ let {
33349
+ emit,
33350
+ slots
33351
+ } = _ref;
33352
+ const {
33353
+ t
33354
+ } = useLocale();
33355
+ const {
33356
+ themeClasses
33357
+ } = provideTheme(props);
33358
+ const {
33359
+ densityClasses
33360
+ } = useDensity(props);
33361
+ const {
33362
+ elevationClasses
33363
+ } = useElevation(props);
33364
+ const {
33365
+ backgroundColorClasses,
33366
+ backgroundColorStyles
33367
+ } = useBackgroundColor(() => {
33368
+ const fallbackBackground = props.detached ? 'surface' : undefined;
33369
+ return props.backgroundColor ?? fallbackBackground;
33370
+ });
33371
+ const playing = useProxiedModel(props, 'playing');
33372
+ const progress = useProxiedModel(props, 'progress');
33373
+ const volume = useProxiedModel(props, 'volume', 0, v => Number(v ?? 0));
33374
+ const lastVolume = vue.shallowRef();
33375
+ const currentTime = vue.computed(() => {
33376
+ const secondsElapsed = Math.round(props.progress / 100 * props.duration);
33377
+ return {
33378
+ elapsed: formatTime(secondsElapsed),
33379
+ remaining: formatTime(props.duration - secondsElapsed),
33380
+ total: formatTime(props.duration)
33381
+ };
33382
+ });
33383
+ const labels = vue.computed(() => {
33384
+ const playIconLocaleKey = playing.value ? 'pause' : 'play';
33385
+ const volumeIconLocaleKey = props.volumeProps?.inline ? volume.value ? 'mute' : 'unmute' : 'showVolume';
33386
+ const fullscreenIconLocaleKey = props.fullscreen ? 'exitFullscreen' : 'enterFullscreen';
33387
+ return {
33388
+ seek: t('$vuetify.video.seek'),
33389
+ volume: t('$vuetify.video.volume'),
33390
+ playAction: t(`$vuetify.video.${playIconLocaleKey}`),
33391
+ volumeAction: t(`$vuetify.video.${volumeIconLocaleKey}`),
33392
+ fullscreenAction: t(`$vuetify.video.${fullscreenIconLocaleKey}`)
33393
+ };
33394
+ });
33395
+ function play() {
33396
+ playing.value = true;
33397
+ }
33398
+ function pause() {
33399
+ playing.value = false;
33400
+ }
33401
+ function skipTo(v) {
33402
+ progress.value = v;
33403
+ }
33404
+ function toggleMuted() {
33405
+ if (volume.value) {
33406
+ lastVolume.value = volume.value;
33407
+ volume.value = 0;
33408
+ } else {
33409
+ volume.value = lastVolume.value ?? 100;
33410
+ }
33411
+ }
33412
+ function toggleFullscreen() {
33413
+ emit('click:fullscreen');
33414
+ }
33415
+ useRender(() => {
33416
+ const sizes = props.pills ? [42, 36, 30] : [32, 28, 24];
33417
+ const innerDefaults = {
33418
+ VIconBtn: {
33419
+ size: props.density === 'compact' ? sizes[2] : props.density === 'comfortable' ? sizes[1] : sizes[0],
33420
+ iconSize: props.density === 'compact' ? 20 : props.density === 'comfortable' ? 24 : 26,
33421
+ variant: 'text',
33422
+ color: props.color
33423
+ },
33424
+ VSlider: {
33425
+ thumbSize: props.variant === 'tube' ? 10 : 16,
33426
+ hideDetails: true
33427
+ }
33428
+ };
33429
+ const regularBtnSize = innerDefaults.VIconBtn.size;
33430
+ const playBtnSize = props.pills ? regularBtnSize + 8 : regularBtnSize;
33431
+ const pillClasses = ['v-video-control__pill', props.pills ? elevationClasses.value : []];
33432
+ const slotProps = {
33433
+ play,
33434
+ pause,
33435
+ playing: playing.value,
33436
+ progress: progress.value,
33437
+ currentTime: currentTime.value,
33438
+ skipTo,
33439
+ volume,
33440
+ toggleMuted,
33441
+ fullscreen: props.fullscreen,
33442
+ toggleFullscreen,
33443
+ labels: labels.value
33444
+ };
33445
+ return vue.createElementVNode("div", {
33446
+ "class": vue.normalizeClass(['v-video-controls', `v-video-controls--variant-${props.variant}`, {
33447
+ 'v-video-controls--pills': props.pills
33448
+ }, {
33449
+ 'v-video-controls--detached': props.detached
33450
+ }, {
33451
+ 'v-video-controls--floating': props.floating
33452
+ }, {
33453
+ 'v-video-controls--split-time': props.splitTime
33454
+ }, backgroundColorClasses.value, props.detached && !props.pills ? elevationClasses.value : [], densityClasses.value, themeClasses.value]),
33455
+ "style": vue.normalizeStyle([backgroundColorStyles.value, {
33456
+ '--v-video-controls-pill-height': `${regularBtnSize}px`
33457
+ }])
33458
+ }, [vue.createVNode(VDefaultsProvider, {
33459
+ "defaults": innerDefaults
33460
+ }, {
33461
+ default: () => [slots.default?.(slotProps) ?? vue.createElementVNode(vue.Fragment, null, [props.variant !== 'mini' && vue.createElementVNode(vue.Fragment, null, [!props.hidePlay && vue.createElementVNode("div", {
33462
+ "class": vue.normalizeClass([pillClasses, 'v-video__action-play'])
33463
+ }, [vue.withDirectives(vue.createVNode(VIconBtn, {
33464
+ "icon": playing.value ? '$pause' : '$play',
33465
+ "size": playBtnSize,
33466
+ "aria-label": labels.value.playAction,
33467
+ "onClick": () => playing.value = !playing.value
33468
+ }, null), [[vue.resolveDirective("tooltip"), labels.value.playAction, 'top']])]), slots.prepend && vue.createElementVNode("div", {
33469
+ "class": vue.normalizeClass(pillClasses)
33470
+ }, [slots.prepend(slotProps)]), props.splitTime ? vue.createElementVNode("span", {
33471
+ "class": vue.normalizeClass([pillClasses, 'v-video__time'])
33472
+ }, [currentTime.value.elapsed]) : props.variant !== 'default' ? vue.createElementVNode("span", {
33473
+ "class": vue.normalizeClass([pillClasses, 'v-video__time'])
33474
+ }, [currentTime.value.elapsed, vue.createTextVNode(" / "), currentTime.value.total]) : '', vue.createVNode(VSlider, {
33475
+ "modelValue": props.progress,
33476
+ "noKeyboard": true,
33477
+ "color": props.trackColor ?? props.color,
33478
+ "trackColor": props.variant === 'tube' ? 'white' : undefined,
33479
+ "class": "v-video__track",
33480
+ "thumbLabel": "always",
33481
+ "aria-label": labels.value.seek,
33482
+ "onUpdate:modelValue": skipTo
33483
+ }, {
33484
+ 'thumb-label': () => currentTime.value.elapsed
33485
+ }), props.variant === 'tube' && vue.createVNode(VSpacer, null, null), props.splitTime ? vue.createElementVNode("span", {
33486
+ "class": vue.normalizeClass([pillClasses, 'v-video__time'])
33487
+ }, [currentTime.value.remaining]) : '']), props.variant === 'mini' && vue.createElementVNode(vue.Fragment, null, [vue.createVNode(VSpacer, null, null), slots.prepend && vue.createElementVNode("div", {
33488
+ "class": vue.normalizeClass(pillClasses)
33489
+ }, [slots.prepend(slotProps)]), !props.hidePlay && vue.createElementVNode("div", {
33490
+ "class": vue.normalizeClass([pillClasses, 'v-video__action-play'])
33491
+ }, [vue.withDirectives(vue.createVNode(VIconBtn, {
33492
+ "icon": playing.value ? '$pause' : '$play',
33493
+ "size": playBtnSize,
33494
+ "aria-label": labels.value.playAction,
33495
+ "onClick": () => playing.value = !playing.value
33496
+ }, null), [[vue.resolveDirective("tooltip"), labels.value.playAction, 'top']])])]), (!props.hideVolume || !props.hideFullscreen || slots.append) && vue.createElementVNode("div", {
33497
+ "class": vue.normalizeClass(pillClasses)
33498
+ }, [!props.hideVolume && vue.createVNode(VVideoVolume, vue.mergeProps({
33499
+ "key": "volume-control",
33500
+ "sliderProps": {
33501
+ color: props.color
33502
+ },
33503
+ "modelValue": volume.value,
33504
+ "label": labels.value.volumeAction,
33505
+ "onUpdate:modelValue": v => volume.value = v,
33506
+ "onClick": () => props.volumeProps?.inline && toggleMuted()
33507
+ }, props.volumeProps), null), slots.append?.(slotProps), !props.hideFullscreen && vue.withDirectives(vue.createVNode(VIconBtn, {
33508
+ "icon": props.fullscreen ? '$fullscreenExit' : '$fullscreen',
33509
+ "aria-label": labels.value.fullscreenAction,
33510
+ "onClick": toggleFullscreen
33511
+ }, null), [[vue.resolveDirective("tooltip"), labels.value.fullscreenAction, 'top']])]), props.variant === 'mini' && vue.createVNode(VSpacer, null, null)])]
33512
+ })]);
33513
+ });
33514
+ return {
33515
+ toggleMuted
33516
+ };
33517
+ }
33518
+ });
33519
+
33520
+ // Types
33521
+
33522
+ const allowedVariants = ['background', 'player'];
33523
+ const makeVVideoProps = propsFactory({
33524
+ autoplay: Boolean,
33525
+ muted: Boolean,
33526
+ eager: Boolean,
33527
+ src: String,
33528
+ type: String,
33529
+ // e.g. video/mp4
33530
+ image: String,
33531
+ hideOverlay: Boolean,
33532
+ noFullscreen: Boolean,
33533
+ startAt: [Number, String],
33534
+ variant: {
33535
+ type: String,
33536
+ default: 'player',
33537
+ validator: v => allowedVariants.includes(v)
33538
+ },
33539
+ controlsTransition: {
33540
+ type: [Boolean, String, Object],
33541
+ component: VFadeTransition
33542
+ },
33543
+ controlsVariant: {
33544
+ type: String,
33545
+ default: 'default'
33546
+ },
33547
+ controlsProps: {
33548
+ type: Object
33549
+ },
33550
+ rounded: [Boolean, Number, String, Array],
33551
+ ...makeComponentProps(),
33552
+ ...makeDensityProps(),
33553
+ ...makeDimensionProps(),
33554
+ ...makeThemeProps(),
33555
+ ...omit(makeVVideoControlsProps(), ['fullscreen', 'variant'])
33556
+ }, 'VVideo');
33557
+ const VVideo = genericComponent()({
33558
+ name: 'VVideo',
33559
+ inheritAttrs: false,
33560
+ props: makeVVideoProps(),
33561
+ emits: {
33562
+ loaded: element => true,
33563
+ 'update:playing': val => true,
33564
+ 'update:progress': val => true,
33565
+ 'update:volume': val => true
33566
+ },
33567
+ setup(props, _ref) {
33568
+ let {
33569
+ attrs,
33570
+ emit,
33571
+ slots
33572
+ } = _ref;
33573
+ const {
33574
+ themeClasses
33575
+ } = provideTheme(props);
33576
+ const {
33577
+ densityClasses
33578
+ } = useDensity(props);
33579
+ const {
33580
+ dimensionStyles
33581
+ } = useDimension(props);
33582
+ const {
33583
+ elevationClasses
33584
+ } = useElevation(props);
33585
+ const {
33586
+ ssr
33587
+ } = useDisplay();
33588
+ const roundedForContainer = vue.toRef(() => Array.isArray(props.rounded) ? props.rounded[0] : props.rounded);
33589
+ const roundedForControls = vue.toRef(() => Array.isArray(props.rounded) ? props.rounded.at(-1) : props.rounded ?? false);
33590
+ const {
33591
+ roundedClasses: roundedContainerClasses
33592
+ } = useRounded(roundedForContainer);
33593
+ const {
33594
+ roundedClasses: roundedControlsClasses
33595
+ } = useRounded(roundedForControls);
33596
+ const containerRef = vue.ref();
33597
+ const videoRef = vue.ref();
33598
+ const controlsRef = vue.ref();
33599
+ const playing = useProxiedModel(props, 'playing');
33600
+ const progress = useProxiedModel(props, 'progress');
33601
+ const volume = useProxiedModel(props, 'volume', 0, v => Number(v ?? 0));
33602
+ const fullscreen = vue.shallowRef(false);
33603
+ const waiting = vue.shallowRef(false);
33604
+ const triggered = vue.shallowRef(false);
33605
+ const startAfterLoad = vue.shallowRef(false);
33606
+ const state = vue.shallowRef(props.autoplay ? 'loading' : 'idle');
33607
+ const duration = vue.shallowRef(0);
33608
+ const fullscreenEnabled = vue.toRef(() => !props.noFullscreen && !String(attrs.controlsList ?? '').includes('nofullscreen'));
33609
+ function onTimeupdate() {
33610
+ const {
33611
+ currentTime,
33612
+ duration
33613
+ } = videoRef.value;
33614
+ progress.value = duration === 0 ? 0 : 100 * currentTime / duration;
33615
+ }
33616
+ async function onTriggered() {
33617
+ await vue.nextTick();
33618
+ if (!videoRef.value) return;
33619
+ videoRef.value.addEventListener('timeupdate', onTimeupdate);
33620
+ videoRef.value.volume = volume.value / 100;
33621
+ if (state.value !== 'loaded') {
33622
+ state.value = 'loading';
33623
+ }
33624
+ }
33625
+ function onVideoLoaded() {
33626
+ state.value = 'loaded';
33627
+ duration.value = videoRef.value.duration;
33628
+ const startTime = Number(props.startAt ?? 0);
33629
+ if (startTime && startTime <= duration.value) {
33630
+ videoRef.value.currentTime = startTime;
33631
+ progress.value = duration.value === 0 ? 0 : 100 * startTime / duration.value;
33632
+ }
33633
+ if (startAfterLoad.value) {
33634
+ setTimeout(() => playing.value = true, 100);
33635
+ }
33636
+ emit('loaded', videoRef.value);
33637
+ }
33638
+ function onClick() {
33639
+ if (state.value !== 'loaded') {
33640
+ triggered.value = true;
33641
+ startAfterLoad.value = !startAfterLoad.value;
33642
+ }
33643
+ }
33644
+ function onKeydown(e) {
33645
+ if (!videoRef.value || e.ctrlKey) return;
33646
+ if (e.key.startsWith('Arrow')) {
33647
+ e.preventDefault();
33648
+ }
33649
+ switch (true) {
33650
+ case e.key === ' ':
33651
+ {
33652
+ if (!['A', 'BUTTON'].includes(e.target?.tagName)) {
33653
+ e.preventDefault();
33654
+ playing.value = !playing.value;
33655
+ }
33656
+ break;
33657
+ }
33658
+ case e.key === 'ArrowRight':
33659
+ {
33660
+ const step = 10 * (e.shiftKey ? 6 : 1);
33661
+ videoRef.value.currentTime = Math.min(videoRef.value.currentTime + step, duration.value);
33662
+ // TODO: show skip indicator
33663
+ break;
33664
+ }
33665
+ case e.key === 'ArrowLeft':
33666
+ {
33667
+ const step = 10 * (e.shiftKey ? 6 : 1);
33668
+ videoRef.value.currentTime = Math.max(videoRef.value.currentTime - step, 0);
33669
+ // TODO: show skip indicator
33670
+ break;
33671
+ }
33672
+ case createRange(10).map(String).includes(e.key):
33673
+ {
33674
+ skipTo(Number(e.key) * 10);
33675
+ break;
33676
+ }
33677
+ case e.key === 'ArrowUp':
33678
+ {
33679
+ volume.value = Math.min(volume.value + 10, 100);
33680
+ // TODO: show volume change indicator
33681
+ break;
33682
+ }
33683
+ case e.key === 'ArrowDown':
33684
+ {
33685
+ volume.value = Math.max(volume.value - 10, 0);
33686
+ // TODO: show volume change indicator
33687
+ break;
33688
+ }
33689
+ case e.key === 'm':
33690
+ {
33691
+ controlsRef.value?.toggleMuted();
33692
+ break;
33693
+ }
33694
+ case e.key === 'f':
33695
+ {
33696
+ toggleFullscreen();
33697
+ break;
33698
+ }
33699
+ }
33700
+ }
33701
+ function skipTo(v) {
33702
+ if (!videoRef.value) return;
33703
+ progress.value = v;
33704
+ videoRef.value.currentTime = duration.value * v / 100;
33705
+ }
33706
+ vue.watch(() => props.src, v => {
33707
+ progress.value = 0;
33708
+ });
33709
+ vue.watch(playing, v => {
33710
+ if (!videoRef.value) return;
33711
+ if (v) {
33712
+ videoRef.value.play();
33713
+ } else {
33714
+ videoRef.value.pause();
33715
+ }
33716
+ });
33717
+ vue.watch(volume, v => {
33718
+ if (!videoRef.value) return;
33719
+ videoRef.value.volume = v / 100;
33720
+ });
33721
+ vue.watch(triggered, () => onTriggered(), {
33722
+ once: true
33723
+ });
33724
+ vue.watch(() => props.eager, v => v && (triggered.value = true), {
33725
+ immediate: true
33726
+ });
33727
+ vue.onMounted(() => {
33728
+ if (props.autoplay && !ssr) {
33729
+ triggered.value = true;
33730
+ startAfterLoad.value = true;
33731
+ }
33732
+ });
33733
+ vue.onBeforeUnmount(() => {
33734
+ videoRef.value?.removeEventListener('timeupdate', onTimeupdate);
33735
+ });
33736
+ function focusSlider() {
33737
+ const container = videoRef.value?.closest('.v-video');
33738
+ const innerSlider = container?.querySelector('[role="slider"]');
33739
+ innerSlider?.focus();
33740
+ }
33741
+ function fullscreenExitShortcut(e) {
33742
+ if (['ESC', 'f'].includes(e.key)) {
33743
+ toggleFullscreen();
33744
+ document.body.removeEventListener('keydown', fullscreenExitShortcut);
33745
+ }
33746
+ }
33747
+ async function toggleFullscreen() {
33748
+ if (!fullscreenEnabled.value || !document.fullscreenEnabled) {
33749
+ return;
33750
+ }
33751
+ if (document.fullscreenElement) {
33752
+ document.exitFullscreen();
33753
+ onFullscreenExit();
33754
+ } else {
33755
+ await containerRef.value?.requestFullscreen();
33756
+ document.body.addEventListener('keydown', fullscreenExitShortcut);
33757
+ document.addEventListener('fullscreenchange', onFullscreenExit);
33758
+ fullscreen.value = true;
33759
+ }
33760
+ }
33761
+ function onFullscreenExit() {
33762
+ // event fires with a delay after requestFullscreen(), ignore first run
33763
+ if (document.fullscreenElement) return;
33764
+ focusSlider();
33765
+ fullscreen.value = false;
33766
+ document.body.removeEventListener('keydown', fullscreenExitShortcut);
33767
+ document.removeEventListener('fullscreenchange', onFullscreenExit);
33768
+ }
33769
+ function onVideoClick(e) {
33770
+ e.preventDefault();
33771
+ if (state.value === 'loaded') {
33772
+ playing.value = !playing.value;
33773
+ focusSlider();
33774
+ }
33775
+ }
33776
+ function onDoubleClick(e) {
33777
+ e.preventDefault();
33778
+ toggleFullscreen();
33779
+ }
33780
+ let lastTap = 0;
33781
+ function onTouchend(e) {
33782
+ const now = performance.now();
33783
+ if (now - lastTap < 500) {
33784
+ e.preventDefault();
33785
+ toggleFullscreen();
33786
+ } else {
33787
+ lastTap = now;
33788
+ }
33789
+ }
33790
+ useRender(() => {
33791
+ const showControls = state.value === 'loaded' && props.variant === 'player' && props.controlsVariant !== 'hidden';
33792
+ const posterTransition = props.variant === 'background' ? 'poster-fade-out' : 'fade-transition';
33793
+ const overlayProps = {
33794
+ contained: true,
33795
+ persistent: true,
33796
+ contentClass: 'v-video__overlay-fill'
33797
+ };
33798
+ const controlsProps = {
33799
+ ...VVideoControls.filterProps(omit(props, ['variant', 'rounded', 'hideVolume'])),
33800
+ rounded: Array.isArray(props.rounded) ? props.rounded.at(-1) : props.rounded,
33801
+ fullscreen: fullscreen.value,
33802
+ hideVolume: props.hideVolume || props.muted,
33803
+ hideFullscreen: props.hideFullscreen || !fullscreenEnabled.value,
33804
+ density: props.density,
33805
+ variant: props.controlsVariant,
33806
+ playing: playing.value,
33807
+ progress: progress.value,
33808
+ duration: duration.value,
33809
+ volume: volume.value,
33810
+ ...props.controlsProps
33811
+ };
33812
+ const controlsEventHandlers = {
33813
+ onSkip: v => skipTo(v),
33814
+ 'onClick:fullscreen': () => toggleFullscreen(),
33815
+ 'onUpdate:playing': v => playing.value = v,
33816
+ 'onUpdate:progress': v => skipTo(v),
33817
+ 'onUpdate:volume': v => volume.value = v,
33818
+ onClick: e => e.stopPropagation()
33819
+ };
33820
+ const controlslist = [attrs.controlslist, props.noFullscreen ? 'nofullscreen' : ''].filter(Boolean).join(' ');
33821
+ const loadingIndicator = vue.createVNode(VProgressCircular, {
33822
+ "indeterminate": true,
33823
+ "color": props.color,
33824
+ "width": "3",
33825
+ "size": Math.min(100, Number(props.height) / 2 || 50)
33826
+ }, null);
33827
+ const overlayPlayIcon = vue.createVNode(VIconBtn, {
33828
+ "icon": "$play",
33829
+ "size": "80",
33830
+ "color": "#fff",
33831
+ "variant": "outlined",
33832
+ "iconSize": "50",
33833
+ "class": "v-video__center-icon"
33834
+ }, null);
33835
+ return vue.createElementVNode("div", {
33836
+ "ref": containerRef,
33837
+ "class": vue.normalizeClass(['v-video', `v-video--variant-${props.variant}`, `v-video--${state.value}`, {
33838
+ 'v-video--playing': playing.value
33839
+ }, themeClasses.value, densityClasses.value, roundedContainerClasses.value, props.class]),
33840
+ "style": vue.normalizeStyle([props.variant === 'background' ? [] : pick(dimensionStyles.value, ['width', 'min-width', 'max-width']), props.style]),
33841
+ "onKeydown": onKeydown,
33842
+ "onClick": onClick
33843
+ }, [vue.createElementVNode("div", {
33844
+ "class": vue.normalizeClass(['v-video__content', elevationClasses.value]),
33845
+ "style": vue.normalizeStyle([props.variant === 'background' ? [] : dimensionStyles.value])
33846
+ }, [(props.eager || triggered.value) && vue.createElementVNode("video", vue.mergeProps({
33847
+ "key": "video-element",
33848
+ "class": ['v-video__video', roundedContainerClasses.value]
33849
+ }, omit(attrs, ['controlslist', 'class', 'style']), {
33850
+ "controlslist": controlslist,
33851
+ "autoplay": props.autoplay,
33852
+ "muted": props.muted,
33853
+ "playsinline": true,
33854
+ "ref": videoRef,
33855
+ "onLoadeddata": onVideoLoaded,
33856
+ "onPlay": () => playing.value = true,
33857
+ "onPause": () => playing.value = false,
33858
+ "onWaiting": () => waiting.value = true,
33859
+ "onPlaying": () => waiting.value = false,
33860
+ "onClick": onVideoClick,
33861
+ "onDblclick": onDoubleClick,
33862
+ "onTouchend": onTouchend
33863
+ }), [slots.sources?.() ?? vue.createElementVNode("source", {
33864
+ "src": props.src,
33865
+ "type": props.type
33866
+ }, null)]), props.variant === 'player' && !props.hideOverlay && vue.createVNode(VOverlay, vue.mergeProps({
33867
+ "key": "pause-overlay",
33868
+ "modelValue": state.value === 'loaded',
33869
+ "opacity": "0"
33870
+ }, overlayProps), {
33871
+ default: () => [vue.createVNode(VSpacer, null, null), vue.createVNode(MaybeTransition, {
33872
+ "name": "fade-transition"
33873
+ }, {
33874
+ default: () => [!playing.value && overlayPlayIcon]
33875
+ }), vue.createVNode(VSpacer, null, null)]
33876
+ }), props.variant === 'player' && !!slots.header ? vue.createElementVNode("div", {
33877
+ "key": "header",
33878
+ "class": "v-video__header"
33879
+ }, [slots.header()]) : '', vue.createVNode(VOverlay, vue.mergeProps({
33880
+ "key": "poster-overlay",
33881
+ "modelValue": state.value !== 'loaded',
33882
+ "transition": posterTransition
33883
+ }, overlayProps), {
33884
+ default: () => [vue.createVNode(VImg, {
33885
+ "cover": true,
33886
+ "src": props.image
33887
+ }, {
33888
+ default: () => [vue.createElementVNode("div", {
33889
+ "class": vue.normalizeClass(['v-video__overlay-fill', ...roundedContainerClasses.value])
33890
+ }, [overlayPlayIcon])]
33891
+ })]
33892
+ }), vue.createVNode(VOverlay, vue.mergeProps({
33893
+ "key": "loading-overlay",
33894
+ "modelValue": state.value === 'loading' || waiting.value,
33895
+ "opacity": ".1"
33896
+ }, overlayProps), {
33897
+ default: () => [loadingIndicator]
33898
+ })]), vue.createVNode(MaybeTransition, {
33899
+ "key": "actions",
33900
+ "transition": props.controlsTransition
33901
+ }, {
33902
+ default: () => [showControls && vue.createVNode(VVideoControls, vue.mergeProps({
33903
+ "ref": controlsRef,
33904
+ "class": roundedControlsClasses.value
33905
+ }, controlsProps, controlsEventHandlers), {
33906
+ default: slots.controls,
33907
+ prepend: slots.prepend,
33908
+ append: slots.append
33909
+ })]
33910
+ })]);
33911
+ });
33912
+ return {
33913
+ video: videoRef,
33914
+ ...forwardRefs({
33915
+ skipTo,
33916
+ toggleFullscreen
33917
+ }, controlsRef)
33918
+ };
33919
+ }
33920
+ });
33921
+
33189
33922
  var components = /*#__PURE__*/Object.freeze({
33190
33923
  __proto__: null,
33191
33924
  VAlert: VAlert,
@@ -33376,6 +34109,9 @@
33376
34109
  VTreeviewGroup: VTreeviewGroup,
33377
34110
  VTreeviewItem: VTreeviewItem,
33378
34111
  VValidation: VValidation,
34112
+ VVideo: VVideo,
34113
+ VVideoControls: VVideoControls,
34114
+ VVideoVolume: VVideoVolume,
33379
34115
  VVirtualScroll: VVirtualScroll,
33380
34116
  VWindow: VWindow,
33381
34117
  VWindowItem: VWindowItem
@@ -33698,7 +34434,7 @@
33698
34434
  };
33699
34435
  });
33700
34436
  }
33701
- const version$1 = "3.9.2-master.2025-07-23";
34437
+ const version$1 = "3.9.2-master.2025-07-24";
33702
34438
  createVuetify$1.version = version$1;
33703
34439
 
33704
34440
  // Vue's inject() can only be used in setup
@@ -33996,7 +34732,7 @@
33996
34732
 
33997
34733
  /* eslint-disable local-rules/sort-imports */
33998
34734
 
33999
- const version = "3.9.2-master.2025-07-23";
34735
+ const version = "3.9.2-master.2025-07-24";
34000
34736
 
34001
34737
  /* eslint-disable local-rules/sort-imports */
34002
34738