@varlet/ui
Version:
A Vue3 component library based on Material Design 2 and 3, supporting mobile and desktop.
535 lines (534 loc) • 18.5 kB
JavaScript
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
import { computed, defineComponent, onActivated, ref, watch } from "vue";
import { call, clamp, doubleRaf, isNumber, preventDefault, toNumber } from "@varlet/shared";
import { onSmartUnmounted, onWindowResize, useEventListener, useTouch } from "@varlet/use";
import VarButton from "../button/index.mjs";
import Hover from "../hover/index.mjs";
import VarIcon from "../icon/index.mjs";
import { usePopup } from "../popup/provide.mjs";
import { createNamespace } from "../utils/components.mjs";
import { toSizeUnit } from "../utils/elements.mjs";
import { props } from "./props.mjs";
import { useSwipeItems, useSwipeResizeListeners } from "./provide.mjs";
const SWIPE_DELAY = 250;
const SWIPE_OFFSET = 20;
const { name, n, classes } = createNamespace("swipe");
import { renderSlot as _renderSlot, normalizeClass as _normalizeClass, normalizeStyle as _normalizeStyle, createElementVNode as _createElementVNode, normalizeProps as _normalizeProps, guardReactiveProps as _guardReactiveProps, resolveComponent as _resolveComponent, createVNode as _createVNode, withCtx as _withCtx, openBlock as _openBlock, createElementBlock as _createElementBlock, createCommentVNode as _createCommentVNode, Transition as _Transition, mergeProps as _mergeProps, renderList as _renderList, Fragment as _Fragment, resolveDirective as _resolveDirective, withDirectives as _withDirectives } from "vue";
const _hoisted_1 = ["onClick"];
function __render__(_ctx, _cache) {
const _component_var_icon = _resolveComponent("var-icon");
const _component_var_button = _resolveComponent("var-button");
const _directive_hover = _resolveDirective("hover");
return _withDirectives((_openBlock(), _createElementBlock(
"div",
{
ref: "swipeEl",
class: _normalizeClass(_ctx.n())
},
[
_createElementVNode(
"div",
{
class: _normalizeClass(_ctx.classes(_ctx.n("track"), [_ctx.vertical, _ctx.n("--vertical")])),
style: _normalizeStyle({
width: !_ctx.vertical ? _ctx.toSizeUnit(_ctx.trackSize) : void 0,
height: _ctx.vertical ? _ctx.toSizeUnit(_ctx.trackSize) : void 0,
transform: `translate${_ctx.vertical ? "Y" : "X"}(${_ctx.toSizeUnit(_ctx.trackTranslate)})`,
transitionDuration: _ctx.lockDuration ? "0ms" : `${_ctx.toNumber(_ctx.duration)}ms`
}),
onTouchstart: _cache[0] || (_cache[0] = (...args) => _ctx.handleTouchstart && _ctx.handleTouchstart(...args)),
onTouchmove: _cache[1] || (_cache[1] = (...args) => _ctx.handleTouchmove && _ctx.handleTouchmove(...args)),
onTouchend: _cache[2] || (_cache[2] = (...args) => _ctx.handleTouchend && _ctx.handleTouchend(...args))
},
[
_renderSlot(_ctx.$slots, "default")
],
38
/* CLASS, STYLE, NEED_HYDRATION */
),
_ctx.navigation ? _renderSlot(_ctx.$slots, "prev", _normalizeProps(_mergeProps({ key: 0 }, {
index: _ctx.index,
length: _ctx.length,
prev: _ctx.prev,
next: _ctx.next,
to: _ctx.to,
hovering: _ctx.hovering
})), () => [
_createVNode(_Transition, {
name: _ctx.getNavigationAnimation("prev")
}, {
default: _withCtx(() => [
_ctx.navigation === true || _ctx.hovering ? (_openBlock(), _createElementBlock(
"div",
{
key: 0,
class: _normalizeClass(_ctx.classes(_ctx.n("navigation"), _ctx.n("navigation-prev"), [_ctx.vertical, _ctx.n("--navigation-vertical-prev")]))
},
[
_createVNode(_component_var_button, {
"var-swipe-cover": "",
disabled: !_ctx.loop && _ctx.index === 0,
class: _normalizeClass(_ctx.n("navigation-prev-button")),
onClick: _cache[3] || (_cache[3] = ($event) => _ctx.prev())
}, {
default: _withCtx(() => [
_createVNode(_component_var_icon, {
"var-swipe-cover": "",
class: _normalizeClass(_ctx.n("navigation-prev-button-icon")),
name: _ctx.vertical ? "chevron-up" : "chevron-left"
}, null, 8, ["class", "name"])
]),
_: 1
/* STABLE */
}, 8, ["disabled", "class"])
],
2
/* CLASS */
)) : _createCommentVNode("v-if", true)
]),
_: 1
/* STABLE */
}, 8, ["name"])
]) : _createCommentVNode("v-if", true),
_ctx.navigation ? _renderSlot(_ctx.$slots, "next", _normalizeProps(_mergeProps({ key: 1 }, {
index: _ctx.index,
length: _ctx.length,
hovering: _ctx.hovering,
prev: _ctx.prev,
next: _ctx.next,
to: _ctx.to
})), () => [
_createVNode(_Transition, {
name: _ctx.getNavigationAnimation("next")
}, {
default: _withCtx(() => [
_ctx.navigation === true || _ctx.hovering ? (_openBlock(), _createElementBlock(
"div",
{
key: 0,
class: _normalizeClass(_ctx.classes(_ctx.n("navigation"), _ctx.n("navigation-next"), [_ctx.vertical, _ctx.n("--navigation-vertical-next")]))
},
[
_createVNode(_component_var_button, {
"var-swipe-cover": "",
class: _normalizeClass(_ctx.n("navigation-next-button")),
disabled: !_ctx.loop && _ctx.index === _ctx.length - 1,
onClick: _cache[4] || (_cache[4] = ($event) => _ctx.next())
}, {
default: _withCtx(() => [
_createVNode(_component_var_icon, {
"var-swipe-cover": "",
class: _normalizeClass(_ctx.n("navigation-next-button-icon")),
name: _ctx.vertical ? "chevron-down" : "chevron-right"
}, null, 8, ["class", "name"])
]),
_: 1
/* STABLE */
}, 8, ["class", "disabled"])
],
2
/* CLASS */
)) : _createCommentVNode("v-if", true)
]),
_: 1
/* STABLE */
}, 8, ["name"])
]) : _createCommentVNode("v-if", true),
_renderSlot(_ctx.$slots, "indicator", _normalizeProps(_guardReactiveProps({
index: _ctx.index,
length: _ctx.length,
hovering: _ctx.hovering,
prev: _ctx.prev,
next: _ctx.next,
to: _ctx.to
})), () => [
_ctx.indicator && _ctx.length ? (_openBlock(), _createElementBlock(
"div",
{
key: 0,
class: _normalizeClass(_ctx.classes(_ctx.n("indicators"), [_ctx.vertical, _ctx.n("--indicators-vertical")]))
},
[
(_openBlock(true), _createElementBlock(
_Fragment,
null,
_renderList(_ctx.length, (l, idx) => {
return _openBlock(), _createElementBlock("div", {
key: l,
class: _normalizeClass(
_ctx.classes(_ctx.n("indicator"), [_ctx.index === idx, _ctx.n("--indicator-active")], [_ctx.vertical, _ctx.n("--indicator-vertical")])
),
style: _normalizeStyle({ background: _ctx.indicatorColor }),
onClick: ($event) => _ctx.to(idx)
}, null, 14, _hoisted_1);
}),
128
/* KEYED_FRAGMENT */
))
],
2
/* CLASS */
)) : _createCommentVNode("v-if", true)
])
],
2
/* CLASS */
)), [
[_directive_hover, _ctx.handleHovering]
]);
}
const __sfc__ = defineComponent({
name,
directives: { Hover },
components: { VarButton, VarIcon },
props,
setup(props2) {
const swipeEl = ref(null);
const size = ref(0);
const vertical = computed(() => props2.vertical);
const trackSize = ref(0);
const trackTranslate = ref(0);
const lockDuration = ref(false);
const index = ref(0);
const hovering = ref(false);
const { swipeItems, bindSwipeItems, length } = useSwipeItems();
const { swipeResizeListeners, bindSwipeResizeListeners } = useSwipeResizeListeners();
const { popup, bindPopup } = usePopup();
const {
deltaX,
deltaY,
moveX,
moveY,
offsetX,
offsetY,
touching,
direction,
startTime,
startTouch,
moveTouch,
endTouch
} = useTouch();
const isExpectDirection = computed(() => direction.value === (props2.vertical ? "vertical" : "horizontal"));
let initializedIndex = false;
let timer = -1;
const swipeProvider = {
size,
currentIndex: index,
vertical
};
bindSwipeItems(swipeProvider);
useEventListener(() => window, "keydown", handleKeydown);
call(bindPopup, null);
call(bindSwipeResizeListeners, null);
watch(
() => length.value,
() => __async(this, null, function* () {
yield doubleRaf();
initialIndex();
resize();
})
);
if (popup) {
watch(
() => popup.show.value,
(show) => __async(this, null, function* () {
if (show) {
yield doubleRaf();
resize();
} else {
stopAutoplay();
}
})
);
}
onActivated(resize);
onSmartUnmounted(stopAutoplay);
onWindowResize(resize);
function findSwipeItem(idx) {
return swipeItems.find(({ index: index2 }) => index2.value === idx);
}
function dispatchSwipeItems() {
if (!props2.loop) {
return;
}
if (trackTranslate.value >= 0) {
findSwipeItem(length.value - 1).setTranslate(-trackSize.value);
}
if (trackTranslate.value <= -(trackSize.value - size.value)) {
findSwipeItem(0).setTranslate(trackSize.value);
}
if (trackTranslate.value > -(trackSize.value - size.value) && trackTranslate.value < 0) {
findSwipeItem(length.value - 1).setTranslate(0);
findSwipeItem(0).setTranslate(0);
}
}
function getSwipeIndex(targetSwipeIndex) {
const swipeIndex = isNumber(targetSwipeIndex) ? targetSwipeIndex : Math.floor((trackTranslate.value - size.value / 2) / -size.value);
const { loop } = props2;
if (swipeIndex <= -1) {
return loop ? -1 : 0;
}
if (swipeIndex >= length.value) {
return loop ? length.value : length.value - 1;
}
return swipeIndex;
}
function swipeIndexToIndex(swipeIndex) {
const { loop } = props2;
if (swipeIndex === -1) {
return loop ? length.value - 1 : 0;
}
if (swipeIndex === length.value) {
return loop ? 0 : length.value - 1;
}
return swipeIndex;
}
function clampIndex(index2) {
if (props2.loop) {
if (index2 < 0) {
return length.value + index2;
}
if (index2 >= length.value) {
return index2 - length.value;
}
return index2;
}
return clamp(index2, 0, length.value - 1);
}
function fixPosition() {
return __async(this, null, function* () {
const overLeft = trackTranslate.value >= size.value;
const overRight = trackTranslate.value <= -trackSize.value;
const leftTranslate = 0;
const rightTranslate = -(trackSize.value - size.value);
lockDuration.value = true;
if (overLeft || overRight) {
lockDuration.value = true;
trackTranslate.value = overRight ? leftTranslate : rightTranslate;
findSwipeItem(0).setTranslate(0);
findSwipeItem(length.value - 1).setTranslate(0);
}
yield doubleRaf();
lockDuration.value = false;
});
}
function initialIndex() {
if (initializedIndex) {
return;
}
index.value = clampIndex(toNumber(props2.initialIndex));
initializedIndex = true;
}
function startAutoplay() {
const { autoplay } = props2;
if (!autoplay || length.value <= 1) {
return;
}
stopAutoplay();
timer = window.setTimeout(() => {
next();
startAutoplay();
}, toNumber(autoplay));
}
function stopAutoplay() {
timer && clearTimeout(timer);
}
function handleTouchstart(event) {
return __async(this, null, function* () {
if (length.value <= 1 || !props2.touchable) {
return;
}
startTouch(event);
stopAutoplay();
yield fixPosition();
lockDuration.value = true;
});
}
function handleTouchmove(event) {
const { touchable, vertical: vertical2 } = props2;
if (!touching.value || !touchable) {
return;
}
moveTouch(event);
if (!isExpectDirection.value) {
return;
}
preventDefault(event);
trackTranslate.value += vertical2 ? moveY.value : moveX.value;
dispatchSwipeItems();
}
function handleTouchend() {
if (!touching.value) {
return;
}
endTouch();
if (!isExpectDirection.value) {
return;
}
const { vertical: vertical2, onChange } = props2;
const positive = vertical2 ? deltaY.value < 0 : deltaX.value < 0;
const offset = vertical2 ? offsetY.value : offsetX.value;
const quickSwiping = performance.now() - startTime.value <= SWIPE_DELAY && offset >= SWIPE_OFFSET;
const swipeIndex = quickSwiping ? positive ? getSwipeIndex(index.value + 1) : getSwipeIndex(index.value - 1) : getSwipeIndex();
lockDuration.value = false;
trackTranslate.value = swipeIndex * -size.value;
const prevIndex = index.value;
index.value = swipeIndexToIndex(swipeIndex);
startAutoplay();
if (prevIndex !== index.value) {
call(onChange, index.value);
}
}
function handleHovering(value) {
if (props2.navigation === "hover") {
hovering.value = value;
}
}
function getNavigationAnimation(type) {
if (props2.navigation !== "hover") {
return "";
}
return n(`--navigation${props2.vertical ? "-vertical" : ""}-${type}-animation`);
}
function handleKeydown(event) {
if (!swipeItems.length) {
return;
}
const focusingSwipeItemIndex = swipeItems.findIndex(({ isFocusing }) => isFocusing.value);
if (focusingSwipeItemIndex === -1) {
return;
}
const { key } = event;
preventDefault(event);
if (key === "ArrowLeft") {
prev();
}
if (key === "ArrowRight") {
next();
}
}
function resize() {
if (!swipeEl.value) {
return;
}
lockDuration.value = true;
size.value = props2.vertical ? swipeEl.value.offsetHeight : swipeEl.value.offsetWidth;
trackSize.value = size.value * length.value;
trackTranslate.value = index.value * -size.value;
swipeItems.forEach((swipeItem) => {
swipeItem.setTranslate(0);
});
startAutoplay();
setTimeout(() => {
lockDuration.value = false;
});
swipeResizeListeners.forEach(({ onResize }) => {
onResize();
});
}
function next(options) {
return __async(this, null, function* () {
if (length.value <= 1) {
return;
}
initialIndex();
const { loop, onChange } = props2;
const currentIndex = index.value;
index.value = clampIndex(currentIndex + 1);
if ((options == null ? void 0 : options.event) !== false) {
call(onChange, index.value);
}
yield fixPosition();
if (currentIndex === length.value - 1 && loop) {
findSwipeItem(0).setTranslate(trackSize.value);
trackTranslate.value = length.value * -size.value;
return;
}
if (currentIndex !== length.value - 1) {
trackTranslate.value = index.value * -size.value;
}
});
}
function prev(options) {
return __async(this, null, function* () {
if (length.value <= 1) {
return;
}
initialIndex();
const { loop, onChange } = props2;
const currentIndex = index.value;
index.value = clampIndex(currentIndex - 1);
if ((options == null ? void 0 : options.event) !== false) {
call(onChange, index.value);
}
yield fixPosition();
if (currentIndex === 0 && loop) {
findSwipeItem(length.value - 1).setTranslate(-trackSize.value);
trackTranslate.value = size.value;
return;
}
if (currentIndex !== 0) {
trackTranslate.value = index.value * -size.value;
}
});
}
function to(idx, options) {
if (length.value <= 1 || idx === index.value) {
return;
}
idx = idx < 0 ? 0 : idx;
idx = idx >= length.value ? length.value : idx;
const task = idx > index.value ? next : prev;
const count = Math.abs(idx - index.value);
Array.from({ length: count }).forEach((_, index2) => {
task({ event: index2 === count - 1 ? options == null ? void 0 : options.event : false });
});
}
return {
length,
index,
swipeEl,
trackSize,
trackTranslate,
lockDuration,
hovering,
n,
toSizeUnit,
classes,
handleTouchstart,
handleTouchmove,
handleTouchend,
next,
prev,
to,
resize,
toNumber,
handleHovering,
getNavigationAnimation
};
}
});
__sfc__.render = __render__;
var stdin_default = __sfc__;
export {
stdin_default as default
};