@squirkle-ui/swiper 0.0.0-stage → 0.1.0

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.
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
+ const vue = require("vue");
4
+ const core = require("@squirkle-ui/core");
5
+ const ui = require("@squirkle-ui/ui/vue2");
6
+ const _sfc_main = vue.defineComponent({
7
+ name: "SqSwiper",
8
+ components: { SqBtn: ui.SqBtn, SqShape: ui.SqShape },
9
+ model: ui.vModel,
10
+ props: {
11
+ modelValue: { type: Number, default: 0 },
12
+ items: { type: Array, default: () => [] },
13
+ itemKey: { type: String, default: void 0 },
14
+ slidesPerView: { type: Number, default: 1 },
15
+ spaceBetween: { type: Number, default: 16 },
16
+ /** { 640: { slidesPerView: 2 }, 1024: { slidesPerView: 3 } } — keys are min container widths. */
17
+ breakpoints: { type: Object, default: void 0 },
18
+ effect: { type: String, default: "slide" },
19
+ loop: Boolean,
20
+ centered: Boolean,
21
+ vertical: Boolean,
22
+ /** Autoplay delay in ms; 0 disables. */
23
+ autoplay: { type: Number, default: 0 },
24
+ pauseOnHover: { type: Boolean, default: true },
25
+ speed: { type: Number, default: 420 },
26
+ navigation: { type: Boolean, default: true },
27
+ pagination: { type: [String, Boolean], default: "dots" },
28
+ height: { type: [Number, String], default: 320 },
29
+ rounded: { type: [String, Number], default: "xl" },
30
+ label: { type: String, default: "Carousel" }
31
+ },
32
+ emits: ["update:modelValue", "change"],
33
+ setup(props, { emit }) {
34
+ const model = ui.useProxiedModel(props, emit);
35
+ const root = vue.ref(null);
36
+ const size = vue.ref(800);
37
+ const drag = vue.ref(0);
38
+ const dragging = vue.ref(false);
39
+ const hovering = vue.ref(false);
40
+ const jumping = vue.ref(/* @__PURE__ */ new Set());
41
+ const list = vue.computed(() => props.items);
42
+ const n = vue.computed(() => list.value.length);
43
+ const keyOf = (item, i) => props.itemKey ? core.getByPath(item, props.itemKey) : i;
44
+ const responsive = vue.computed(() => {
45
+ let r = { slidesPerView: props.slidesPerView, spaceBetween: props.spaceBetween };
46
+ if (props.breakpoints) {
47
+ for (const bp of Object.keys(props.breakpoints).map(Number).sort((a, b) => a - b)) if (size.value >= bp) r = { ...r, ...props.breakpoints[bp] };
48
+ }
49
+ if (props.effect !== "slide") r = { ...r, slidesPerView: 1 };
50
+ return r;
51
+ });
52
+ const spv = vue.computed(() => Math.max(1, Math.min(responsive.value.slidesPerView, n.value || 1)));
53
+ const slideSize = vue.computed(() => (size.value - responsive.value.spaceBetween * (spv.value - 1)) / spv.value);
54
+ const step = vue.computed(() => slideSize.value + responsive.value.spaceBetween);
55
+ const maxIndex = vue.computed(() => props.loop || props.centered ? n.value - 1 : Math.max(0, n.value - spv.value));
56
+ const normIndex = vue.computed(() => n.value ? (model.value % n.value + n.value) % n.value : 0);
57
+ const pageCount = vue.computed(() => props.loop || props.centered ? n.value : maxIndex.value + 1);
58
+ const canPrev = vue.computed(() => props.loop || normIndex.value > 0);
59
+ const canNext = vue.computed(() => props.loop || normIndex.value < maxIndex.value);
60
+ const offsetOf = (i) => {
61
+ let o = i - normIndex.value;
62
+ if (props.loop && n.value > 1) {
63
+ const half = n.value / 2;
64
+ o = ((o + half) % n.value + n.value) % n.value - half;
65
+ }
66
+ return o;
67
+ };
68
+ const prevOffsets = /* @__PURE__ */ new Map();
69
+ vue.watch(normIndex, () => {
70
+ const jumps = /* @__PURE__ */ new Set();
71
+ for (let i = 0; i < n.value; i++) {
72
+ const o = offsetOf(i);
73
+ const was = prevOffsets.get(i);
74
+ if (was != null && Math.abs(o - was) > 1.5) jumps.add(i);
75
+ prevOffsets.set(i, o);
76
+ }
77
+ jumping.value = jumps;
78
+ requestAnimationFrame(() => requestAnimationFrame(() => jumping.value = /* @__PURE__ */ new Set()));
79
+ emit("change", normIndex.value);
80
+ });
81
+ const isVisible = (i) => {
82
+ const o = offsetOf(i);
83
+ return props.centered ? Math.abs(o) <= spv.value / 2 : o >= 0 && o < spv.value;
84
+ };
85
+ const slideStyle = (i) => {
86
+ const o = offsetOf(i);
87
+ const dragFrac = drag.value / step.value;
88
+ const pos = o + dragFrac;
89
+ const center = props.centered ? (size.value - slideSize.value) / 2 : 0;
90
+ const axis = props.vertical ? "Y" : "X";
91
+ const s = { [props.vertical ? "height" : "width"]: `${slideSize.value}px`, transitionDuration: dragging.value ? "0ms" : `${props.speed}ms` };
92
+ if (props.effect === "fade") {
93
+ s.opacity = String(Math.max(0, 1 - Math.abs(pos)));
94
+ s.zIndex = String(o === 0 ? 2 : 1);
95
+ } else if (props.effect === "coverflow") {
96
+ const x = (size.value - slideSize.value) / 2 + pos * slideSize.value * 0.62;
97
+ s.transform = `translate${axis}(${x}px) perspective(900px) rotateY(${Math.max(-1, Math.min(1, pos)) * -42}deg) scale(${1 - Math.min(1, Math.abs(pos)) * 0.18})`;
98
+ s.zIndex = String(100 - Math.round(Math.abs(pos) * 10));
99
+ s.opacity = Math.abs(pos) > 2.5 ? "0" : "1";
100
+ } else if (props.effect === "cards") {
101
+ const p = Math.max(-1, pos);
102
+ s.transform = p < 0 ? `translateX(${p * size.value}px) rotate(${p * 8}deg)` : `translateY(${Math.min(p, 3) * 14}px) scale(${1 - Math.min(p, 3) * 0.06})`;
103
+ s.zIndex = String(100 - Math.round(Math.abs(pos) * 10));
104
+ s.opacity = pos > 3 ? "0" : "1";
105
+ } else s.transform = `translate${axis}(${center + pos * step.value}px)`;
106
+ return s;
107
+ };
108
+ const goTo = (i) => {
109
+ if (!n.value) return;
110
+ if (props.loop) {
111
+ const target = (i % n.value + n.value) % n.value;
112
+ model.value = model.value + offsetOfTarget(target);
113
+ } else model.value = Math.max(0, Math.min(maxIndex.value, i));
114
+ };
115
+ const offsetOfTarget = (target) => {
116
+ let d = target - normIndex.value;
117
+ const half = n.value / 2;
118
+ d = ((d + half) % n.value + n.value) % n.value - half;
119
+ return d;
120
+ };
121
+ const next = () => canNext.value ? props.loop ? model.value = model.value + 1 : goTo(normIndex.value + 1) : props.autoplay && goTo(0);
122
+ const prev = () => canPrev.value && (props.loop ? model.value = model.value - 1 : goTo(normIndex.value - 1));
123
+ let start = 0;
124
+ let startT = 0;
125
+ const onMove = (e) => {
126
+ const d = (props.vertical ? e.clientY : e.clientX) - start;
127
+ const edge = !props.loop && (normIndex.value === 0 && d > 0 || normIndex.value >= maxIndex.value && d < 0);
128
+ drag.value = edge ? d * 0.3 : d;
129
+ };
130
+ const onUp = () => {
131
+ window.removeEventListener("pointermove", onMove);
132
+ window.removeEventListener("pointerup", onUp);
133
+ const d = drag.value;
134
+ const fast = Math.abs(d) > 30 && Date.now() - startT < 250;
135
+ const steps = Math.round(-d / step.value) || (fast ? -Math.sign(d) : 0);
136
+ dragging.value = false;
137
+ drag.value = 0;
138
+ if (steps) props.loop ? model.value = model.value + steps : goTo(normIndex.value + steps);
139
+ };
140
+ const onDown = (e) => {
141
+ if (e.button !== 0 || e.target.closest("button, a, input")) return;
142
+ start = props.vertical ? e.clientY : e.clientX;
143
+ startT = Date.now();
144
+ dragging.value = true;
145
+ window.addEventListener("pointermove", onMove);
146
+ window.addEventListener("pointerup", onUp);
147
+ };
148
+ let timer;
149
+ const restart = () => {
150
+ clearInterval(timer);
151
+ if (props.autoplay > 0) timer = setInterval(() => !(props.pauseOnHover && hovering.value) && !dragging.value && !document.hidden && next(), props.autoplay);
152
+ };
153
+ vue.watch(() => props.autoplay, restart);
154
+ let ro;
155
+ vue.onMounted(() => {
156
+ const measure = () => root.value && (size.value = props.vertical ? root.value.clientHeight : root.value.clientWidth);
157
+ measure();
158
+ if (typeof ResizeObserver !== "undefined" && root.value) {
159
+ ro = new ResizeObserver(measure);
160
+ ro.observe(root.value);
161
+ }
162
+ for (let i = 0; i < n.value; i++) prevOffsets.set(i, offsetOf(i));
163
+ restart();
164
+ });
165
+ vue.onBeforeUnmount(() => {
166
+ clearInterval(timer);
167
+ ro == null ? void 0 : ro.disconnect();
168
+ onUp();
169
+ });
170
+ const rootStyle = vue.computed(() => ({ height: typeof props.height === "number" ? `${props.height}px` : props.height, "--sq-r": ui.radiusValue(props.rounded), "--sq-bg": "var(--sq-surface-variant)" }));
171
+ return { root, list, keyOf, normIndex, pageCount, canPrev, canNext, slideStyle, isVisible, goTo, next, prev, onDown, dragging, hovering, jumping, rootStyle };
172
+ }
173
+ });
174
+ function normalizeComponent(scriptExports, render2, staticRenderFns, functionalTemplate, injectStyles, scopeId, moduleIdentifier, shadowMode) {
175
+ var options = typeof scriptExports === "function" ? scriptExports.options : scriptExports;
176
+ if (render2) {
177
+ options.render = render2;
178
+ options.staticRenderFns = staticRenderFns;
179
+ options._compiled = true;
180
+ }
181
+ return {
182
+ exports: scriptExports,
183
+ options
184
+ };
185
+ }
186
+ var _sfc_render = function render() {
187
+ var _vm = this, _c = _vm._self._c;
188
+ _vm._self._setupProxy;
189
+ return _c("div", { ref: "root", staticClass: "sq-swiper sq-surface", class: [`sq-swiper--${_vm.effect}`, { "sq-swiper--dragging": _vm.dragging, "sq-swiper--vertical": _vm.vertical }], style: _vm.rootStyle, attrs: { "role": "region", "aria-roledescription": "carousel", "aria-label": _vm.label, "tabindex": "0" }, on: { "keydown": [function($event) {
190
+ if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "left", 37, $event.key, ["Left", "ArrowLeft"])) return null;
191
+ if ("button" in $event && $event.button !== 0) return null;
192
+ $event.preventDefault();
193
+ !_vm.vertical && _vm.prev();
194
+ }, function($event) {
195
+ if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "right", 39, $event.key, ["Right", "ArrowRight"])) return null;
196
+ if ("button" in $event && $event.button !== 2) return null;
197
+ $event.preventDefault();
198
+ !_vm.vertical && _vm.next();
199
+ }, function($event) {
200
+ if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "up", 38, $event.key, ["Up", "ArrowUp"])) return null;
201
+ $event.preventDefault();
202
+ _vm.vertical && _vm.prev();
203
+ }, function($event) {
204
+ if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "down", 40, $event.key, ["Down", "ArrowDown"])) return null;
205
+ $event.preventDefault();
206
+ _vm.vertical && _vm.next();
207
+ }], "mouseenter": function($event) {
208
+ _vm.hovering = true;
209
+ }, "mouseleave": function($event) {
210
+ _vm.hovering = false;
211
+ } } }, [_c("SqShape", { attrs: { "clip": "" } }), _c("div", { staticClass: "sq-swiper__track", on: { "pointerdown": _vm.onDown } }, _vm._l(_vm.list, function(item, i) {
212
+ return _c("div", { key: _vm.keyOf(item, i), staticClass: "sq-swiper__slide", class: { "sq-swiper__slide--active": i === _vm.normIndex, "sq-swiper__slide--jump": _vm.jumping.has(i) }, style: _vm.slideStyle(i), attrs: { "role": "group", "aria-roledescription": "slide", "aria-label": `${i + 1} / ${_vm.list.length}`, "aria-hidden": _vm.isVisible(i) ? void 0 : "true" } }, [_vm._t("default", null, { "item": item, "index": i, "active": i === _vm.normIndex })], 2);
213
+ }), 0), _vm.navigation && _vm.list.length > 1 ? [_c("SqBtn", { staticClass: "sq-swiper__nav sq-swiper__nav--prev", attrs: { "icon": _vm.vertical ? "chevronUp" : "chevronLeft", "color": "surface", "variant": "elevated", "size": "small", "disabled": !_vm.canPrev, "aria-label": "Previous slide" }, on: { "click": _vm.prev } }), _c("SqBtn", { staticClass: "sq-swiper__nav sq-swiper__nav--next", attrs: { "icon": _vm.vertical ? "chevronDown" : "chevronRight", "color": "surface", "variant": "elevated", "size": "small", "disabled": !_vm.canNext, "aria-label": "Next slide" }, on: { "click": _vm.next } })] : _vm._e(), _vm.pagination === "dots" && _vm.pageCount > 1 ? _c("div", { staticClass: "sq-swiper__dots" }, _vm._l(_vm.pageCount, function(p) {
214
+ return _c("button", { key: p, staticClass: "sq-swiper__dot", class: { "sq-swiper__dot--active": p - 1 === _vm.normIndex }, attrs: { "type": "button", "aria-label": `Go to slide ${p}` }, on: { "click": function($event) {
215
+ return _vm.goTo(p - 1);
216
+ } } });
217
+ }), 0) : _vm.pagination === "fraction" ? _c("div", { staticClass: "sq-swiper__fraction" }, [_vm._v(_vm._s(_vm.normIndex + 1) + " / " + _vm._s(_vm.list.length))]) : _vm.pagination === "progress" ? _c("div", { staticClass: "sq-swiper__progress" }, [_c("div", { style: { width: (_vm.normIndex + 1) / Math.max(1, _vm.list.length) * 100 + "%" } })]) : _vm._e()], 2);
218
+ };
219
+ var _sfc_staticRenderFns = [];
220
+ var __component__ = /* @__PURE__ */ normalizeComponent(
221
+ _sfc_main,
222
+ _sfc_render,
223
+ _sfc_staticRenderFns
224
+ );
225
+ const SqSwiper = __component__.exports;
226
+ const componentNames = ["SqSwiper"];
227
+ exports.SqSwiper = SqSwiper;
228
+ exports.componentNames = componentNames;
229
+ exports.default = SqSwiper;
230
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../src/SqSwiper.vue","../../src/index.ts"],"sourcesContent":["<template>\n <div\n ref=\"root\"\n class=\"sq-swiper sq-surface\"\n :class=\"[`sq-swiper--${effect}`, { 'sq-swiper--dragging': dragging, 'sq-swiper--vertical': vertical }]\"\n :style=\"rootStyle\"\n role=\"region\"\n aria-roledescription=\"carousel\"\n :aria-label=\"label\"\n tabindex=\"0\"\n @keydown.left.prevent=\"!vertical && prev()\"\n @keydown.right.prevent=\"!vertical && next()\"\n @keydown.up.prevent=\"vertical && prev()\"\n @keydown.down.prevent=\"vertical && next()\"\n @mouseenter=\"hovering = true\"\n @mouseleave=\"hovering = false\"\n >\n <SqShape clip />\n <div class=\"sq-swiper__track\" @pointerdown=\"onDown\">\n <div\n v-for=\"(item, i) in list\"\n :key=\"keyOf(item, i)\"\n class=\"sq-swiper__slide\"\n :class=\"{ 'sq-swiper__slide--active': i === normIndex, 'sq-swiper__slide--jump': jumping.has(i) }\"\n :style=\"slideStyle(i)\"\n role=\"group\"\n aria-roledescription=\"slide\"\n :aria-label=\"`${i + 1} / ${list.length}`\"\n :aria-hidden=\"isVisible(i) ? undefined : 'true'\"\n >\n <slot :item=\"item\" :index=\"i\" :active=\"i === normIndex\" />\n </div>\n </div>\n <template v-if=\"navigation && list.length > 1\">\n <SqBtn class=\"sq-swiper__nav sq-swiper__nav--prev\" :icon=\"vertical ? 'chevronUp' : 'chevronLeft'\" color=\"surface\" variant=\"elevated\" size=\"small\" :disabled=\"!canPrev\" aria-label=\"Previous slide\" @click=\"prev\" />\n <SqBtn class=\"sq-swiper__nav sq-swiper__nav--next\" :icon=\"vertical ? 'chevronDown' : 'chevronRight'\" color=\"surface\" variant=\"elevated\" size=\"small\" :disabled=\"!canNext\" aria-label=\"Next slide\" @click=\"next\" />\n </template>\n <div v-if=\"pagination === 'dots' && pageCount > 1\" class=\"sq-swiper__dots\">\n <button v-for=\"p in pageCount\" :key=\"p\" type=\"button\" class=\"sq-swiper__dot\" :class=\"{ 'sq-swiper__dot--active': p - 1 === normIndex }\" :aria-label=\"`Go to slide ${p}`\" @click=\"goTo(p - 1)\"></button>\n </div>\n <div v-else-if=\"pagination === 'fraction'\" class=\"sq-swiper__fraction\">{{ normIndex + 1 }} / {{ list.length }}</div>\n <div v-else-if=\"pagination === 'progress'\" class=\"sq-swiper__progress\"><div :style=\"{ width: ((normIndex + 1) / Math.max(1, list.length)) * 100 + '%' }\"></div></div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, onBeforeUnmount, onMounted, ref, watch, type PropType } from 'vue'\nimport { getByPath } from '@squirkle-ui/core'\nimport { SqBtn, SqShape, radiusValue, useProxiedModel, vModel } from '@squirkle-ui/ui'\n\ntype Effect = 'slide' | 'fade' | 'coverflow' | 'cards'\ninterface Responsive { slidesPerView?: number; spaceBetween?: number }\n\n/**\n * Touch/mouse swiper. `loop` is a real infinite loop without cloned slides: every slide is positioned\n * at its wrapped offset from the active index, and slides that wrap around jump without animating.\n */\nexport default defineComponent({\n name: 'SqSwiper',\n components: { SqBtn, SqShape },\n model: vModel,\n props: {\n modelValue: { type: Number, default: 0 },\n items: { type: Array as PropType<unknown[]>, default: () => [] },\n itemKey: { type: String, default: undefined },\n slidesPerView: { type: Number, default: 1 },\n spaceBetween: { type: Number, default: 16 },\n /** { 640: { slidesPerView: 2 }, 1024: { slidesPerView: 3 } } — keys are min container widths. */\n breakpoints: { type: Object as PropType<Record<number, Responsive>>, default: undefined },\n effect: { type: String as PropType<Effect>, default: 'slide' },\n loop: Boolean,\n centered: Boolean,\n vertical: Boolean,\n /** Autoplay delay in ms; 0 disables. */\n autoplay: { type: Number, default: 0 },\n pauseOnHover: { type: Boolean, default: true },\n speed: { type: Number, default: 420 },\n navigation: { type: Boolean, default: true },\n pagination: { type: [String, Boolean] as PropType<'dots' | 'fraction' | 'progress' | false>, default: 'dots' },\n height: { type: [Number, String], default: 320 },\n rounded: { type: [String, Number], default: 'xl' },\n label: { type: String, default: 'Carousel' },\n },\n emits: ['update:modelValue', 'change'],\n setup(props, { emit }) {\n const model = useProxiedModel<number>(props, emit)\n const root = ref<HTMLElement | null>(null)\n const size = ref(800)\n const drag = ref(0)\n const dragging = ref(false)\n const hovering = ref(false)\n const jumping = ref(new Set<number>())\n const list = computed(() => props.items)\n const n = computed(() => list.value.length)\n const keyOf = (item: unknown, i: number) => (props.itemKey ? (getByPath(item, props.itemKey) as string) : i)\n\n const responsive = computed<Required<Responsive>>(() => {\n let r: Required<Responsive> = { slidesPerView: props.slidesPerView, spaceBetween: props.spaceBetween }\n if (props.breakpoints) for (const bp of Object.keys(props.breakpoints).map(Number).sort((a, b) => a - b)) if (size.value >= bp) r = { ...r, ...props.breakpoints[bp] }\n if (props.effect !== 'slide') r = { ...r, slidesPerView: 1 }\n return r\n })\n const spv = computed(() => Math.max(1, Math.min(responsive.value.slidesPerView, n.value || 1)))\n const slideSize = computed(() => (size.value - responsive.value.spaceBetween * (spv.value - 1)) / spv.value)\n const step = computed(() => slideSize.value + responsive.value.spaceBetween)\n const maxIndex = computed(() => (props.loop || props.centered ? n.value - 1 : Math.max(0, n.value - spv.value)))\n const normIndex = computed(() => (n.value ? ((model.value % n.value) + n.value) % n.value : 0))\n const pageCount = computed(() => (props.loop || props.centered ? n.value : maxIndex.value + 1))\n const canPrev = computed(() => props.loop || normIndex.value > 0)\n const canNext = computed(() => props.loop || normIndex.value < maxIndex.value)\n\n const offsetOf = (i: number) => {\n let o = i - normIndex.value\n if (props.loop && n.value > 1) {\n const half = n.value / 2\n o = ((((o + half) % n.value) + n.value) % n.value) - half\n }\n return o\n }\n const prevOffsets = new Map<number, number>()\n watch(normIndex, () => {\n const jumps = new Set<number>()\n for (let i = 0; i < n.value; i++) {\n const o = offsetOf(i)\n const was = prevOffsets.get(i)\n if (was != null && Math.abs(o - was) > 1.5) jumps.add(i)\n prevOffsets.set(i, o)\n }\n jumping.value = jumps\n requestAnimationFrame(() => requestAnimationFrame(() => (jumping.value = new Set())))\n emit('change', normIndex.value)\n })\n\n const isVisible = (i: number) => {\n const o = offsetOf(i)\n return props.centered ? Math.abs(o) <= spv.value / 2 : o >= 0 && o < spv.value\n }\n const slideStyle = (i: number) => {\n const o = offsetOf(i)\n const dragFrac = drag.value / step.value\n const pos = o + dragFrac\n const center = props.centered ? (size.value - slideSize.value) / 2 : 0\n const axis = props.vertical ? 'Y' : 'X'\n const s: Record<string, string> = { [props.vertical ? 'height' : 'width']: `${slideSize.value}px`, transitionDuration: dragging.value ? '0ms' : `${props.speed}ms` }\n if (props.effect === 'fade') {\n s.opacity = String(Math.max(0, 1 - Math.abs(pos)))\n s.zIndex = String(o === 0 ? 2 : 1)\n } else if (props.effect === 'coverflow') {\n const x = (size.value - slideSize.value) / 2 + pos * slideSize.value * 0.62\n s.transform = `translate${axis}(${x}px) perspective(900px) rotateY(${Math.max(-1, Math.min(1, pos)) * -42}deg) scale(${1 - Math.min(1, Math.abs(pos)) * 0.18})`\n s.zIndex = String(100 - Math.round(Math.abs(pos) * 10))\n s.opacity = Math.abs(pos) > 2.5 ? '0' : '1'\n } else if (props.effect === 'cards') {\n const p = Math.max(-1, pos)\n s.transform = p < 0 ? `translateX(${p * size.value}px) rotate(${p * 8}deg)` : `translateY(${Math.min(p, 3) * 14}px) scale(${1 - Math.min(p, 3) * 0.06})`\n s.zIndex = String(100 - Math.round(Math.abs(pos) * 10))\n s.opacity = pos > 3 ? '0' : '1'\n } else s.transform = `translate${axis}(${center + pos * step.value}px)`\n return s\n }\n\n const goTo = (i: number) => {\n if (!n.value) return\n if (props.loop) {\n const target = ((i % n.value) + n.value) % n.value\n model.value = model.value + offsetOfTarget(target)\n } else model.value = Math.max(0, Math.min(maxIndex.value, i))\n }\n const offsetOfTarget = (target: number) => {\n let d = target - normIndex.value\n const half = n.value / 2\n d = ((((d + half) % n.value) + n.value) % n.value) - half\n return d\n }\n const next = () => (canNext.value ? (props.loop ? (model.value = model.value + 1) : goTo(normIndex.value + 1)) : props.autoplay && goTo(0))\n const prev = () => canPrev.value && (props.loop ? (model.value = model.value - 1) : goTo(normIndex.value - 1))\n\n // drag\n let start = 0\n let startT = 0\n const onMove = (e: PointerEvent) => {\n const d = (props.vertical ? e.clientY : e.clientX) - start\n const edge = !props.loop && ((normIndex.value === 0 && d > 0) || (normIndex.value >= maxIndex.value && d < 0))\n drag.value = edge ? d * 0.3 : d\n }\n const onUp = () => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n const d = drag.value\n const fast = Math.abs(d) > 30 && Date.now() - startT < 250\n const steps = Math.round(-d / step.value) || (fast ? -Math.sign(d) : 0)\n dragging.value = false\n drag.value = 0\n if (steps) props.loop ? (model.value = model.value + steps) : goTo(normIndex.value + steps)\n }\n const onDown = (e: PointerEvent) => {\n if (e.button !== 0 || (e.target as HTMLElement).closest('button, a, input')) return\n start = props.vertical ? e.clientY : e.clientX\n startT = Date.now()\n dragging.value = true\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n }\n\n // autoplay\n let timer: ReturnType<typeof setInterval> | undefined\n const restart = () => {\n clearInterval(timer)\n if (props.autoplay > 0) timer = setInterval(() => !(props.pauseOnHover && hovering.value) && !dragging.value && !document.hidden && next(), props.autoplay)\n }\n watch(() => props.autoplay, restart)\n\n let ro: ResizeObserver | undefined\n onMounted(() => {\n const measure = () => root.value && (size.value = props.vertical ? root.value.clientHeight : root.value.clientWidth)\n measure()\n if (typeof ResizeObserver !== 'undefined' && root.value) { ro = new ResizeObserver(measure); ro.observe(root.value) }\n for (let i = 0; i < n.value; i++) prevOffsets.set(i, offsetOf(i))\n restart()\n })\n onBeforeUnmount(() => { clearInterval(timer); ro?.disconnect(); onUp() })\n\n const rootStyle = computed(() => ({ height: typeof props.height === 'number' ? `${props.height}px` : props.height, '--sq-r': radiusValue(props.rounded as string), '--sq-bg': 'var(--sq-surface-variant)' }))\n return { root, list, keyOf, normIndex, pageCount, canPrev, canNext, slideStyle, isVisible, goTo, next, prev, onDown, dragging, hovering, jumping, rootStyle }\n },\n})\n</script>\n\n<style>\n.sq-swiper { position: relative; overflow: hidden; outline: none; touch-action: pan-y; user-select: none; }\n.sq-swiper--vertical { touch-action: pan-x; }\n.sq-swiper:focus-visible { box-shadow: var(--sq-focus-ring); }\n.sq-swiper__track { position: relative; width: 100%; height: 100%; cursor: grab; }\n.sq-swiper--dragging .sq-swiper__track { cursor: grabbing; }\n.sq-swiper__slide { position: absolute; top: 0; left: 0; height: 100%; transition-property: transform, opacity; transition-timing-function: var(--sq-ease); will-change: transform; }\n.sq-swiper--vertical .sq-swiper__slide { width: 100%; height: auto; }\n.sq-swiper__slide--jump { transition: none !important; }\n.sq-swiper__slide > * { width: 100%; height: 100%; }\n.sq-swiper--fade .sq-swiper__slide, .sq-swiper--cards .sq-swiper__slide { width: 100% !important; }\n.sq-swiper--cards { overflow: visible; --sq-bg: transparent; }\n.sq-swiper__nav { position: absolute; top: 50%; z-index: 120; transform: translateY(-50%); }\n.sq-swiper__nav--prev { left: var(--sq-space-3); }\n.sq-swiper__nav--next { right: var(--sq-space-3); }\n.sq-swiper--vertical .sq-swiper__nav { left: 50%; top: auto; transform: translateX(-50%); }\n.sq-swiper--vertical .sq-swiper__nav--prev { top: var(--sq-space-3); }\n.sq-swiper--vertical .sq-swiper__nav--next { bottom: var(--sq-space-3); }\n.sq-swiper__dots { position: absolute; z-index: 120; left: 50%; bottom: var(--sq-space-3); transform: translateX(-50%); display: flex; gap: 6px; padding: 6px 8px; border-radius: var(--sq-radius-pill); background: color-mix(in srgb, var(--sq-overlay) 28%, transparent); backdrop-filter: blur(8px); }\n.sq-swiper__dot { width: 7px; height: 7px; padding: 0; border: 0; border-radius: var(--sq-radius-pill); background: rgb(255 255 255 / 0.55); cursor: pointer; transition: width var(--sq-duration) var(--sq-ease), background var(--sq-duration); }\n.sq-swiper__dot--active { width: 22px; background: #fff; }\n.sq-swiper__fraction { position: absolute; z-index: 120; right: var(--sq-space-3); bottom: var(--sq-space-3); padding: 2px 10px; border-radius: var(--sq-radius-pill); background: color-mix(in srgb, var(--sq-overlay) 45%, transparent); color: #fff; font-size: var(--sq-text-xs); font-weight: var(--sq-weight-semibold); }\n.sq-swiper__progress { position: absolute; z-index: 120; left: 0; right: 0; bottom: 0; height: 4px; background: color-mix(in srgb, var(--sq-overlay) 20%, transparent); }\n.sq-swiper__progress > div { height: 100%; background: var(--sq-primary); transition: width var(--sq-duration-slow) var(--sq-ease); }\n</style>\n","import SqSwiper from './SqSwiper.vue'\n\nexport { SqSwiper }\nexport const componentNames = ['SqSwiper'] as const\nexport default SqSwiper\n"],"names":["defineComponent","SqBtn","SqShape","vModel","useProxiedModel","ref","computed","getByPath","watch","onMounted","onBeforeUnmount","radiusValue"],"mappings":";;;;;AAyDA,MAAA,YAAAA,oBAAA;AAAA,EACA,MAAA;AAAA,EACA,YAAA,EAAA,OAAAC,GAAAA,OAAA,SAAAC,WAAA;AAAA,EACA,OAAAC,GAAAA;AAAAA,EACA,OAAA;AAAA,IACA,YAAA,EAAA,MAAA,QAAA,SAAA,EAAA;AAAA,IACA,OAAA,EAAA,MAAA,OAAA,SAAA,MAAA,CAAA,EAAA;AAAA,IACA,SAAA,EAAA,MAAA,QAAA,SAAA,OAAA;AAAA,IACA,eAAA,EAAA,MAAA,QAAA,SAAA,EAAA;AAAA,IACA,cAAA,EAAA,MAAA,QAAA,SAAA,GAAA;AAAA;AAAA,IAEA,aAAA,EAAA,MAAA,QAAA,SAAA,OAAA;AAAA,IACA,QAAA,EAAA,MAAA,QAAA,SAAA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA;AAAA,IACA,UAAA;AAAA;AAAA,IAEA,UAAA,EAAA,MAAA,QAAA,SAAA,EAAA;AAAA,IACA,cAAA,EAAA,MAAA,SAAA,SAAA,KAAA;AAAA,IACA,OAAA,EAAA,MAAA,QAAA,SAAA,IAAA;AAAA,IACA,YAAA,EAAA,MAAA,SAAA,SAAA,KAAA;AAAA,IACA,YAAA,EAAA,MAAA,CAAA,QAAA,OAAA,GAAA,SAAA,OAAA;AAAA,IACA,QAAA,EAAA,MAAA,CAAA,QAAA,MAAA,GAAA,SAAA,IAAA;AAAA,IACA,SAAA,EAAA,MAAA,CAAA,QAAA,MAAA,GAAA,SAAA,KAAA;AAAA,IACA,OAAA,EAAA,MAAA,QAAA,SAAA,WAAA;AAAA,EAAA;AAAA,EAEA,OAAA,CAAA,qBAAA,QAAA;AAAA,EACA,MAAA,OAAA,EAAA,QAAA;AACA,UAAA,QAAAC,GAAAA,gBAAA,OAAA,IAAA;AACA,UAAA,OAAAC,IAAAA,IAAA,IAAA;AACA,UAAA,OAAAA,IAAAA,IAAA,GAAA;AACA,UAAA,OAAAA,IAAAA,IAAA,CAAA;AACA,UAAA,WAAAA,IAAAA,IAAA,KAAA;AACA,UAAA,WAAAA,IAAAA,IAAA,KAAA;AACA,UAAA,UAAAA,IAAAA,IAAA,oBAAA,KAAA;AACA,UAAA,OAAAC,IAAAA,SAAA,MAAA,MAAA,KAAA;AACA,UAAA,IAAAA,IAAAA,SAAA,MAAA,KAAA,MAAA,MAAA;AACA,UAAA,QAAA,CAAA,MAAA,MAAA,MAAA,UAAAC,KAAAA,UAAA,MAAA,MAAA,OAAA,IAAA;AAEA,UAAA,aAAAD,IAAAA,SAAA,MAAA;AACA,UAAA,IAAA,EAAA,eAAA,MAAA,eAAA,cAAA,MAAA,aAAA;AACA,UAAA,MAAA,aAAA;AAAA,mBAAA,MAAA,OAAA,KAAA,MAAA,WAAA,EAAA,IAAA,MAAA,EAAA,KAAA,CAAA,GAAA,MAAA,IAAA,CAAA,EAAA,KAAA,KAAA,SAAA,GAAA,KAAA,EAAA,GAAA,GAAA,GAAA,MAAA,YAAA,EAAA,EAAA;AAAA,MAAA;AACA,UAAA,MAAA,WAAA,QAAA,KAAA,EAAA,GAAA,GAAA,eAAA,EAAA;AACA,aAAA;AAAA,IACA,CAAA;AACA,UAAA,MAAAA,IAAAA,SAAA,MAAA,KAAA,IAAA,GAAA,KAAA,IAAA,WAAA,MAAA,eAAA,EAAA,SAAA,CAAA,CAAA,CAAA;AACA,UAAA,YAAAA,IAAAA,SAAA,OAAA,KAAA,QAAA,WAAA,MAAA,gBAAA,IAAA,QAAA,MAAA,IAAA,KAAA;AACA,UAAA,OAAAA,IAAAA,SAAA,MAAA,UAAA,QAAA,WAAA,MAAA,YAAA;AACA,UAAA,WAAAA,IAAAA,SAAA,MAAA,MAAA,QAAA,MAAA,WAAA,EAAA,QAAA,IAAA,KAAA,IAAA,GAAA,EAAA,QAAA,IAAA,KAAA,CAAA;AACA,UAAA,YAAAA,IAAAA,SAAA,MAAA,EAAA,SAAA,MAAA,QAAA,EAAA,QAAA,EAAA,SAAA,EAAA,QAAA,CAAA;AACA,UAAA,YAAAA,IAAAA,SAAA,MAAA,MAAA,QAAA,MAAA,WAAA,EAAA,QAAA,SAAA,QAAA,CAAA;AACA,UAAA,UAAAA,IAAAA,SAAA,MAAA,MAAA,QAAA,UAAA,QAAA,CAAA;AACA,UAAA,UAAAA,IAAAA,SAAA,MAAA,MAAA,QAAA,UAAA,QAAA,SAAA,KAAA;AAEA,UAAA,WAAA,CAAA,MAAA;AACA,UAAA,IAAA,IAAA,UAAA;AACA,UAAA,MAAA,QAAA,EAAA,QAAA,GAAA;AACA,cAAA,OAAA,EAAA,QAAA;AACA,cAAA,IAAA,QAAA,EAAA,QAAA,EAAA,SAAA,EAAA,QAAA;AAAA,MACA;AACA,aAAA;AAAA,IACA;AACA,UAAA,kCAAA,IAAA;AACAE,QAAAA,MAAA,WAAA,MAAA;AACA,YAAA,4BAAA,IAAA;AACA,eAAA,IAAA,GAAA,IAAA,EAAA,OAAA,KAAA;AACA,cAAA,IAAA,SAAA,CAAA;AACA,cAAA,MAAA,YAAA,IAAA,CAAA;AACA,YAAA,OAAA,QAAA,KAAA,IAAA,IAAA,GAAA,IAAA,IAAA,OAAA,IAAA,CAAA;AACA,oBAAA,IAAA,GAAA,CAAA;AAAA,MACA;AACA,cAAA,QAAA;AACA,4BAAA,MAAA,sBAAA,MAAA,QAAA,QAAA,oBAAA,IAAA,CAAA,CAAA;AACA,WAAA,UAAA,UAAA,KAAA;AAAA,IACA,CAAA;AAEA,UAAA,YAAA,CAAA,MAAA;AACA,YAAA,IAAA,SAAA,CAAA;AACA,aAAA,MAAA,WAAA,KAAA,IAAA,CAAA,KAAA,IAAA,QAAA,IAAA,KAAA,KAAA,IAAA,IAAA;AAAA,IACA;AACA,UAAA,aAAA,CAAA,MAAA;AACA,YAAA,IAAA,SAAA,CAAA;AACA,YAAA,WAAA,KAAA,QAAA,KAAA;AACA,YAAA,MAAA,IAAA;AACA,YAAA,SAAA,MAAA,YAAA,KAAA,QAAA,UAAA,SAAA,IAAA;AACA,YAAA,OAAA,MAAA,WAAA,MAAA;AACA,YAAA,IAAA,EAAA,CAAA,MAAA,WAAA,WAAA,OAAA,GAAA,GAAA,UAAA,KAAA,MAAA,oBAAA,SAAA,QAAA,QAAA,GAAA,MAAA,KAAA,KAAA;AACA,UAAA,MAAA,WAAA,QAAA;AACA,UAAA,UAAA,OAAA,KAAA,IAAA,GAAA,IAAA,KAAA,IAAA,GAAA,CAAA,CAAA;AACA,UAAA,SAAA,OAAA,MAAA,IAAA,IAAA,CAAA;AAAA,MACA,WAAA,MAAA,WAAA,aAAA;AACA,cAAA,KAAA,KAAA,QAAA,UAAA,SAAA,IAAA,MAAA,UAAA,QAAA;AACA,UAAA,YAAA,YAAA,IAAA,IAAA,CAAA,kCAAA,KAAA,IAAA,IAAA,KAAA,IAAA,GAAA,GAAA,CAAA,IAAA,GAAA,cAAA,IAAA,KAAA,IAAA,GAAA,KAAA,IAAA,GAAA,CAAA,IAAA,IAAA;AACA,UAAA,SAAA,OAAA,MAAA,KAAA,MAAA,KAAA,IAAA,GAAA,IAAA,EAAA,CAAA;AACA,UAAA,UAAA,KAAA,IAAA,GAAA,IAAA,MAAA,MAAA;AAAA,MACA,WAAA,MAAA,WAAA,SAAA;AACA,cAAA,IAAA,KAAA,IAAA,IAAA,GAAA;AACA,UAAA,YAAA,IAAA,IAAA,cAAA,IAAA,KAAA,KAAA,cAAA,IAAA,CAAA,SAAA,cAAA,KAAA,IAAA,GAAA,CAAA,IAAA,EAAA,aAAA,IAAA,KAAA,IAAA,GAAA,CAAA,IAAA,IAAA;AACA,UAAA,SAAA,OAAA,MAAA,KAAA,MAAA,KAAA,IAAA,GAAA,IAAA,EAAA,CAAA;AACA,UAAA,UAAA,MAAA,IAAA,MAAA;AAAA,MACA,SAAA,YAAA,YAAA,IAAA,IAAA,SAAA,MAAA,KAAA,KAAA;AACA,aAAA;AAAA,IACA;AAEA,UAAA,OAAA,CAAA,MAAA;AACA,UAAA,CAAA,EAAA,MAAA;AACA,UAAA,MAAA,MAAA;AACA,cAAA,UAAA,IAAA,EAAA,QAAA,EAAA,SAAA,EAAA;AACA,cAAA,QAAA,MAAA,QAAA,eAAA,MAAA;AAAA,MACA,MAAA,OAAA,QAAA,KAAA,IAAA,GAAA,KAAA,IAAA,SAAA,OAAA,CAAA,CAAA;AAAA,IACA;AACA,UAAA,iBAAA,CAAA,WAAA;AACA,UAAA,IAAA,SAAA,UAAA;AACA,YAAA,OAAA,EAAA,QAAA;AACA,YAAA,IAAA,QAAA,EAAA,QAAA,EAAA,SAAA,EAAA,QAAA;AACA,aAAA;AAAA,IACA;AACA,UAAA,OAAA,MAAA,QAAA,QAAA,MAAA,OAAA,MAAA,QAAA,MAAA,QAAA,IAAA,KAAA,UAAA,QAAA,CAAA,IAAA,MAAA,YAAA,KAAA,CAAA;AACA,UAAA,OAAA,MAAA,QAAA,UAAA,MAAA,OAAA,MAAA,QAAA,MAAA,QAAA,IAAA,KAAA,UAAA,QAAA,CAAA;AAGA,QAAA,QAAA;AACA,QAAA,SAAA;AACA,UAAA,SAAA,CAAA,MAAA;AACA,YAAA,KAAA,MAAA,WAAA,EAAA,UAAA,EAAA,WAAA;AACA,YAAA,OAAA,CAAA,MAAA,SAAA,UAAA,UAAA,KAAA,IAAA,KAAA,UAAA,SAAA,SAAA,SAAA,IAAA;AACA,WAAA,QAAA,OAAA,IAAA,MAAA;AAAA,IACA;AACA,UAAA,OAAA,MAAA;AACA,aAAA,oBAAA,eAAA,MAAA;AACA,aAAA,oBAAA,aAAA,IAAA;AACA,YAAA,IAAA,KAAA;AACA,YAAA,OAAA,KAAA,IAAA,CAAA,IAAA,MAAA,KAAA,QAAA,SAAA;AACA,YAAA,QAAA,KAAA,MAAA,CAAA,IAAA,KAAA,KAAA,MAAA,OAAA,CAAA,KAAA,KAAA,CAAA,IAAA;AACA,eAAA,QAAA;AACA,WAAA,QAAA;AACA,UAAA,MAAA,OAAA,OAAA,MAAA,QAAA,MAAA,QAAA,QAAA,KAAA,UAAA,QAAA,KAAA;AAAA,IACA;AACA,UAAA,SAAA,CAAA,MAAA;AACA,UAAA,EAAA,WAAA,KAAA,EAAA,OAAA,QAAA,kBAAA,EAAA;AACA,cAAA,MAAA,WAAA,EAAA,UAAA,EAAA;AACA,eAAA,KAAA,IAAA;AACA,eAAA,QAAA;AACA,aAAA,iBAAA,eAAA,MAAA;AACA,aAAA,iBAAA,aAAA,IAAA;AAAA,IACA;AAGA,QAAA;AACA,UAAA,UAAA,MAAA;AACA,oBAAA,KAAA;AACA,UAAA,MAAA,WAAA,EAAA,SAAA,YAAA,MAAA,EAAA,MAAA,gBAAA,SAAA,UAAA,CAAA,SAAA,SAAA,CAAA,SAAA,UAAA,KAAA,GAAA,MAAA,QAAA;AAAA,IACA;AACAA,QAAAA,MAAA,MAAA,MAAA,UAAA,OAAA;AAEA,QAAA;AACAC,QAAAA,UAAA,MAAA;AACA,YAAA,UAAA,MAAA,KAAA,UAAA,KAAA,QAAA,MAAA,WAAA,KAAA,MAAA,eAAA,KAAA,MAAA;AACA,cAAA;AACA,UAAA,OAAA,mBAAA,eAAA,KAAA,OAAA;AAAA,aAAA,IAAA,eAAA,OAAA;AAAA,WAAA,QAAA,KAAA,KAAA;AAAA,MAAA;AACA,eAAA,IAAA,GAAA,IAAA,EAAA,OAAA,IAAA,aAAA,IAAA,GAAA,SAAA,CAAA,CAAA;AACA,cAAA;AAAA,IACA,CAAA;AACAC,QAAAA,gBAAA,MAAA;AAAA,oBAAA,KAAA;AAAA,+BAAA;AAAA,WAAA;AAAA,IAAA,CAAA;AAEA,UAAA,YAAAJ,aAAA,OAAA,EAAA,QAAA,OAAA,MAAA,WAAA,WAAA,GAAA,MAAA,MAAA,OAAA,MAAA,QAAA,UAAAK,GAAAA,YAAA,MAAA,OAAA,GAAA,WAAA,4BAAA,EAAA;AACA,WAAA,EAAA,MAAA,MAAA,OAAA,WAAA,WAAA,SAAA,SAAA,YAAA,WAAA,MAAA,MAAA,MAAA,QAAA,UAAA,UAAA,SAAA,UAAA;AAAA,EACA;AACA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC9NO,MAAM,iBAAiB,CAAC,UAAU;;;;"}
@@ -0,0 +1,230 @@
1
+ import { defineComponent, ref, computed, watch, onMounted, onBeforeUnmount } from "vue";
2
+ import { getByPath } from "@squirkle-ui/core";
3
+ import { vModel, SqShape, SqBtn, useProxiedModel, radiusValue } from "@squirkle-ui/ui/vue2";
4
+ const _sfc_main = defineComponent({
5
+ name: "SqSwiper",
6
+ components: { SqBtn, SqShape },
7
+ model: vModel,
8
+ props: {
9
+ modelValue: { type: Number, default: 0 },
10
+ items: { type: Array, default: () => [] },
11
+ itemKey: { type: String, default: void 0 },
12
+ slidesPerView: { type: Number, default: 1 },
13
+ spaceBetween: { type: Number, default: 16 },
14
+ /** { 640: { slidesPerView: 2 }, 1024: { slidesPerView: 3 } } — keys are min container widths. */
15
+ breakpoints: { type: Object, default: void 0 },
16
+ effect: { type: String, default: "slide" },
17
+ loop: Boolean,
18
+ centered: Boolean,
19
+ vertical: Boolean,
20
+ /** Autoplay delay in ms; 0 disables. */
21
+ autoplay: { type: Number, default: 0 },
22
+ pauseOnHover: { type: Boolean, default: true },
23
+ speed: { type: Number, default: 420 },
24
+ navigation: { type: Boolean, default: true },
25
+ pagination: { type: [String, Boolean], default: "dots" },
26
+ height: { type: [Number, String], default: 320 },
27
+ rounded: { type: [String, Number], default: "xl" },
28
+ label: { type: String, default: "Carousel" }
29
+ },
30
+ emits: ["update:modelValue", "change"],
31
+ setup(props, { emit }) {
32
+ const model = useProxiedModel(props, emit);
33
+ const root = ref(null);
34
+ const size = ref(800);
35
+ const drag = ref(0);
36
+ const dragging = ref(false);
37
+ const hovering = ref(false);
38
+ const jumping = ref(/* @__PURE__ */ new Set());
39
+ const list = computed(() => props.items);
40
+ const n = computed(() => list.value.length);
41
+ const keyOf = (item, i) => props.itemKey ? getByPath(item, props.itemKey) : i;
42
+ const responsive = computed(() => {
43
+ let r = { slidesPerView: props.slidesPerView, spaceBetween: props.spaceBetween };
44
+ if (props.breakpoints) {
45
+ for (const bp of Object.keys(props.breakpoints).map(Number).sort((a, b) => a - b)) if (size.value >= bp) r = { ...r, ...props.breakpoints[bp] };
46
+ }
47
+ if (props.effect !== "slide") r = { ...r, slidesPerView: 1 };
48
+ return r;
49
+ });
50
+ const spv = computed(() => Math.max(1, Math.min(responsive.value.slidesPerView, n.value || 1)));
51
+ const slideSize = computed(() => (size.value - responsive.value.spaceBetween * (spv.value - 1)) / spv.value);
52
+ const step = computed(() => slideSize.value + responsive.value.spaceBetween);
53
+ const maxIndex = computed(() => props.loop || props.centered ? n.value - 1 : Math.max(0, n.value - spv.value));
54
+ const normIndex = computed(() => n.value ? (model.value % n.value + n.value) % n.value : 0);
55
+ const pageCount = computed(() => props.loop || props.centered ? n.value : maxIndex.value + 1);
56
+ const canPrev = computed(() => props.loop || normIndex.value > 0);
57
+ const canNext = computed(() => props.loop || normIndex.value < maxIndex.value);
58
+ const offsetOf = (i) => {
59
+ let o = i - normIndex.value;
60
+ if (props.loop && n.value > 1) {
61
+ const half = n.value / 2;
62
+ o = ((o + half) % n.value + n.value) % n.value - half;
63
+ }
64
+ return o;
65
+ };
66
+ const prevOffsets = /* @__PURE__ */ new Map();
67
+ watch(normIndex, () => {
68
+ const jumps = /* @__PURE__ */ new Set();
69
+ for (let i = 0; i < n.value; i++) {
70
+ const o = offsetOf(i);
71
+ const was = prevOffsets.get(i);
72
+ if (was != null && Math.abs(o - was) > 1.5) jumps.add(i);
73
+ prevOffsets.set(i, o);
74
+ }
75
+ jumping.value = jumps;
76
+ requestAnimationFrame(() => requestAnimationFrame(() => jumping.value = /* @__PURE__ */ new Set()));
77
+ emit("change", normIndex.value);
78
+ });
79
+ const isVisible = (i) => {
80
+ const o = offsetOf(i);
81
+ return props.centered ? Math.abs(o) <= spv.value / 2 : o >= 0 && o < spv.value;
82
+ };
83
+ const slideStyle = (i) => {
84
+ const o = offsetOf(i);
85
+ const dragFrac = drag.value / step.value;
86
+ const pos = o + dragFrac;
87
+ const center = props.centered ? (size.value - slideSize.value) / 2 : 0;
88
+ const axis = props.vertical ? "Y" : "X";
89
+ const s = { [props.vertical ? "height" : "width"]: `${slideSize.value}px`, transitionDuration: dragging.value ? "0ms" : `${props.speed}ms` };
90
+ if (props.effect === "fade") {
91
+ s.opacity = String(Math.max(0, 1 - Math.abs(pos)));
92
+ s.zIndex = String(o === 0 ? 2 : 1);
93
+ } else if (props.effect === "coverflow") {
94
+ const x = (size.value - slideSize.value) / 2 + pos * slideSize.value * 0.62;
95
+ s.transform = `translate${axis}(${x}px) perspective(900px) rotateY(${Math.max(-1, Math.min(1, pos)) * -42}deg) scale(${1 - Math.min(1, Math.abs(pos)) * 0.18})`;
96
+ s.zIndex = String(100 - Math.round(Math.abs(pos) * 10));
97
+ s.opacity = Math.abs(pos) > 2.5 ? "0" : "1";
98
+ } else if (props.effect === "cards") {
99
+ const p = Math.max(-1, pos);
100
+ s.transform = p < 0 ? `translateX(${p * size.value}px) rotate(${p * 8}deg)` : `translateY(${Math.min(p, 3) * 14}px) scale(${1 - Math.min(p, 3) * 0.06})`;
101
+ s.zIndex = String(100 - Math.round(Math.abs(pos) * 10));
102
+ s.opacity = pos > 3 ? "0" : "1";
103
+ } else s.transform = `translate${axis}(${center + pos * step.value}px)`;
104
+ return s;
105
+ };
106
+ const goTo = (i) => {
107
+ if (!n.value) return;
108
+ if (props.loop) {
109
+ const target = (i % n.value + n.value) % n.value;
110
+ model.value = model.value + offsetOfTarget(target);
111
+ } else model.value = Math.max(0, Math.min(maxIndex.value, i));
112
+ };
113
+ const offsetOfTarget = (target) => {
114
+ let d = target - normIndex.value;
115
+ const half = n.value / 2;
116
+ d = ((d + half) % n.value + n.value) % n.value - half;
117
+ return d;
118
+ };
119
+ const next = () => canNext.value ? props.loop ? model.value = model.value + 1 : goTo(normIndex.value + 1) : props.autoplay && goTo(0);
120
+ const prev = () => canPrev.value && (props.loop ? model.value = model.value - 1 : goTo(normIndex.value - 1));
121
+ let start = 0;
122
+ let startT = 0;
123
+ const onMove = (e) => {
124
+ const d = (props.vertical ? e.clientY : e.clientX) - start;
125
+ const edge = !props.loop && (normIndex.value === 0 && d > 0 || normIndex.value >= maxIndex.value && d < 0);
126
+ drag.value = edge ? d * 0.3 : d;
127
+ };
128
+ const onUp = () => {
129
+ window.removeEventListener("pointermove", onMove);
130
+ window.removeEventListener("pointerup", onUp);
131
+ const d = drag.value;
132
+ const fast = Math.abs(d) > 30 && Date.now() - startT < 250;
133
+ const steps = Math.round(-d / step.value) || (fast ? -Math.sign(d) : 0);
134
+ dragging.value = false;
135
+ drag.value = 0;
136
+ if (steps) props.loop ? model.value = model.value + steps : goTo(normIndex.value + steps);
137
+ };
138
+ const onDown = (e) => {
139
+ if (e.button !== 0 || e.target.closest("button, a, input")) return;
140
+ start = props.vertical ? e.clientY : e.clientX;
141
+ startT = Date.now();
142
+ dragging.value = true;
143
+ window.addEventListener("pointermove", onMove);
144
+ window.addEventListener("pointerup", onUp);
145
+ };
146
+ let timer;
147
+ const restart = () => {
148
+ clearInterval(timer);
149
+ if (props.autoplay > 0) timer = setInterval(() => !(props.pauseOnHover && hovering.value) && !dragging.value && !document.hidden && next(), props.autoplay);
150
+ };
151
+ watch(() => props.autoplay, restart);
152
+ let ro;
153
+ onMounted(() => {
154
+ const measure = () => root.value && (size.value = props.vertical ? root.value.clientHeight : root.value.clientWidth);
155
+ measure();
156
+ if (typeof ResizeObserver !== "undefined" && root.value) {
157
+ ro = new ResizeObserver(measure);
158
+ ro.observe(root.value);
159
+ }
160
+ for (let i = 0; i < n.value; i++) prevOffsets.set(i, offsetOf(i));
161
+ restart();
162
+ });
163
+ onBeforeUnmount(() => {
164
+ clearInterval(timer);
165
+ ro == null ? void 0 : ro.disconnect();
166
+ onUp();
167
+ });
168
+ const rootStyle = computed(() => ({ height: typeof props.height === "number" ? `${props.height}px` : props.height, "--sq-r": radiusValue(props.rounded), "--sq-bg": "var(--sq-surface-variant)" }));
169
+ return { root, list, keyOf, normIndex, pageCount, canPrev, canNext, slideStyle, isVisible, goTo, next, prev, onDown, dragging, hovering, jumping, rootStyle };
170
+ }
171
+ });
172
+ function normalizeComponent(scriptExports, render2, staticRenderFns, functionalTemplate, injectStyles, scopeId, moduleIdentifier, shadowMode) {
173
+ var options = typeof scriptExports === "function" ? scriptExports.options : scriptExports;
174
+ if (render2) {
175
+ options.render = render2;
176
+ options.staticRenderFns = staticRenderFns;
177
+ options._compiled = true;
178
+ }
179
+ return {
180
+ exports: scriptExports,
181
+ options
182
+ };
183
+ }
184
+ var _sfc_render = function render() {
185
+ var _vm = this, _c = _vm._self._c;
186
+ _vm._self._setupProxy;
187
+ return _c("div", { ref: "root", staticClass: "sq-swiper sq-surface", class: [`sq-swiper--${_vm.effect}`, { "sq-swiper--dragging": _vm.dragging, "sq-swiper--vertical": _vm.vertical }], style: _vm.rootStyle, attrs: { "role": "region", "aria-roledescription": "carousel", "aria-label": _vm.label, "tabindex": "0" }, on: { "keydown": [function($event) {
188
+ if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "left", 37, $event.key, ["Left", "ArrowLeft"])) return null;
189
+ if ("button" in $event && $event.button !== 0) return null;
190
+ $event.preventDefault();
191
+ !_vm.vertical && _vm.prev();
192
+ }, function($event) {
193
+ if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "right", 39, $event.key, ["Right", "ArrowRight"])) return null;
194
+ if ("button" in $event && $event.button !== 2) return null;
195
+ $event.preventDefault();
196
+ !_vm.vertical && _vm.next();
197
+ }, function($event) {
198
+ if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "up", 38, $event.key, ["Up", "ArrowUp"])) return null;
199
+ $event.preventDefault();
200
+ _vm.vertical && _vm.prev();
201
+ }, function($event) {
202
+ if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "down", 40, $event.key, ["Down", "ArrowDown"])) return null;
203
+ $event.preventDefault();
204
+ _vm.vertical && _vm.next();
205
+ }], "mouseenter": function($event) {
206
+ _vm.hovering = true;
207
+ }, "mouseleave": function($event) {
208
+ _vm.hovering = false;
209
+ } } }, [_c("SqShape", { attrs: { "clip": "" } }), _c("div", { staticClass: "sq-swiper__track", on: { "pointerdown": _vm.onDown } }, _vm._l(_vm.list, function(item, i) {
210
+ return _c("div", { key: _vm.keyOf(item, i), staticClass: "sq-swiper__slide", class: { "sq-swiper__slide--active": i === _vm.normIndex, "sq-swiper__slide--jump": _vm.jumping.has(i) }, style: _vm.slideStyle(i), attrs: { "role": "group", "aria-roledescription": "slide", "aria-label": `${i + 1} / ${_vm.list.length}`, "aria-hidden": _vm.isVisible(i) ? void 0 : "true" } }, [_vm._t("default", null, { "item": item, "index": i, "active": i === _vm.normIndex })], 2);
211
+ }), 0), _vm.navigation && _vm.list.length > 1 ? [_c("SqBtn", { staticClass: "sq-swiper__nav sq-swiper__nav--prev", attrs: { "icon": _vm.vertical ? "chevronUp" : "chevronLeft", "color": "surface", "variant": "elevated", "size": "small", "disabled": !_vm.canPrev, "aria-label": "Previous slide" }, on: { "click": _vm.prev } }), _c("SqBtn", { staticClass: "sq-swiper__nav sq-swiper__nav--next", attrs: { "icon": _vm.vertical ? "chevronDown" : "chevronRight", "color": "surface", "variant": "elevated", "size": "small", "disabled": !_vm.canNext, "aria-label": "Next slide" }, on: { "click": _vm.next } })] : _vm._e(), _vm.pagination === "dots" && _vm.pageCount > 1 ? _c("div", { staticClass: "sq-swiper__dots" }, _vm._l(_vm.pageCount, function(p) {
212
+ return _c("button", { key: p, staticClass: "sq-swiper__dot", class: { "sq-swiper__dot--active": p - 1 === _vm.normIndex }, attrs: { "type": "button", "aria-label": `Go to slide ${p}` }, on: { "click": function($event) {
213
+ return _vm.goTo(p - 1);
214
+ } } });
215
+ }), 0) : _vm.pagination === "fraction" ? _c("div", { staticClass: "sq-swiper__fraction" }, [_vm._v(_vm._s(_vm.normIndex + 1) + " / " + _vm._s(_vm.list.length))]) : _vm.pagination === "progress" ? _c("div", { staticClass: "sq-swiper__progress" }, [_c("div", { style: { width: (_vm.normIndex + 1) / Math.max(1, _vm.list.length) * 100 + "%" } })]) : _vm._e()], 2);
216
+ };
217
+ var _sfc_staticRenderFns = [];
218
+ var __component__ = /* @__PURE__ */ normalizeComponent(
219
+ _sfc_main,
220
+ _sfc_render,
221
+ _sfc_staticRenderFns
222
+ );
223
+ const SqSwiper = __component__.exports;
224
+ const componentNames = ["SqSwiper"];
225
+ export {
226
+ SqSwiper,
227
+ componentNames,
228
+ SqSwiper as default
229
+ };
230
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/SqSwiper.vue","../../src/index.ts"],"sourcesContent":["<template>\n <div\n ref=\"root\"\n class=\"sq-swiper sq-surface\"\n :class=\"[`sq-swiper--${effect}`, { 'sq-swiper--dragging': dragging, 'sq-swiper--vertical': vertical }]\"\n :style=\"rootStyle\"\n role=\"region\"\n aria-roledescription=\"carousel\"\n :aria-label=\"label\"\n tabindex=\"0\"\n @keydown.left.prevent=\"!vertical && prev()\"\n @keydown.right.prevent=\"!vertical && next()\"\n @keydown.up.prevent=\"vertical && prev()\"\n @keydown.down.prevent=\"vertical && next()\"\n @mouseenter=\"hovering = true\"\n @mouseleave=\"hovering = false\"\n >\n <SqShape clip />\n <div class=\"sq-swiper__track\" @pointerdown=\"onDown\">\n <div\n v-for=\"(item, i) in list\"\n :key=\"keyOf(item, i)\"\n class=\"sq-swiper__slide\"\n :class=\"{ 'sq-swiper__slide--active': i === normIndex, 'sq-swiper__slide--jump': jumping.has(i) }\"\n :style=\"slideStyle(i)\"\n role=\"group\"\n aria-roledescription=\"slide\"\n :aria-label=\"`${i + 1} / ${list.length}`\"\n :aria-hidden=\"isVisible(i) ? undefined : 'true'\"\n >\n <slot :item=\"item\" :index=\"i\" :active=\"i === normIndex\" />\n </div>\n </div>\n <template v-if=\"navigation && list.length > 1\">\n <SqBtn class=\"sq-swiper__nav sq-swiper__nav--prev\" :icon=\"vertical ? 'chevronUp' : 'chevronLeft'\" color=\"surface\" variant=\"elevated\" size=\"small\" :disabled=\"!canPrev\" aria-label=\"Previous slide\" @click=\"prev\" />\n <SqBtn class=\"sq-swiper__nav sq-swiper__nav--next\" :icon=\"vertical ? 'chevronDown' : 'chevronRight'\" color=\"surface\" variant=\"elevated\" size=\"small\" :disabled=\"!canNext\" aria-label=\"Next slide\" @click=\"next\" />\n </template>\n <div v-if=\"pagination === 'dots' && pageCount > 1\" class=\"sq-swiper__dots\">\n <button v-for=\"p in pageCount\" :key=\"p\" type=\"button\" class=\"sq-swiper__dot\" :class=\"{ 'sq-swiper__dot--active': p - 1 === normIndex }\" :aria-label=\"`Go to slide ${p}`\" @click=\"goTo(p - 1)\"></button>\n </div>\n <div v-else-if=\"pagination === 'fraction'\" class=\"sq-swiper__fraction\">{{ normIndex + 1 }} / {{ list.length }}</div>\n <div v-else-if=\"pagination === 'progress'\" class=\"sq-swiper__progress\"><div :style=\"{ width: ((normIndex + 1) / Math.max(1, list.length)) * 100 + '%' }\"></div></div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, onBeforeUnmount, onMounted, ref, watch, type PropType } from 'vue'\nimport { getByPath } from '@squirkle-ui/core'\nimport { SqBtn, SqShape, radiusValue, useProxiedModel, vModel } from '@squirkle-ui/ui'\n\ntype Effect = 'slide' | 'fade' | 'coverflow' | 'cards'\ninterface Responsive { slidesPerView?: number; spaceBetween?: number }\n\n/**\n * Touch/mouse swiper. `loop` is a real infinite loop without cloned slides: every slide is positioned\n * at its wrapped offset from the active index, and slides that wrap around jump without animating.\n */\nexport default defineComponent({\n name: 'SqSwiper',\n components: { SqBtn, SqShape },\n model: vModel,\n props: {\n modelValue: { type: Number, default: 0 },\n items: { type: Array as PropType<unknown[]>, default: () => [] },\n itemKey: { type: String, default: undefined },\n slidesPerView: { type: Number, default: 1 },\n spaceBetween: { type: Number, default: 16 },\n /** { 640: { slidesPerView: 2 }, 1024: { slidesPerView: 3 } } — keys are min container widths. */\n breakpoints: { type: Object as PropType<Record<number, Responsive>>, default: undefined },\n effect: { type: String as PropType<Effect>, default: 'slide' },\n loop: Boolean,\n centered: Boolean,\n vertical: Boolean,\n /** Autoplay delay in ms; 0 disables. */\n autoplay: { type: Number, default: 0 },\n pauseOnHover: { type: Boolean, default: true },\n speed: { type: Number, default: 420 },\n navigation: { type: Boolean, default: true },\n pagination: { type: [String, Boolean] as PropType<'dots' | 'fraction' | 'progress' | false>, default: 'dots' },\n height: { type: [Number, String], default: 320 },\n rounded: { type: [String, Number], default: 'xl' },\n label: { type: String, default: 'Carousel' },\n },\n emits: ['update:modelValue', 'change'],\n setup(props, { emit }) {\n const model = useProxiedModel<number>(props, emit)\n const root = ref<HTMLElement | null>(null)\n const size = ref(800)\n const drag = ref(0)\n const dragging = ref(false)\n const hovering = ref(false)\n const jumping = ref(new Set<number>())\n const list = computed(() => props.items)\n const n = computed(() => list.value.length)\n const keyOf = (item: unknown, i: number) => (props.itemKey ? (getByPath(item, props.itemKey) as string) : i)\n\n const responsive = computed<Required<Responsive>>(() => {\n let r: Required<Responsive> = { slidesPerView: props.slidesPerView, spaceBetween: props.spaceBetween }\n if (props.breakpoints) for (const bp of Object.keys(props.breakpoints).map(Number).sort((a, b) => a - b)) if (size.value >= bp) r = { ...r, ...props.breakpoints[bp] }\n if (props.effect !== 'slide') r = { ...r, slidesPerView: 1 }\n return r\n })\n const spv = computed(() => Math.max(1, Math.min(responsive.value.slidesPerView, n.value || 1)))\n const slideSize = computed(() => (size.value - responsive.value.spaceBetween * (spv.value - 1)) / spv.value)\n const step = computed(() => slideSize.value + responsive.value.spaceBetween)\n const maxIndex = computed(() => (props.loop || props.centered ? n.value - 1 : Math.max(0, n.value - spv.value)))\n const normIndex = computed(() => (n.value ? ((model.value % n.value) + n.value) % n.value : 0))\n const pageCount = computed(() => (props.loop || props.centered ? n.value : maxIndex.value + 1))\n const canPrev = computed(() => props.loop || normIndex.value > 0)\n const canNext = computed(() => props.loop || normIndex.value < maxIndex.value)\n\n const offsetOf = (i: number) => {\n let o = i - normIndex.value\n if (props.loop && n.value > 1) {\n const half = n.value / 2\n o = ((((o + half) % n.value) + n.value) % n.value) - half\n }\n return o\n }\n const prevOffsets = new Map<number, number>()\n watch(normIndex, () => {\n const jumps = new Set<number>()\n for (let i = 0; i < n.value; i++) {\n const o = offsetOf(i)\n const was = prevOffsets.get(i)\n if (was != null && Math.abs(o - was) > 1.5) jumps.add(i)\n prevOffsets.set(i, o)\n }\n jumping.value = jumps\n requestAnimationFrame(() => requestAnimationFrame(() => (jumping.value = new Set())))\n emit('change', normIndex.value)\n })\n\n const isVisible = (i: number) => {\n const o = offsetOf(i)\n return props.centered ? Math.abs(o) <= spv.value / 2 : o >= 0 && o < spv.value\n }\n const slideStyle = (i: number) => {\n const o = offsetOf(i)\n const dragFrac = drag.value / step.value\n const pos = o + dragFrac\n const center = props.centered ? (size.value - slideSize.value) / 2 : 0\n const axis = props.vertical ? 'Y' : 'X'\n const s: Record<string, string> = { [props.vertical ? 'height' : 'width']: `${slideSize.value}px`, transitionDuration: dragging.value ? '0ms' : `${props.speed}ms` }\n if (props.effect === 'fade') {\n s.opacity = String(Math.max(0, 1 - Math.abs(pos)))\n s.zIndex = String(o === 0 ? 2 : 1)\n } else if (props.effect === 'coverflow') {\n const x = (size.value - slideSize.value) / 2 + pos * slideSize.value * 0.62\n s.transform = `translate${axis}(${x}px) perspective(900px) rotateY(${Math.max(-1, Math.min(1, pos)) * -42}deg) scale(${1 - Math.min(1, Math.abs(pos)) * 0.18})`\n s.zIndex = String(100 - Math.round(Math.abs(pos) * 10))\n s.opacity = Math.abs(pos) > 2.5 ? '0' : '1'\n } else if (props.effect === 'cards') {\n const p = Math.max(-1, pos)\n s.transform = p < 0 ? `translateX(${p * size.value}px) rotate(${p * 8}deg)` : `translateY(${Math.min(p, 3) * 14}px) scale(${1 - Math.min(p, 3) * 0.06})`\n s.zIndex = String(100 - Math.round(Math.abs(pos) * 10))\n s.opacity = pos > 3 ? '0' : '1'\n } else s.transform = `translate${axis}(${center + pos * step.value}px)`\n return s\n }\n\n const goTo = (i: number) => {\n if (!n.value) return\n if (props.loop) {\n const target = ((i % n.value) + n.value) % n.value\n model.value = model.value + offsetOfTarget(target)\n } else model.value = Math.max(0, Math.min(maxIndex.value, i))\n }\n const offsetOfTarget = (target: number) => {\n let d = target - normIndex.value\n const half = n.value / 2\n d = ((((d + half) % n.value) + n.value) % n.value) - half\n return d\n }\n const next = () => (canNext.value ? (props.loop ? (model.value = model.value + 1) : goTo(normIndex.value + 1)) : props.autoplay && goTo(0))\n const prev = () => canPrev.value && (props.loop ? (model.value = model.value - 1) : goTo(normIndex.value - 1))\n\n // drag\n let start = 0\n let startT = 0\n const onMove = (e: PointerEvent) => {\n const d = (props.vertical ? e.clientY : e.clientX) - start\n const edge = !props.loop && ((normIndex.value === 0 && d > 0) || (normIndex.value >= maxIndex.value && d < 0))\n drag.value = edge ? d * 0.3 : d\n }\n const onUp = () => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n const d = drag.value\n const fast = Math.abs(d) > 30 && Date.now() - startT < 250\n const steps = Math.round(-d / step.value) || (fast ? -Math.sign(d) : 0)\n dragging.value = false\n drag.value = 0\n if (steps) props.loop ? (model.value = model.value + steps) : goTo(normIndex.value + steps)\n }\n const onDown = (e: PointerEvent) => {\n if (e.button !== 0 || (e.target as HTMLElement).closest('button, a, input')) return\n start = props.vertical ? e.clientY : e.clientX\n startT = Date.now()\n dragging.value = true\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n }\n\n // autoplay\n let timer: ReturnType<typeof setInterval> | undefined\n const restart = () => {\n clearInterval(timer)\n if (props.autoplay > 0) timer = setInterval(() => !(props.pauseOnHover && hovering.value) && !dragging.value && !document.hidden && next(), props.autoplay)\n }\n watch(() => props.autoplay, restart)\n\n let ro: ResizeObserver | undefined\n onMounted(() => {\n const measure = () => root.value && (size.value = props.vertical ? root.value.clientHeight : root.value.clientWidth)\n measure()\n if (typeof ResizeObserver !== 'undefined' && root.value) { ro = new ResizeObserver(measure); ro.observe(root.value) }\n for (let i = 0; i < n.value; i++) prevOffsets.set(i, offsetOf(i))\n restart()\n })\n onBeforeUnmount(() => { clearInterval(timer); ro?.disconnect(); onUp() })\n\n const rootStyle = computed(() => ({ height: typeof props.height === 'number' ? `${props.height}px` : props.height, '--sq-r': radiusValue(props.rounded as string), '--sq-bg': 'var(--sq-surface-variant)' }))\n return { root, list, keyOf, normIndex, pageCount, canPrev, canNext, slideStyle, isVisible, goTo, next, prev, onDown, dragging, hovering, jumping, rootStyle }\n },\n})\n</script>\n\n<style>\n.sq-swiper { position: relative; overflow: hidden; outline: none; touch-action: pan-y; user-select: none; }\n.sq-swiper--vertical { touch-action: pan-x; }\n.sq-swiper:focus-visible { box-shadow: var(--sq-focus-ring); }\n.sq-swiper__track { position: relative; width: 100%; height: 100%; cursor: grab; }\n.sq-swiper--dragging .sq-swiper__track { cursor: grabbing; }\n.sq-swiper__slide { position: absolute; top: 0; left: 0; height: 100%; transition-property: transform, opacity; transition-timing-function: var(--sq-ease); will-change: transform; }\n.sq-swiper--vertical .sq-swiper__slide { width: 100%; height: auto; }\n.sq-swiper__slide--jump { transition: none !important; }\n.sq-swiper__slide > * { width: 100%; height: 100%; }\n.sq-swiper--fade .sq-swiper__slide, .sq-swiper--cards .sq-swiper__slide { width: 100% !important; }\n.sq-swiper--cards { overflow: visible; --sq-bg: transparent; }\n.sq-swiper__nav { position: absolute; top: 50%; z-index: 120; transform: translateY(-50%); }\n.sq-swiper__nav--prev { left: var(--sq-space-3); }\n.sq-swiper__nav--next { right: var(--sq-space-3); }\n.sq-swiper--vertical .sq-swiper__nav { left: 50%; top: auto; transform: translateX(-50%); }\n.sq-swiper--vertical .sq-swiper__nav--prev { top: var(--sq-space-3); }\n.sq-swiper--vertical .sq-swiper__nav--next { bottom: var(--sq-space-3); }\n.sq-swiper__dots { position: absolute; z-index: 120; left: 50%; bottom: var(--sq-space-3); transform: translateX(-50%); display: flex; gap: 6px; padding: 6px 8px; border-radius: var(--sq-radius-pill); background: color-mix(in srgb, var(--sq-overlay) 28%, transparent); backdrop-filter: blur(8px); }\n.sq-swiper__dot { width: 7px; height: 7px; padding: 0; border: 0; border-radius: var(--sq-radius-pill); background: rgb(255 255 255 / 0.55); cursor: pointer; transition: width var(--sq-duration) var(--sq-ease), background var(--sq-duration); }\n.sq-swiper__dot--active { width: 22px; background: #fff; }\n.sq-swiper__fraction { position: absolute; z-index: 120; right: var(--sq-space-3); bottom: var(--sq-space-3); padding: 2px 10px; border-radius: var(--sq-radius-pill); background: color-mix(in srgb, var(--sq-overlay) 45%, transparent); color: #fff; font-size: var(--sq-text-xs); font-weight: var(--sq-weight-semibold); }\n.sq-swiper__progress { position: absolute; z-index: 120; left: 0; right: 0; bottom: 0; height: 4px; background: color-mix(in srgb, var(--sq-overlay) 20%, transparent); }\n.sq-swiper__progress > div { height: 100%; background: var(--sq-primary); transition: width var(--sq-duration-slow) var(--sq-ease); }\n</style>\n","import SqSwiper from './SqSwiper.vue'\n\nexport { SqSwiper }\nexport const componentNames = ['SqSwiper'] as const\nexport default SqSwiper\n"],"names":[],"mappings":"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"}