@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.
- package/CHANGELOG.md +11 -3
- package/dist/_component-variables-labs.sass +2 -1
- package/dist/json/attributes.json +2563 -2299
- package/dist/json/importMap-labs.json +24 -12
- package/dist/json/importMap.json +174 -174
- package/dist/json/tags.json +81 -0
- package/dist/json/web-types.json +5100 -3978
- package/dist/vuetify-labs.cjs +751 -15
- package/dist/vuetify-labs.css +5171 -4837
- package/dist/vuetify-labs.d.ts +6526 -845
- package/dist/vuetify-labs.esm.js +752 -16
- package/dist/vuetify-labs.esm.js.map +1 -1
- package/dist/vuetify-labs.js +751 -15
- package/dist/vuetify-labs.min.css +2 -2
- package/dist/vuetify.cjs +37 -9
- package/dist/vuetify.cjs.map +1 -1
- package/dist/vuetify.css +3169 -3169
- package/dist/vuetify.d.ts +88 -68
- package/dist/vuetify.esm.js +37 -9
- package/dist/vuetify.esm.js.map +1 -1
- package/dist/vuetify.js +37 -9
- package/dist/vuetify.js.map +1 -1
- package/dist/vuetify.min.css +2 -2
- package/dist/vuetify.min.js +264 -263
- package/dist/vuetify.min.js.map +1 -1
- package/lib/components/VBottomSheet/VBottomSheet.d.ts +6 -6
- package/lib/components/VDialog/VDialog.d.ts +6 -6
- package/lib/components/VOverlay/VOverlay.js +1 -0
- package/lib/components/VOverlay/VOverlay.js.map +1 -1
- package/lib/components/VOverlay/scrollStrategies.d.ts +1 -0
- package/lib/components/VOverlay/scrollStrategies.js +6 -4
- package/lib/components/VOverlay/scrollStrategies.js.map +1 -1
- package/lib/components/VRangeSlider/VRangeSlider.d.ts +13 -0
- package/lib/components/VSlider/VSlider.d.ts +13 -0
- package/lib/components/VSlider/VSlider.js +3 -1
- package/lib/components/VSlider/VSlider.js.map +1 -1
- package/lib/components/VSlider/VSliderThumb.d.ts +13 -0
- package/lib/components/VSlider/VSliderThumb.js +2 -0
- package/lib/components/VSlider/VSliderThumb.js.map +1 -1
- package/lib/components/VSlider/slider.d.ts +6 -0
- package/lib/components/VSlider/slider.js +2 -0
- package/lib/components/VSlider/slider.js.map +1 -1
- package/lib/components/index.js +1 -1
- package/lib/components/index.js.map +1 -1
- package/lib/entry-bundler.js +1 -1
- package/lib/framework.d.ts +60 -56
- package/lib/framework.js +1 -1
- package/lib/iconsets/fa.js +9 -1
- package/lib/iconsets/fa.js.map +1 -1
- package/lib/iconsets/fa4.js +9 -1
- package/lib/iconsets/fa4.js.map +1 -1
- package/lib/iconsets/md.js +9 -1
- package/lib/iconsets/md.js.map +1 -1
- package/lib/iconsets/mdi-svg.js +9 -1
- package/lib/iconsets/mdi-svg.js.map +1 -1
- package/lib/iconsets/mdi.js +9 -1
- package/lib/iconsets/mdi.js.map +1 -1
- package/lib/labs/VVideo/VVideo.css +319 -0
- package/lib/labs/VVideo/VVideo.d.ts +6932 -0
- package/lib/labs/VVideo/VVideo.js +424 -0
- package/lib/labs/VVideo/VVideo.js.map +1 -0
- package/lib/labs/VVideo/VVideo.sass +301 -0
- package/lib/labs/VVideo/VVideoControls.d.ts +3524 -0
- package/lib/labs/VVideo/VVideoControls.js +232 -0
- package/lib/labs/VVideo/VVideoControls.js.map +1 -0
- package/lib/labs/VVideo/VVideoVolume.d.ts +3088 -0
- package/lib/labs/VVideo/VVideoVolume.js +90 -0
- package/lib/labs/VVideo/VVideoVolume.js.map +1 -0
- package/lib/labs/VVideo/_variables.scss +58 -0
- package/lib/labs/VVideo/index.d.ts +3 -0
- package/lib/labs/VVideo/index.js +4 -0
- package/lib/labs/VVideo/index.js.map +1 -0
- package/lib/labs/components.d.ts +1 -0
- package/lib/labs/components.js +1 -0
- package/lib/labs/components.js.map +1 -1
- package/lib/locale/af.d.ts +11 -0
- package/lib/locale/af.js +11 -0
- package/lib/locale/af.js.map +1 -1
- package/lib/locale/ar.d.ts +11 -0
- package/lib/locale/ar.js +11 -0
- package/lib/locale/ar.js.map +1 -1
- package/lib/locale/az.d.ts +11 -0
- package/lib/locale/az.js +11 -0
- package/lib/locale/az.js.map +1 -1
- package/lib/locale/bg.d.ts +11 -0
- package/lib/locale/bg.js +11 -0
- package/lib/locale/bg.js.map +1 -1
- package/lib/locale/ca.d.ts +11 -0
- package/lib/locale/ca.js +11 -0
- package/lib/locale/ca.js.map +1 -1
- package/lib/locale/ckb.d.ts +11 -0
- package/lib/locale/ckb.js +11 -0
- package/lib/locale/ckb.js.map +1 -1
- package/lib/locale/cs.d.ts +11 -0
- package/lib/locale/cs.js +11 -0
- package/lib/locale/cs.js.map +1 -1
- package/lib/locale/da.d.ts +11 -0
- package/lib/locale/da.js +11 -0
- package/lib/locale/da.js.map +1 -1
- package/lib/locale/de.d.ts +11 -0
- package/lib/locale/de.js +11 -0
- package/lib/locale/de.js.map +1 -1
- package/lib/locale/el.d.ts +11 -0
- package/lib/locale/el.js +11 -0
- package/lib/locale/el.js.map +1 -1
- package/lib/locale/en.d.ts +11 -0
- package/lib/locale/en.js +11 -0
- package/lib/locale/en.js.map +1 -1
- package/lib/locale/es.d.ts +11 -0
- package/lib/locale/es.js +11 -0
- package/lib/locale/es.js.map +1 -1
- package/lib/locale/et.d.ts +11 -0
- package/lib/locale/et.js +11 -0
- package/lib/locale/et.js.map +1 -1
- package/lib/locale/fa.d.ts +11 -0
- package/lib/locale/fa.js +11 -0
- package/lib/locale/fa.js.map +1 -1
- package/lib/locale/fi.d.ts +11 -0
- package/lib/locale/fi.js +11 -0
- package/lib/locale/fi.js.map +1 -1
- package/lib/locale/fr.d.ts +11 -0
- package/lib/locale/fr.js +11 -0
- package/lib/locale/fr.js.map +1 -1
- package/lib/locale/he.d.ts +11 -0
- package/lib/locale/he.js +11 -0
- package/lib/locale/he.js.map +1 -1
- package/lib/locale/hr.d.ts +11 -0
- package/lib/locale/hr.js +11 -0
- package/lib/locale/hr.js.map +1 -1
- package/lib/locale/hu.d.ts +11 -0
- package/lib/locale/hu.js +11 -0
- package/lib/locale/hu.js.map +1 -1
- package/lib/locale/id.d.ts +11 -0
- package/lib/locale/id.js +11 -0
- package/lib/locale/id.js.map +1 -1
- package/lib/locale/it.d.ts +11 -0
- package/lib/locale/it.js +11 -0
- package/lib/locale/it.js.map +1 -1
- package/lib/locale/ja.d.ts +11 -0
- package/lib/locale/ja.js +11 -0
- package/lib/locale/ja.js.map +1 -1
- package/lib/locale/km.d.ts +11 -0
- package/lib/locale/km.js +11 -0
- package/lib/locale/km.js.map +1 -1
- package/lib/locale/ko.d.ts +11 -0
- package/lib/locale/ko.js +11 -0
- package/lib/locale/ko.js.map +1 -1
- package/lib/locale/lt.d.ts +11 -0
- package/lib/locale/lt.js +11 -0
- package/lib/locale/lt.js.map +1 -1
- package/lib/locale/lv.d.ts +11 -0
- package/lib/locale/lv.js +11 -0
- package/lib/locale/lv.js.map +1 -1
- package/lib/locale/nl.d.ts +11 -0
- package/lib/locale/nl.js +11 -0
- package/lib/locale/nl.js.map +1 -1
- package/lib/locale/no.d.ts +11 -0
- package/lib/locale/no.js +11 -0
- package/lib/locale/no.js.map +1 -1
- package/lib/locale/pl.d.ts +11 -0
- package/lib/locale/pl.js +11 -0
- package/lib/locale/pl.js.map +1 -1
- package/lib/locale/pt.d.ts +11 -0
- package/lib/locale/pt.js +11 -0
- package/lib/locale/pt.js.map +1 -1
- package/lib/locale/ro.d.ts +11 -0
- package/lib/locale/ro.js +11 -0
- package/lib/locale/ro.js.map +1 -1
- package/lib/locale/ru.d.ts +11 -0
- package/lib/locale/ru.js +11 -0
- package/lib/locale/ru.js.map +1 -1
- package/lib/locale/sk.d.ts +11 -0
- package/lib/locale/sk.js +11 -0
- package/lib/locale/sk.js.map +1 -1
- package/lib/locale/sl.d.ts +11 -0
- package/lib/locale/sl.js +11 -0
- package/lib/locale/sl.js.map +1 -1
- package/lib/locale/sr-Cyrl.d.ts +11 -0
- package/lib/locale/sr-Cyrl.js +11 -0
- package/lib/locale/sr-Cyrl.js.map +1 -1
- package/lib/locale/sr-Latn.d.ts +11 -0
- package/lib/locale/sr-Latn.js +11 -0
- package/lib/locale/sr-Latn.js.map +1 -1
- package/lib/locale/sv.d.ts +11 -0
- package/lib/locale/sv.js +11 -0
- package/lib/locale/sv.js.map +1 -1
- package/lib/locale/th.d.ts +11 -0
- package/lib/locale/th.js +11 -0
- package/lib/locale/th.js.map +1 -1
- package/lib/locale/tr.d.ts +11 -0
- package/lib/locale/tr.js +11 -0
- package/lib/locale/tr.js.map +1 -1
- package/lib/locale/uk.d.ts +11 -0
- package/lib/locale/uk.js +11 -0
- package/lib/locale/uk.js.map +1 -1
- package/lib/locale/vi.d.ts +11 -0
- package/lib/locale/vi.js +11 -0
- package/lib/locale/vi.js.map +1 -1
- package/lib/locale/zh-Hans.d.ts +11 -0
- package/lib/locale/zh-Hans.js +11 -0
- package/lib/locale/zh-Hans.js.map +1 -1
- package/lib/locale/zh-Hant.d.ts +11 -0
- package/lib/locale/zh-Hant.js +11 -0
- package/lib/locale/zh-Hant.js.map +1 -1
- package/lib/util/index.d.ts +1 -0
- package/lib/util/index.js +1 -0
- package/lib/util/index.js.map +1 -1
- package/lib/util/timeUtils.d.ts +1 -0
- package/lib/util/timeUtils.js +4 -0
- package/lib/util/timeUtils.js.map +1 -0
- package/package.json +1 -1
package/dist/vuetify-labs.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* Vuetify v3.9.2-master.2025-07-
|
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$
|
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$
|
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.
|
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
|
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.
|
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(
|
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$
|
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$
|
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-
|
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-
|
34735
|
+
const version = "3.9.2-master.2025-07-24";
|
34000
34736
|
|
34001
34737
|
/* eslint-disable local-rules/sort-imports */
|
34002
34738
|
|