buefy
Version:
Lightweight UI components for Vue.js (v3) based on Bulma
819 lines (810 loc) • 24.5 kB
JavaScript
import { defineComponent, resolveComponent, createElementBlock, openBlock, normalizeClass, createCommentVNode, createElementVNode, renderSlot, toDisplayString, withModifiers, withDirectives, createVNode, vShow, Fragment, renderList, createBlock, Transition, withCtx, normalizeStyle, mergeProps } from 'vue';
import { c as config } from './config-CKuo-p6e.js';
import { B as BIcon } from './Icon-DPyGDeRK.js';
import { P as ProviderParentMixin, S as Sorted, I as InjectedChildMixin, a as Sorted$1 } from './InjectedChildMixin-D2K-FwuO.js';
import { mod, bound, sign } from './helpers.js';
import { _ as _export_sfc } from './_plugin-vue_export-helper-OJRSZE6i.js';
import { I as Image } from './Image-DhX-4hlV.js';
import { a as registerComponent } from './plugins-B172kuKE.js';
var _sfc_main$2 = defineComponent({
name: "BCarousel",
components: {
BIcon
},
mixins: [ProviderParentMixin("carousel", Sorted)],
props: {
modelValue: {
type: Number,
default: 0
},
animated: {
type: String,
default: "slide"
},
interval: Number,
hasDrag: {
type: Boolean,
default: true
},
autoplay: {
type: Boolean,
default: true
},
pauseHover: {
type: Boolean,
default: true
},
pauseInfo: {
type: Boolean,
default: true
},
pauseInfoType: {
type: String,
default: "is-white"
},
pauseText: {
type: String,
default: "Pause"
},
arrow: {
type: Boolean,
default: true
},
arrowHover: {
type: Boolean,
default: true
},
repeat: {
type: Boolean,
default: true
},
iconPack: String,
iconSize: String,
iconPrev: {
type: String,
default: () => {
return config.defaultIconPrev;
}
},
iconNext: {
type: String,
default: () => {
return config.defaultIconNext;
}
},
indicator: {
type: Boolean,
default: true
},
indicatorBackground: Boolean,
indicatorCustom: Boolean,
indicatorCustomSize: {
type: String,
default: "is-small"
},
indicatorInside: {
type: Boolean,
default: true
},
indicatorMode: {
type: String,
default: "click"
},
indicatorPosition: {
type: String,
default: "is-bottom"
},
indicatorStyle: {
type: String,
default: "is-dots"
},
overlay: Boolean,
progress: Boolean,
progressType: {
type: String,
default: "is-primary"
},
withCarouselList: Boolean
},
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
change: (_index) => true,
click: () => true,
"update:modelValue": (_value) => true
/* eslint-enable @typescript-eslint/no-unused-vars */
},
data() {
return {
transition: "next",
activeChild: this.modelValue || 0,
isPause: false,
dragX: false,
timer: void 0
};
},
computed: {
indicatorClasses() {
return [
{
"has-background": this.indicatorBackground,
"has-custom": this.indicatorCustom,
"is-inside": this.indicatorInside
},
this.indicatorCustom && this.indicatorCustomSize,
this.indicatorInside && this.indicatorPosition
];
},
// checking arrows
hasPrev() {
return this.repeat || this.activeChild !== 0;
},
hasNext() {
return this.repeat || this.activeChild < this.childItems.length - 1;
},
activeChildIndex() {
const item = this.sortedItems[this.activeChild];
return item != null ? item.index : void 0;
}
},
watch: {
/*
* When v-model is changed set the new active item.
*/
modelValue(value) {
this.changeActive(value);
},
/*
* When carousel-items are updated, set active one.
*/
sortedItems(items) {
if (this.activeChild >= items.length && this.activeChild > 0) {
this.changeActive(this.activeChild - 1);
}
},
/*
* When autoplay is changed, start or pause timer accordingly
*/
autoplay(status) {
status ? this.startTimer() : this.pauseTimer();
},
/*
* Since the timer can get paused at the end, if repeat is changed we need to restart it
*/
repeat(status) {
if (status) {
this.startTimer();
}
}
},
methods: {
startTimer() {
if (!this.autoplay || this.timer) return;
this.isPause = false;
this.timer = setInterval(() => {
if (!this.repeat && this.activeChild >= this.childItems.length - 1) {
this.pauseTimer();
} else {
this.next();
}
}, this.interval || config.defaultCarouselInterval);
},
pauseTimer() {
this.isPause = true;
if (this.timer) {
clearInterval(this.timer);
this.timer = void 0;
}
},
restartTimer() {
this.pauseTimer();
this.startTimer();
},
checkPause() {
if (this.pauseHover && this.autoplay) {
this.pauseTimer();
}
},
/*
* Change the active item and emit change event.
* action only for animated slide, there true = next, false = prev
*/
changeActive(newIndex, direction = 0) {
if (this.activeChild === newIndex || isNaN(newIndex)) return;
direction = direction || newIndex - this.activeChild;
newIndex = this.repeat ? mod(newIndex, this.childItems.length) : bound(newIndex, 0, this.childItems.length - 1);
this.transition = direction > 0 ? "prev" : "next";
this.activeChild = newIndex;
if (newIndex !== this.modelValue) {
this.$emit("update:modelValue", newIndex);
}
this.restartTimer();
this.$emit("change", newIndex);
},
// Indicator trigger when change active item.
modeChange(trigger, value) {
if (this.indicatorMode === trigger) {
return this.changeActive(value);
}
},
prev() {
this.changeActive(this.activeChild - 1, -1);
},
next() {
this.changeActive(this.activeChild + 1, 1);
},
// handle drag event
dragStart(event) {
if (!this.hasDrag || !event.target.draggable) return;
const touches = event.touches;
this.dragX = touches ? event.changedTouches[0].pageX : event.pageX;
if (touches) {
this.pauseTimer();
} else {
event.preventDefault();
}
},
dragEnd(event) {
if (this.dragX === false) return;
const touches = event.touches;
const detected = touches ? event.changedTouches[0].pageX : event.pageX;
const diffX = detected - this.dragX;
if (Math.abs(diffX) > 30) {
if (diffX < 0) {
this.next();
} else {
this.prev();
}
} else {
event.target.click();
this.sortedItems[this.activeChild].$emit("click");
this.$emit("click");
}
if (touches) {
this.startTimer();
}
this.dragX = false;
}
},
mounted() {
this.startTimer();
},
beforeUnmount() {
this.pauseTimer();
}
});
const _hoisted_1$2 = ["value", "max"];
const _hoisted_2 = {
key: 1,
class: "carousel-pause"
};
const _hoisted_3 = ["onMouseover", "onClick"];
function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
const _component_b_icon = resolveComponent("b-icon");
return openBlock(), createElementBlock(
"div",
{
class: normalizeClass(["carousel", { "is-overlay": _ctx.overlay }]),
onMouseenter: _cache[4] || (_cache[4] = (...args) => _ctx.checkPause && _ctx.checkPause(...args)),
onMouseleave: _cache[5] || (_cache[5] = (...args) => _ctx.startTimer && _ctx.startTimer(...args))
},
[
_ctx.progress ? (openBlock(), createElementBlock("progress", {
key: 0,
class: normalizeClass(["progress", _ctx.progressType]),
value: _ctx.activeChild,
max: _ctx.childItems.length - 1
}, toDisplayString(_ctx.childItems.length - 1), 11, _hoisted_1$2)) : createCommentVNode("v-if", true),
createElementVNode(
"div",
{
class: "carousel-items",
onMousedown: _cache[0] || (_cache[0] = (...args) => _ctx.dragStart && _ctx.dragStart(...args)),
onMouseup: _cache[1] || (_cache[1] = (...args) => _ctx.dragEnd && _ctx.dragEnd(...args)),
onTouchstart: _cache[2] || (_cache[2] = withModifiers((...args) => _ctx.dragStart && _ctx.dragStart(...args), ["stop"])),
onTouchend: _cache[3] || (_cache[3] = withModifiers((...args) => _ctx.dragEnd && _ctx.dragEnd(...args), ["stop"]))
},
[
renderSlot(_ctx.$slots, "default"),
_ctx.arrow ? (openBlock(), createElementBlock(
"div",
{
key: 0,
class: normalizeClass(["carousel-arrow", { "is-hovered": _ctx.arrowHover }])
},
[
withDirectives(createVNode(_component_b_icon, {
class: "has-icons-left",
onClick: _ctx.prev,
pack: _ctx.iconPack,
icon: _ctx.iconPrev,
size: _ctx.iconSize,
both: ""
}, null, 8, ["onClick", "pack", "icon", "size"]), [
[vShow, _ctx.hasPrev]
]),
withDirectives(createVNode(_component_b_icon, {
class: "has-icons-right",
onClick: _ctx.next,
pack: _ctx.iconPack,
icon: _ctx.iconNext,
size: _ctx.iconSize,
both: ""
}, null, 8, ["onClick", "pack", "icon", "size"]), [
[vShow, _ctx.hasNext]
])
],
2
/* CLASS */
)) : createCommentVNode("v-if", true)
],
32
/* NEED_HYDRATION */
),
_ctx.autoplay && _ctx.pauseHover && _ctx.pauseInfo && _ctx.isPause ? (openBlock(), createElementBlock("div", _hoisted_2, [
createElementVNode(
"span",
{
class: normalizeClass(["tag", _ctx.pauseInfoType])
},
toDisplayString(_ctx.pauseText),
3
/* TEXT, CLASS */
)
])) : createCommentVNode("v-if", true),
_ctx.withCarouselList && !_ctx.indicator ? renderSlot(_ctx.$slots, "list", {
key: 2,
active: _ctx.activeChild,
switch: _ctx.changeActive
}) : createCommentVNode("v-if", true),
_ctx.indicator ? (openBlock(), createElementBlock(
"div",
{
key: 3,
class: normalizeClass(["carousel-indicator", _ctx.indicatorClasses])
},
[
(openBlock(true), createElementBlock(
Fragment,
null,
renderList(_ctx.sortedItems, (item, index) => {
return openBlock(), createElementBlock("a", {
class: normalizeClass(["indicator-item", { "is-active": item.isActive }]),
onMouseover: ($event) => _ctx.modeChange("hover", index),
onClick: ($event) => _ctx.modeChange("click", index),
key: item.uniqueValue
}, [
renderSlot(_ctx.$slots, "indicators", { i: index }, () => [
createElementVNode(
"span",
{
class: normalizeClass(["indicator-style", _ctx.indicatorStyle])
},
null,
2
/* CLASS */
)
])
], 42, _hoisted_3);
}),
128
/* KEYED_FRAGMENT */
))
],
2
/* CLASS */
)) : createCommentVNode("v-if", true),
_ctx.overlay ? renderSlot(_ctx.$slots, "overlay", { key: 4 }) : createCommentVNode("v-if", true)
],
34
/* CLASS, NEED_HYDRATION */
);
}
var Carousel = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$2]]);
var _sfc_main$1 = defineComponent({
name: "BCarouselItem",
mixins: [InjectedChildMixin("carousel", Sorted$1)],
data() {
return {
transitionName: null
};
},
computed: {
transition() {
if (this.parent.animated === "fade") {
return "fade";
} else if (this.parent.transition) {
return "slide-" + this.parent.transition;
} else {
return void 0;
}
},
isActive() {
return this.parent.activeChildIndex === this.index;
}
}
});
const _hoisted_1$1 = { class: "carousel-item" };
function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
return openBlock(), createBlock(Transition, {
name: _ctx.transition,
persisted: ""
}, {
default: withCtx(() => [
withDirectives(createElementVNode(
"div",
_hoisted_1$1,
[
renderSlot(_ctx.$slots, "default")
],
512
/* NEED_PATCH */
), [
[vShow, _ctx.isActive]
])
]),
_: 3
/* FORWARDED */
}, 8, ["name"]);
}
var CarouselItem = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render$1]]);
var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var _sfc_main = defineComponent({
name: "BCarouselList",
components: {
BIcon,
BImage: Image
},
props: {
data: {
type: Array,
default: () => []
},
modelValue: {
type: Number,
default: 0
},
scrollValue: {
type: Number,
default: 0
},
hasDrag: {
type: Boolean,
default: true
},
hasGrayscale: Boolean,
hasOpacity: Boolean,
repeat: Boolean,
itemsToShow: {
type: Number,
default: 4
},
itemsToList: {
type: Number,
default: 1
},
asIndicator: Boolean,
arrow: {
type: Boolean,
default: true
},
arrowHover: {
type: Boolean,
default: true
},
iconPack: String,
iconSize: String,
iconPrev: {
type: String,
default: () => {
return config.defaultIconPrev;
}
},
iconNext: {
type: String,
default: () => {
return config.defaultIconNext;
}
},
breakpoints: {
type: Object,
default: () => ({})
}
},
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
switch: (_value) => true,
"update:modelValue": (_value) => true,
"updated:scroll": (_index) => true
/* eslint-enable @typescript-eslint/no-unused-vars */
},
data() {
return {
activeItem: this.modelValue,
scrollIndex: this.asIndicator ? this.scrollValue : this.modelValue,
delta: 0,
dragX: false,
hold: 0,
windowWidth: 0,
touch: false,
observer: null,
refresh_: 0
};
},
computed: {
dragging() {
return this.dragX !== false;
},
listClass() {
return [
{
"has-grayscale": this.settings.hasGrayscale,
"has-opacity": this.settings.hasOpacity,
"is-dragging": this.dragging
}
];
},
itemStyle() {
return `width: ${this.itemWidth}px;`;
},
translation() {
return -bound(
this.delta + this.scrollIndex * this.itemWidth,
0,
(this.data.length - this.settings.itemsToShow) * this.itemWidth
);
},
total() {
return this.data.length - this.settings.itemsToShow;
},
hasPrev() {
return this.settings.repeat || this.scrollIndex > 0;
},
hasNext() {
return this.settings.repeat || this.scrollIndex < this.total;
},
breakpointKeys() {
return Object.keys(this.breakpoints).sort((a, b) => +b - +a);
},
settings() {
const breakpoint = this.breakpointKeys.filter((breakpoint2) => {
if (this.windowWidth >= +breakpoint2) {
return true;
} else {
return false;
}
})[0];
if (breakpoint) {
return __spreadValues(__spreadValues({}, this.$props), this.breakpoints[+breakpoint]);
}
return this.$props;
},
itemWidth() {
if (this.windowWidth) {
this.refresh_;
const rect = this.$el.getBoundingClientRect();
return rect.width / this.settings.itemsToShow;
}
return 0;
}
},
watch: {
/*
* When v-model is changed set the new active item.
*/
modelValue(value) {
this.switchTo(this.asIndicator ? value - (this.itemsToShow - 3) / 2 : value);
if (this.activeItem !== value) {
this.activeItem = bound(value, 0, this.data.length - 1);
}
},
scrollValue(value) {
this.switchTo(value);
}
},
methods: {
resized() {
this.windowWidth = window.innerWidth;
},
switchTo(newIndex) {
if (newIndex === this.scrollIndex || isNaN(newIndex)) {
return;
}
if (this.settings.repeat) {
newIndex = mod(newIndex, this.total + 1);
}
newIndex = bound(newIndex, 0, this.total);
this.scrollIndex = newIndex;
if (!this.asIndicator && this.modelValue !== newIndex) {
this.$emit("update:modelValue", newIndex);
} else if (this.scrollIndex !== newIndex) {
this.$emit("updated:scroll", newIndex);
}
},
next() {
this.switchTo(this.scrollIndex + this.settings.itemsToList);
},
prev() {
this.switchTo(this.scrollIndex - this.settings.itemsToList);
},
checkAsIndicator(value, event) {
if (!this.asIndicator) return;
const dragEndX = event.changedTouches ? event.changedTouches[0].clientX : event.clientX;
if (this.hold - Date.now() > 2e3 || Math.abs(+this.dragX - dragEndX) > 10) return;
this.dragX = false;
this.hold = 0;
event.preventDefault();
this.activeItem = value;
this.$emit("switch", value);
},
// handle drag event
dragStart(event) {
if (this.dragging || !this.settings.hasDrag || event.button !== 0 && event.type !== "touchstart") return;
this.hold = Date.now();
this.touch = !!event.touches;
this.dragX = this.touch ? event.touches[0].clientX : event.clientX;
window.addEventListener(this.touch ? "touchmove" : "mousemove", this.dragMove);
window.addEventListener(this.touch ? "touchend" : "mouseup", this.dragEnd);
},
dragMove(event) {
if (!this.dragging) return;
const dragEndX = event.touches ? (event.changedTouches[0] || event.touches[0]).clientX : event.clientX;
this.delta = +this.dragX - dragEndX;
if (!event.touches) {
event.preventDefault();
}
},
dragEnd() {
if (!this.dragging && !this.hold) return;
if (this.hold) {
const signCheck = sign(this.delta);
const results = Math.round(Math.abs(this.delta / this.itemWidth) + 0.15);
this.switchTo(this.scrollIndex + signCheck * results);
}
this.delta = 0;
this.dragX = false;
window.removeEventListener(this.touch ? "touchmove" : "mousemove", this.dragMove);
window.removeEventListener(this.touch ? "touchend" : "mouseup", this.dragEnd);
},
refresh() {
this.$nextTick(() => {
this.refresh_++;
});
}
},
mounted() {
if (typeof window !== "undefined") {
if (window.ResizeObserver) {
this.observer = new ResizeObserver(this.refresh);
this.observer.observe(this.$el);
}
window.addEventListener("resize", this.resized);
document.addEventListener("animationend", this.refresh);
document.addEventListener("transitionend", this.refresh);
document.addEventListener("transitionstart", this.refresh);
this.resized();
}
if (this.$attrs.config) {
throw new Error("The config prop was removed, you need to use v-bind instead");
}
},
beforeUnmount() {
if (typeof window !== "undefined") {
if (window.ResizeObserver) {
this.observer.disconnect();
}
window.removeEventListener("resize", this.resized);
document.removeEventListener("animationend", this.refresh);
document.removeEventListener("transitionend", this.refresh);
document.removeEventListener("transitionstart", this.refresh);
this.dragEnd();
}
}
});
const _hoisted_1 = ["onMouseup", "onTouchend"];
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_b_image = resolveComponent("b-image");
const _component_b_icon = resolveComponent("b-icon");
return openBlock(), createElementBlock(
"div",
{
class: normalizeClass(["carousel-list", { "has-shadow": _ctx.scrollIndex > 0 }]),
onMousedown: _cache[0] || (_cache[0] = withModifiers((...args) => _ctx.dragStart && _ctx.dragStart(...args), ["prevent"])),
onTouchstart: _cache[1] || (_cache[1] = (...args) => _ctx.dragStart && _ctx.dragStart(...args))
},
[
createElementVNode(
"div",
{
class: normalizeClass(["carousel-slides", _ctx.listClass]),
style: normalizeStyle("transform:translateX(" + _ctx.translation + "px)")
},
[
(openBlock(true), createElementBlock(
Fragment,
null,
renderList(_ctx.data, (list, index) => {
return openBlock(), createElementBlock("div", {
class: normalizeClass(["carousel-slide", { "is-active": _ctx.asIndicator ? _ctx.activeItem === index : _ctx.scrollIndex === index }]),
onMouseup: ($event) => _ctx.checkAsIndicator(index, $event),
onTouchend: ($event) => _ctx.checkAsIndicator(index, $event),
key: index,
style: normalizeStyle(_ctx.itemStyle)
}, [
renderSlot(_ctx.$slots, "item", mergeProps({
index,
active: _ctx.activeItem,
scroll: _ctx.scrollIndex
}, list, { list }), () => [
createVNode(_component_b_image, mergeProps({
src: list.image
}, list), null, 16, ["src"])
])
], 46, _hoisted_1);
}),
128
/* KEYED_FRAGMENT */
))
],
6
/* CLASS, STYLE */
),
_ctx.arrow ? (openBlock(), createElementBlock(
"div",
{
key: 0,
class: normalizeClass(["carousel-arrow", { "is-hovered": _ctx.settings.arrowHover }])
},
[
withDirectives(createVNode(_component_b_icon, {
class: "has-icons-left",
onClick: withModifiers(_ctx.prev, ["prevent"]),
pack: _ctx.settings.iconPack,
icon: _ctx.settings.iconPrev,
size: _ctx.settings.iconSize,
both: ""
}, null, 8, ["onClick", "pack", "icon", "size"]), [
[vShow, _ctx.hasPrev]
]),
withDirectives(createVNode(_component_b_icon, {
class: "has-icons-right",
onClick: withModifiers(_ctx.next, ["prevent"]),
pack: _ctx.settings.iconPack,
icon: _ctx.settings.iconNext,
size: _ctx.settings.iconSize,
both: ""
}, null, 8, ["onClick", "pack", "icon", "size"]), [
[vShow, _ctx.hasNext]
])
],
2
/* CLASS */
)) : createCommentVNode("v-if", true)
],
34
/* CLASS, NEED_HYDRATION */
);
}
var CarouselList = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
const Plugin = {
install(Vue) {
registerComponent(Vue, Carousel);
registerComponent(Vue, CarouselItem);
registerComponent(Vue, CarouselList);
}
};
export { Carousel as BCarousel, CarouselItem as BCarouselItem, CarouselList as BCarouselList, Plugin as default };