@vuetify/nightly 3.9.2-master.2025-07-23 → 3.9.2-master.2025-07-25
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 +15 -3
- package/dist/_component-variables-labs.sass +3 -1
- package/dist/json/attributes.json +4029 -3617
- package/dist/json/importMap-labs.json +38 -14
- package/dist/json/importMap.json +148 -148
- package/dist/json/tags.json +133 -0
- package/dist/json/web-types.json +13484 -11867
- package/dist/vuetify-labs.cjs +1525 -126
- package/dist/vuetify-labs.css +5448 -5007
- package/dist/vuetify-labs.d.ts +7670 -974
- package/dist/vuetify-labs.esm.js +1526 -127
- package/dist/vuetify-labs.esm.js.map +1 -1
- package/dist/vuetify-labs.js +1525 -126
- package/dist/vuetify-labs.min.css +2 -2
- package/dist/vuetify.cjs +74 -34
- package/dist/vuetify.cjs.map +1 -1
- package/dist/vuetify.css +3415 -3415
- package/dist/vuetify.d.ts +86 -61
- package/dist/vuetify.esm.js +74 -34
- package/dist/vuetify.esm.js.map +1 -1
- package/dist/vuetify.js +74 -34
- package/dist/vuetify.js.map +1 -1
- package/dist/vuetify.min.css +2 -2
- package/dist/vuetify.min.js +976 -977
- 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/locationStrategies.js +16 -10
- package/lib/components/VOverlay/locationStrategies.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 +2 -2
- package/lib/components/index.js.map +1 -1
- package/lib/composables/goto.d.ts +3 -2
- package/lib/composables/goto.js +2 -16
- package/lib/composables/goto.js.map +1 -1
- package/lib/composables/reveal.d.ts +36 -0
- package/lib/composables/reveal.js +30 -0
- package/lib/composables/reveal.js.map +1 -0
- package/lib/entry-bundler.js +1 -1
- package/lib/framework.d.ts +142 -133
- 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/VPie/VPie.css +105 -0
- package/lib/labs/VPie/VPie.d.ts +891 -0
- package/lib/labs/VPie/VPie.js +291 -0
- package/lib/labs/VPie/VPie.js.map +1 -0
- package/lib/labs/VPie/VPie.sass +109 -0
- package/lib/labs/VPie/VPieSegment.d.ts +310 -0
- package/lib/labs/VPie/VPieSegment.js +103 -0
- package/lib/labs/VPie/VPieSegment.js.map +1 -0
- package/lib/labs/VPie/VPieTooltip.d.ts +279 -0
- package/lib/labs/VPie/VPieTooltip.js +84 -0
- package/lib/labs/VPie/VPieTooltip.js.map +1 -0
- package/lib/labs/VPie/_variables.scss +11 -0
- package/lib/labs/VPie/index.d.ts +3 -0
- package/lib/labs/VPie/index.js +4 -0
- package/lib/labs/VPie/index.js.map +1 -0
- package/lib/labs/VPie/types.d.ts +16 -0
- package/lib/labs/VPie/types.js +2 -0
- package/lib/labs/VPie/types.js.map +1 -0
- package/lib/labs/VPie/utils.d.ts +23 -0
- package/lib/labs/VPie/utils.js +49 -0
- package/lib/labs/VPie/utils.js.map +1 -0
- package/lib/labs/VVideo/VVideo.css +322 -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 +304 -0
- package/lib/labs/VVideo/VVideoControls.d.ts +3524 -0
- package/lib/labs/VVideo/VVideoControls.js +236 -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 +94 -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 +2 -0
- package/lib/labs/components.js +2 -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/easing.d.ts +22 -0
- package/lib/util/easing.js +53 -0
- package/lib/util/easing.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/svg-arc-corners.d.ts +4 -0
- package/lib/util/svg-arc-corners.js +73 -0
- package/lib/util/svg-arc-corners.js.map +1 -0
- 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-25
|
3
3
|
* Forged by John Leider
|
4
4
|
* Released under the MIT License.
|
5
5
|
*/
|
@@ -1566,10 +1566,64 @@
|
|
1566
1566
|
return root;
|
1567
1567
|
}
|
1568
1568
|
|
1569
|
+
// Utilities
|
1570
|
+
|
1571
|
+
// Types
|
1572
|
+
|
1569
1573
|
const standardEasing = 'cubic-bezier(0.4, 0, 0.2, 1)';
|
1570
1574
|
const deceleratedEasing = 'cubic-bezier(0.0, 0, 0.2, 1)'; // Entering
|
1571
1575
|
const acceleratedEasing = 'cubic-bezier(0.4, 0, 1, 1)'; // Leaving
|
1572
1576
|
|
1577
|
+
const easingPatterns = {
|
1578
|
+
linear: t => t,
|
1579
|
+
easeInQuad: t => t ** 2,
|
1580
|
+
easeOutQuad: t => t * (2 - t),
|
1581
|
+
easeInOutQuad: t => t < 0.5 ? 2 * t ** 2 : -1 + (4 - 2 * t) * t,
|
1582
|
+
easeInCubic: t => t ** 3,
|
1583
|
+
easeOutCubic: t => --t ** 3 + 1,
|
1584
|
+
easeInOutCubic: t => t < 0.5 ? 4 * t ** 3 : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
|
1585
|
+
easeInQuart: t => t ** 4,
|
1586
|
+
easeOutQuart: t => 1 - --t ** 4,
|
1587
|
+
easeInOutQuart: t => t < 0.5 ? 8 * t ** 4 : 1 - 8 * --t ** 4,
|
1588
|
+
easeInQuint: t => t ** 5,
|
1589
|
+
easeOutQuint: t => 1 + --t ** 5,
|
1590
|
+
easeInOutQuint: t => t < 0.5 ? 16 * t ** 5 : 1 + 16 * --t ** 5
|
1591
|
+
};
|
1592
|
+
function useTransition(source, options) {
|
1593
|
+
const defaultTransition = {
|
1594
|
+
duration: 300,
|
1595
|
+
transition: easingPatterns.easeInOutCubic
|
1596
|
+
};
|
1597
|
+
let raf = -1;
|
1598
|
+
const outputRef = vue.shallowRef(vue.toValue(source));
|
1599
|
+
vue.watch(() => vue.toValue(source), async to => {
|
1600
|
+
cancelAnimationFrame(raf);
|
1601
|
+
const easing = {
|
1602
|
+
...defaultTransition,
|
1603
|
+
...vue.toValue(options)
|
1604
|
+
};
|
1605
|
+
await executeTransition(outputRef, outputRef.value, to, easing);
|
1606
|
+
});
|
1607
|
+
function executeTransition(out, from, to, options) {
|
1608
|
+
const startTime = performance.now();
|
1609
|
+
const ease = options.transition ?? easingPatterns.easeInOutCubic;
|
1610
|
+
return new Promise(resolve => {
|
1611
|
+
raf = requestAnimationFrame(function step(currentTime) {
|
1612
|
+
const timeElapsed = currentTime - startTime;
|
1613
|
+
const progress = timeElapsed / options.duration;
|
1614
|
+
out.value = from + (to - from) * ease(clamp(progress, 0, 1));
|
1615
|
+
if (progress < 1) {
|
1616
|
+
raf = requestAnimationFrame(step);
|
1617
|
+
} else {
|
1618
|
+
out.value = to;
|
1619
|
+
resolve();
|
1620
|
+
}
|
1621
|
+
});
|
1622
|
+
});
|
1623
|
+
}
|
1624
|
+
return vue.computed(() => outputRef.value);
|
1625
|
+
}
|
1626
|
+
|
1573
1627
|
// Utilities
|
1574
1628
|
function getPrefixedEventHandlers(attrs, suffix, getData) {
|
1575
1629
|
return Object.keys(attrs).filter(key => isOn(key) && key.endsWith(suffix)).reduce((acc, key) => {
|
@@ -1660,6 +1714,10 @@
|
|
1660
1714
|
vm.render = render;
|
1661
1715
|
}
|
1662
1716
|
|
1717
|
+
function formatTime(seconds) {
|
1718
|
+
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(':');
|
1719
|
+
}
|
1720
|
+
|
1663
1721
|
// Utilities
|
1664
1722
|
|
1665
1723
|
// Types
|
@@ -2180,6 +2238,17 @@
|
|
2180
2238
|
option: 'Option',
|
2181
2239
|
plus: 'plus',
|
2182
2240
|
shortcut: 'Keyboard shortcut: {0}'
|
2241
|
+
},
|
2242
|
+
video: {
|
2243
|
+
play: 'Play',
|
2244
|
+
pause: 'Pause',
|
2245
|
+
seek: 'Seek',
|
2246
|
+
volume: 'Volume',
|
2247
|
+
showVolume: 'Show volume control',
|
2248
|
+
mute: 'Mute',
|
2249
|
+
unmute: 'Unmute',
|
2250
|
+
enterFullscreen: 'Full screen',
|
2251
|
+
exitFullscreen: 'Exit full screen'
|
2183
2252
|
}
|
2184
2253
|
};
|
2185
2254
|
|
@@ -4262,7 +4331,7 @@
|
|
4262
4331
|
|
4263
4332
|
// Types
|
4264
4333
|
|
4265
|
-
const allowedVariants$
|
4334
|
+
const allowedVariants$4 = ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain'];
|
4266
4335
|
function genOverlays(isClickable, name) {
|
4267
4336
|
return vue.createElementVNode(vue.Fragment, null, [isClickable && vue.createElementVNode("span", {
|
4268
4337
|
"key": "overlay",
|
@@ -4277,7 +4346,7 @@
|
|
4277
4346
|
variant: {
|
4278
4347
|
type: String,
|
4279
4348
|
default: 'elevated',
|
4280
|
-
validator: v => allowedVariants$
|
4349
|
+
validator: v => allowedVariants$4.includes(v)
|
4281
4350
|
}
|
4282
4351
|
}, 'variant');
|
4283
4352
|
function useVariant(props) {
|
@@ -4701,7 +4770,15 @@
|
|
4701
4770
|
arrowdown: 'mdi-arrow-down',
|
4702
4771
|
arrowleft: 'mdi-arrow-left',
|
4703
4772
|
arrowright: 'mdi-arrow-right',
|
4704
|
-
backspace: 'mdi-backspace'
|
4773
|
+
backspace: 'mdi-backspace',
|
4774
|
+
play: 'mdi-play',
|
4775
|
+
pause: 'mdi-pause',
|
4776
|
+
fullscreen: 'mdi-fullscreen',
|
4777
|
+
fullscreenExit: 'mdi-fullscreen-exit',
|
4778
|
+
volumeHigh: 'mdi-volume-high',
|
4779
|
+
volumeMedium: 'mdi-volume-medium',
|
4780
|
+
volumeLow: 'mdi-volume-low',
|
4781
|
+
volumeOff: 'mdi-volume-variant-off'
|
4705
4782
|
};
|
4706
4783
|
const mdi = {
|
4707
4784
|
// Not using mergeProps here, functional components merge props by default (?)
|
@@ -7670,21 +7747,7 @@
|
|
7670
7747
|
layout: false,
|
7671
7748
|
offset: 0,
|
7672
7749
|
easing: 'easeInOutCubic',
|
7673
|
-
patterns:
|
7674
|
-
linear: t => t,
|
7675
|
-
easeInQuad: t => t ** 2,
|
7676
|
-
easeOutQuad: t => t * (2 - t),
|
7677
|
-
easeInOutQuad: t => t < 0.5 ? 2 * t ** 2 : -1 + (4 - 2 * t) * t,
|
7678
|
-
easeInCubic: t => t ** 3,
|
7679
|
-
easeOutCubic: t => --t ** 3 + 1,
|
7680
|
-
easeInOutCubic: t => t < 0.5 ? 4 * t ** 3 : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
|
7681
|
-
easeInQuart: t => t ** 4,
|
7682
|
-
easeOutQuart: t => 1 - --t ** 4,
|
7683
|
-
easeInOutQuart: t => t < 0.5 ? 8 * t ** 4 : 1 - 8 * --t ** 4,
|
7684
|
-
easeInQuint: t => t ** 5,
|
7685
|
-
easeOutQuint: t => 1 + --t ** 5,
|
7686
|
-
easeInOutQuint: t => t < 0.5 ? 16 * t ** 5 : 1 + 16 * --t ** 5
|
7687
|
-
}
|
7750
|
+
patterns: easingPatterns
|
7688
7751
|
};
|
7689
7752
|
}
|
7690
7753
|
function getContainer(el) {
|
@@ -10521,11 +10584,23 @@
|
|
10521
10584
|
const result = updateLocation();
|
10522
10585
|
if (result) flipped.push(result.flipped);
|
10523
10586
|
});
|
10524
|
-
|
10525
|
-
|
10526
|
-
|
10587
|
+
let targetBox = new Box({
|
10588
|
+
x: 0,
|
10589
|
+
y: 0,
|
10590
|
+
width: 0,
|
10591
|
+
height: 0
|
10592
|
+
});
|
10593
|
+
vue.watch(data.target, (newTarget, oldTarget) => {
|
10527
10594
|
if (oldTarget && !Array.isArray(oldTarget)) observer.unobserve(oldTarget);
|
10528
|
-
if (
|
10595
|
+
if (!Array.isArray(newTarget)) {
|
10596
|
+
if (newTarget) observer.observe(newTarget);
|
10597
|
+
} else if (!deepEqual(newTarget, oldTarget)) {
|
10598
|
+
updateLocation();
|
10599
|
+
}
|
10600
|
+
}, {
|
10601
|
+
immediate: true
|
10602
|
+
});
|
10603
|
+
vue.watch(data.contentEl, (newContentEl, oldContentEl) => {
|
10529
10604
|
if (oldContentEl) observer.unobserve(oldContentEl);
|
10530
10605
|
if (newContentEl) observer.observe(newContentEl);
|
10531
10606
|
}, {
|
@@ -10534,12 +10609,6 @@
|
|
10534
10609
|
vue.onScopeDispose(() => {
|
10535
10610
|
observer.disconnect();
|
10536
10611
|
});
|
10537
|
-
let targetBox = new Box({
|
10538
|
-
x: 0,
|
10539
|
-
y: 0,
|
10540
|
-
width: 0,
|
10541
|
-
height: 0
|
10542
|
-
});
|
10543
10612
|
|
10544
10613
|
// eslint-disable-next-line max-statements
|
10545
10614
|
function updateLocation() {
|
@@ -10831,11 +10900,12 @@
|
|
10831
10900
|
function onScroll(e) {
|
10832
10901
|
data.isActive.value = false;
|
10833
10902
|
}
|
10834
|
-
bindScroll(data.
|
10903
|
+
bindScroll(data.target.value ?? data.contentEl.value, onScroll);
|
10835
10904
|
}
|
10836
10905
|
function blockScrollStrategy(data, props) {
|
10837
10906
|
const offsetParent = data.root.value?.offsetParent;
|
10838
|
-
const
|
10907
|
+
const target = Array.isArray(data.target.value) ? document.elementFromPoint(...data.target.value) : data.target.value;
|
10908
|
+
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
10909
|
const scrollbarWidth = window.innerWidth - document.documentElement.offsetWidth;
|
10840
10910
|
const scrollableParent = (el => hasScrollbar(el) && el)(offsetParent || document.documentElement);
|
10841
10911
|
if (scrollableParent) {
|
@@ -10882,7 +10952,7 @@
|
|
10882
10952
|
}
|
10883
10953
|
ric = (typeof requestIdleCallback === 'undefined' ? cb => cb() : requestIdleCallback)(() => {
|
10884
10954
|
scope.run(() => {
|
10885
|
-
bindScroll(data.
|
10955
|
+
bindScroll(data.target.value ?? data.contentEl.value, e => {
|
10886
10956
|
if (slow) {
|
10887
10957
|
// If the position calculation is slow,
|
10888
10958
|
// defer updates until scrolling is finished.
|
@@ -10907,7 +10977,8 @@
|
|
10907
10977
|
}
|
10908
10978
|
|
10909
10979
|
/** @private */
|
10910
|
-
function bindScroll(
|
10980
|
+
function bindScroll(target, onScroll) {
|
10981
|
+
const el = Array.isArray(target) ? document.elementFromPoint(...target) : target;
|
10911
10982
|
const scrollElements = [document, ...getScrollParents(el)];
|
10912
10983
|
scrollElements.forEach(el => {
|
10913
10984
|
el.addEventListener('scroll', onScroll, {
|
@@ -11589,6 +11660,7 @@
|
|
11589
11660
|
root,
|
11590
11661
|
contentEl,
|
11591
11662
|
targetEl,
|
11663
|
+
target,
|
11592
11664
|
isActive,
|
11593
11665
|
updateLocation
|
11594
11666
|
});
|
@@ -11984,7 +12056,7 @@
|
|
11984
12056
|
|
11985
12057
|
// Types
|
11986
12058
|
|
11987
|
-
const allowedVariants$
|
12059
|
+
const allowedVariants$3 = ['underlined', 'outlined', 'filled', 'solo', 'solo-inverted', 'solo-filled', 'plain'];
|
11988
12060
|
const makeVFieldProps = propsFactory({
|
11989
12061
|
appendInnerIcon: IconValue,
|
11990
12062
|
bgColor: String,
|
@@ -12018,7 +12090,7 @@
|
|
12018
12090
|
variant: {
|
12019
12091
|
type: String,
|
12020
12092
|
default: 'filled',
|
12021
|
-
validator: v => allowedVariants$
|
12093
|
+
validator: v => allowedVariants$3.includes(v)
|
12022
12094
|
},
|
12023
12095
|
'onClick:clear': EventProp(),
|
12024
12096
|
'onClick:appendInner': EventProp(),
|
@@ -16180,6 +16252,7 @@
|
|
16180
16252
|
validator: v => ['vertical', 'horizontal'].includes(v)
|
16181
16253
|
},
|
16182
16254
|
reverse: Boolean,
|
16255
|
+
noKeyboard: Boolean,
|
16183
16256
|
...makeRoundedProps(),
|
16184
16257
|
...makeElevationProps({
|
16185
16258
|
elevation: 2
|
@@ -16383,6 +16456,7 @@
|
|
16383
16456
|
min,
|
16384
16457
|
max,
|
16385
16458
|
mousePressed,
|
16459
|
+
noKeyboard: vue.toRef(() => props.noKeyboard),
|
16386
16460
|
numTicks,
|
16387
16461
|
onSliderMousedown,
|
16388
16462
|
onSliderTouchstart,
|
@@ -16435,6 +16509,7 @@
|
|
16435
16509
|
default: true
|
16436
16510
|
},
|
16437
16511
|
name: String,
|
16512
|
+
noKeyboard: Boolean,
|
16438
16513
|
...makeComponentProps()
|
16439
16514
|
}, 'VSliderThumb');
|
16440
16515
|
const VSliderThumb = genericComponent()({
|
@@ -16497,6 +16572,7 @@
|
|
16497
16572
|
if (step.value) return [1, 2, 3];else return [1, 5, 10];
|
16498
16573
|
});
|
16499
16574
|
function parseKeydown(e, value) {
|
16575
|
+
if (props.noKeyboard) return;
|
16500
16576
|
if (!relevantKeys.includes(e.key)) return;
|
16501
16577
|
e.preventDefault();
|
16502
16578
|
const _step = step.value || 0.1;
|
@@ -16732,7 +16808,8 @@
|
|
16732
16808
|
trackContainerRef,
|
16733
16809
|
position,
|
16734
16810
|
hasLabels,
|
16735
|
-
readonly
|
16811
|
+
readonly,
|
16812
|
+
noKeyboard
|
16736
16813
|
} = useSlider({
|
16737
16814
|
props,
|
16738
16815
|
steps,
|
@@ -16808,6 +16885,7 @@
|
|
16808
16885
|
"ref": thumbContainerRef,
|
16809
16886
|
"aria-describedby": messagesId.value,
|
16810
16887
|
"focused": isFocused.value,
|
16888
|
+
"noKeyboard": noKeyboard.value,
|
16811
16889
|
"min": min.value,
|
16812
16890
|
"max": max.value,
|
16813
16891
|
"modelValue": model.value,
|
@@ -23884,7 +23962,7 @@
|
|
23884
23962
|
|
23885
23963
|
// Types
|
23886
23964
|
|
23887
|
-
const allowedVariants = ['default', 'accordion', 'inset', 'popout'];
|
23965
|
+
const allowedVariants$2 = ['default', 'accordion', 'inset', 'popout'];
|
23888
23966
|
const makeVExpansionPanelsProps = propsFactory({
|
23889
23967
|
flat: Boolean,
|
23890
23968
|
...makeGroupProps(),
|
@@ -23895,7 +23973,7 @@
|
|
23895
23973
|
variant: {
|
23896
23974
|
type: String,
|
23897
23975
|
default: 'default',
|
23898
|
-
validator: v => allowedVariants.includes(v)
|
23976
|
+
validator: v => allowedVariants$2.includes(v)
|
23899
23977
|
}
|
23900
23978
|
}, 'VExpansionPanels');
|
23901
23979
|
const VExpansionPanels = genericComponent()({
|
@@ -32427,6 +32505,614 @@
|
|
32427
32505
|
}
|
32428
32506
|
});
|
32429
32507
|
|
32508
|
+
// Utilities
|
32509
|
+
|
32510
|
+
// Types
|
32511
|
+
|
32512
|
+
// Types
|
32513
|
+
|
32514
|
+
// Composables
|
32515
|
+
const makeRevealProps = propsFactory({
|
32516
|
+
reveal: {
|
32517
|
+
type: [Boolean, Object],
|
32518
|
+
default: false
|
32519
|
+
}
|
32520
|
+
}, 'reveal');
|
32521
|
+
function useReveal(props) {
|
32522
|
+
const defaultDuration = 900;
|
32523
|
+
const duration = vue.toRef(() => typeof props.reveal === 'object' ? Math.max(0, Number(props.reveal.duration ?? defaultDuration)) : defaultDuration);
|
32524
|
+
const state = vue.shallowRef(props.reveal ? 'initial' : 'disabled');
|
32525
|
+
vue.onMounted(async () => {
|
32526
|
+
if (props.reveal) {
|
32527
|
+
state.value = 'initial';
|
32528
|
+
await new Promise(resolve => requestAnimationFrame(resolve));
|
32529
|
+
state.value = 'pending';
|
32530
|
+
await new Promise(resolve => setTimeout(resolve, duration.value));
|
32531
|
+
state.value = 'done';
|
32532
|
+
}
|
32533
|
+
});
|
32534
|
+
return {
|
32535
|
+
duration,
|
32536
|
+
state
|
32537
|
+
};
|
32538
|
+
}
|
32539
|
+
|
32540
|
+
/*
|
32541
|
+
* Credits: Alexander Milevski https://github.com/w8r/svg-arc-corners
|
32542
|
+
*/
|
32543
|
+
|
32544
|
+
function pointOnArc(center, radius, angle) {
|
32545
|
+
const radians = (angle - 90) * Math.PI / 180.0;
|
32546
|
+
return [center[0] + radius * Math.cos(radians), center[1] + radius * Math.sin(radians)];
|
32547
|
+
}
|
32548
|
+
function drawCircle(_ref, r, width) {
|
32549
|
+
let [x, y] = _ref;
|
32550
|
+
const innerRadius = r - width;
|
32551
|
+
return ['M', x - r, y, 'A', r, r, 0, 1, 0, x + r, y, 'A', r, r, 0, 1, 0, x - r, y, 'M', x - innerRadius, y, 'A', innerRadius, innerRadius, 0, 1, 0, x + innerRadius, y, 'A', innerRadius, innerRadius, 0, 1, 0, x - innerRadius, y, 'Z'];
|
32552
|
+
}
|
32553
|
+
function simpleArc(center, r, startAngle, endAngle) {
|
32554
|
+
const start = pointOnArc(center, r, startAngle);
|
32555
|
+
const end = pointOnArc(center, r, endAngle);
|
32556
|
+
const sweep = endAngle - startAngle > 180 ? 1 : 0;
|
32557
|
+
return [`M${start[0]} ${start[1]}`, `A${r} ${r} 0 ${sweep} 1 ${end[0]} ${end[1]}`, `L${center[0]} ${center[1]}Z`].join(' ');
|
32558
|
+
}
|
32559
|
+
function roundedArc(center, radius, startAngle, endAngle, width, rounding) {
|
32560
|
+
width = Math.min(radius, width);
|
32561
|
+
if (Math.abs(endAngle - startAngle) === 360) {
|
32562
|
+
return drawCircle(center, radius, width).join(' ');
|
32563
|
+
}
|
32564
|
+
if (rounding === 0 && radius === width) {
|
32565
|
+
return simpleArc(center, radius, startAngle, endAngle);
|
32566
|
+
}
|
32567
|
+
const innerR = radius - width;
|
32568
|
+
const circumference = Math.abs(endAngle - startAngle);
|
32569
|
+
rounding = Math.min(width / 2, rounding);
|
32570
|
+
if (360 * (rounding / (Math.PI * (radius - width))) > Math.abs(startAngle - endAngle)) {
|
32571
|
+
rounding = circumference / 360 * innerR * Math.PI;
|
32572
|
+
}
|
32573
|
+
|
32574
|
+
// inner and outer radiuses
|
32575
|
+
const innerR2 = innerR + rounding;
|
32576
|
+
const outerRadius = radius - rounding;
|
32577
|
+
|
32578
|
+
// butts corner points
|
32579
|
+
const oStart = pointOnArc(center, outerRadius, startAngle);
|
32580
|
+
const oEnd = pointOnArc(center, outerRadius, endAngle);
|
32581
|
+
const iStart = pointOnArc(center, innerR2, startAngle);
|
32582
|
+
const iEnd = pointOnArc(center, innerR2, endAngle);
|
32583
|
+
const iSection = innerR ? 360 * (rounding / (2 * Math.PI * innerR)) : 0;
|
32584
|
+
const oSection = 360 * (rounding / (2 * Math.PI * radius));
|
32585
|
+
|
32586
|
+
// arcs endpoints
|
32587
|
+
const iArcStart = pointOnArc(center, innerR, startAngle + iSection);
|
32588
|
+
const iArcEnd = pointOnArc(center, innerR, endAngle - iSection);
|
32589
|
+
const oArcStart = pointOnArc(center, radius, startAngle + oSection);
|
32590
|
+
const oArcEnd = pointOnArc(center, radius, endAngle - oSection);
|
32591
|
+
const arcSweep1 = circumference > 180 + 2 * oSection ? 1 : 0;
|
32592
|
+
const arcSweep2 = circumference > 180 + 2 * iSection ? 1 : 0;
|
32593
|
+
return [
|
32594
|
+
// begin path
|
32595
|
+
'M', oStart[0], oStart[1],
|
32596
|
+
// outer start corner
|
32597
|
+
'A', rounding, rounding, 0, 0, 1, oArcStart[0], oArcStart[1],
|
32598
|
+
// outer main arc
|
32599
|
+
'A', radius, radius, 0, arcSweep1, 1, oArcEnd[0], oArcEnd[1],
|
32600
|
+
// outer end corner
|
32601
|
+
'A', rounding, rounding, 0, 0, 1, oEnd[0], oEnd[1],
|
32602
|
+
// end butt
|
32603
|
+
'L', iEnd[0], iEnd[1],
|
32604
|
+
// inner end corner
|
32605
|
+
'A', rounding, rounding, 0, 0, 1, iArcEnd[0], iArcEnd[1],
|
32606
|
+
// inner arc
|
32607
|
+
'A', innerR, innerR, 0, arcSweep2, 0, iArcStart[0], iArcStart[1],
|
32608
|
+
// inner start corner
|
32609
|
+
'A', rounding, rounding, 0, 0, 1, iStart[0], iStart[1], 'Z' // end path
|
32610
|
+
].join(' ');
|
32611
|
+
}
|
32612
|
+
|
32613
|
+
// Utilities
|
32614
|
+
|
32615
|
+
// Types
|
32616
|
+
|
32617
|
+
function formatTextTemplate(template, item) {
|
32618
|
+
return item ? template.replaceAll('[title]', item.title).replaceAll('[value]', String(item.value)) : undefined;
|
32619
|
+
}
|
32620
|
+
function usePieArc(props, isHovering) {
|
32621
|
+
const hoverZoomRatio = vue.toRef(() => clamp(Number(props.hoverScale ?? 0), 0, 0.25));
|
32622
|
+
const normalizedValue = vue.toRef(() => clamp(props.value - 100 * Number(props.gap ?? 0) / 360, 0.01, 99.99));
|
32623
|
+
const normalizedInnerCut = vue.toRef(() => {
|
32624
|
+
const min = Number(props.rounded ?? 0) > 0 ? 0.2 : 0;
|
32625
|
+
return clamp(Number(props.innerCut ?? 0) / 100, min, 1);
|
32626
|
+
});
|
32627
|
+
const radians = vue.computed(() => (360 * (-normalizedValue.value / 100) + 90) * (Math.PI / 180));
|
32628
|
+
const arcWidth = vue.computed(() => 50 * (1 - normalizedInnerCut.value) * (isHovering.value ? 1 : 1 - hoverZoomRatio.value));
|
32629
|
+
const outerX = vue.toRef(() => 50 + 50 * Math.cos(radians.value));
|
32630
|
+
const outerY = vue.toRef(() => 50 - 50 * Math.sin(radians.value));
|
32631
|
+
return {
|
32632
|
+
hoverZoomRatio,
|
32633
|
+
normalizedValue,
|
32634
|
+
normalizedInnerCut,
|
32635
|
+
outerX,
|
32636
|
+
outerY,
|
32637
|
+
arcWidth
|
32638
|
+
};
|
32639
|
+
}
|
32640
|
+
function useOuterSlicePath(_ref) {
|
32641
|
+
let {
|
32642
|
+
angle,
|
32643
|
+
radius,
|
32644
|
+
size,
|
32645
|
+
width,
|
32646
|
+
rounded
|
32647
|
+
} = _ref;
|
32648
|
+
return vue.computed(() => roundedArc([50, 50], vue.toValue(radius), vue.toValue(angle), vue.toValue(angle) + 360 * vue.toValue(size) / 100,
|
32649
|
+
// angle end,
|
32650
|
+
vue.toValue(width), vue.toValue(rounded)));
|
32651
|
+
}
|
32652
|
+
function useInnerSlicePath(_ref2) {
|
32653
|
+
let {
|
32654
|
+
angle,
|
32655
|
+
radius,
|
32656
|
+
size
|
32657
|
+
} = _ref2;
|
32658
|
+
return vue.computed(() => simpleArc([50, 50], vue.toValue(radius), vue.toValue(angle), vue.toValue(angle) + 360 * vue.toValue(size) / 100 // angle end,
|
32659
|
+
));
|
32660
|
+
}
|
32661
|
+
|
32662
|
+
// Types
|
32663
|
+
|
32664
|
+
const makeVPieSegmentProps = propsFactory({
|
32665
|
+
rotate: [Number, String],
|
32666
|
+
value: {
|
32667
|
+
type: Number,
|
32668
|
+
default: 0
|
32669
|
+
},
|
32670
|
+
color: String,
|
32671
|
+
innerCut: [Number, String],
|
32672
|
+
hoverScale: {
|
32673
|
+
type: [Number, String],
|
32674
|
+
default: 0.05
|
32675
|
+
},
|
32676
|
+
gap: [Number, String],
|
32677
|
+
rounded: [Number, String],
|
32678
|
+
animation: {
|
32679
|
+
type: [Boolean, Object],
|
32680
|
+
default: false
|
32681
|
+
},
|
32682
|
+
pattern: String,
|
32683
|
+
hideSlice: Boolean,
|
32684
|
+
...makeRevealProps()
|
32685
|
+
}, 'VPieSegment');
|
32686
|
+
const VPieSegment = genericComponent()({
|
32687
|
+
name: 'VPieSegment',
|
32688
|
+
props: makeVPieSegmentProps(),
|
32689
|
+
setup(props) {
|
32690
|
+
const isHovering = vue.shallowRef(false);
|
32691
|
+
const {
|
32692
|
+
state: revealState,
|
32693
|
+
duration: revealDuration
|
32694
|
+
} = useReveal(props);
|
32695
|
+
const transitionConfig = vue.computed(() => {
|
32696
|
+
const defaultEasing = 'easeInOutCubic';
|
32697
|
+
const defaultDuration = 400;
|
32698
|
+
const easingName = typeof props.animation === 'object' ? props.animation.easing ?? defaultEasing : defaultEasing;
|
32699
|
+
return {
|
32700
|
+
duration: ['initial', 'pending'].includes(revealState.value) ? revealDuration.value : typeof props.animation === 'object' ? props.animation.duration : props.animation ? defaultDuration : 0,
|
32701
|
+
transition: easingPatterns[easingName]
|
32702
|
+
};
|
32703
|
+
});
|
32704
|
+
const {
|
32705
|
+
hoverZoomRatio,
|
32706
|
+
normalizedValue,
|
32707
|
+
normalizedInnerCut,
|
32708
|
+
outerX,
|
32709
|
+
outerY,
|
32710
|
+
arcWidth
|
32711
|
+
} = usePieArc(props, isHovering);
|
32712
|
+
const arcSize = vue.toRef(() => revealState.value === 'initial' ? 0 : normalizedValue.value);
|
32713
|
+
const currentArcSize = useTransition(arcSize, transitionConfig);
|
32714
|
+
const angle = vue.toRef(() => revealState.value === 'initial' ? 0 : Number(props.rotate ?? 0) + Number(props.gap ?? 0) / 2);
|
32715
|
+
const currentAngle = useTransition(angle, transitionConfig);
|
32716
|
+
const arcRadius = vue.toRef(() => 50 * (isHovering.value ? 1 : 1 - hoverZoomRatio.value));
|
32717
|
+
const currentArcRadius = useTransition(arcRadius, transitionConfig);
|
32718
|
+
const currentArcWidth = useTransition(arcWidth, transitionConfig);
|
32719
|
+
const outerSlicePath = useOuterSlicePath({
|
32720
|
+
angle: currentAngle,
|
32721
|
+
radius: currentArcRadius,
|
32722
|
+
size: currentArcSize,
|
32723
|
+
width: currentArcWidth,
|
32724
|
+
rounded: () => Number(props.rounded ?? 0)
|
32725
|
+
});
|
32726
|
+
const innerSlicePath = useInnerSlicePath({
|
32727
|
+
angle: currentAngle,
|
32728
|
+
radius: () => currentArcRadius.value - currentArcWidth.value,
|
32729
|
+
size: currentArcSize
|
32730
|
+
});
|
32731
|
+
const overlayPath = vue.toRef(() => `M 50 0 A 50 50 0 ${normalizedValue.value > 50 ? 1 : 0} 1 ${outerX.value} ${outerY.value} L 50 50`);
|
32732
|
+
return () => vue.createElementVNode("g", {
|
32733
|
+
"class": "v-pie-segment",
|
32734
|
+
"style": {
|
32735
|
+
color: props.color
|
32736
|
+
}
|
32737
|
+
}, [vue.createElementVNode("path", {
|
32738
|
+
"key": "outer-slice",
|
32739
|
+
"fill": "currentColor",
|
32740
|
+
"shape-rendering": "geometricPrecision",
|
32741
|
+
"d": outerSlicePath.value
|
32742
|
+
}, null), props.pattern && vue.createElementVNode("path", {
|
32743
|
+
"key": "pattern-overlay",
|
32744
|
+
"shape-rendering": "geometricPrecision",
|
32745
|
+
"fill": props.pattern,
|
32746
|
+
"d": outerSlicePath.value
|
32747
|
+
}, null), !props.hideSlice && normalizedInnerCut.value > 0 && vue.createElementVNode("path", {
|
32748
|
+
"key": "inner-slice",
|
32749
|
+
"fill": "oklch(from currentColor l c h / calc(alpha / 2))",
|
32750
|
+
"d": innerSlicePath.value
|
32751
|
+
}, null), ['disabled', 'done'].includes(revealState.value) && vue.createElementVNode("path", {
|
32752
|
+
"transform": `rotate(${currentAngle.value} 50 50)`,
|
32753
|
+
"class": "v-pie-segment__overlay",
|
32754
|
+
"d": overlayPath.value,
|
32755
|
+
"onMouseenter": () => isHovering.value = true,
|
32756
|
+
"onMouseleave": () => isHovering.value = false
|
32757
|
+
}, null)]);
|
32758
|
+
}
|
32759
|
+
});
|
32760
|
+
|
32761
|
+
// Types
|
32762
|
+
|
32763
|
+
const makeVPieTooltipProps = propsFactory({
|
32764
|
+
modelValue: Boolean,
|
32765
|
+
item: {
|
32766
|
+
type: Object,
|
32767
|
+
default: null
|
32768
|
+
},
|
32769
|
+
titleFormat: {
|
32770
|
+
type: [String, Function],
|
32771
|
+
default: '[title]'
|
32772
|
+
},
|
32773
|
+
subtitleFormat: {
|
32774
|
+
type: [String, Function],
|
32775
|
+
default: '[value]'
|
32776
|
+
},
|
32777
|
+
...makeTransitionProps(),
|
32778
|
+
...pick(makeVTooltipProps(), ['offset'])
|
32779
|
+
}, 'VPieTooltip');
|
32780
|
+
const VPieTooltip = genericComponent()({
|
32781
|
+
name: 'VPieTooltip',
|
32782
|
+
props: makeVPieTooltipProps(),
|
32783
|
+
setup(props, _ref) {
|
32784
|
+
let {
|
32785
|
+
slots
|
32786
|
+
} = _ref;
|
32787
|
+
const target = vue.shallowRef([0, 0]);
|
32788
|
+
const vm = getCurrentInstance('VPieTooltip');
|
32789
|
+
let frame = -1;
|
32790
|
+
function onMouseMove(_ref2) {
|
32791
|
+
let {
|
32792
|
+
clientX,
|
32793
|
+
clientY
|
32794
|
+
} = _ref2;
|
32795
|
+
cancelAnimationFrame(frame);
|
32796
|
+
frame = requestAnimationFrame(() => {
|
32797
|
+
target.value = [clientX, clientY];
|
32798
|
+
});
|
32799
|
+
}
|
32800
|
+
vue.onMounted(() => {
|
32801
|
+
vm.proxy.$el.parentNode.addEventListener('mousemove', onMouseMove);
|
32802
|
+
});
|
32803
|
+
vue.onBeforeUnmount(() => {
|
32804
|
+
vm.proxy.$el.parentNode.removeEventListener('mousemove', onMouseMove);
|
32805
|
+
});
|
32806
|
+
const tooltipTitleFormatFunction = vue.toRef(() => segment => {
|
32807
|
+
return typeof props.titleFormat === 'function' ? props.titleFormat(segment) : formatTextTemplate(props.titleFormat, segment);
|
32808
|
+
});
|
32809
|
+
const tooltipSubtitleFormatFunction = vue.toRef(() => segment => {
|
32810
|
+
return typeof props.subtitleFormat === 'function' ? props.subtitleFormat(segment) : formatTextTemplate(props.subtitleFormat, segment);
|
32811
|
+
});
|
32812
|
+
return () => vue.createVNode(VTooltip, {
|
32813
|
+
"offset": props.offset,
|
32814
|
+
"modelValue": props.modelValue,
|
32815
|
+
"target": target.value,
|
32816
|
+
"contentClass": "v-pie__tooltip-content"
|
32817
|
+
}, {
|
32818
|
+
default: () => [!!props.item && (slots.default?.({
|
32819
|
+
item: props.item
|
32820
|
+
}) ?? vue.createVNode(MaybeTransition, {
|
32821
|
+
"transition": props.transition,
|
32822
|
+
"mode": "out-in"
|
32823
|
+
}, {
|
32824
|
+
default: () => [vue.createVNode(VListItem, {
|
32825
|
+
"key": props.item.key,
|
32826
|
+
"density": "compact",
|
32827
|
+
"title": tooltipTitleFormatFunction.value(props.item),
|
32828
|
+
"subtitle": tooltipSubtitleFormatFunction.value(props.item)
|
32829
|
+
}, {
|
32830
|
+
prepend: slots.prepend ? () => slots.prepend({
|
32831
|
+
item: props.item
|
32832
|
+
}) : undefined
|
32833
|
+
})]
|
32834
|
+
}))]
|
32835
|
+
});
|
32836
|
+
}
|
32837
|
+
});
|
32838
|
+
|
32839
|
+
// Types
|
32840
|
+
|
32841
|
+
const makeVPieProps = propsFactory({
|
32842
|
+
title: String,
|
32843
|
+
bgColor: String,
|
32844
|
+
items: {
|
32845
|
+
type: Array,
|
32846
|
+
default: () => []
|
32847
|
+
},
|
32848
|
+
palette: {
|
32849
|
+
type: Array,
|
32850
|
+
default: () => []
|
32851
|
+
},
|
32852
|
+
itemKey: {
|
32853
|
+
type: String,
|
32854
|
+
default: 'key'
|
32855
|
+
},
|
32856
|
+
itemValue: {
|
32857
|
+
type: String,
|
32858
|
+
default: 'value'
|
32859
|
+
},
|
32860
|
+
itemTitle: {
|
32861
|
+
type: String,
|
32862
|
+
default: 'title'
|
32863
|
+
},
|
32864
|
+
size: {
|
32865
|
+
type: [Number, String],
|
32866
|
+
default: 250
|
32867
|
+
},
|
32868
|
+
rotate: [Number, String],
|
32869
|
+
gaugeCut: [Number, String],
|
32870
|
+
legend: {
|
32871
|
+
type: [Boolean, Object],
|
32872
|
+
default: false
|
32873
|
+
},
|
32874
|
+
tooltip: {
|
32875
|
+
type: [Boolean, Object],
|
32876
|
+
default: false
|
32877
|
+
},
|
32878
|
+
...makeDensityProps(),
|
32879
|
+
...pick(makeVPieSegmentProps(), ['animation', 'gap', 'rounded', 'innerCut', 'hoverScale', 'hideSlice', 'reveal'])
|
32880
|
+
}, 'VPie');
|
32881
|
+
const VPie = genericComponent()({
|
32882
|
+
name: 'VPie',
|
32883
|
+
props: makeVPieProps(),
|
32884
|
+
setup(props, _ref) {
|
32885
|
+
let {
|
32886
|
+
slots
|
32887
|
+
} = _ref;
|
32888
|
+
const legendConfig = vue.computed(() => ({
|
32889
|
+
visible: !!props.legend,
|
32890
|
+
position: 'bottom',
|
32891
|
+
textFormat: '[title]',
|
32892
|
+
...(typeof props.legend === 'object' ? props.legend : {})
|
32893
|
+
}));
|
32894
|
+
const {
|
32895
|
+
colorClasses,
|
32896
|
+
colorStyles
|
32897
|
+
} = useColor(() => ({
|
32898
|
+
background: props.bgColor
|
32899
|
+
}));
|
32900
|
+
const textColorStyles = vue.toRef(() => pick(colorStyles.value, ['color', 'caretColor']));
|
32901
|
+
const legendAvatarSize = vue.toRef(() => ({
|
32902
|
+
default: 20,
|
32903
|
+
comfortable: 18,
|
32904
|
+
compact: 16
|
32905
|
+
})[props.density ?? 'default']);
|
32906
|
+
const legendDirection = vue.toRef(() => ['left', 'right'].includes(legendConfig.value.position) ? 'vertical' : 'horizontal');
|
32907
|
+
const legendMode = vue.toRef(() => !legendConfig.value.visible ? 'hidden' : legendConfig.value.position);
|
32908
|
+
const legendTextFormatFunction = vue.toRef(() => item => {
|
32909
|
+
return typeof legendConfig.value.textFormat === 'function' ? legendConfig.value.textFormat(item) : formatTextTemplate(legendConfig.value.textFormat, item);
|
32910
|
+
});
|
32911
|
+
const arcs = vue.computed(() => {
|
32912
|
+
// hidden items get (value: 0) to trigger disappearing animation
|
32913
|
+
return props.items.filter(Boolean).map((item, index) => {
|
32914
|
+
return {
|
32915
|
+
key: item[props.itemKey],
|
32916
|
+
color: item.color ?? colorFromPalette(index),
|
32917
|
+
value: item[props.itemValue],
|
32918
|
+
title: String(item[props.itemTitle]),
|
32919
|
+
pattern: item.pattern ?? patternFromPalette(index),
|
32920
|
+
raw: item
|
32921
|
+
};
|
32922
|
+
});
|
32923
|
+
});
|
32924
|
+
const visibleItemsKeys = vue.shallowRef([]);
|
32925
|
+
vue.watch(() => arcs.value.length, () => {
|
32926
|
+
// reset when number of items changes
|
32927
|
+
visibleItemsKeys.value = arcs.value.map(a => a.key);
|
32928
|
+
}, {
|
32929
|
+
immediate: true
|
32930
|
+
});
|
32931
|
+
const visibleItems = vue.computed(() => {
|
32932
|
+
// hidden items get (value: 0) to trigger disappearing animation
|
32933
|
+
return arcs.value.map(item => {
|
32934
|
+
return isActive(item) ? item : {
|
32935
|
+
...item,
|
32936
|
+
value: 0
|
32937
|
+
};
|
32938
|
+
});
|
32939
|
+
});
|
32940
|
+
const total = vue.computed(() => visibleItems.value.reduce((sum, item) => sum + item.value, 0));
|
32941
|
+
const gaugeCut = vue.toRef(() => Number(props.gaugeCut ?? 0));
|
32942
|
+
const gaugeOffset = vue.computed(() => (1 - Math.cos(Math.PI * Math.min(90, gaugeCut.value / 2) / 180)) / 2);
|
32943
|
+
const rotateDeg = vue.computed(() => `${gaugeCut.value ? 180 + gaugeCut.value / 2 : props.rotate ?? 0}deg`);
|
32944
|
+
function arcOffset(index) {
|
32945
|
+
return visibleItems.value.slice(0, index).reduce((acc, s) => acc + (total.value > 0 ? s.value / total.value : 0) * (360 - gaugeCut.value), 0);
|
32946
|
+
}
|
32947
|
+
function arcSize(v) {
|
32948
|
+
return v / total.value * (100 - gaugeCut.value / 3.6);
|
32949
|
+
}
|
32950
|
+
function colorFromPalette(index) {
|
32951
|
+
if (props.palette.length === 0) return undefined;
|
32952
|
+
const paletteItem = props.palette[index % props.palette.length];
|
32953
|
+
return typeof paletteItem === 'object' ? paletteItem.color : paletteItem;
|
32954
|
+
}
|
32955
|
+
function patternFromPalette(index) {
|
32956
|
+
if (props.palette.length === 0) return undefined;
|
32957
|
+
const paletteItem = props.palette[index % props.palette.length];
|
32958
|
+
return typeof paletteItem === 'object' ? paletteItem.pattern : undefined;
|
32959
|
+
}
|
32960
|
+
function isActive(item) {
|
32961
|
+
return visibleItemsKeys.value.includes(item.key);
|
32962
|
+
}
|
32963
|
+
function toggle(item) {
|
32964
|
+
if (isActive(item)) {
|
32965
|
+
visibleItemsKeys.value = visibleItemsKeys.value.filter(x => x !== item.key);
|
32966
|
+
} else {
|
32967
|
+
visibleItemsKeys.value = [...visibleItemsKeys.value, item.key];
|
32968
|
+
}
|
32969
|
+
}
|
32970
|
+
const tooltipItem = vue.shallowRef(null);
|
32971
|
+
const tooltipVisible = vue.shallowRef(false);
|
32972
|
+
let mouseLeaveTimeout = null;
|
32973
|
+
function onMouseenter(item) {
|
32974
|
+
if (!props.tooltip) return;
|
32975
|
+
clearTimeout(mouseLeaveTimeout);
|
32976
|
+
tooltipVisible.value = true;
|
32977
|
+
tooltipItem.value = item;
|
32978
|
+
}
|
32979
|
+
function onMouseleave() {
|
32980
|
+
if (!props.tooltip) return;
|
32981
|
+
clearTimeout(mouseLeaveTimeout);
|
32982
|
+
mouseLeaveTimeout = setTimeout(() => {
|
32983
|
+
tooltipVisible.value = false;
|
32984
|
+
|
32985
|
+
// intentionally reusing timeout here
|
32986
|
+
mouseLeaveTimeout = setTimeout(() => {
|
32987
|
+
tooltipItem.value = null;
|
32988
|
+
}, 500);
|
32989
|
+
}, 100);
|
32990
|
+
}
|
32991
|
+
return () => {
|
32992
|
+
const segmentProps = pick(props, ['animation', 'gap', 'rounded', 'hideSlice', 'reveal', 'innerCut', 'hoverScale']);
|
32993
|
+
const defaultTooltipTransition = {
|
32994
|
+
name: 'fade-transition',
|
32995
|
+
duration: 150
|
32996
|
+
};
|
32997
|
+
const tooltipProps = {
|
32998
|
+
item: tooltipItem.value,
|
32999
|
+
modelValue: tooltipVisible.value,
|
33000
|
+
titleFormat: typeof props.tooltip === 'object' ? props.tooltip.titleFormat : '[title]',
|
33001
|
+
subtitleFormat: typeof props.tooltip === 'object' ? props.tooltip.subtitleFormat : '[value]',
|
33002
|
+
transition: typeof props.tooltip === 'object' ? props.tooltip.transition : defaultTooltipTransition,
|
33003
|
+
offset: typeof props.tooltip === 'object' ? props.tooltip.offset : 16
|
33004
|
+
};
|
33005
|
+
const legendDefaults = {
|
33006
|
+
VChipGroup: {
|
33007
|
+
direction: legendDirection.value
|
33008
|
+
},
|
33009
|
+
VChip: {
|
33010
|
+
density: props.density
|
33011
|
+
},
|
33012
|
+
VAvatar: {
|
33013
|
+
size: legendAvatarSize.value
|
33014
|
+
}
|
33015
|
+
};
|
33016
|
+
const tooltipDefaults = {
|
33017
|
+
VAvatar: {
|
33018
|
+
size: 28
|
33019
|
+
}
|
33020
|
+
};
|
33021
|
+
const avatarSlot = _ref2 => {
|
33022
|
+
let {
|
33023
|
+
item
|
33024
|
+
} = _ref2;
|
33025
|
+
return vue.createVNode(VAvatar, {
|
33026
|
+
"color": item.color,
|
33027
|
+
"start": true
|
33028
|
+
}, {
|
33029
|
+
default: () => [item.pattern && vue.createElementVNode("svg", {
|
33030
|
+
"height": "40",
|
33031
|
+
"width": "40"
|
33032
|
+
}, [vue.createElementVNode("rect", {
|
33033
|
+
"width": "40",
|
33034
|
+
"height": "40",
|
33035
|
+
"fill": item.pattern
|
33036
|
+
}, null)])]
|
33037
|
+
});
|
33038
|
+
};
|
33039
|
+
return vue.createElementVNode("div", {
|
33040
|
+
"class": vue.normalizeClass(['v-pie', `v-pie--legend-${legendMode.value}`]),
|
33041
|
+
"style": {
|
33042
|
+
'--v-pie-size': convertToUnit(props.size)
|
33043
|
+
}
|
33044
|
+
}, [slots.title?.() ?? (props.title && vue.createElementVNode("div", {
|
33045
|
+
"class": "v-pie__title"
|
33046
|
+
}, [props.title])), vue.createElementVNode("div", {
|
33047
|
+
"class": vue.normalizeClass(['v-pie__content', colorClasses.value]),
|
33048
|
+
"style": vue.normalizeStyle([{
|
33049
|
+
transform: `rotate(${rotateDeg.value})`,
|
33050
|
+
marginBottom: `calc(-1 * ${convertToUnit(props.size)} * ${gaugeOffset.value})`
|
33051
|
+
}, textColorStyles.value])
|
33052
|
+
}, [vue.createElementVNode("div", {
|
33053
|
+
"class": vue.normalizeClass(['v-pie__content-underlay', colorClasses.value]),
|
33054
|
+
"style": vue.normalizeStyle(colorStyles.value)
|
33055
|
+
}, null), vue.createElementVNode("svg", {
|
33056
|
+
"xmlns": "http://www.w3.org/2000/svg",
|
33057
|
+
"viewBox": "0 0 100 100"
|
33058
|
+
}, [arcs.value.map((item, index) => vue.createVNode(VPieSegment, vue.mergeProps(segmentProps, {
|
33059
|
+
"key": item.key,
|
33060
|
+
"color": item.color,
|
33061
|
+
"value": isActive(item) ? arcSize(item.value) : 0,
|
33062
|
+
"rotate": arcOffset(index),
|
33063
|
+
"pattern": item.pattern,
|
33064
|
+
"onMouseenter": () => onMouseenter(item),
|
33065
|
+
"onMouseleave": () => onMouseleave()
|
33066
|
+
}), null))]), vue.createElementVNode("div", {
|
33067
|
+
"class": "v-pie__center-content",
|
33068
|
+
"style": {
|
33069
|
+
transform: `translate(-50%, -50%)
|
33070
|
+
rotate(-${rotateDeg.value})
|
33071
|
+
translateY(calc(-100% * ${gaugeOffset.value}))`
|
33072
|
+
}
|
33073
|
+
}, [vue.createElementVNode("div", null, [slots.center?.({
|
33074
|
+
total: total.value
|
33075
|
+
})])])]), legendConfig.value.visible && vue.createVNode(VDefaultsProvider, {
|
33076
|
+
"key": "legend",
|
33077
|
+
"defaults": legendDefaults
|
33078
|
+
}, {
|
33079
|
+
default: () => [vue.createElementVNode("div", {
|
33080
|
+
"class": "v-pie__legend"
|
33081
|
+
}, [slots.legend?.({
|
33082
|
+
isActive,
|
33083
|
+
toggle,
|
33084
|
+
items: arcs.value
|
33085
|
+
}) ?? vue.createVNode(VChipGroup, {
|
33086
|
+
"column": true,
|
33087
|
+
"multiple": true,
|
33088
|
+
"modelValue": visibleItemsKeys.value,
|
33089
|
+
"onUpdate:modelValue": $event => visibleItemsKeys.value = $event
|
33090
|
+
}, {
|
33091
|
+
default: () => [arcs.value.map(item => vue.createVNode(VChip, {
|
33092
|
+
"value": item.key
|
33093
|
+
}, {
|
33094
|
+
prepend: () => avatarSlot({
|
33095
|
+
item
|
33096
|
+
}),
|
33097
|
+
default: () => vue.createElementVNode("div", {
|
33098
|
+
"class": "v-pie__legend__text"
|
33099
|
+
}, [slots['legend-text']?.({
|
33100
|
+
item
|
33101
|
+
}) ?? legendTextFormatFunction.value(item)])
|
33102
|
+
}))]
|
33103
|
+
})])]
|
33104
|
+
}), !!props.tooltip && vue.createVNode(VDefaultsProvider, {
|
33105
|
+
"defaults": tooltipDefaults
|
33106
|
+
}, {
|
33107
|
+
default: () => [vue.createVNode(VPieTooltip, tooltipProps, {
|
33108
|
+
default: slots.tooltip,
|
33109
|
+
prepend: avatarSlot
|
33110
|
+
})]
|
33111
|
+
})]);
|
33112
|
+
};
|
33113
|
+
}
|
33114
|
+
});
|
33115
|
+
|
32430
33116
|
// Types
|
32431
33117
|
|
32432
33118
|
const makeVStepperVerticalActionsProps = propsFactory({
|
@@ -33186,6 +33872,799 @@
|
|
33186
33872
|
}
|
33187
33873
|
});
|
33188
33874
|
|
33875
|
+
// Utilities
|
33876
|
+
|
33877
|
+
// Types
|
33878
|
+
|
33879
|
+
function useDirectiveComponent(component, props) {
|
33880
|
+
const concreteComponent = typeof component === 'string' ? vue.resolveComponent(component) : component;
|
33881
|
+
const hook = mountComponent(concreteComponent, props);
|
33882
|
+
return {
|
33883
|
+
mounted: hook,
|
33884
|
+
updated: hook,
|
33885
|
+
unmounted(el) {
|
33886
|
+
vue.render(null, el);
|
33887
|
+
}
|
33888
|
+
};
|
33889
|
+
}
|
33890
|
+
function mountComponent(component, props) {
|
33891
|
+
return function (el, binding, vnode) {
|
33892
|
+
const _props = typeof props === 'function' ? props(binding) : props;
|
33893
|
+
const text = binding.value?.text ?? binding.value ?? _props?.text;
|
33894
|
+
const value = isObject(binding.value) ? binding.value : {};
|
33895
|
+
|
33896
|
+
// Get the children from the props or directive value, or the element's children
|
33897
|
+
const children = () => text ?? el.textContent;
|
33898
|
+
|
33899
|
+
// If vnode.ctx is the same as the instance, then we're bound to a plain element
|
33900
|
+
// and need to find the nearest parent component instance to inherit provides from
|
33901
|
+
const provides = (vnode.ctx === binding.instance.$ ? findComponentParent(vnode, binding.instance.$)?.provides : vnode.ctx?.provides) ?? binding.instance.$.provides;
|
33902
|
+
const node = vue.h(component, vue.mergeProps(_props, value), children);
|
33903
|
+
node.appContext = Object.assign(Object.create(null), binding.instance.$.appContext, {
|
33904
|
+
provides
|
33905
|
+
});
|
33906
|
+
vue.render(node, el);
|
33907
|
+
};
|
33908
|
+
}
|
33909
|
+
function findComponentParent(vnode, root) {
|
33910
|
+
// Walk the tree from root until we find the child vnode
|
33911
|
+
const stack = new Set();
|
33912
|
+
const walk = children => {
|
33913
|
+
for (const child of children) {
|
33914
|
+
if (!child) continue;
|
33915
|
+
if (child === vnode || child.el && vnode.el && child.el === vnode.el) {
|
33916
|
+
return true;
|
33917
|
+
}
|
33918
|
+
stack.add(child);
|
33919
|
+
let result;
|
33920
|
+
if (child.suspense) {
|
33921
|
+
result = walk([child.ssContent]);
|
33922
|
+
} else if (Array.isArray(child.children)) {
|
33923
|
+
result = walk(child.children);
|
33924
|
+
} else if (child.component?.vnode) {
|
33925
|
+
result = walk([child.component?.subTree]);
|
33926
|
+
}
|
33927
|
+
if (result) {
|
33928
|
+
return result;
|
33929
|
+
}
|
33930
|
+
stack.delete(child);
|
33931
|
+
}
|
33932
|
+
return false;
|
33933
|
+
};
|
33934
|
+
if (!walk([root.subTree])) {
|
33935
|
+
consoleError('Could not find original vnode, component will not inherit provides');
|
33936
|
+
return root;
|
33937
|
+
}
|
33938
|
+
|
33939
|
+
// Return the first component parent
|
33940
|
+
const result = Array.from(stack).reverse();
|
33941
|
+
for (const child of result) {
|
33942
|
+
if (child.component) {
|
33943
|
+
return child.component;
|
33944
|
+
}
|
33945
|
+
}
|
33946
|
+
return root;
|
33947
|
+
}
|
33948
|
+
|
33949
|
+
// Components
|
33950
|
+
|
33951
|
+
// Types
|
33952
|
+
|
33953
|
+
const Tooltip = useDirectiveComponent(VTooltip, binding => {
|
33954
|
+
return {
|
33955
|
+
activator: 'parent',
|
33956
|
+
location: binding.arg?.replace('-', ' '),
|
33957
|
+
text: typeof binding.value === 'boolean' ? undefined : binding.value
|
33958
|
+
};
|
33959
|
+
});
|
33960
|
+
|
33961
|
+
// Types
|
33962
|
+
|
33963
|
+
const makeVVideoVolumeProps = propsFactory({
|
33964
|
+
inline: Boolean,
|
33965
|
+
label: String,
|
33966
|
+
direction: {
|
33967
|
+
type: String,
|
33968
|
+
default: 'vertical'
|
33969
|
+
},
|
33970
|
+
modelValue: {
|
33971
|
+
type: Number,
|
33972
|
+
default: 0
|
33973
|
+
},
|
33974
|
+
menuProps: Object,
|
33975
|
+
sliderProps: Object,
|
33976
|
+
onClick: EventProp(),
|
33977
|
+
...makeComponentProps()
|
33978
|
+
}, 'VVideoVolume');
|
33979
|
+
const VVideoVolume = genericComponent()({
|
33980
|
+
name: 'VVideoVolume',
|
33981
|
+
directives: {
|
33982
|
+
vTooltip: Tooltip
|
33983
|
+
},
|
33984
|
+
props: makeVVideoVolumeProps(),
|
33985
|
+
emits: {
|
33986
|
+
'update:modelValue': val => true
|
33987
|
+
},
|
33988
|
+
setup(props, _ref) {
|
33989
|
+
let {
|
33990
|
+
attrs
|
33991
|
+
} = _ref;
|
33992
|
+
const {
|
33993
|
+
t
|
33994
|
+
} = useLocale();
|
33995
|
+
const volume = useProxiedModel(props, 'modelValue');
|
33996
|
+
const volumeIcon = vue.toRef(() => volume.value > 70 ? '$volumeHigh' : volume.value > 40 ? '$volumeMedium' : volume.value > 10 ? '$volumeLow' : '$volumeOff');
|
33997
|
+
const containerRef = vue.ref();
|
33998
|
+
useRender(() => {
|
33999
|
+
const sliderDefaults = {
|
34000
|
+
hideDetails: true,
|
34001
|
+
step: 5,
|
34002
|
+
thumbSize: 16
|
34003
|
+
};
|
34004
|
+
return vue.createElementVNode("div", {
|
34005
|
+
"class": vue.normalizeClass(['v-video-volume', {
|
34006
|
+
'v-video-volume--inline': props.inline
|
34007
|
+
}, props.class]),
|
34008
|
+
"style": vue.normalizeStyle(props.style),
|
34009
|
+
"ref": containerRef
|
34010
|
+
}, [vue.withDirectives(vue.createVNode(VIconBtn, vue.mergeProps({
|
34011
|
+
"icon": volumeIcon.value,
|
34012
|
+
"aria-label": props.label,
|
34013
|
+
"onClick": props.onClick
|
34014
|
+
}, attrs), {
|
34015
|
+
default: () => [vue.createVNode(VIcon, null, null), !props.inline && vue.createVNode(VMenu, {
|
34016
|
+
"offset": "8",
|
34017
|
+
"activator": "parent",
|
34018
|
+
"attach": containerRef.value,
|
34019
|
+
"location": props.menuProps?.location ?? 'top center',
|
34020
|
+
"closeOnContentClick": false
|
34021
|
+
}, {
|
34022
|
+
default: () => [vue.createElementVNode("div", {
|
34023
|
+
"class": vue.normalizeClass(['v-video-volume__menu', `v-video-volume__menu--${props.direction}`])
|
34024
|
+
}, [vue.createVNode(VSlider, vue.mergeProps({
|
34025
|
+
"direction": props.direction,
|
34026
|
+
"aria-label": t('$vuetify.video.volume'),
|
34027
|
+
"modelValue": volume.value,
|
34028
|
+
"onUpdate:modelValue": v => volume.value = v
|
34029
|
+
}, sliderDefaults, props.sliderProps), null)])]
|
34030
|
+
})]
|
34031
|
+
}), [[Tooltip, props.label, 'top']]), props.inline && vue.createVNode(VSlider, vue.mergeProps({
|
34032
|
+
"class": "v-video-volume-inline__slider",
|
34033
|
+
"minWidth": "50",
|
34034
|
+
"aria-label": t('$vuetify.video.volume'),
|
34035
|
+
"modelValue": volume.value,
|
34036
|
+
"onUpdate:modelValue": v => volume.value = v,
|
34037
|
+
"onKeydown": e => {
|
34038
|
+
e.stopPropagation();
|
34039
|
+
}
|
34040
|
+
}, sliderDefaults, props.sliderProps), null)]);
|
34041
|
+
});
|
34042
|
+
}
|
34043
|
+
});
|
34044
|
+
|
34045
|
+
// Types
|
34046
|
+
|
34047
|
+
const allowedVariants$1 = ['hidden', 'default', 'tube', 'mini'];
|
34048
|
+
const makeVVideoControlsProps = propsFactory({
|
34049
|
+
color: String,
|
34050
|
+
backgroundColor: String,
|
34051
|
+
trackColor: String,
|
34052
|
+
playing: Boolean,
|
34053
|
+
hidePlay: Boolean,
|
34054
|
+
hideVolume: Boolean,
|
34055
|
+
hideFullscreen: Boolean,
|
34056
|
+
fullscreen: Boolean,
|
34057
|
+
floating: Boolean,
|
34058
|
+
splitTime: Boolean,
|
34059
|
+
pills: Boolean,
|
34060
|
+
detached: Boolean,
|
34061
|
+
progress: {
|
34062
|
+
type: Number,
|
34063
|
+
default: 0
|
34064
|
+
},
|
34065
|
+
duration: {
|
34066
|
+
type: Number,
|
34067
|
+
default: 0
|
34068
|
+
},
|
34069
|
+
volume: [Number, String],
|
34070
|
+
variant: {
|
34071
|
+
type: String,
|
34072
|
+
default: 'default',
|
34073
|
+
validator: v => allowedVariants$1.includes(v)
|
34074
|
+
},
|
34075
|
+
volumeProps: Object,
|
34076
|
+
...makeDensityProps(),
|
34077
|
+
...makeElevationProps(),
|
34078
|
+
...makeThemeProps()
|
34079
|
+
}, 'VVideoControls');
|
34080
|
+
const VVideoControls = genericComponent()({
|
34081
|
+
name: 'VVideoControls',
|
34082
|
+
directives: {
|
34083
|
+
vTooltip: Tooltip
|
34084
|
+
},
|
34085
|
+
props: makeVVideoControlsProps(),
|
34086
|
+
emits: {
|
34087
|
+
'update:playing': val => true,
|
34088
|
+
'update:progress': val => true,
|
34089
|
+
'update:volume': val => true,
|
34090
|
+
skip: val => true,
|
34091
|
+
'click:fullscreen': () => true
|
34092
|
+
},
|
34093
|
+
setup(props, _ref) {
|
34094
|
+
let {
|
34095
|
+
emit,
|
34096
|
+
slots
|
34097
|
+
} = _ref;
|
34098
|
+
const {
|
34099
|
+
t
|
34100
|
+
} = useLocale();
|
34101
|
+
const {
|
34102
|
+
themeClasses
|
34103
|
+
} = provideTheme(props);
|
34104
|
+
const {
|
34105
|
+
densityClasses
|
34106
|
+
} = useDensity(props);
|
34107
|
+
const {
|
34108
|
+
elevationClasses
|
34109
|
+
} = useElevation(props);
|
34110
|
+
const {
|
34111
|
+
backgroundColorClasses,
|
34112
|
+
backgroundColorStyles
|
34113
|
+
} = useBackgroundColor(() => {
|
34114
|
+
const fallbackBackground = props.detached ? 'surface' : undefined;
|
34115
|
+
return props.backgroundColor ?? fallbackBackground;
|
34116
|
+
});
|
34117
|
+
const playing = useProxiedModel(props, 'playing');
|
34118
|
+
const progress = useProxiedModel(props, 'progress');
|
34119
|
+
const volume = useProxiedModel(props, 'volume', 0, v => Number(v ?? 0));
|
34120
|
+
const lastVolume = vue.shallowRef();
|
34121
|
+
const currentTime = vue.computed(() => {
|
34122
|
+
const secondsElapsed = Math.round(props.progress / 100 * props.duration);
|
34123
|
+
return {
|
34124
|
+
elapsed: formatTime(secondsElapsed),
|
34125
|
+
remaining: formatTime(props.duration - secondsElapsed),
|
34126
|
+
total: formatTime(props.duration)
|
34127
|
+
};
|
34128
|
+
});
|
34129
|
+
const labels = vue.computed(() => {
|
34130
|
+
const playIconLocaleKey = playing.value ? 'pause' : 'play';
|
34131
|
+
const volumeIconLocaleKey = props.volumeProps?.inline ? volume.value ? 'mute' : 'unmute' : 'showVolume';
|
34132
|
+
const fullscreenIconLocaleKey = props.fullscreen ? 'exitFullscreen' : 'enterFullscreen';
|
34133
|
+
return {
|
34134
|
+
seek: t('$vuetify.video.seek'),
|
34135
|
+
volume: t('$vuetify.video.volume'),
|
34136
|
+
playAction: t(`$vuetify.video.${playIconLocaleKey}`),
|
34137
|
+
volumeAction: t(`$vuetify.video.${volumeIconLocaleKey}`),
|
34138
|
+
fullscreenAction: t(`$vuetify.video.${fullscreenIconLocaleKey}`)
|
34139
|
+
};
|
34140
|
+
});
|
34141
|
+
function play() {
|
34142
|
+
playing.value = true;
|
34143
|
+
}
|
34144
|
+
function pause() {
|
34145
|
+
playing.value = false;
|
34146
|
+
}
|
34147
|
+
function skipTo(v) {
|
34148
|
+
progress.value = v;
|
34149
|
+
}
|
34150
|
+
function toggleMuted() {
|
34151
|
+
if (volume.value) {
|
34152
|
+
lastVolume.value = volume.value;
|
34153
|
+
volume.value = 0;
|
34154
|
+
} else {
|
34155
|
+
volume.value = lastVolume.value ?? 100;
|
34156
|
+
}
|
34157
|
+
}
|
34158
|
+
function toggleFullscreen() {
|
34159
|
+
emit('click:fullscreen');
|
34160
|
+
}
|
34161
|
+
useRender(() => {
|
34162
|
+
const sizes = props.pills ? [42, 36, 30] : [32, 28, 24];
|
34163
|
+
const innerDefaults = {
|
34164
|
+
VIconBtn: {
|
34165
|
+
size: props.density === 'compact' ? sizes[2] : props.density === 'comfortable' ? sizes[1] : sizes[0],
|
34166
|
+
iconSize: props.density === 'compact' ? 20 : props.density === 'comfortable' ? 24 : 26,
|
34167
|
+
variant: 'text',
|
34168
|
+
color: props.color
|
34169
|
+
},
|
34170
|
+
VSlider: {
|
34171
|
+
thumbSize: props.variant === 'tube' ? 10 : 16,
|
34172
|
+
hideDetails: true
|
34173
|
+
}
|
34174
|
+
};
|
34175
|
+
const regularBtnSize = innerDefaults.VIconBtn.size;
|
34176
|
+
const playBtnSize = props.pills ? regularBtnSize + 8 : regularBtnSize;
|
34177
|
+
const pillClasses = ['v-video-control__pill', props.pills ? elevationClasses.value : []];
|
34178
|
+
const slotProps = {
|
34179
|
+
play,
|
34180
|
+
pause,
|
34181
|
+
playing: playing.value,
|
34182
|
+
progress: progress.value,
|
34183
|
+
currentTime: currentTime.value,
|
34184
|
+
skipTo,
|
34185
|
+
volume,
|
34186
|
+
toggleMuted,
|
34187
|
+
fullscreen: props.fullscreen,
|
34188
|
+
toggleFullscreen,
|
34189
|
+
labels: labels.value
|
34190
|
+
};
|
34191
|
+
return vue.createElementVNode("div", {
|
34192
|
+
"class": vue.normalizeClass(['v-video-controls', `v-video-controls--variant-${props.variant}`, {
|
34193
|
+
'v-video-controls--pills': props.pills
|
34194
|
+
}, {
|
34195
|
+
'v-video-controls--detached': props.detached
|
34196
|
+
}, {
|
34197
|
+
'v-video-controls--floating': props.floating
|
34198
|
+
}, {
|
34199
|
+
'v-video-controls--split-time': props.splitTime
|
34200
|
+
}, backgroundColorClasses.value, props.detached && !props.pills ? elevationClasses.value : [], densityClasses.value, themeClasses.value]),
|
34201
|
+
"style": vue.normalizeStyle([backgroundColorStyles.value, {
|
34202
|
+
'--v-video-controls-pill-height': `${regularBtnSize}px`
|
34203
|
+
}])
|
34204
|
+
}, [vue.createVNode(VDefaultsProvider, {
|
34205
|
+
"defaults": innerDefaults
|
34206
|
+
}, {
|
34207
|
+
default: () => [slots.default?.(slotProps) ?? vue.createElementVNode(vue.Fragment, null, [props.variant !== 'mini' && vue.createElementVNode(vue.Fragment, null, [!props.hidePlay && vue.createElementVNode("div", {
|
34208
|
+
"class": vue.normalizeClass([pillClasses, 'v-video__action-play'])
|
34209
|
+
}, [vue.withDirectives(vue.createVNode(VIconBtn, {
|
34210
|
+
"icon": playing.value ? '$pause' : '$play',
|
34211
|
+
"size": playBtnSize,
|
34212
|
+
"aria-label": labels.value.playAction,
|
34213
|
+
"onClick": () => playing.value = !playing.value
|
34214
|
+
}, null), [[Tooltip, labels.value.playAction, 'top']])]), slots.prepend && vue.createElementVNode("div", {
|
34215
|
+
"class": vue.normalizeClass(pillClasses)
|
34216
|
+
}, [slots.prepend(slotProps)]), props.splitTime ? vue.createElementVNode("span", {
|
34217
|
+
"class": vue.normalizeClass([pillClasses, 'v-video__time'])
|
34218
|
+
}, [currentTime.value.elapsed]) : props.variant !== 'default' ? vue.createElementVNode("span", {
|
34219
|
+
"class": vue.normalizeClass([pillClasses, 'v-video__time'])
|
34220
|
+
}, [currentTime.value.elapsed, vue.createTextVNode(" / "), currentTime.value.total]) : '', vue.createVNode(VSlider, {
|
34221
|
+
"modelValue": props.progress,
|
34222
|
+
"noKeyboard": true,
|
34223
|
+
"color": props.trackColor ?? props.color,
|
34224
|
+
"trackColor": props.variant === 'tube' ? 'white' : undefined,
|
34225
|
+
"class": "v-video__track",
|
34226
|
+
"thumbLabel": "always",
|
34227
|
+
"aria-label": labels.value.seek,
|
34228
|
+
"onUpdate:modelValue": skipTo
|
34229
|
+
}, {
|
34230
|
+
'thumb-label': () => currentTime.value.elapsed
|
34231
|
+
}), props.variant === 'tube' && vue.createVNode(VSpacer, null, null), props.splitTime ? vue.createElementVNode("span", {
|
34232
|
+
"class": vue.normalizeClass([pillClasses, 'v-video__time'])
|
34233
|
+
}, [currentTime.value.remaining]) : '']), props.variant === 'mini' && vue.createElementVNode(vue.Fragment, null, [vue.createVNode(VSpacer, null, null), slots.prepend && vue.createElementVNode("div", {
|
34234
|
+
"class": vue.normalizeClass(pillClasses)
|
34235
|
+
}, [slots.prepend(slotProps)]), !props.hidePlay && vue.createElementVNode("div", {
|
34236
|
+
"class": vue.normalizeClass([pillClasses, 'v-video__action-play'])
|
34237
|
+
}, [vue.withDirectives(vue.createVNode(VIconBtn, {
|
34238
|
+
"icon": playing.value ? '$pause' : '$play',
|
34239
|
+
"size": playBtnSize,
|
34240
|
+
"aria-label": labels.value.playAction,
|
34241
|
+
"onClick": () => playing.value = !playing.value
|
34242
|
+
}, null), [[Tooltip, labels.value.playAction, 'top']])])]), (!props.hideVolume || !props.hideFullscreen || slots.append) && vue.createElementVNode("div", {
|
34243
|
+
"class": vue.normalizeClass(pillClasses)
|
34244
|
+
}, [!props.hideVolume && vue.createVNode(VVideoVolume, vue.mergeProps({
|
34245
|
+
"key": "volume-control",
|
34246
|
+
"sliderProps": {
|
34247
|
+
color: props.color
|
34248
|
+
},
|
34249
|
+
"modelValue": volume.value,
|
34250
|
+
"label": labels.value.volumeAction,
|
34251
|
+
"onUpdate:modelValue": v => volume.value = v,
|
34252
|
+
"onClick": () => props.volumeProps?.inline && toggleMuted()
|
34253
|
+
}, props.volumeProps), null), slots.append?.(slotProps), !props.hideFullscreen && vue.withDirectives(vue.createVNode(VIconBtn, {
|
34254
|
+
"icon": props.fullscreen ? '$fullscreenExit' : '$fullscreen',
|
34255
|
+
"aria-label": labels.value.fullscreenAction,
|
34256
|
+
"onClick": toggleFullscreen
|
34257
|
+
}, null), [[Tooltip, labels.value.fullscreenAction, 'top']])]), props.variant === 'mini' && vue.createVNode(VSpacer, null, null)])]
|
34258
|
+
})]);
|
34259
|
+
});
|
34260
|
+
return {
|
34261
|
+
toggleMuted
|
34262
|
+
};
|
34263
|
+
}
|
34264
|
+
});
|
34265
|
+
|
34266
|
+
// Types
|
34267
|
+
|
34268
|
+
const allowedVariants = ['background', 'player'];
|
34269
|
+
const makeVVideoProps = propsFactory({
|
34270
|
+
autoplay: Boolean,
|
34271
|
+
muted: Boolean,
|
34272
|
+
eager: Boolean,
|
34273
|
+
src: String,
|
34274
|
+
type: String,
|
34275
|
+
// e.g. video/mp4
|
34276
|
+
image: String,
|
34277
|
+
hideOverlay: Boolean,
|
34278
|
+
noFullscreen: Boolean,
|
34279
|
+
startAt: [Number, String],
|
34280
|
+
variant: {
|
34281
|
+
type: String,
|
34282
|
+
default: 'player',
|
34283
|
+
validator: v => allowedVariants.includes(v)
|
34284
|
+
},
|
34285
|
+
controlsTransition: {
|
34286
|
+
type: [Boolean, String, Object],
|
34287
|
+
component: VFadeTransition
|
34288
|
+
},
|
34289
|
+
controlsVariant: {
|
34290
|
+
type: String,
|
34291
|
+
default: 'default'
|
34292
|
+
},
|
34293
|
+
controlsProps: {
|
34294
|
+
type: Object
|
34295
|
+
},
|
34296
|
+
rounded: [Boolean, Number, String, Array],
|
34297
|
+
...makeComponentProps(),
|
34298
|
+
...makeDensityProps(),
|
34299
|
+
...makeDimensionProps(),
|
34300
|
+
...makeThemeProps(),
|
34301
|
+
...omit(makeVVideoControlsProps(), ['fullscreen', 'variant'])
|
34302
|
+
}, 'VVideo');
|
34303
|
+
const VVideo = genericComponent()({
|
34304
|
+
name: 'VVideo',
|
34305
|
+
inheritAttrs: false,
|
34306
|
+
props: makeVVideoProps(),
|
34307
|
+
emits: {
|
34308
|
+
loaded: element => true,
|
34309
|
+
'update:playing': val => true,
|
34310
|
+
'update:progress': val => true,
|
34311
|
+
'update:volume': val => true
|
34312
|
+
},
|
34313
|
+
setup(props, _ref) {
|
34314
|
+
let {
|
34315
|
+
attrs,
|
34316
|
+
emit,
|
34317
|
+
slots
|
34318
|
+
} = _ref;
|
34319
|
+
const {
|
34320
|
+
themeClasses
|
34321
|
+
} = provideTheme(props);
|
34322
|
+
const {
|
34323
|
+
densityClasses
|
34324
|
+
} = useDensity(props);
|
34325
|
+
const {
|
34326
|
+
dimensionStyles
|
34327
|
+
} = useDimension(props);
|
34328
|
+
const {
|
34329
|
+
elevationClasses
|
34330
|
+
} = useElevation(props);
|
34331
|
+
const {
|
34332
|
+
ssr
|
34333
|
+
} = useDisplay();
|
34334
|
+
const roundedForContainer = vue.toRef(() => Array.isArray(props.rounded) ? props.rounded[0] : props.rounded);
|
34335
|
+
const roundedForControls = vue.toRef(() => Array.isArray(props.rounded) ? props.rounded.at(-1) : props.rounded ?? false);
|
34336
|
+
const {
|
34337
|
+
roundedClasses: roundedContainerClasses
|
34338
|
+
} = useRounded(roundedForContainer);
|
34339
|
+
const {
|
34340
|
+
roundedClasses: roundedControlsClasses
|
34341
|
+
} = useRounded(roundedForControls);
|
34342
|
+
const containerRef = vue.ref();
|
34343
|
+
const videoRef = vue.ref();
|
34344
|
+
const controlsRef = vue.ref();
|
34345
|
+
const playing = useProxiedModel(props, 'playing');
|
34346
|
+
const progress = useProxiedModel(props, 'progress');
|
34347
|
+
const volume = useProxiedModel(props, 'volume', 0, v => Number(v ?? 0));
|
34348
|
+
const fullscreen = vue.shallowRef(false);
|
34349
|
+
const waiting = vue.shallowRef(false);
|
34350
|
+
const triggered = vue.shallowRef(false);
|
34351
|
+
const startAfterLoad = vue.shallowRef(false);
|
34352
|
+
const state = vue.shallowRef(props.autoplay ? 'loading' : 'idle');
|
34353
|
+
const duration = vue.shallowRef(0);
|
34354
|
+
const fullscreenEnabled = vue.toRef(() => !props.noFullscreen && !String(attrs.controlsList ?? '').includes('nofullscreen'));
|
34355
|
+
function onTimeupdate() {
|
34356
|
+
const {
|
34357
|
+
currentTime,
|
34358
|
+
duration
|
34359
|
+
} = videoRef.value;
|
34360
|
+
progress.value = duration === 0 ? 0 : 100 * currentTime / duration;
|
34361
|
+
}
|
34362
|
+
async function onTriggered() {
|
34363
|
+
await vue.nextTick();
|
34364
|
+
if (!videoRef.value) return;
|
34365
|
+
videoRef.value.addEventListener('timeupdate', onTimeupdate);
|
34366
|
+
videoRef.value.volume = volume.value / 100;
|
34367
|
+
if (state.value !== 'loaded') {
|
34368
|
+
state.value = 'loading';
|
34369
|
+
}
|
34370
|
+
}
|
34371
|
+
function onVideoLoaded() {
|
34372
|
+
state.value = 'loaded';
|
34373
|
+
duration.value = videoRef.value.duration;
|
34374
|
+
const startTime = Number(props.startAt ?? 0);
|
34375
|
+
if (startTime && startTime <= duration.value) {
|
34376
|
+
videoRef.value.currentTime = startTime;
|
34377
|
+
progress.value = duration.value === 0 ? 0 : 100 * startTime / duration.value;
|
34378
|
+
}
|
34379
|
+
if (startAfterLoad.value) {
|
34380
|
+
setTimeout(() => playing.value = true, 100);
|
34381
|
+
}
|
34382
|
+
emit('loaded', videoRef.value);
|
34383
|
+
}
|
34384
|
+
function onClick() {
|
34385
|
+
if (state.value !== 'loaded') {
|
34386
|
+
triggered.value = true;
|
34387
|
+
startAfterLoad.value = !startAfterLoad.value;
|
34388
|
+
}
|
34389
|
+
}
|
34390
|
+
function onKeydown(e) {
|
34391
|
+
if (!videoRef.value || e.ctrlKey) return;
|
34392
|
+
if (e.key.startsWith('Arrow')) {
|
34393
|
+
e.preventDefault();
|
34394
|
+
}
|
34395
|
+
switch (true) {
|
34396
|
+
case e.key === ' ':
|
34397
|
+
{
|
34398
|
+
if (!['A', 'BUTTON'].includes(e.target?.tagName)) {
|
34399
|
+
e.preventDefault();
|
34400
|
+
playing.value = !playing.value;
|
34401
|
+
}
|
34402
|
+
break;
|
34403
|
+
}
|
34404
|
+
case e.key === 'ArrowRight':
|
34405
|
+
{
|
34406
|
+
const step = 10 * (e.shiftKey ? 6 : 1);
|
34407
|
+
videoRef.value.currentTime = Math.min(videoRef.value.currentTime + step, duration.value);
|
34408
|
+
// TODO: show skip indicator
|
34409
|
+
break;
|
34410
|
+
}
|
34411
|
+
case e.key === 'ArrowLeft':
|
34412
|
+
{
|
34413
|
+
const step = 10 * (e.shiftKey ? 6 : 1);
|
34414
|
+
videoRef.value.currentTime = Math.max(videoRef.value.currentTime - step, 0);
|
34415
|
+
// TODO: show skip indicator
|
34416
|
+
break;
|
34417
|
+
}
|
34418
|
+
case createRange(10).map(String).includes(e.key):
|
34419
|
+
{
|
34420
|
+
skipTo(Number(e.key) * 10);
|
34421
|
+
break;
|
34422
|
+
}
|
34423
|
+
case e.key === 'ArrowUp':
|
34424
|
+
{
|
34425
|
+
volume.value = Math.min(volume.value + 10, 100);
|
34426
|
+
// TODO: show volume change indicator
|
34427
|
+
break;
|
34428
|
+
}
|
34429
|
+
case e.key === 'ArrowDown':
|
34430
|
+
{
|
34431
|
+
volume.value = Math.max(volume.value - 10, 0);
|
34432
|
+
// TODO: show volume change indicator
|
34433
|
+
break;
|
34434
|
+
}
|
34435
|
+
case e.key === 'm':
|
34436
|
+
{
|
34437
|
+
controlsRef.value?.toggleMuted();
|
34438
|
+
break;
|
34439
|
+
}
|
34440
|
+
case e.key === 'f':
|
34441
|
+
{
|
34442
|
+
toggleFullscreen();
|
34443
|
+
break;
|
34444
|
+
}
|
34445
|
+
}
|
34446
|
+
}
|
34447
|
+
function skipTo(v) {
|
34448
|
+
if (!videoRef.value) return;
|
34449
|
+
progress.value = v;
|
34450
|
+
videoRef.value.currentTime = duration.value * v / 100;
|
34451
|
+
}
|
34452
|
+
vue.watch(() => props.src, v => {
|
34453
|
+
progress.value = 0;
|
34454
|
+
});
|
34455
|
+
vue.watch(playing, v => {
|
34456
|
+
if (!videoRef.value) return;
|
34457
|
+
if (v) {
|
34458
|
+
videoRef.value.play();
|
34459
|
+
} else {
|
34460
|
+
videoRef.value.pause();
|
34461
|
+
}
|
34462
|
+
});
|
34463
|
+
vue.watch(volume, v => {
|
34464
|
+
if (!videoRef.value) return;
|
34465
|
+
videoRef.value.volume = v / 100;
|
34466
|
+
});
|
34467
|
+
vue.watch(triggered, () => onTriggered(), {
|
34468
|
+
once: true
|
34469
|
+
});
|
34470
|
+
vue.watch(() => props.eager, v => v && (triggered.value = true), {
|
34471
|
+
immediate: true
|
34472
|
+
});
|
34473
|
+
vue.onMounted(() => {
|
34474
|
+
if (props.autoplay && !ssr) {
|
34475
|
+
triggered.value = true;
|
34476
|
+
startAfterLoad.value = true;
|
34477
|
+
}
|
34478
|
+
});
|
34479
|
+
vue.onBeforeUnmount(() => {
|
34480
|
+
videoRef.value?.removeEventListener('timeupdate', onTimeupdate);
|
34481
|
+
});
|
34482
|
+
function focusSlider() {
|
34483
|
+
const container = videoRef.value?.closest('.v-video');
|
34484
|
+
const innerSlider = container?.querySelector('[role="slider"]');
|
34485
|
+
innerSlider?.focus();
|
34486
|
+
}
|
34487
|
+
function fullscreenExitShortcut(e) {
|
34488
|
+
if (['ESC', 'f'].includes(e.key)) {
|
34489
|
+
toggleFullscreen();
|
34490
|
+
document.body.removeEventListener('keydown', fullscreenExitShortcut);
|
34491
|
+
}
|
34492
|
+
}
|
34493
|
+
async function toggleFullscreen() {
|
34494
|
+
if (!fullscreenEnabled.value || !document.fullscreenEnabled) {
|
34495
|
+
return;
|
34496
|
+
}
|
34497
|
+
if (document.fullscreenElement) {
|
34498
|
+
document.exitFullscreen();
|
34499
|
+
onFullscreenExit();
|
34500
|
+
} else {
|
34501
|
+
await containerRef.value?.requestFullscreen();
|
34502
|
+
document.body.addEventListener('keydown', fullscreenExitShortcut);
|
34503
|
+
document.addEventListener('fullscreenchange', onFullscreenExit);
|
34504
|
+
fullscreen.value = true;
|
34505
|
+
}
|
34506
|
+
}
|
34507
|
+
function onFullscreenExit() {
|
34508
|
+
// event fires with a delay after requestFullscreen(), ignore first run
|
34509
|
+
if (document.fullscreenElement) return;
|
34510
|
+
focusSlider();
|
34511
|
+
fullscreen.value = false;
|
34512
|
+
document.body.removeEventListener('keydown', fullscreenExitShortcut);
|
34513
|
+
document.removeEventListener('fullscreenchange', onFullscreenExit);
|
34514
|
+
}
|
34515
|
+
function onVideoClick(e) {
|
34516
|
+
e.preventDefault();
|
34517
|
+
if (state.value === 'loaded') {
|
34518
|
+
playing.value = !playing.value;
|
34519
|
+
focusSlider();
|
34520
|
+
}
|
34521
|
+
}
|
34522
|
+
function onDoubleClick(e) {
|
34523
|
+
e.preventDefault();
|
34524
|
+
toggleFullscreen();
|
34525
|
+
}
|
34526
|
+
let lastTap = 0;
|
34527
|
+
function onTouchend(e) {
|
34528
|
+
const now = performance.now();
|
34529
|
+
if (now - lastTap < 500) {
|
34530
|
+
e.preventDefault();
|
34531
|
+
toggleFullscreen();
|
34532
|
+
} else {
|
34533
|
+
lastTap = now;
|
34534
|
+
}
|
34535
|
+
}
|
34536
|
+
useRender(() => {
|
34537
|
+
const showControls = state.value === 'loaded' && props.variant === 'player' && props.controlsVariant !== 'hidden';
|
34538
|
+
const posterTransition = props.variant === 'background' ? 'poster-fade-out' : 'fade-transition';
|
34539
|
+
const overlayProps = {
|
34540
|
+
contained: true,
|
34541
|
+
persistent: true,
|
34542
|
+
contentClass: 'v-video__overlay-fill'
|
34543
|
+
};
|
34544
|
+
const controlsProps = {
|
34545
|
+
...VVideoControls.filterProps(omit(props, ['variant', 'rounded', 'hideVolume'])),
|
34546
|
+
rounded: Array.isArray(props.rounded) ? props.rounded.at(-1) : props.rounded,
|
34547
|
+
fullscreen: fullscreen.value,
|
34548
|
+
hideVolume: props.hideVolume || props.muted,
|
34549
|
+
hideFullscreen: props.hideFullscreen || !fullscreenEnabled.value,
|
34550
|
+
density: props.density,
|
34551
|
+
variant: props.controlsVariant,
|
34552
|
+
playing: playing.value,
|
34553
|
+
progress: progress.value,
|
34554
|
+
duration: duration.value,
|
34555
|
+
volume: volume.value,
|
34556
|
+
...props.controlsProps
|
34557
|
+
};
|
34558
|
+
const controlsEventHandlers = {
|
34559
|
+
onSkip: v => skipTo(v),
|
34560
|
+
'onClick:fullscreen': () => toggleFullscreen(),
|
34561
|
+
'onUpdate:playing': v => playing.value = v,
|
34562
|
+
'onUpdate:progress': v => skipTo(v),
|
34563
|
+
'onUpdate:volume': v => volume.value = v,
|
34564
|
+
onClick: e => e.stopPropagation()
|
34565
|
+
};
|
34566
|
+
const controlslist = [attrs.controlslist, props.noFullscreen ? 'nofullscreen' : ''].filter(Boolean).join(' ');
|
34567
|
+
const loadingIndicator = vue.createVNode(VProgressCircular, {
|
34568
|
+
"indeterminate": true,
|
34569
|
+
"color": props.color,
|
34570
|
+
"width": "3",
|
34571
|
+
"size": Math.min(100, Number(props.height) / 2 || 50)
|
34572
|
+
}, null);
|
34573
|
+
const overlayPlayIcon = vue.createVNode(VIconBtn, {
|
34574
|
+
"icon": "$play",
|
34575
|
+
"size": "80",
|
34576
|
+
"color": "#fff",
|
34577
|
+
"variant": "outlined",
|
34578
|
+
"iconSize": "50",
|
34579
|
+
"class": "v-video__center-icon"
|
34580
|
+
}, null);
|
34581
|
+
return vue.createElementVNode("div", {
|
34582
|
+
"ref": containerRef,
|
34583
|
+
"class": vue.normalizeClass(['v-video', `v-video--variant-${props.variant}`, `v-video--${state.value}`, {
|
34584
|
+
'v-video--playing': playing.value
|
34585
|
+
}, themeClasses.value, densityClasses.value, roundedContainerClasses.value, props.class]),
|
34586
|
+
"style": vue.normalizeStyle([props.variant === 'background' ? [] : pick(dimensionStyles.value, ['width', 'min-width', 'max-width']), props.style]),
|
34587
|
+
"onKeydown": onKeydown,
|
34588
|
+
"onClick": onClick
|
34589
|
+
}, [vue.createElementVNode("div", {
|
34590
|
+
"class": vue.normalizeClass(['v-video__content', elevationClasses.value]),
|
34591
|
+
"style": vue.normalizeStyle([props.variant === 'background' ? [] : dimensionStyles.value])
|
34592
|
+
}, [(props.eager || triggered.value) && vue.createElementVNode("video", vue.mergeProps({
|
34593
|
+
"key": "video-element",
|
34594
|
+
"class": ['v-video__video', roundedContainerClasses.value]
|
34595
|
+
}, omit(attrs, ['controlslist', 'class', 'style']), {
|
34596
|
+
"controlslist": controlslist,
|
34597
|
+
"autoplay": props.autoplay,
|
34598
|
+
"muted": props.muted,
|
34599
|
+
"playsinline": true,
|
34600
|
+
"ref": videoRef,
|
34601
|
+
"onLoadeddata": onVideoLoaded,
|
34602
|
+
"onPlay": () => playing.value = true,
|
34603
|
+
"onPause": () => playing.value = false,
|
34604
|
+
"onWaiting": () => waiting.value = true,
|
34605
|
+
"onPlaying": () => waiting.value = false,
|
34606
|
+
"onClick": onVideoClick,
|
34607
|
+
"onDblclick": onDoubleClick,
|
34608
|
+
"onTouchend": onTouchend
|
34609
|
+
}), [slots.sources?.() ?? vue.createElementVNode("source", {
|
34610
|
+
"src": props.src,
|
34611
|
+
"type": props.type
|
34612
|
+
}, null)]), props.variant === 'player' && !props.hideOverlay && vue.createVNode(VOverlay, vue.mergeProps({
|
34613
|
+
"key": "pause-overlay",
|
34614
|
+
"modelValue": state.value === 'loaded',
|
34615
|
+
"opacity": "0"
|
34616
|
+
}, overlayProps), {
|
34617
|
+
default: () => [vue.createVNode(VSpacer, null, null), vue.createVNode(MaybeTransition, {
|
34618
|
+
"name": "fade-transition"
|
34619
|
+
}, {
|
34620
|
+
default: () => [!playing.value && overlayPlayIcon]
|
34621
|
+
}), vue.createVNode(VSpacer, null, null)]
|
34622
|
+
}), props.variant === 'player' && !!slots.header ? vue.createElementVNode("div", {
|
34623
|
+
"key": "header",
|
34624
|
+
"class": "v-video__header"
|
34625
|
+
}, [slots.header()]) : '', vue.createVNode(VOverlay, vue.mergeProps({
|
34626
|
+
"key": "poster-overlay",
|
34627
|
+
"modelValue": state.value !== 'loaded',
|
34628
|
+
"transition": posterTransition
|
34629
|
+
}, overlayProps), {
|
34630
|
+
default: () => [vue.createVNode(VImg, {
|
34631
|
+
"cover": true,
|
34632
|
+
"src": props.image
|
34633
|
+
}, {
|
34634
|
+
default: () => [vue.createElementVNode("div", {
|
34635
|
+
"class": vue.normalizeClass(['v-video__overlay-fill', ...roundedContainerClasses.value])
|
34636
|
+
}, [overlayPlayIcon])]
|
34637
|
+
})]
|
34638
|
+
}), vue.createVNode(VOverlay, vue.mergeProps({
|
34639
|
+
"key": "loading-overlay",
|
34640
|
+
"modelValue": state.value === 'loading' || waiting.value,
|
34641
|
+
"opacity": ".1"
|
34642
|
+
}, overlayProps), {
|
34643
|
+
default: () => [loadingIndicator]
|
34644
|
+
})]), vue.createVNode(MaybeTransition, {
|
34645
|
+
"key": "actions",
|
34646
|
+
"transition": props.controlsTransition
|
34647
|
+
}, {
|
34648
|
+
default: () => [showControls && vue.createVNode(VVideoControls, vue.mergeProps({
|
34649
|
+
"ref": controlsRef,
|
34650
|
+
"class": roundedControlsClasses.value
|
34651
|
+
}, controlsProps, controlsEventHandlers), {
|
34652
|
+
default: slots.controls,
|
34653
|
+
prepend: slots.prepend,
|
34654
|
+
append: slots.append
|
34655
|
+
})]
|
34656
|
+
})]);
|
34657
|
+
});
|
34658
|
+
return {
|
34659
|
+
video: videoRef,
|
34660
|
+
...forwardRefs({
|
34661
|
+
skipTo,
|
34662
|
+
toggleFullscreen
|
34663
|
+
}, controlsRef)
|
34664
|
+
};
|
34665
|
+
}
|
34666
|
+
});
|
34667
|
+
|
33189
34668
|
var components = /*#__PURE__*/Object.freeze({
|
33190
34669
|
__proto__: null,
|
33191
34670
|
VAlert: VAlert,
|
@@ -33312,6 +34791,9 @@
|
|
33312
34791
|
VParallax: VParallax,
|
33313
34792
|
VPicker: VPicker,
|
33314
34793
|
VPickerTitle: VPickerTitle,
|
34794
|
+
VPie: VPie,
|
34795
|
+
VPieSegment: VPieSegment,
|
34796
|
+
VPieTooltip: VPieTooltip,
|
33315
34797
|
VProgressCircular: VProgressCircular,
|
33316
34798
|
VProgressLinear: VProgressLinear,
|
33317
34799
|
VPullToRefresh: VPullToRefresh,
|
@@ -33376,6 +34858,9 @@
|
|
33376
34858
|
VTreeviewGroup: VTreeviewGroup,
|
33377
34859
|
VTreeviewItem: VTreeviewItem,
|
33378
34860
|
VValidation: VValidation,
|
34861
|
+
VVideo: VVideo,
|
34862
|
+
VVideoControls: VVideoControls,
|
34863
|
+
VVideoVolume: VVideoVolume,
|
33379
34864
|
VVirtualScroll: VVirtualScroll,
|
33380
34865
|
VWindow: VWindow,
|
33381
34866
|
VWindowItem: VWindowItem
|
@@ -33501,92 +34986,6 @@
|
|
33501
34986
|
updated
|
33502
34987
|
};
|
33503
34988
|
|
33504
|
-
// Utilities
|
33505
|
-
|
33506
|
-
// Types
|
33507
|
-
|
33508
|
-
function useDirectiveComponent(component, props) {
|
33509
|
-
const concreteComponent = typeof component === 'string' ? vue.resolveComponent(component) : component;
|
33510
|
-
const hook = mountComponent(concreteComponent, props);
|
33511
|
-
return {
|
33512
|
-
mounted: hook,
|
33513
|
-
updated: hook,
|
33514
|
-
unmounted(el) {
|
33515
|
-
vue.render(null, el);
|
33516
|
-
}
|
33517
|
-
};
|
33518
|
-
}
|
33519
|
-
function mountComponent(component, props) {
|
33520
|
-
return function (el, binding, vnode) {
|
33521
|
-
const _props = typeof props === 'function' ? props(binding) : props;
|
33522
|
-
const text = binding.value?.text ?? binding.value ?? _props?.text;
|
33523
|
-
const value = isObject(binding.value) ? binding.value : {};
|
33524
|
-
|
33525
|
-
// Get the children from the props or directive value, or the element's children
|
33526
|
-
const children = () => text ?? el.textContent;
|
33527
|
-
|
33528
|
-
// If vnode.ctx is the same as the instance, then we're bound to a plain element
|
33529
|
-
// and need to find the nearest parent component instance to inherit provides from
|
33530
|
-
const provides = (vnode.ctx === binding.instance.$ ? findComponentParent(vnode, binding.instance.$)?.provides : vnode.ctx?.provides) ?? binding.instance.$.provides;
|
33531
|
-
const node = vue.h(component, vue.mergeProps(_props, value), children);
|
33532
|
-
node.appContext = Object.assign(Object.create(null), binding.instance.$.appContext, {
|
33533
|
-
provides
|
33534
|
-
});
|
33535
|
-
vue.render(node, el);
|
33536
|
-
};
|
33537
|
-
}
|
33538
|
-
function findComponentParent(vnode, root) {
|
33539
|
-
// Walk the tree from root until we find the child vnode
|
33540
|
-
const stack = new Set();
|
33541
|
-
const walk = children => {
|
33542
|
-
for (const child of children) {
|
33543
|
-
if (!child) continue;
|
33544
|
-
if (child === vnode || child.el && vnode.el && child.el === vnode.el) {
|
33545
|
-
return true;
|
33546
|
-
}
|
33547
|
-
stack.add(child);
|
33548
|
-
let result;
|
33549
|
-
if (child.suspense) {
|
33550
|
-
result = walk([child.ssContent]);
|
33551
|
-
} else if (Array.isArray(child.children)) {
|
33552
|
-
result = walk(child.children);
|
33553
|
-
} else if (child.component?.vnode) {
|
33554
|
-
result = walk([child.component?.subTree]);
|
33555
|
-
}
|
33556
|
-
if (result) {
|
33557
|
-
return result;
|
33558
|
-
}
|
33559
|
-
stack.delete(child);
|
33560
|
-
}
|
33561
|
-
return false;
|
33562
|
-
};
|
33563
|
-
if (!walk([root.subTree])) {
|
33564
|
-
consoleError('Could not find original vnode, component will not inherit provides');
|
33565
|
-
return root;
|
33566
|
-
}
|
33567
|
-
|
33568
|
-
// Return the first component parent
|
33569
|
-
const result = Array.from(stack).reverse();
|
33570
|
-
for (const child of result) {
|
33571
|
-
if (child.component) {
|
33572
|
-
return child.component;
|
33573
|
-
}
|
33574
|
-
}
|
33575
|
-
return root;
|
33576
|
-
}
|
33577
|
-
|
33578
|
-
// Components
|
33579
|
-
|
33580
|
-
// Types
|
33581
|
-
|
33582
|
-
const Tooltip = useDirectiveComponent(VTooltip, binding => {
|
33583
|
-
return {
|
33584
|
-
activator: 'parent',
|
33585
|
-
location: binding.arg?.replace('-', ' '),
|
33586
|
-
text: typeof binding.value === 'boolean' ? undefined : binding.value
|
33587
|
-
};
|
33588
|
-
});
|
33589
|
-
|
33590
34989
|
var directives = /*#__PURE__*/Object.freeze({
|
33591
34990
|
__proto__: null,
|
33592
34991
|
ClickOutside: ClickOutside,
|
@@ -33698,7 +35097,7 @@
|
|
33698
35097
|
};
|
33699
35098
|
});
|
33700
35099
|
}
|
33701
|
-
const version$1 = "3.9.2-master.2025-07-
|
35100
|
+
const version$1 = "3.9.2-master.2025-07-25";
|
33702
35101
|
createVuetify$1.version = version$1;
|
33703
35102
|
|
33704
35103
|
// Vue's inject() can only be used in setup
|
@@ -33996,7 +35395,7 @@
|
|
33996
35395
|
|
33997
35396
|
/* eslint-disable local-rules/sort-imports */
|
33998
35397
|
|
33999
|
-
const version = "3.9.2-master.2025-07-
|
35398
|
+
const version = "3.9.2-master.2025-07-25";
|
34000
35399
|
|
34001
35400
|
/* eslint-disable local-rules/sort-imports */
|
34002
35401
|
|