Some checks failed
🚀 Deploy - Demo / deployment (push) Has been cancelled
- 웹훅 URL을 https://admin.youtooplay.com/webhook로 변경 - Nginx 리버스 프록시 설정 파일 추가 - 배포 가이드 업데이트
1012 lines
32 KiB
JavaScript
1012 lines
32 KiB
JavaScript
import { computed, toRef, createVNode, Fragment, mergeProps, ref, shallowRef, watch, provide, withDirectives, resolveDirective, inject, vShow, nextTick } from 'vue';
|
|
import { g as genericComponent, p as propsFactory, n as useProxiedModel, ai as useDensity, a0 as useBackgroundColor, aB as useScopeId, G as provideDefaults, a as useRender, j as convertToUnit, at as useTextColor, D as VBtn, o as forwardRefs, F as provideTheme, E as useRtl, l as useLocale, ae as useGroup, am as useGroupItem, ay as useLazy, aA as MaybeTransition, L as makeTagProps, P as makeDensityProps, aC as isObject, b as useDisplay, u as useResizeObserver, ar as useGoTo, s as VIcon, r as omit, au as makeVBtnProps, av as animate, aw as standardEasing, K as makeThemeProps, m as makeComponentProps, ax as keys, az as makeLazyProps, aq as makeGroupItemProps, ad as makeGroupProps, Z as makeDisplayProps, I as IconValue, as as focusableChildren } from './server.mjs';
|
|
import { u as useSsrBoot } from './ssrBoot-BtvJZs44.mjs';
|
|
import { b as VFadeTransition } from './index-BNHdF426.mjs';
|
|
|
|
function calculateUpdatedTarget(_ref) {
|
|
let {
|
|
selectedElement,
|
|
containerElement,
|
|
isRtl,
|
|
isHorizontal
|
|
} = _ref;
|
|
const containerSize = getOffsetSize(isHorizontal, containerElement);
|
|
const scrollPosition = getScrollPosition(isHorizontal, isRtl, containerElement);
|
|
const childrenSize = getOffsetSize(isHorizontal, selectedElement);
|
|
const childrenStartPosition = getOffsetPosition(isHorizontal, selectedElement);
|
|
const additionalOffset = childrenSize * 0.4;
|
|
if (scrollPosition > childrenStartPosition) {
|
|
return childrenStartPosition - additionalOffset;
|
|
} else if (scrollPosition + containerSize < childrenStartPosition + childrenSize) {
|
|
return childrenStartPosition - containerSize + childrenSize + additionalOffset;
|
|
}
|
|
return scrollPosition;
|
|
}
|
|
function getScrollSize(isHorizontal, element) {
|
|
const key = isHorizontal ? "scrollWidth" : "scrollHeight";
|
|
return (element == null ? void 0 : element[key]) || 0;
|
|
}
|
|
function getClientSize(isHorizontal, element) {
|
|
const key = isHorizontal ? "clientWidth" : "clientHeight";
|
|
return (element == null ? void 0 : element[key]) || 0;
|
|
}
|
|
function getScrollPosition(isHorizontal, rtl, element) {
|
|
if (!element) {
|
|
return 0;
|
|
}
|
|
const {
|
|
scrollLeft,
|
|
offsetWidth,
|
|
scrollWidth
|
|
} = element;
|
|
if (isHorizontal) {
|
|
return rtl ? scrollWidth - offsetWidth + scrollLeft : scrollLeft;
|
|
}
|
|
return element.scrollTop;
|
|
}
|
|
function getOffsetSize(isHorizontal, element) {
|
|
const key = isHorizontal ? "offsetWidth" : "offsetHeight";
|
|
return (element == null ? void 0 : element[key]) || 0;
|
|
}
|
|
function getOffsetPosition(isHorizontal, element) {
|
|
const key = isHorizontal ? "offsetLeft" : "offsetTop";
|
|
return (element == null ? void 0 : element[key]) || 0;
|
|
}
|
|
const VSlideGroupSymbol = Symbol.for("vuetify:v-slide-group");
|
|
const makeVSlideGroupProps = propsFactory({
|
|
centerActive: Boolean,
|
|
direction: {
|
|
type: String,
|
|
default: "horizontal"
|
|
},
|
|
symbol: {
|
|
type: null,
|
|
default: VSlideGroupSymbol
|
|
},
|
|
nextIcon: {
|
|
type: IconValue,
|
|
default: "$next"
|
|
},
|
|
prevIcon: {
|
|
type: IconValue,
|
|
default: "$prev"
|
|
},
|
|
showArrows: {
|
|
type: [Boolean, String],
|
|
validator: (v) => typeof v === "boolean" || ["always", "desktop", "mobile"].includes(v)
|
|
},
|
|
...makeComponentProps(),
|
|
...makeDisplayProps({
|
|
mobile: null
|
|
}),
|
|
...makeTagProps(),
|
|
...makeGroupProps({
|
|
selectedClass: "v-slide-group-item--active"
|
|
})
|
|
}, "VSlideGroup");
|
|
const VSlideGroup = genericComponent()({
|
|
name: "VSlideGroup",
|
|
props: makeVSlideGroupProps(),
|
|
emits: {
|
|
"update:modelValue": (value) => true
|
|
},
|
|
setup(props, _ref) {
|
|
let {
|
|
slots
|
|
} = _ref;
|
|
const {
|
|
isRtl
|
|
} = useRtl();
|
|
const {
|
|
displayClasses,
|
|
mobile
|
|
} = useDisplay(props);
|
|
const group = useGroup(props, props.symbol);
|
|
const isOverflowing = shallowRef(false);
|
|
const scrollOffset = shallowRef(0);
|
|
const containerSize = shallowRef(0);
|
|
shallowRef(0);
|
|
const isHorizontal = computed(() => props.direction === "horizontal");
|
|
const {
|
|
resizeRef: containerRef
|
|
} = useResizeObserver();
|
|
const {
|
|
resizeRef: contentRef
|
|
} = useResizeObserver();
|
|
useGoTo();
|
|
computed(() => {
|
|
return {
|
|
container: containerRef.el,
|
|
duration: 200,
|
|
easing: "easeOutQuart"
|
|
};
|
|
});
|
|
computed(() => {
|
|
if (!group.selected.value.length) return -1;
|
|
return group.items.value.findIndex((item) => item.id === group.selected.value[0]);
|
|
});
|
|
computed(() => {
|
|
if (!group.selected.value.length) return -1;
|
|
return group.items.value.findIndex((item) => item.id === group.selected.value[group.selected.value.length - 1]);
|
|
});
|
|
const isFocused = shallowRef(false);
|
|
function scrollToChildren(children, center) {
|
|
{
|
|
calculateUpdatedTarget({
|
|
containerElement: containerRef.el,
|
|
isHorizontal: isHorizontal.value,
|
|
isRtl: isRtl.value,
|
|
selectedElement: children
|
|
});
|
|
}
|
|
}
|
|
function onScroll(e) {
|
|
const {
|
|
scrollTop,
|
|
scrollLeft
|
|
} = e.target;
|
|
scrollOffset.value = isHorizontal.value ? scrollLeft : scrollTop;
|
|
}
|
|
function onFocusin(e) {
|
|
isFocused.value = true;
|
|
if (!isOverflowing.value || !contentRef.el) return;
|
|
for (const el of e.composedPath()) {
|
|
for (const item of contentRef.el.children) {
|
|
if (item === el) {
|
|
scrollToChildren(item);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function onFocusout(e) {
|
|
isFocused.value = false;
|
|
}
|
|
let ignoreFocusEvent = false;
|
|
function onFocus(e) {
|
|
var _a;
|
|
if (!ignoreFocusEvent && !isFocused.value && !(e.relatedTarget && ((_a = contentRef.el) == null ? void 0 : _a.contains(e.relatedTarget)))) focus();
|
|
ignoreFocusEvent = false;
|
|
}
|
|
function onFocusAffixes() {
|
|
ignoreFocusEvent = true;
|
|
}
|
|
function onKeydown(e) {
|
|
if (!contentRef.el) return;
|
|
function toFocus(location) {
|
|
e.preventDefault();
|
|
focus(location);
|
|
}
|
|
if (isHorizontal.value) {
|
|
if (e.key === "ArrowRight") {
|
|
toFocus(isRtl.value ? "prev" : "next");
|
|
} else if (e.key === "ArrowLeft") {
|
|
toFocus(isRtl.value ? "next" : "prev");
|
|
}
|
|
} else {
|
|
if (e.key === "ArrowDown") {
|
|
toFocus("next");
|
|
} else if (e.key === "ArrowUp") {
|
|
toFocus("prev");
|
|
}
|
|
}
|
|
if (e.key === "Home") {
|
|
toFocus("first");
|
|
} else if (e.key === "End") {
|
|
toFocus("last");
|
|
}
|
|
}
|
|
function focus(location) {
|
|
var _a, _b;
|
|
if (!contentRef.el) return;
|
|
let el;
|
|
if (!location) {
|
|
const focusable = focusableChildren(contentRef.el);
|
|
el = focusable[0];
|
|
} else if (location === "next") {
|
|
el = (_a = contentRef.el.querySelector(":focus")) == null ? void 0 : _a.nextElementSibling;
|
|
if (!el) return focus("first");
|
|
} else if (location === "prev") {
|
|
el = (_b = contentRef.el.querySelector(":focus")) == null ? void 0 : _b.previousElementSibling;
|
|
if (!el) return focus("last");
|
|
} else if (location === "first") {
|
|
el = contentRef.el.firstElementChild;
|
|
} else if (location === "last") {
|
|
el = contentRef.el.lastElementChild;
|
|
}
|
|
if (el) {
|
|
el.focus({
|
|
preventScroll: true
|
|
});
|
|
}
|
|
}
|
|
function scrollTo(location) {
|
|
const direction = isHorizontal.value && isRtl.value ? -1 : 1;
|
|
const offsetStep = (location === "prev" ? -direction : direction) * containerSize.value;
|
|
scrollOffset.value + offsetStep;
|
|
if (isHorizontal.value && isRtl.value && containerRef.el) {
|
|
const {
|
|
scrollWidth,
|
|
offsetWidth: containerWidth
|
|
} = containerRef.el;
|
|
}
|
|
}
|
|
const slotProps = computed(() => ({
|
|
next: group.next,
|
|
prev: group.prev,
|
|
select: group.select,
|
|
isSelected: group.isSelected
|
|
}));
|
|
const hasAffixes = computed(() => {
|
|
switch (props.showArrows) {
|
|
case "always":
|
|
return true;
|
|
case "desktop":
|
|
return !mobile.value;
|
|
case true:
|
|
return isOverflowing.value || Math.abs(scrollOffset.value) > 0;
|
|
case "mobile":
|
|
return mobile.value || isOverflowing.value || Math.abs(scrollOffset.value) > 0;
|
|
default:
|
|
return !mobile.value && (isOverflowing.value || Math.abs(scrollOffset.value) > 0);
|
|
}
|
|
});
|
|
const hasPrev = computed(() => {
|
|
return Math.abs(scrollOffset.value) > 1;
|
|
});
|
|
const hasNext = computed(() => {
|
|
if (!containerRef.value) return false;
|
|
const scrollSize = getScrollSize(isHorizontal.value, containerRef.el);
|
|
const clientSize = getClientSize(isHorizontal.value, containerRef.el);
|
|
const scrollSizeMax = scrollSize - clientSize;
|
|
return scrollSizeMax - Math.abs(scrollOffset.value) > 1;
|
|
});
|
|
useRender(() => createVNode(props.tag, {
|
|
"class": ["v-slide-group", {
|
|
"v-slide-group--vertical": !isHorizontal.value,
|
|
"v-slide-group--has-affixes": hasAffixes.value,
|
|
"v-slide-group--is-overflowing": isOverflowing.value
|
|
}, displayClasses.value, props.class],
|
|
"style": props.style,
|
|
"tabindex": isFocused.value || group.selected.value.length ? -1 : 0,
|
|
"onFocus": onFocus
|
|
}, {
|
|
default: () => {
|
|
var _a2, _b2;
|
|
var _a, _b, _c;
|
|
return [hasAffixes.value && createVNode("div", {
|
|
"key": "prev",
|
|
"class": ["v-slide-group__prev", {
|
|
"v-slide-group__prev--disabled": !hasPrev.value
|
|
}],
|
|
"onMousedown": onFocusAffixes,
|
|
"onClick": () => hasPrev.value && scrollTo("prev")
|
|
}, [(_a2 = (_a = slots.prev) == null ? void 0 : _a.call(slots, slotProps.value)) != null ? _a2 : createVNode(VFadeTransition, null, {
|
|
default: () => [createVNode(VIcon, {
|
|
"icon": isRtl.value ? props.nextIcon : props.prevIcon
|
|
}, null)]
|
|
})]), createVNode("div", {
|
|
"key": "container",
|
|
"ref": containerRef,
|
|
"class": "v-slide-group__container",
|
|
"onScroll": onScroll
|
|
}, [createVNode("div", {
|
|
"ref": contentRef,
|
|
"class": "v-slide-group__content",
|
|
"onFocusin": onFocusin,
|
|
"onFocusout": onFocusout,
|
|
"onKeydown": onKeydown
|
|
}, [(_b = slots.default) == null ? void 0 : _b.call(slots, slotProps.value)])]), hasAffixes.value && createVNode("div", {
|
|
"key": "next",
|
|
"class": ["v-slide-group__next", {
|
|
"v-slide-group__next--disabled": !hasNext.value
|
|
}],
|
|
"onMousedown": onFocusAffixes,
|
|
"onClick": () => hasNext.value && scrollTo("next")
|
|
}, [(_b2 = (_c = slots.next) == null ? void 0 : _c.call(slots, slotProps.value)) != null ? _b2 : createVNode(VFadeTransition, null, {
|
|
default: () => [createVNode(VIcon, {
|
|
"icon": isRtl.value ? props.prevIcon : props.nextIcon
|
|
}, null)]
|
|
})])];
|
|
}
|
|
}));
|
|
return {
|
|
selected: group.selected,
|
|
scrollTo,
|
|
scrollOffset,
|
|
focus,
|
|
hasPrev,
|
|
hasNext
|
|
};
|
|
}
|
|
});
|
|
const VTabsSymbol = Symbol.for("vuetify:v-tabs");
|
|
const makeVTabProps = propsFactory({
|
|
fixed: Boolean,
|
|
sliderColor: String,
|
|
hideSlider: Boolean,
|
|
direction: {
|
|
type: String,
|
|
default: "horizontal"
|
|
},
|
|
...omit(makeVBtnProps({
|
|
selectedClass: "v-tab--selected",
|
|
variant: "text"
|
|
}), ["active", "block", "flat", "location", "position", "symbol"])
|
|
}, "VTab");
|
|
const VTab = genericComponent()({
|
|
name: "VTab",
|
|
props: makeVTabProps(),
|
|
setup(props, _ref) {
|
|
let {
|
|
slots,
|
|
attrs
|
|
} = _ref;
|
|
const {
|
|
textColorClasses: sliderColorClasses,
|
|
textColorStyles: sliderColorStyles
|
|
} = useTextColor(props, "sliderColor");
|
|
const rootEl = ref();
|
|
const sliderEl = ref();
|
|
const isHorizontal = computed(() => props.direction === "horizontal");
|
|
const isSelected = computed(() => {
|
|
var _a2;
|
|
var _a, _b;
|
|
return (_a2 = (_b = (_a = rootEl.value) == null ? void 0 : _a.group) == null ? void 0 : _b.isSelected.value) != null ? _a2 : false;
|
|
});
|
|
function updateSlider(_ref2) {
|
|
var _a, _b;
|
|
let {
|
|
value
|
|
} = _ref2;
|
|
if (value) {
|
|
const prevEl = (_b = (_a = rootEl.value) == null ? void 0 : _a.$el.parentElement) == null ? void 0 : _b.querySelector(".v-tab--selected .v-tab__slider");
|
|
const nextEl = sliderEl.value;
|
|
if (!prevEl || !nextEl) return;
|
|
const color = getComputedStyle(prevEl).color;
|
|
const prevBox = prevEl.getBoundingClientRect();
|
|
const nextBox = nextEl.getBoundingClientRect();
|
|
const xy = isHorizontal.value ? "x" : "y";
|
|
const XY = isHorizontal.value ? "X" : "Y";
|
|
const rightBottom = isHorizontal.value ? "right" : "bottom";
|
|
const widthHeight = isHorizontal.value ? "width" : "height";
|
|
const prevPos = prevBox[xy];
|
|
const nextPos = nextBox[xy];
|
|
const delta = prevPos > nextPos ? prevBox[rightBottom] - nextBox[rightBottom] : prevBox[xy] - nextBox[xy];
|
|
const origin = Math.sign(delta) > 0 ? isHorizontal.value ? "right" : "bottom" : Math.sign(delta) < 0 ? isHorizontal.value ? "left" : "top" : "center";
|
|
const size = Math.abs(delta) + (Math.sign(delta) < 0 ? prevBox[widthHeight] : nextBox[widthHeight]);
|
|
const scale = size / Math.max(prevBox[widthHeight], nextBox[widthHeight]) || 0;
|
|
const initialScale = prevBox[widthHeight] / nextBox[widthHeight] || 0;
|
|
const sigma = 1.5;
|
|
animate(nextEl, {
|
|
backgroundColor: [color, "currentcolor"],
|
|
transform: [`translate${XY}(${delta}px) scale${XY}(${initialScale})`, `translate${XY}(${delta / sigma}px) scale${XY}(${(scale - 1) / sigma + 1})`, "none"],
|
|
transformOrigin: Array(3).fill(origin)
|
|
}, {
|
|
duration: 225,
|
|
easing: standardEasing
|
|
});
|
|
}
|
|
}
|
|
useRender(() => {
|
|
const btnProps = VBtn.filterProps(props);
|
|
return createVNode(VBtn, mergeProps({
|
|
"symbol": VTabsSymbol,
|
|
"ref": rootEl,
|
|
"class": ["v-tab", props.class],
|
|
"style": props.style,
|
|
"tabindex": isSelected.value ? 0 : -1,
|
|
"role": "tab",
|
|
"aria-selected": String(isSelected.value),
|
|
"active": false
|
|
}, btnProps, attrs, {
|
|
"block": props.fixed,
|
|
"maxWidth": props.fixed ? 300 : void 0,
|
|
"onGroup:selected": updateSlider
|
|
}), {
|
|
...slots,
|
|
default: () => {
|
|
var _a2;
|
|
var _a;
|
|
return createVNode(Fragment, null, [(_a2 = (_a = slots.default) == null ? void 0 : _a.call(slots)) != null ? _a2 : props.text, !props.hideSlider && createVNode("div", {
|
|
"ref": sliderEl,
|
|
"class": ["v-tab__slider", sliderColorClasses.value],
|
|
"style": sliderColorStyles.value
|
|
}, null)]);
|
|
}
|
|
});
|
|
});
|
|
return forwardRefs({}, rootEl);
|
|
}
|
|
});
|
|
const handleGesture = (wrapper) => {
|
|
const {
|
|
touchstartX,
|
|
touchendX,
|
|
touchstartY,
|
|
touchendY
|
|
} = wrapper;
|
|
const dirRatio = 0.5;
|
|
const minDistance = 16;
|
|
wrapper.offsetX = touchendX - touchstartX;
|
|
wrapper.offsetY = touchendY - touchstartY;
|
|
if (Math.abs(wrapper.offsetY) < dirRatio * Math.abs(wrapper.offsetX)) {
|
|
wrapper.left && touchendX < touchstartX - minDistance && wrapper.left(wrapper);
|
|
wrapper.right && touchendX > touchstartX + minDistance && wrapper.right(wrapper);
|
|
}
|
|
if (Math.abs(wrapper.offsetX) < dirRatio * Math.abs(wrapper.offsetY)) {
|
|
wrapper.up && touchendY < touchstartY - minDistance && wrapper.up(wrapper);
|
|
wrapper.down && touchendY > touchstartY + minDistance && wrapper.down(wrapper);
|
|
}
|
|
};
|
|
function touchstart(event, wrapper) {
|
|
var _a;
|
|
const touch = event.changedTouches[0];
|
|
wrapper.touchstartX = touch.clientX;
|
|
wrapper.touchstartY = touch.clientY;
|
|
(_a = wrapper.start) == null ? void 0 : _a.call(wrapper, {
|
|
originalEvent: event,
|
|
...wrapper
|
|
});
|
|
}
|
|
function touchend(event, wrapper) {
|
|
var _a;
|
|
const touch = event.changedTouches[0];
|
|
wrapper.touchendX = touch.clientX;
|
|
wrapper.touchendY = touch.clientY;
|
|
(_a = wrapper.end) == null ? void 0 : _a.call(wrapper, {
|
|
originalEvent: event,
|
|
...wrapper
|
|
});
|
|
handleGesture(wrapper);
|
|
}
|
|
function touchmove(event, wrapper) {
|
|
var _a;
|
|
const touch = event.changedTouches[0];
|
|
wrapper.touchmoveX = touch.clientX;
|
|
wrapper.touchmoveY = touch.clientY;
|
|
(_a = wrapper.move) == null ? void 0 : _a.call(wrapper, {
|
|
originalEvent: event,
|
|
...wrapper
|
|
});
|
|
}
|
|
function createHandlers() {
|
|
let value = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
const wrapper = {
|
|
touchstartX: 0,
|
|
touchstartY: 0,
|
|
touchendX: 0,
|
|
touchendY: 0,
|
|
touchmoveX: 0,
|
|
touchmoveY: 0,
|
|
offsetX: 0,
|
|
offsetY: 0,
|
|
left: value.left,
|
|
right: value.right,
|
|
up: value.up,
|
|
down: value.down,
|
|
start: value.start,
|
|
move: value.move,
|
|
end: value.end
|
|
};
|
|
return {
|
|
touchstart: (e) => touchstart(e, wrapper),
|
|
touchend: (e) => touchend(e, wrapper),
|
|
touchmove: (e) => touchmove(e, wrapper)
|
|
};
|
|
}
|
|
function mounted(el, binding) {
|
|
var _a2, _b;
|
|
var _a;
|
|
const value = binding.value;
|
|
const target = (value == null ? void 0 : value.parent) ? el.parentElement : el;
|
|
const options = (_a2 = value == null ? void 0 : value.options) != null ? _a2 : {
|
|
passive: true
|
|
};
|
|
const uid = (_a = binding.instance) == null ? void 0 : _a.$.uid;
|
|
if (!target || !uid) return;
|
|
const handlers = createHandlers(binding.value);
|
|
target._touchHandlers = (_b = target._touchHandlers) != null ? _b : /* @__PURE__ */ Object.create(null);
|
|
target._touchHandlers[uid] = handlers;
|
|
keys(handlers).forEach((eventName) => {
|
|
target.addEventListener(eventName, handlers[eventName], options);
|
|
});
|
|
}
|
|
function unmounted(el, binding) {
|
|
var _a, _b;
|
|
const target = ((_a = binding.value) == null ? void 0 : _a.parent) ? el.parentElement : el;
|
|
const uid = (_b = binding.instance) == null ? void 0 : _b.$.uid;
|
|
if (!(target == null ? void 0 : target._touchHandlers) || !uid) return;
|
|
const handlers = target._touchHandlers[uid];
|
|
keys(handlers).forEach((eventName) => {
|
|
target.removeEventListener(eventName, handlers[eventName]);
|
|
});
|
|
delete target._touchHandlers[uid];
|
|
}
|
|
const Touch = {
|
|
mounted,
|
|
unmounted
|
|
};
|
|
const VWindowSymbol = Symbol.for("vuetify:v-window");
|
|
const VWindowGroupSymbol = Symbol.for("vuetify:v-window-group");
|
|
const makeVWindowProps = propsFactory({
|
|
continuous: Boolean,
|
|
nextIcon: {
|
|
type: [Boolean, String, Function, Object],
|
|
default: "$next"
|
|
},
|
|
prevIcon: {
|
|
type: [Boolean, String, Function, Object],
|
|
default: "$prev"
|
|
},
|
|
reverse: Boolean,
|
|
showArrows: {
|
|
type: [Boolean, String],
|
|
validator: (v) => typeof v === "boolean" || v === "hover"
|
|
},
|
|
touch: {
|
|
type: [Object, Boolean],
|
|
default: void 0
|
|
},
|
|
direction: {
|
|
type: String,
|
|
default: "horizontal"
|
|
},
|
|
modelValue: null,
|
|
disabled: Boolean,
|
|
selectedClass: {
|
|
type: String,
|
|
default: "v-window-item--active"
|
|
},
|
|
// TODO: mandatory should probably not be exposed but do this for now
|
|
mandatory: {
|
|
type: [Boolean, String],
|
|
default: "force"
|
|
},
|
|
...makeComponentProps(),
|
|
...makeTagProps(),
|
|
...makeThemeProps()
|
|
}, "VWindow");
|
|
const VWindow = genericComponent()({
|
|
name: "VWindow",
|
|
directives: {
|
|
Touch
|
|
},
|
|
props: makeVWindowProps(),
|
|
emits: {
|
|
"update:modelValue": (value) => true
|
|
},
|
|
setup(props, _ref) {
|
|
let {
|
|
slots
|
|
} = _ref;
|
|
const {
|
|
themeClasses
|
|
} = provideTheme(props);
|
|
const {
|
|
isRtl
|
|
} = useRtl();
|
|
const {
|
|
t
|
|
} = useLocale();
|
|
const group = useGroup(props, VWindowGroupSymbol);
|
|
const rootRef = ref();
|
|
const isRtlReverse = computed(() => isRtl.value ? !props.reverse : props.reverse);
|
|
const isReversed = shallowRef(false);
|
|
const transition = computed(() => {
|
|
const axis = props.direction === "vertical" ? "y" : "x";
|
|
const reverse = isRtlReverse.value ? !isReversed.value : isReversed.value;
|
|
const direction = reverse ? "-reverse" : "";
|
|
return `v-window-${axis}${direction}-transition`;
|
|
});
|
|
const transitionCount = shallowRef(0);
|
|
const transitionHeight = ref(void 0);
|
|
const activeIndex = computed(() => {
|
|
return group.items.value.findIndex((item) => group.selected.value.includes(item.id));
|
|
});
|
|
watch(activeIndex, (newVal, oldVal) => {
|
|
const itemsLength = group.items.value.length;
|
|
const lastIndex = itemsLength - 1;
|
|
if (itemsLength <= 2) {
|
|
isReversed.value = newVal < oldVal;
|
|
} else if (newVal === lastIndex && oldVal === 0) {
|
|
isReversed.value = true;
|
|
} else if (newVal === 0 && oldVal === lastIndex) {
|
|
isReversed.value = false;
|
|
} else {
|
|
isReversed.value = newVal < oldVal;
|
|
}
|
|
});
|
|
provide(VWindowSymbol, {
|
|
transition,
|
|
isReversed,
|
|
transitionCount,
|
|
transitionHeight,
|
|
rootRef
|
|
});
|
|
const canMoveBack = computed(() => props.continuous || activeIndex.value !== 0);
|
|
const canMoveForward = computed(() => props.continuous || activeIndex.value !== group.items.value.length - 1);
|
|
function prev() {
|
|
canMoveBack.value && group.prev();
|
|
}
|
|
function next() {
|
|
canMoveForward.value && group.next();
|
|
}
|
|
const arrows = computed(() => {
|
|
const arrows2 = [];
|
|
const prevProps = {
|
|
icon: isRtl.value ? props.nextIcon : props.prevIcon,
|
|
class: `v-window__${isRtlReverse.value ? "right" : "left"}`,
|
|
onClick: group.prev,
|
|
"aria-label": t("$vuetify.carousel.prev")
|
|
};
|
|
arrows2.push(canMoveBack.value ? slots.prev ? slots.prev({
|
|
props: prevProps
|
|
}) : createVNode(VBtn, prevProps, null) : createVNode("div", null, null));
|
|
const nextProps = {
|
|
icon: isRtl.value ? props.prevIcon : props.nextIcon,
|
|
class: `v-window__${isRtlReverse.value ? "left" : "right"}`,
|
|
onClick: group.next,
|
|
"aria-label": t("$vuetify.carousel.next")
|
|
};
|
|
arrows2.push(canMoveForward.value ? slots.next ? slots.next({
|
|
props: nextProps
|
|
}) : createVNode(VBtn, nextProps, null) : createVNode("div", null, null));
|
|
return arrows2;
|
|
});
|
|
const touchOptions = computed(() => {
|
|
if (props.touch === false) return props.touch;
|
|
const options = {
|
|
left: () => {
|
|
isRtlReverse.value ? prev() : next();
|
|
},
|
|
right: () => {
|
|
isRtlReverse.value ? next() : prev();
|
|
},
|
|
start: (_ref2) => {
|
|
let {
|
|
originalEvent
|
|
} = _ref2;
|
|
originalEvent.stopPropagation();
|
|
}
|
|
};
|
|
return {
|
|
...options,
|
|
...props.touch === true ? {} : props.touch
|
|
};
|
|
});
|
|
useRender(() => withDirectives(createVNode(props.tag, {
|
|
"ref": rootRef,
|
|
"class": ["v-window", {
|
|
"v-window--show-arrows-on-hover": props.showArrows === "hover"
|
|
}, themeClasses.value, props.class],
|
|
"style": props.style
|
|
}, {
|
|
default: () => {
|
|
var _a, _b;
|
|
return [createVNode("div", {
|
|
"class": "v-window__container",
|
|
"style": {
|
|
height: transitionHeight.value
|
|
}
|
|
}, [(_a = slots.default) == null ? void 0 : _a.call(slots, {
|
|
group
|
|
}), props.showArrows !== false && createVNode("div", {
|
|
"class": "v-window__controls"
|
|
}, [arrows.value])]), (_b = slots.additional) == null ? void 0 : _b.call(slots, {
|
|
group
|
|
})];
|
|
}
|
|
}), [[resolveDirective("touch"), touchOptions.value]]));
|
|
return {
|
|
group
|
|
};
|
|
}
|
|
});
|
|
const makeVTabsWindowProps = propsFactory({
|
|
...omit(makeVWindowProps(), ["continuous", "nextIcon", "prevIcon", "showArrows", "touch", "mandatory"])
|
|
}, "VTabsWindow");
|
|
const VTabsWindow = genericComponent()({
|
|
name: "VTabsWindow",
|
|
props: makeVTabsWindowProps(),
|
|
emits: {
|
|
"update:modelValue": (v) => true
|
|
},
|
|
setup(props, _ref) {
|
|
let {
|
|
slots
|
|
} = _ref;
|
|
const group = inject(VTabsSymbol, null);
|
|
const _model = useProxiedModel(props, "modelValue");
|
|
const model = computed({
|
|
get() {
|
|
var _a;
|
|
if (_model.value != null || !group) return _model.value;
|
|
return (_a = group.items.value.find((item) => group.selected.value.includes(item.id))) == null ? void 0 : _a.value;
|
|
},
|
|
set(val) {
|
|
_model.value = val;
|
|
}
|
|
});
|
|
useRender(() => {
|
|
const windowProps = VWindow.filterProps(props);
|
|
return createVNode(VWindow, mergeProps({
|
|
"_as": "VTabsWindow"
|
|
}, windowProps, {
|
|
"modelValue": model.value,
|
|
"onUpdate:modelValue": ($event) => model.value = $event,
|
|
"class": ["v-tabs-window", props.class],
|
|
"style": props.style,
|
|
"mandatory": false,
|
|
"touch": false
|
|
}), slots);
|
|
});
|
|
return {};
|
|
}
|
|
});
|
|
const makeVWindowItemProps = propsFactory({
|
|
reverseTransition: {
|
|
type: [Boolean, String],
|
|
default: void 0
|
|
},
|
|
transition: {
|
|
type: [Boolean, String],
|
|
default: void 0
|
|
},
|
|
...makeComponentProps(),
|
|
...makeGroupItemProps(),
|
|
...makeLazyProps()
|
|
}, "VWindowItem");
|
|
const VWindowItem = genericComponent()({
|
|
name: "VWindowItem",
|
|
directives: {
|
|
Touch
|
|
},
|
|
props: makeVWindowItemProps(),
|
|
emits: {
|
|
"group:selected": (val) => true
|
|
},
|
|
setup(props, _ref) {
|
|
let {
|
|
slots
|
|
} = _ref;
|
|
const window = inject(VWindowSymbol);
|
|
const groupItem = useGroupItem(props, VWindowGroupSymbol);
|
|
const {
|
|
isBooted
|
|
} = useSsrBoot();
|
|
if (!window || !groupItem) throw new Error("[Vuetify] VWindowItem must be used inside VWindow");
|
|
const isTransitioning = shallowRef(false);
|
|
const hasTransition = computed(() => isBooted.value && (window.isReversed.value ? props.reverseTransition !== false : props.transition !== false));
|
|
function onAfterTransition() {
|
|
if (!isTransitioning.value || !window) {
|
|
return;
|
|
}
|
|
isTransitioning.value = false;
|
|
if (window.transitionCount.value > 0) {
|
|
window.transitionCount.value -= 1;
|
|
if (window.transitionCount.value === 0) {
|
|
window.transitionHeight.value = void 0;
|
|
}
|
|
}
|
|
}
|
|
function onBeforeTransition() {
|
|
var _a;
|
|
if (isTransitioning.value || !window) {
|
|
return;
|
|
}
|
|
isTransitioning.value = true;
|
|
if (window.transitionCount.value === 0) {
|
|
window.transitionHeight.value = convertToUnit((_a = window.rootRef.value) == null ? void 0 : _a.clientHeight);
|
|
}
|
|
window.transitionCount.value += 1;
|
|
}
|
|
function onTransitionCancelled() {
|
|
onAfterTransition();
|
|
}
|
|
function onEnterTransition(el) {
|
|
if (!isTransitioning.value) {
|
|
return;
|
|
}
|
|
nextTick(() => {
|
|
if (!hasTransition.value || !isTransitioning.value || !window) {
|
|
return;
|
|
}
|
|
window.transitionHeight.value = convertToUnit(el.clientHeight);
|
|
});
|
|
}
|
|
const transition = computed(() => {
|
|
const name = window.isReversed.value ? props.reverseTransition : props.transition;
|
|
return !hasTransition.value ? false : {
|
|
name: typeof name !== "string" ? window.transition.value : name,
|
|
onBeforeEnter: onBeforeTransition,
|
|
onAfterEnter: onAfterTransition,
|
|
onEnterCancelled: onTransitionCancelled,
|
|
onBeforeLeave: onBeforeTransition,
|
|
onAfterLeave: onAfterTransition,
|
|
onLeaveCancelled: onTransitionCancelled,
|
|
onEnter: onEnterTransition
|
|
};
|
|
});
|
|
const {
|
|
hasContent
|
|
} = useLazy(props, groupItem.isSelected);
|
|
useRender(() => createVNode(MaybeTransition, {
|
|
"transition": transition.value,
|
|
"disabled": !isBooted.value
|
|
}, {
|
|
default: () => {
|
|
var _a;
|
|
return [withDirectives(createVNode("div", {
|
|
"class": ["v-window-item", groupItem.selectedClass.value, props.class],
|
|
"style": props.style
|
|
}, [hasContent.value && ((_a = slots.default) == null ? void 0 : _a.call(slots))]), [[vShow, groupItem.isSelected.value]])];
|
|
}
|
|
}));
|
|
return {
|
|
groupItem
|
|
};
|
|
}
|
|
});
|
|
const makeVTabsWindowItemProps = propsFactory({
|
|
...makeVWindowItemProps()
|
|
}, "VTabsWindowItem");
|
|
const VTabsWindowItem = genericComponent()({
|
|
name: "VTabsWindowItem",
|
|
props: makeVTabsWindowItemProps(),
|
|
setup(props, _ref) {
|
|
let {
|
|
slots
|
|
} = _ref;
|
|
useRender(() => {
|
|
const windowItemProps = VWindowItem.filterProps(props);
|
|
return createVNode(VWindowItem, mergeProps({
|
|
"_as": "VTabsWindowItem"
|
|
}, windowItemProps, {
|
|
"class": ["v-tabs-window-item", props.class],
|
|
"style": props.style
|
|
}), slots);
|
|
});
|
|
return {};
|
|
}
|
|
});
|
|
function parseItems(items) {
|
|
if (!items) return [];
|
|
return items.map((item) => {
|
|
if (!isObject(item)) return {
|
|
text: item,
|
|
value: item
|
|
};
|
|
return item;
|
|
});
|
|
}
|
|
const makeVTabsProps = propsFactory({
|
|
alignTabs: {
|
|
type: String,
|
|
default: "start"
|
|
},
|
|
color: String,
|
|
fixedTabs: Boolean,
|
|
items: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
stacked: Boolean,
|
|
bgColor: String,
|
|
grow: Boolean,
|
|
height: {
|
|
type: [Number, String],
|
|
default: void 0
|
|
},
|
|
hideSlider: Boolean,
|
|
sliderColor: String,
|
|
...makeVSlideGroupProps({
|
|
mandatory: "force",
|
|
selectedClass: "v-tab-item--selected"
|
|
}),
|
|
...makeDensityProps(),
|
|
...makeTagProps()
|
|
}, "VTabs");
|
|
const VTabs = genericComponent()({
|
|
name: "VTabs",
|
|
props: makeVTabsProps(),
|
|
emits: {
|
|
"update:modelValue": (v) => true
|
|
},
|
|
setup(props, _ref) {
|
|
let {
|
|
attrs,
|
|
slots
|
|
} = _ref;
|
|
const model = useProxiedModel(props, "modelValue");
|
|
const items = computed(() => parseItems(props.items));
|
|
const {
|
|
densityClasses
|
|
} = useDensity(props);
|
|
const {
|
|
backgroundColorClasses,
|
|
backgroundColorStyles
|
|
} = useBackgroundColor(toRef(props, "bgColor"));
|
|
const {
|
|
scopeId
|
|
} = useScopeId();
|
|
provideDefaults({
|
|
VTab: {
|
|
color: toRef(props, "color"),
|
|
direction: toRef(props, "direction"),
|
|
stacked: toRef(props, "stacked"),
|
|
fixed: toRef(props, "fixedTabs"),
|
|
sliderColor: toRef(props, "sliderColor"),
|
|
hideSlider: toRef(props, "hideSlider")
|
|
}
|
|
});
|
|
useRender(() => {
|
|
const slideGroupProps = VSlideGroup.filterProps(props);
|
|
const hasWindow = !!(slots.window || props.items.length > 0);
|
|
return createVNode(Fragment, null, [createVNode(VSlideGroup, mergeProps(slideGroupProps, {
|
|
"modelValue": model.value,
|
|
"onUpdate:modelValue": ($event) => model.value = $event,
|
|
"class": ["v-tabs", `v-tabs--${props.direction}`, `v-tabs--align-tabs-${props.alignTabs}`, {
|
|
"v-tabs--fixed-tabs": props.fixedTabs,
|
|
"v-tabs--grow": props.grow,
|
|
"v-tabs--stacked": props.stacked
|
|
}, densityClasses.value, backgroundColorClasses.value, props.class],
|
|
"style": [{
|
|
"--v-tabs-height": convertToUnit(props.height)
|
|
}, backgroundColorStyles.value, props.style],
|
|
"role": "tablist",
|
|
"symbol": VTabsSymbol
|
|
}, scopeId, attrs), {
|
|
default: () => {
|
|
var _a2;
|
|
var _a;
|
|
return [(_a2 = (_a = slots.default) == null ? void 0 : _a.call(slots)) != null ? _a2 : items.value.map((item) => {
|
|
var _a3;
|
|
var _a22;
|
|
return (_a3 = (_a22 = slots.tab) == null ? void 0 : _a22.call(slots, {
|
|
item
|
|
})) != null ? _a3 : createVNode(VTab, mergeProps(item, {
|
|
"key": item.text,
|
|
"value": item.value
|
|
}), {
|
|
default: slots[`tab.${item.value}`] ? () => {
|
|
var _a32;
|
|
return (_a32 = slots[`tab.${item.value}`]) == null ? void 0 : _a32.call(slots, {
|
|
item
|
|
});
|
|
} : void 0
|
|
});
|
|
})];
|
|
}
|
|
}), hasWindow && createVNode(VTabsWindow, mergeProps({
|
|
"modelValue": model.value,
|
|
"onUpdate:modelValue": ($event) => model.value = $event,
|
|
"key": "tabs-window"
|
|
}, scopeId), {
|
|
default: () => {
|
|
var _a;
|
|
return [items.value.map((item) => {
|
|
var _a3;
|
|
var _a2;
|
|
return (_a3 = (_a2 = slots.item) == null ? void 0 : _a2.call(slots, {
|
|
item
|
|
})) != null ? _a3 : createVNode(VTabsWindowItem, {
|
|
"value": item.value
|
|
}, {
|
|
default: () => {
|
|
var _a32;
|
|
return (_a32 = slots[`item.${item.value}`]) == null ? void 0 : _a32.call(slots, {
|
|
item
|
|
});
|
|
}
|
|
});
|
|
}), (_a = slots.window) == null ? void 0 : _a.call(slots)];
|
|
}
|
|
})]);
|
|
});
|
|
return {};
|
|
}
|
|
});
|
|
|
|
export { VTabs as V, VTab as a, VWindow as b, VWindowItem as c, VSlideGroup as d, makeVSlideGroupProps as m };
|