@oruga-ui/oruga-next
Version:
UI components for Vue.js and CSS framework agnostic
513 lines (512 loc) • 20.3 kB
JavaScript
"use strict";
/*! Oruga v0.11.0 | MIT License | github.com/oruga-ui/oruga */
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const vue = require("vue");
const Icon_vue_vue_type_script_setup_true_lang = require("./Icon.vue_vue_type_script_setup_true_lang-ZtEqoTvT.cjs");
const config = require("./config-eYBvpFOZ.cjs");
const helpers = require("./helpers.cjs");
const defineClasses = require("./defineClasses-Cqhbv-UT.cjs");
const useParentProvider = require("./useParentProvider-CPNahRzD.cjs");
const _hoisted_1$1 = ["onKeydown"];
const _hoisted_2 = ["aria-live"];
const _hoisted_3 = ["id", "tabindex", "aria-label", "aria-controls", "aria-selected", "onClick", "onKeydown"];
const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
...{
isOruga: true,
name: "OCarousel",
configField: "carousel"
},
__name: "Carousel",
props: /* @__PURE__ */ vue.mergeModels({
override: { type: Boolean, default: void 0 },
modelValue: { default: 0 },
dragable: { type: Boolean, default: true },
autoplay: { type: Boolean, default: false },
interval: { default: () => config.getDefault("carousel.interval", 3500) },
pauseHover: { type: Boolean, default: false },
repeat: { type: Boolean, default: false },
overlay: { type: Boolean, default: false },
indicators: { type: Boolean, default: true },
indicatorInside: { type: Boolean, default: false },
indicatorPosition: { default: () => config.getDefault("carousel.indicatorPosition", "bottom") },
indicatorStyle: { default: () => config.getDefault("carousel.indicatorStyle", "dots") },
itemsToShow: { default: () => config.getDefault("carousel.itemsToShow", 1) },
itemsToList: { default: () => config.getDefault("carousel.itemsToList", 1) },
arrows: { type: Boolean, default: () => config.getDefault("carousel.arrows", true) },
arrowsHover: { type: Boolean, default: () => config.getDefault("carousel.arrowsHover", true) },
iconPack: { default: () => config.getDefault("carousel.iconPack") },
iconSize: { default: () => config.getDefault("carousel.iconSize") },
iconPrev: { default: () => config.getDefault("carousel.iconPrev", "chevron-left") },
iconNext: { default: () => config.getDefault("carousel.iconNext", "chevron-right") },
iconAutoplayPause: { default: () => config.getDefault("carousel.iconAutoplayPause", "pause") },
iconAutoplayResume: { default: () => config.getDefault("carousel.iconAutoplayResume", "play") },
breakpoints: { default: () => ({}) },
ariaAutoplayPauseLabel: { default: () => config.getDefault(
"carousel.ariaAutoplayPauseLabel",
"Stop Automatic Slide Show"
) },
ariaAutoplayResumeLabel: { default: () => config.getDefault(
"carousel.ariaAutoplayResumeLabel",
"Start Automatic Slide Show"
) },
ariaNextLabel: { default: () => config.getDefault("carousel.ariaNextLabel", "Next Slide") },
ariaPreviousLabel: { default: () => config.getDefault("carousel.ariaPreviousLabel", "Previous Slide") },
rootClass: {},
overlayClass: {},
wrapperClass: {},
itemsClass: {},
itemsDraggingClass: {},
iconClass: {},
iconPrevClass: {},
iconNextClass: {},
iconAutoplayClass: {},
indicatorsClass: {},
indicatorsInsideClass: {},
indicatorsPositionClass: {},
indicatorClass: {},
indicatorItemClass: {},
indicatorItemActiveClass: {},
indicatorItemStyleClass: {}
}, {
"modelValue": { default: 0 },
"modelModifiers": {}
}),
emits: /* @__PURE__ */ vue.mergeModels(["update:model-value", "change", "click"], ["update:modelValue"]),
setup(__props, { emit: __emit }) {
const props = __props;
const emits = __emit;
const rootRef = vue.useTemplateRef("rootElement");
const provideData = vue.computed(() => ({
activeIndex: activeIndex.value,
indicators: props.indicators,
total: total.value,
itemWidth: itemWidth.value,
onDrag: onDragStart,
onClick: (event) => emits("click", event),
setActive: (index2) => switchTo(index2)
}));
const { childItems } = useParentProvider.useProviderParent({ rootRef, data: provideData });
const activeIndex = vue.useModel(__props, "modelValue");
const total = vue.computed(() => childItems.value.length);
const indicatorItems = vue.computed(
() => childItems.value.filter(
(el, i) => helpers.mod(i, settings.value.itemsToList) === 0
)
);
let resizeObserver;
if (config.isClient && window.ResizeObserver) {
resizeObserver = new window.ResizeObserver(onRefresh);
}
vue.watch(
[
() => props.itemsToList,
() => props.itemsToShow,
() => props.arrowsHover,
() => props.repeat
],
() => onRefresh()
);
const windowWidth = vue.ref(0);
function onRefresh() {
activeIndex.value = 0;
windowWidth.value = window.innerWidth;
vue.nextTick(() => vue.triggerRef(settings));
}
vue.onMounted(() => {
if (config.isClient) {
if (window.ResizeObserver && resizeObserver && rootRef.value)
resizeObserver.observe(rootRef.value);
windowWidth.value = window.innerWidth;
const hasReducedMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
);
if (!(hasReducedMotion == null ? void 0 : hasReducedMotion.matches)) startTimer();
}
});
vue.onBeforeUnmount(() => {
if (config.isClient) {
if (window.ResizeObserver && resizeObserver)
resizeObserver.disconnect();
onDragEnd();
pauseTimer();
}
});
const settings = vue.computed(() => {
const breakpoints = Object.keys(props.breakpoints).map(Number).sort((a, b) => b - a);
const breakpoint = breakpoints.find(
(breakpoint2) => windowWidth.value >= breakpoint2
);
const settings2 = vue.toRaw(
breakpoint ? { ...props, ...props.breakpoints[breakpoint] } : props
);
if (!settings2.itemsToList) settings2.itemsToList = 1;
if (!settings2.itemsToShow) settings2.itemsToShow = 1;
return vue.readonly(settings2);
});
const itemWidth = vue.computed(() => {
if (!windowWidth.value || !rootRef.value) return 0;
const rect = rootRef.value.getBoundingClientRect();
return rect.width / settings.value.itemsToShow;
});
const hasArrows = vue.computed(
() => settings.value.arrowsHover && isHovered.value || !settings.value.arrowsHover
);
const hasPrev = vue.computed(() => settings.value.repeat || activeIndex.value > 0);
function onPrev() {
switchTo(activeIndex.value - settings.value.itemsToList);
}
const hasNext = vue.computed(
() => settings.value.repeat || activeIndex.value < total.value - settings.value.itemsToList
);
function onNext() {
switchTo(activeIndex.value + settings.value.itemsToList);
}
function onHomePressed() {
switchTo(0);
}
function onEndPressed() {
switchTo(total.value - settings.value.itemsToList);
}
function switchTo(index2 = 0) {
if (settings.value.repeat) index2 = helpers.mod(index2, total.value);
index2 = helpers.bound(index2, 0, total.value - 1);
activeIndex.value = index2;
emits("change", index2);
}
function onChange(item) {
switchTo(item.index);
}
const isHovered = vue.ref(false);
let timer;
const isAutoplayPaused = vue.ref(false);
function onMouseEnter() {
isHovered.value = true;
if (props.autoplay && props.pauseHover) pauseTimer();
}
function onMouseLeave() {
isHovered.value = false;
if (props.autoplay && props.pauseHover) startTimer();
}
vue.watch(
() => props.autoplay,
(status) => {
if (status) startTimer();
else pauseTimer();
}
);
vue.watch(
() => props.repeat,
(status) => {
if (status) startTimer();
}
);
function onToggleAutoplay() {
if (!isAutoplayPaused.value) {
isAutoplayPaused.value = true;
pauseTimer();
} else {
isAutoplayPaused.value = false;
startTimer();
}
}
function startTimer() {
if (!props.autoplay || timer) return;
if (isAutoplayPaused.value) return;
timer = setInterval(() => {
if (!props.repeat && !hasNext.value) pauseTimer();
else onNext();
}, props.interval);
}
function pauseTimer() {
if (timer) {
clearInterval(timer);
timer = void 0;
}
}
const dragX = vue.ref();
const delta = vue.ref(0);
const isDragging = vue.computed(() => helpers.isDefined(dragX.value));
const translation = vue.computed(
() => -helpers.bound(
delta.value + activeIndex.value * itemWidth.value,
0,
(childItems.value.length - settings.value.itemsToShow) * itemWidth.value
)
);
function onDragStart(event) {
if (isDragging.value || !settings.value.dragable || event.button !== 0 && event.type !== "touchstart")
return;
delta.value = 0;
dragX.value = !!event.touches ? event.touches[0].clientX : event.clientX;
pauseTimer();
}
function onDragOver(event) {
if (!isDragging.value) return;
const dragEndX = !!event.touches ? (event.changedTouches[0] || event.touches[0]).clientX : event.clientX;
delta.value = dragX.value - dragEndX;
}
function onDragEnd() {
if (!isDragging.value) return;
const signCheck = helpers.sign(delta.value);
const results = Math.round(Math.abs(delta.value / itemWidth.value) + 0.15);
switchTo(activeIndex.value + signCheck * results);
delta.value = 0;
dragX.value = void 0;
startTimer();
}
const rootClasses = defineClasses.defineClasses(
["rootClass", "o-carousel"],
[
"overlayClass",
"o-carousel__overlay",
null,
vue.computed(() => props.overlay)
]
);
const wrapperClasses = defineClasses.defineClasses(["wrapperClass", "o-carousel__wrapper"]);
const itemsClasses = defineClasses.defineClasses(
["itemsClass", "o-carousel__items"],
["itemsDraggingClass", "o-carousel__items--dragging", null, isDragging]
);
const prevIconClasses = defineClasses.defineClasses(
["iconClass", "o-carousel__icon"],
["iconPrevClass", "o-carousel__icon-prev"]
);
const nextIconClasses = defineClasses.defineClasses(
["iconClass", "o-carousel__icon"],
["iconNextClass", "o-carousel__icon-next"]
);
const autoplayIconClasses = defineClasses.defineClasses(
["iconClass", "o-carousel__icon"],
["iconAutoplayClass", "o-carousel__icon-autoplay"]
);
const indicatorsClasses = defineClasses.defineClasses(
["indicatorsClass", "o-carousel__indicators"],
[
"indicatorsInsideClass",
"o-carousel__indicators--inside",
null,
vue.computed(() => !!props.indicatorInside)
],
[
"indicatorsPositionClass",
"o-carousel__indicators--",
vue.computed(() => props.indicatorPosition),
vue.computed(() => !!props.indicatorPosition)
]
);
const indicatorClasses = defineClasses.defineClasses([
"indicatorClass",
"o-carousel__indicator"
]);
const indicatorItemClasses = defineClasses.defineClasses(
["indicatorItemClass", "o-carousel__indicator__item"],
[
"indicatorItemStyleClass",
"o-carousel__indicator__item--",
vue.computed(() => props.indicatorStyle),
vue.computed(() => !!props.indicatorStyle)
]
);
const indicatorItemActiveClasses = defineClasses.defineClasses([
"indicatorItemActiveClass",
"o-carousel__indicator__item--active"
]);
function indicatorItemAppliedClasses(item) {
const activeClasses = activeIndex.value === item.index ? indicatorItemActiveClasses.value : [];
return [...indicatorItemClasses.value, ...activeClasses];
}
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock("div", {
ref: "rootElement",
"data-oruga": "carousel",
class: vue.normalizeClass(vue.unref(rootClasses)),
role: "region",
"aria-roledescription": "carousel",
onMouseover: onMouseEnter,
onMouseleave: onMouseLeave,
onFocusin: onMouseEnter,
onFocusout: onMouseLeave,
onKeydown: [
vue.withKeys(onPrev, ["left"]),
vue.withKeys(onNext, ["right"]),
vue.withKeys(vue.withModifiers(onHomePressed, ["prevent"]), ["home"]),
vue.withKeys(vue.withModifiers(onEndPressed, ["prevent"]), ["end"])
]
}, [
vue.createElementVNode("div", {
class: vue.normalizeClass(vue.unref(wrapperClasses))
}, [
vue.renderSlot(_ctx.$slots, "pause", {
autoplay: !isAutoplayPaused.value,
toggle: onToggleAutoplay
}, () => [
_ctx.autoplay ? (vue.openBlock(), vue.createBlock(Icon_vue_vue_type_script_setup_true_lang._sfc_main, {
key: 0,
class: vue.normalizeClass(vue.unref(autoplayIconClasses)),
pack: _ctx.iconPack,
icon: !isAutoplayPaused.value ? _ctx.iconAutoplayPause : _ctx.iconAutoplayResume,
size: _ctx.iconSize,
clickable: "",
"aria-label": !isAutoplayPaused.value ? _ctx.ariaAutoplayPauseLabel : _ctx.ariaAutoplayResumeLabel,
onClick: onToggleAutoplay
}, null, 8, ["class", "pack", "icon", "size", "aria-label"])) : vue.createCommentVNode("", true)
]),
vue.renderSlot(_ctx.$slots, "arrow", {
hasPrev: hasPrev.value,
prev: onPrev,
hasNext: hasNext.value,
next: onNext
}, () => [
_ctx.arrows ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
vue.withDirectives(vue.createVNode(Icon_vue_vue_type_script_setup_true_lang._sfc_main, {
class: vue.normalizeClass(vue.unref(prevIconClasses)),
pack: _ctx.iconPack,
icon: _ctx.iconPrev,
size: _ctx.iconSize,
clickable: "",
"aria-label": _ctx.ariaPreviousLabel,
onClick: onPrev
}, null, 8, ["class", "pack", "icon", "size", "aria-label"]), [
[vue.vShow, hasArrows.value && hasPrev.value]
]),
vue.withDirectives(vue.createVNode(Icon_vue_vue_type_script_setup_true_lang._sfc_main, {
class: vue.normalizeClass(vue.unref(nextIconClasses)),
pack: _ctx.iconPack,
icon: _ctx.iconNext,
size: _ctx.iconSize,
clickable: "",
"aria-label": _ctx.ariaNextLabel,
onClick: onNext
}, null, 8, ["class", "pack", "icon", "size", "aria-label"]), [
[vue.vShow, hasArrows.value && hasNext.value]
])
], 64)) : vue.createCommentVNode("", true)
]),
vue.createElementVNode("div", {
class: vue.normalizeClass(vue.unref(itemsClasses)),
style: vue.normalizeStyle("transform:translateX(" + translation.value + "px)"),
"aria-roledescription": "carousel-slide",
"aria-atomic": "false",
"aria-live": _ctx.autoplay ? "off" : "polite",
onDragend: onDragEnd,
onDragover: onDragOver,
onTouchmove: onDragOver,
onTouchend: onDragEnd
}, [
vue.renderSlot(_ctx.$slots, "default")
], 46, _hoisted_2)
], 2),
vue.renderSlot(_ctx.$slots, "indicators", {
active: activeIndex.value,
switchTo
}, () => [
_ctx.indicators ? (vue.openBlock(), vue.createElementBlock("div", {
key: 0,
class: vue.normalizeClass(vue.unref(indicatorsClasses)),
role: "tablist",
"aria-label": "Slides"
}, [
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(indicatorItems.value, (item) => {
return vue.openBlock(), vue.createElementBlock("div", {
id: `carousel-${item.identifier}`,
key: item.index,
class: vue.normalizeClass(vue.unref(indicatorClasses)),
role: "tab",
tabindex: __props.modelValue === item.index ? "0" : "-1",
"aria-label": `Slide ${item.identifier}`,
"aria-controls": `carouselpanel-${item.identifier}`,
"aria-selected": __props.modelValue === item.index,
onClick: ($event) => onChange(item),
onKeydown: [
vue.withKeys(($event) => onChange(item), ["enter"]),
vue.withKeys(($event) => onChange(item), ["space"])
]
}, [
vue.renderSlot(_ctx.$slots, "indicator", {
index: item.index
}, () => [
vue.createElementVNode("span", {
class: vue.normalizeClass(indicatorItemAppliedClasses(item))
}, null, 2)
])
], 42, _hoisted_3);
}), 128))
], 2)) : vue.createCommentVNode("", true)
]),
_ctx.overlay ? vue.renderSlot(_ctx.$slots, "overlay", { key: 0 }) : vue.createCommentVNode("", true)
], 42, _hoisted_1$1);
};
}
});
const _hoisted_1 = ["id", "data-id", "role", "aria-labelledby", "aria-label"];
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
...{
isOruga: true,
name: "OCarouselItem",
configField: "carousel"
},
__name: "CarouselItem",
props: {
override: { type: Boolean, default: void 0 },
clickable: { type: Boolean, default: false },
itemClass: {},
itemActiveClass: {},
itemClickableClass: {}
},
setup(__props) {
const props = __props;
const { parent, item } = useParentProvider.useProviderChild();
const isActive = vue.computed(() => parent.value.activeIndex === item.value.index);
const itemStyle = vue.computed(() => ({ width: `${parent.value.itemWidth}px` }));
function onClick(event) {
if (isActive.value) parent.value.onClick(event);
if (props.clickable) parent.value.setActive(item.value.index);
}
const itemClasses = defineClasses.defineClasses(
["itemClass", "o-carousel__item"],
["itemActiveClass", "o-carousel__item--active", null, isActive],
[
"itemClickableClass",
"o-carousel__item--clickable",
null,
vue.computed(() => props.clickable)
]
);
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock("div", {
id: `carouselpanel-${vue.unref(item).identifier}`,
"data-oruga": "carousel-item",
"data-id": `carousel-${vue.unref(item).identifier}`,
class: vue.normalizeClass(vue.unref(itemClasses)),
style: vue.normalizeStyle(itemStyle.value),
role: vue.unref(parent).indicators ? "tabpanel" : "group",
"aria-labelledby": `carousel-${vue.unref(item).identifier}`,
"aria-roledescription": "slide",
"aria-label": `${vue.unref(item).index + 1} of ${vue.unref(parent).total}`,
draggable: "true",
onClick,
onKeydown: [
vue.withKeys(onClick, ["enter"]),
vue.withKeys(onClick, ["space"])
],
onDragstart: _cache[0] || (_cache[0] = //@ts-ignore
(...args) => vue.unref(parent).onDrag && vue.unref(parent).onDrag(...args)),
onTouchstart: _cache[1] || (_cache[1] = //@ts-ignore
(...args) => vue.unref(parent).onDrag && vue.unref(parent).onDrag(...args))
}, [
vue.renderSlot(_ctx.$slots, "default")
], 46, _hoisted_1);
};
}
});
const index = {
install(app) {
config.registerComponent(app, _sfc_main$1);
config.registerComponent(app, _sfc_main);
}
};
exports.OCarousel = _sfc_main$1;
exports.OCarouselItem = _sfc_main;
exports.default = index;
//# sourceMappingURL=carousel.cjs.map