@kiva/kv-components 4.6.0 → 4.7.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.
- package/CHANGELOG.md +11 -0
- package/dist/components/KvVerticalCarousel.vue +63 -17
- package/dist/components/stories/KvCarousel.stories.js +8 -23
- package/dist/components/stories/KvVerticalCarousel.stories.js +9 -23
- package/dist/utils/carousels.cjs +19 -11
- package/dist/utils/carousels.js +1 -1
- package/dist/utils/{chunk-P6FXCNYP.js → chunk-WLQNGWMC.js} +19 -11
- package/dist/utils/index.cjs +19 -11
- package/dist/utils/index.js +1 -1
- package/package.json +2 -2
- package/utils/carousels.js +31 -11
- package/vue/KvVerticalCarousel.vue +63 -17
- package/vue/stories/KvCarousel.stories.js +8 -23
- package/vue/stories/KvVerticalCarousel.stories.js +9 -23
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [4.7.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@4.6.0...@kiva/kv-components@4.7.0) (2025-01-09)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* add autoplay button if autoplay plugin is enabled ([8bebbe5](https://github.com/kiva/kv-ui-elements/commit/8bebbe5945dd4e34c922f9f511a4145564ae005a))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
# [4.6.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@4.5.1...@kiva/kv-components@4.6.0) (2025-01-08)
|
|
7
18
|
|
|
8
19
|
|
|
@@ -29,40 +29,69 @@
|
|
|
29
29
|
<!-- Carousel Controls -->
|
|
30
30
|
<div
|
|
31
31
|
class="kv-carousel__controls tw-flex
|
|
32
|
-
tw-
|
|
33
|
-
tw-mt-2 tw-w-full
|
|
32
|
+
tw-items-center tw-gap-2
|
|
33
|
+
tw-mt-2 tw-w-full
|
|
34
|
+
tw-justify-between md:tw-justify-center"
|
|
34
35
|
>
|
|
35
|
-
<
|
|
36
|
-
class="tw-
|
|
36
|
+
<div
|
|
37
|
+
class="tw-flex tw-gap-2 tw-w-full md:tw-w-auto"
|
|
38
|
+
:class="{'tw-justify-between md:tw-justify-center': !hasAutoplay}"
|
|
39
|
+
>
|
|
40
|
+
<button
|
|
41
|
+
class="tw-text-primary
|
|
37
42
|
tw-rounded-full
|
|
38
43
|
tw-border-2 tw-border-primary
|
|
39
44
|
tw-h-4 tw-w-4
|
|
40
45
|
tw-flex tw-items-center tw-justify-center
|
|
41
46
|
disabled:tw-opacity-low disabled:tw-cursor-default"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
:disabled="embla && !embla.canScrollPrev()"
|
|
48
|
+
@click="handleUserInteraction(previousIndex, 'click-left-arrow')"
|
|
49
|
+
>
|
|
50
|
+
<kv-material-icon
|
|
51
|
+
class="tw-w-4"
|
|
52
|
+
:icon="mdiChevronUp"
|
|
53
|
+
/>
|
|
54
|
+
<span class="tw-sr-only">Show previous slide</span>
|
|
55
|
+
</button>
|
|
56
|
+
<button
|
|
57
|
+
class="tw-text-primary
|
|
58
|
+
tw-rounded-full
|
|
59
|
+
tw-border-2 tw-border-primary
|
|
60
|
+
tw-h-4 tw-w-4
|
|
61
|
+
tw-flex tw-items-center tw-justify-center
|
|
62
|
+
disabled:tw-opacity-low disabled:tw-cursor-default"
|
|
63
|
+
:disabled="embla && !embla.canScrollNext()"
|
|
64
|
+
@click="handleUserInteraction(nextIndex, 'click-right-arrow')"
|
|
65
|
+
>
|
|
66
|
+
<kv-material-icon
|
|
67
|
+
class="tw-w-4"
|
|
68
|
+
:icon="mdiChevronDown"
|
|
69
|
+
/>
|
|
70
|
+
<span class="tw-sr-only">Show next slide</span>
|
|
71
|
+
</button>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
51
74
|
<button
|
|
75
|
+
v-if="hasAutoplay"
|
|
52
76
|
class="tw-text-primary
|
|
53
77
|
tw-rounded-full
|
|
54
78
|
tw-border-2 tw-border-primary
|
|
55
79
|
tw-h-4 tw-w-4
|
|
56
80
|
tw-flex tw-items-center tw-justify-center
|
|
57
81
|
disabled:tw-opacity-low disabled:tw-cursor-default"
|
|
58
|
-
|
|
59
|
-
@click="handleUserInteraction(nextIndex, 'click-right-arrow')"
|
|
82
|
+
@click.native.prevent="toggleAutoPlay()"
|
|
60
83
|
>
|
|
61
84
|
<kv-material-icon
|
|
85
|
+
v-if="isAutoplaying"
|
|
62
86
|
class="tw-w-4"
|
|
63
|
-
:icon="
|
|
87
|
+
:icon="mdiPause"
|
|
64
88
|
/>
|
|
65
|
-
<
|
|
89
|
+
<kv-material-icon
|
|
90
|
+
v-else
|
|
91
|
+
class="tw-w-4"
|
|
92
|
+
:icon="mdiPlay"
|
|
93
|
+
/>
|
|
94
|
+
<span class="tw-sr-only">Show previous slide</span>
|
|
66
95
|
</button>
|
|
67
96
|
</div>
|
|
68
97
|
</div>
|
|
@@ -70,9 +99,15 @@
|
|
|
70
99
|
|
|
71
100
|
<script>
|
|
72
101
|
import {
|
|
102
|
+
toRefs,
|
|
103
|
+
} from 'vue-demi';
|
|
104
|
+
import {
|
|
105
|
+
mdiPause,
|
|
106
|
+
mdiPlay,
|
|
73
107
|
mdiChevronUp,
|
|
74
108
|
mdiChevronDown,
|
|
75
109
|
} from '@mdi/js';
|
|
110
|
+
import { computed } from 'vue';
|
|
76
111
|
import { carouselUtil } from '../utils/carousels';
|
|
77
112
|
import KvMaterialIcon from './KvMaterialIcon.vue';
|
|
78
113
|
|
|
@@ -129,6 +164,10 @@ export default {
|
|
|
129
164
|
'interact-carousel',
|
|
130
165
|
],
|
|
131
166
|
setup(props, { emit, slots }) {
|
|
167
|
+
const {
|
|
168
|
+
autoplayOptions,
|
|
169
|
+
} = toRefs(props);
|
|
170
|
+
|
|
132
171
|
const {
|
|
133
172
|
componentSlotKeys,
|
|
134
173
|
currentIndex,
|
|
@@ -148,7 +187,12 @@ export default {
|
|
|
148
187
|
toggleAutoPlay,
|
|
149
188
|
} = carouselUtil(props, { emit, slots }, { axis: 'y' });
|
|
150
189
|
|
|
190
|
+
const hasAutoplay = computed(() => {
|
|
191
|
+
return Object.keys(autoplayOptions.value).length !== 0;
|
|
192
|
+
});
|
|
193
|
+
|
|
151
194
|
return {
|
|
195
|
+
hasAutoplay,
|
|
152
196
|
componentSlotKeys,
|
|
153
197
|
currentIndex,
|
|
154
198
|
embla,
|
|
@@ -156,6 +200,8 @@ export default {
|
|
|
156
200
|
handleUserInteraction,
|
|
157
201
|
isAriaHidden,
|
|
158
202
|
isAutoplaying,
|
|
203
|
+
mdiPause,
|
|
204
|
+
mdiPlay,
|
|
159
205
|
mdiChevronDown,
|
|
160
206
|
mdiChevronUp,
|
|
161
207
|
nextIndex,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { watch } from 'vue';
|
|
1
2
|
import KvCarousel from '../KvCarousel.vue';
|
|
2
3
|
import KvLoadingSpinner from '../KvLoadingSpinner.vue';
|
|
3
4
|
import KvButton from '../KvButton.vue';
|
|
@@ -444,14 +445,12 @@ export const AutoPlayButton = () => ({
|
|
|
444
445
|
components: {
|
|
445
446
|
KvCarousel,
|
|
446
447
|
},
|
|
447
|
-
data() {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
};
|
|
451
|
-
},
|
|
448
|
+
data: () => ({
|
|
449
|
+
isAutoplaying: false,
|
|
450
|
+
}),
|
|
452
451
|
mounted() {
|
|
453
|
-
this.$
|
|
454
|
-
this.
|
|
452
|
+
watch(() => this.$refs?.sampleCarousel?.isAutoplaying, (newValue) => {
|
|
453
|
+
this.isAutoplaying = newValue;
|
|
455
454
|
});
|
|
456
455
|
},
|
|
457
456
|
template: `
|
|
@@ -461,34 +460,20 @@ export const AutoPlayButton = () => ({
|
|
|
461
460
|
style="max-width: 400px;"
|
|
462
461
|
:embla-options="{ loop: false }"
|
|
463
462
|
:autoplay-options="{ playOnInit: true, delay: 3000 }"
|
|
464
|
-
@interact-carousel="carouselInteraction"
|
|
465
463
|
>
|
|
466
464
|
${defaultCarouselSlides}
|
|
467
465
|
</kv-carousel>
|
|
468
|
-
<a href="#" @click.native.prevent="toggleAutoPlay()" role="toggleAutoPlayButton">Toggle AutoPlay</a>
|
|
466
|
+
<a href="#" @click.native.prevent="$refs.sampleCarousel.toggleAutoPlay()" role="toggleAutoPlayButton">Toggle AutoPlay</a>
|
|
469
467
|
<br/>
|
|
470
|
-
<p>AutoPlay is: {{
|
|
468
|
+
<p>AutoPlay is: {{ isAutoplaying ? 'ON' : 'OFF' }}</p>
|
|
471
469
|
</div>
|
|
472
470
|
`,
|
|
473
|
-
methods: {
|
|
474
|
-
toggleAutoPlay() {
|
|
475
|
-
this.$refs.sampleCarousel.toggleAutoPlay();
|
|
476
|
-
},
|
|
477
|
-
carouselInteraction() {
|
|
478
|
-
this.isPlaying = this.$refs.sampleCarousel.isAutoplaying();
|
|
479
|
-
},
|
|
480
|
-
},
|
|
481
471
|
});
|
|
482
472
|
|
|
483
473
|
export const Fade = () => ({
|
|
484
474
|
components: {
|
|
485
475
|
KvCarousel,
|
|
486
476
|
},
|
|
487
|
-
mounted() {
|
|
488
|
-
this.$nextTick(() => {
|
|
489
|
-
this.isPlaying = this.$refs.sampleCarousel.isAutoplaying();
|
|
490
|
-
});
|
|
491
|
-
},
|
|
492
477
|
template: `
|
|
493
478
|
<div>
|
|
494
479
|
<kv-carousel
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { watch } from 'vue';
|
|
1
2
|
import KvVerticalCarousel from '../KvVerticalCarousel.vue';
|
|
2
3
|
import KvButton from '../KvButton.vue';
|
|
3
4
|
|
|
@@ -186,14 +187,12 @@ export const AutoPlayButton = () => ({
|
|
|
186
187
|
components: {
|
|
187
188
|
KvVerticalCarousel,
|
|
188
189
|
},
|
|
189
|
-
data() {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
};
|
|
193
|
-
},
|
|
190
|
+
data: () => ({
|
|
191
|
+
isAutoplaying: false,
|
|
192
|
+
}),
|
|
194
193
|
mounted() {
|
|
195
|
-
this.$
|
|
196
|
-
this.
|
|
194
|
+
watch(() => this.$refs?.sampleCarousel?.isAutoplaying, (newValue) => {
|
|
195
|
+
this.isAutoplaying = newValue;
|
|
197
196
|
});
|
|
198
197
|
},
|
|
199
198
|
template: `
|
|
@@ -203,34 +202,21 @@ export const AutoPlayButton = () => ({
|
|
|
203
202
|
style="max-width: 400px;"
|
|
204
203
|
:embla-options="{ loop: false }"
|
|
205
204
|
:autoplay-options="{ playOnInit: true, delay: 3000 }"
|
|
206
|
-
@interact-carousel="carouselInteraction"
|
|
207
205
|
>
|
|
208
206
|
${defaultCarouselSlides}
|
|
209
207
|
</kv-vertical-carousel>
|
|
210
|
-
<a href="#" @click.native.prevent="toggleAutoPlay()" role="toggleAutoPlayButton">Toggle AutoPlay</a>
|
|
208
|
+
<a href="#" @click.native.prevent="$refs.sampleCarousel.toggleAutoPlay()" role="toggleAutoPlayButton">Toggle AutoPlay</a>
|
|
211
209
|
<br/>
|
|
212
|
-
<p>AutoPlay is: {{
|
|
210
|
+
<p>AutoPlay is: {{ isAutoplaying ? 'ON' : 'OFF' }}</p>
|
|
213
211
|
</div>
|
|
214
212
|
`,
|
|
215
|
-
methods: {
|
|
216
|
-
toggleAutoPlay() {
|
|
217
|
-
this.$refs.sampleCarousel.toggleAutoPlay();
|
|
218
|
-
},
|
|
219
|
-
carouselInteraction() {
|
|
220
|
-
this.isPlaying = this.$refs.sampleCarousel.isAutoplaying();
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
213
|
});
|
|
224
214
|
|
|
215
|
+
/** Fade really only works when the carousel displays 1 slide at a time, this story is wonky as expected */
|
|
225
216
|
export const Fade = () => ({
|
|
226
217
|
components: {
|
|
227
218
|
KvVerticalCarousel,
|
|
228
219
|
},
|
|
229
|
-
mounted() {
|
|
230
|
-
this.$nextTick(() => {
|
|
231
|
-
this.isPlaying = this.$refs.sampleCarousel.isAutoplaying();
|
|
232
|
-
});
|
|
233
|
-
},
|
|
234
220
|
template: `
|
|
235
221
|
<div>
|
|
236
222
|
<kv-vertical-carousel
|
package/dist/utils/carousels.cjs
CHANGED
|
@@ -61,6 +61,7 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
61
61
|
const rootEl = (0, import_vue_demi.ref)(null);
|
|
62
62
|
const embla = (0, import_vue_demi.ref)(null);
|
|
63
63
|
const slides = (0, import_vue_demi.ref)([]);
|
|
64
|
+
const isAutoplaying = (0, import_vue_demi.ref)(false);
|
|
64
65
|
const startIndex = ((_a = emblaOptions.value) == null ? void 0 : _a.startIndex) ?? 0;
|
|
65
66
|
const currentIndex = (0, import_vue_demi.ref)(startIndex);
|
|
66
67
|
const slideIndicatorCount = (0, import_vue_demi.ref)(0);
|
|
@@ -86,10 +87,15 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
86
87
|
embla.value.scrollTo(index);
|
|
87
88
|
};
|
|
88
89
|
const handleUserInteraction = async (index, interactionType) => {
|
|
90
|
+
var _a2, _b;
|
|
89
91
|
if (index !== null && typeof index !== "undefined") {
|
|
90
92
|
await (0, import_vue_demi.nextTick)();
|
|
91
93
|
goToSlide(index);
|
|
92
94
|
}
|
|
95
|
+
const autoplay = (_b = (_a2 = embla.value) == null ? void 0 : _a2.plugins()) == null ? void 0 : _b.autoplay;
|
|
96
|
+
if (autoplay) {
|
|
97
|
+
autoplay.stop();
|
|
98
|
+
}
|
|
93
99
|
emit("interact-carousel", interactionType);
|
|
94
100
|
};
|
|
95
101
|
const toggleAutoPlay = () => {
|
|
@@ -99,14 +105,6 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
99
105
|
return;
|
|
100
106
|
const playOrStop = autoplay.isPlaying() ? autoplay.stop : autoplay.play;
|
|
101
107
|
playOrStop();
|
|
102
|
-
handleUserInteraction(null, "autoplay");
|
|
103
|
-
};
|
|
104
|
-
const isAutoplaying = () => {
|
|
105
|
-
var _a2, _b;
|
|
106
|
-
const autoplay = (_b = (_a2 = embla.value) == null ? void 0 : _a2.plugins()) == null ? void 0 : _b.autoplay;
|
|
107
|
-
if (!autoplay)
|
|
108
|
-
return false;
|
|
109
|
-
return autoplay.isPlaying();
|
|
110
108
|
};
|
|
111
109
|
const slideIndicatorListLength = () => {
|
|
112
110
|
const indicator = embla.value ? embla.value.scrollSnapList().length : 0;
|
|
@@ -143,7 +141,7 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
143
141
|
return false;
|
|
144
142
|
};
|
|
145
143
|
(0, import_vue_demi.onMounted)(async () => {
|
|
146
|
-
var _a2;
|
|
144
|
+
var _a2, _b, _c;
|
|
147
145
|
const combinedPluginOptions = [];
|
|
148
146
|
if (Object.keys(autoplayOptions.value).length !== 0) {
|
|
149
147
|
combinedPluginOptions.push((0, import_embla_carousel_autoplay.default)(autoplayOptions.value));
|
|
@@ -181,11 +179,21 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
181
179
|
emit("change", currentIndex);
|
|
182
180
|
});
|
|
183
181
|
});
|
|
182
|
+
(_b = embla == null ? void 0 : embla.value) == null ? void 0 : _b.on("autoplay:play", () => {
|
|
183
|
+
console.log("autoplay:play");
|
|
184
|
+
isAutoplaying.value = true;
|
|
185
|
+
});
|
|
186
|
+
(_c = embla == null ? void 0 : embla.value) == null ? void 0 : _c.on("autoplay:stop", () => {
|
|
187
|
+
console.log("autoplay:stop");
|
|
188
|
+
isAutoplaying.value = false;
|
|
189
|
+
});
|
|
184
190
|
});
|
|
185
191
|
(0, import_vue_demi.onUnmounted)(async () => {
|
|
186
|
-
var _a2, _b;
|
|
192
|
+
var _a2, _b, _c, _d;
|
|
187
193
|
(_a2 = embla == null ? void 0 : embla.value) == null ? void 0 : _a2.off("select");
|
|
188
|
-
(_b = embla == null ? void 0 : embla.value) == null ? void 0 : _b.
|
|
194
|
+
(_b = embla == null ? void 0 : embla.value) == null ? void 0 : _b.off("autoplay:play");
|
|
195
|
+
(_c = embla == null ? void 0 : embla.value) == null ? void 0 : _c.off("autoplay:stop");
|
|
196
|
+
(_d = embla == null ? void 0 : embla.value) == null ? void 0 : _d.destroy();
|
|
189
197
|
});
|
|
190
198
|
return {
|
|
191
199
|
rootEl,
|
package/dist/utils/carousels.js
CHANGED
|
@@ -25,6 +25,7 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
25
25
|
const rootEl = ref(null);
|
|
26
26
|
const embla = ref(null);
|
|
27
27
|
const slides = ref([]);
|
|
28
|
+
const isAutoplaying = ref(false);
|
|
28
29
|
const startIndex = ((_a = emblaOptions.value) == null ? void 0 : _a.startIndex) ?? 0;
|
|
29
30
|
const currentIndex = ref(startIndex);
|
|
30
31
|
const slideIndicatorCount = ref(0);
|
|
@@ -50,10 +51,15 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
50
51
|
embla.value.scrollTo(index);
|
|
51
52
|
};
|
|
52
53
|
const handleUserInteraction = async (index, interactionType) => {
|
|
54
|
+
var _a2, _b;
|
|
53
55
|
if (index !== null && typeof index !== "undefined") {
|
|
54
56
|
await nextTick();
|
|
55
57
|
goToSlide(index);
|
|
56
58
|
}
|
|
59
|
+
const autoplay = (_b = (_a2 = embla.value) == null ? void 0 : _a2.plugins()) == null ? void 0 : _b.autoplay;
|
|
60
|
+
if (autoplay) {
|
|
61
|
+
autoplay.stop();
|
|
62
|
+
}
|
|
57
63
|
emit("interact-carousel", interactionType);
|
|
58
64
|
};
|
|
59
65
|
const toggleAutoPlay = () => {
|
|
@@ -63,14 +69,6 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
63
69
|
return;
|
|
64
70
|
const playOrStop = autoplay.isPlaying() ? autoplay.stop : autoplay.play;
|
|
65
71
|
playOrStop();
|
|
66
|
-
handleUserInteraction(null, "autoplay");
|
|
67
|
-
};
|
|
68
|
-
const isAutoplaying = () => {
|
|
69
|
-
var _a2, _b;
|
|
70
|
-
const autoplay = (_b = (_a2 = embla.value) == null ? void 0 : _a2.plugins()) == null ? void 0 : _b.autoplay;
|
|
71
|
-
if (!autoplay)
|
|
72
|
-
return false;
|
|
73
|
-
return autoplay.isPlaying();
|
|
74
72
|
};
|
|
75
73
|
const slideIndicatorListLength = () => {
|
|
76
74
|
const indicator = embla.value ? embla.value.scrollSnapList().length : 0;
|
|
@@ -107,7 +105,7 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
107
105
|
return false;
|
|
108
106
|
};
|
|
109
107
|
onMounted(async () => {
|
|
110
|
-
var _a2;
|
|
108
|
+
var _a2, _b, _c;
|
|
111
109
|
const combinedPluginOptions = [];
|
|
112
110
|
if (Object.keys(autoplayOptions.value).length !== 0) {
|
|
113
111
|
combinedPluginOptions.push(Autoplay(autoplayOptions.value));
|
|
@@ -145,11 +143,21 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
145
143
|
emit("change", currentIndex);
|
|
146
144
|
});
|
|
147
145
|
});
|
|
146
|
+
(_b = embla == null ? void 0 : embla.value) == null ? void 0 : _b.on("autoplay:play", () => {
|
|
147
|
+
console.log("autoplay:play");
|
|
148
|
+
isAutoplaying.value = true;
|
|
149
|
+
});
|
|
150
|
+
(_c = embla == null ? void 0 : embla.value) == null ? void 0 : _c.on("autoplay:stop", () => {
|
|
151
|
+
console.log("autoplay:stop");
|
|
152
|
+
isAutoplaying.value = false;
|
|
153
|
+
});
|
|
148
154
|
});
|
|
149
155
|
onUnmounted(async () => {
|
|
150
|
-
var _a2, _b;
|
|
156
|
+
var _a2, _b, _c, _d;
|
|
151
157
|
(_a2 = embla == null ? void 0 : embla.value) == null ? void 0 : _a2.off("select");
|
|
152
|
-
(_b = embla == null ? void 0 : embla.value) == null ? void 0 : _b.
|
|
158
|
+
(_b = embla == null ? void 0 : embla.value) == null ? void 0 : _b.off("autoplay:play");
|
|
159
|
+
(_c = embla == null ? void 0 : embla.value) == null ? void 0 : _c.off("autoplay:stop");
|
|
160
|
+
(_d = embla == null ? void 0 : embla.value) == null ? void 0 : _d.destroy();
|
|
153
161
|
});
|
|
154
162
|
return {
|
|
155
163
|
rootEl,
|
package/dist/utils/index.cjs
CHANGED
|
@@ -169,6 +169,7 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
169
169
|
const rootEl = (0, import_vue_demi.ref)(null);
|
|
170
170
|
const embla = (0, import_vue_demi.ref)(null);
|
|
171
171
|
const slides = (0, import_vue_demi.ref)([]);
|
|
172
|
+
const isAutoplaying = (0, import_vue_demi.ref)(false);
|
|
172
173
|
const startIndex = ((_a = emblaOptions.value) == null ? void 0 : _a.startIndex) ?? 0;
|
|
173
174
|
const currentIndex = (0, import_vue_demi.ref)(startIndex);
|
|
174
175
|
const slideIndicatorCount = (0, import_vue_demi.ref)(0);
|
|
@@ -194,10 +195,15 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
194
195
|
embla.value.scrollTo(index);
|
|
195
196
|
};
|
|
196
197
|
const handleUserInteraction = async (index, interactionType) => {
|
|
198
|
+
var _a2, _b;
|
|
197
199
|
if (index !== null && typeof index !== "undefined") {
|
|
198
200
|
await (0, import_vue_demi.nextTick)();
|
|
199
201
|
goToSlide(index);
|
|
200
202
|
}
|
|
203
|
+
const autoplay = (_b = (_a2 = embla.value) == null ? void 0 : _a2.plugins()) == null ? void 0 : _b.autoplay;
|
|
204
|
+
if (autoplay) {
|
|
205
|
+
autoplay.stop();
|
|
206
|
+
}
|
|
201
207
|
emit("interact-carousel", interactionType);
|
|
202
208
|
};
|
|
203
209
|
const toggleAutoPlay = () => {
|
|
@@ -207,14 +213,6 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
207
213
|
return;
|
|
208
214
|
const playOrStop = autoplay.isPlaying() ? autoplay.stop : autoplay.play;
|
|
209
215
|
playOrStop();
|
|
210
|
-
handleUserInteraction(null, "autoplay");
|
|
211
|
-
};
|
|
212
|
-
const isAutoplaying = () => {
|
|
213
|
-
var _a2, _b;
|
|
214
|
-
const autoplay = (_b = (_a2 = embla.value) == null ? void 0 : _a2.plugins()) == null ? void 0 : _b.autoplay;
|
|
215
|
-
if (!autoplay)
|
|
216
|
-
return false;
|
|
217
|
-
return autoplay.isPlaying();
|
|
218
216
|
};
|
|
219
217
|
const slideIndicatorListLength = () => {
|
|
220
218
|
const indicator = embla.value ? embla.value.scrollSnapList().length : 0;
|
|
@@ -251,7 +249,7 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
251
249
|
return false;
|
|
252
250
|
};
|
|
253
251
|
(0, import_vue_demi.onMounted)(async () => {
|
|
254
|
-
var _a2;
|
|
252
|
+
var _a2, _b, _c;
|
|
255
253
|
const combinedPluginOptions = [];
|
|
256
254
|
if (Object.keys(autoplayOptions.value).length !== 0) {
|
|
257
255
|
combinedPluginOptions.push((0, import_embla_carousel_autoplay.default)(autoplayOptions.value));
|
|
@@ -289,11 +287,21 @@ function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
289
287
|
emit("change", currentIndex);
|
|
290
288
|
});
|
|
291
289
|
});
|
|
290
|
+
(_b = embla == null ? void 0 : embla.value) == null ? void 0 : _b.on("autoplay:play", () => {
|
|
291
|
+
console.log("autoplay:play");
|
|
292
|
+
isAutoplaying.value = true;
|
|
293
|
+
});
|
|
294
|
+
(_c = embla == null ? void 0 : embla.value) == null ? void 0 : _c.on("autoplay:stop", () => {
|
|
295
|
+
console.log("autoplay:stop");
|
|
296
|
+
isAutoplaying.value = false;
|
|
297
|
+
});
|
|
292
298
|
});
|
|
293
299
|
(0, import_vue_demi.onUnmounted)(async () => {
|
|
294
|
-
var _a2, _b;
|
|
300
|
+
var _a2, _b, _c, _d;
|
|
295
301
|
(_a2 = embla == null ? void 0 : embla.value) == null ? void 0 : _a2.off("select");
|
|
296
|
-
(_b = embla == null ? void 0 : embla.value) == null ? void 0 : _b.
|
|
302
|
+
(_b = embla == null ? void 0 : embla.value) == null ? void 0 : _b.off("autoplay:play");
|
|
303
|
+
(_c = embla == null ? void 0 : embla.value) == null ? void 0 : _c.off("autoplay:stop");
|
|
304
|
+
(_d = embla == null ? void 0 : embla.value) == null ? void 0 : _d.destroy();
|
|
297
305
|
});
|
|
298
306
|
return {
|
|
299
307
|
rootEl,
|
package/dist/utils/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kiva/kv-components",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -98,5 +98,5 @@
|
|
|
98
98
|
"peerDependencies": {
|
|
99
99
|
"vue": ">=3.0.0"
|
|
100
100
|
},
|
|
101
|
-
"gitHead": "
|
|
101
|
+
"gitHead": "714dd64c1fdea169392d23f77b934c131230df99"
|
|
102
102
|
}
|
package/utils/carousels.js
CHANGED
|
@@ -22,6 +22,8 @@ export function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
22
22
|
const rootEl = ref(null);
|
|
23
23
|
const embla = ref(null);
|
|
24
24
|
const slides = ref([]);
|
|
25
|
+
const isAutoplaying = ref(false);
|
|
26
|
+
|
|
25
27
|
const startIndex = emblaOptions.value?.startIndex ?? 0;
|
|
26
28
|
const currentIndex = ref(startIndex);
|
|
27
29
|
// The indicator count may differ from the slide count when multiple slides are in view
|
|
@@ -63,6 +65,13 @@ export function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
63
65
|
await nextTick(); // wait for embla.
|
|
64
66
|
goToSlide(index);
|
|
65
67
|
}
|
|
68
|
+
|
|
69
|
+
/** Stop autoplay on user interaction */
|
|
70
|
+
const autoplay = embla.value?.plugins()?.autoplay;
|
|
71
|
+
if (autoplay) {
|
|
72
|
+
autoplay.stop();
|
|
73
|
+
}
|
|
74
|
+
|
|
66
75
|
/**
|
|
67
76
|
* Fires when the user interacts with the carousel.
|
|
68
77
|
* Contains the interaction type (swipe-left, click-left-arrow, etc.)
|
|
@@ -81,19 +90,8 @@ export function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
81
90
|
if (!autoplay) return;
|
|
82
91
|
const playOrStop = autoplay.isPlaying() ? autoplay.stop : autoplay.play;
|
|
83
92
|
playOrStop();
|
|
84
|
-
handleUserInteraction(null, 'autoplay');
|
|
85
93
|
};
|
|
86
94
|
|
|
87
|
-
/**
|
|
88
|
-
* Returns true if the carousel is autoplaying
|
|
89
|
-
*
|
|
90
|
-
* @public This is a public method
|
|
91
|
-
*/
|
|
92
|
-
const isAutoplaying = () => {
|
|
93
|
-
const autoplay = embla.value?.plugins()?.autoplay;
|
|
94
|
-
if (!autoplay) return false;
|
|
95
|
-
return autoplay.isPlaying();
|
|
96
|
-
};
|
|
97
95
|
/**
|
|
98
96
|
* Returns number of slides in the carousel
|
|
99
97
|
*
|
|
@@ -198,10 +196,32 @@ export function carouselUtil(props, { emit, slots }, extraEmblaOptions) {
|
|
|
198
196
|
emit('change', currentIndex);
|
|
199
197
|
});
|
|
200
198
|
});
|
|
199
|
+
|
|
200
|
+
embla?.value?.on('autoplay:play', () => {
|
|
201
|
+
console.log('autoplay:play');
|
|
202
|
+
/**
|
|
203
|
+
* Fires when autoplay starts
|
|
204
|
+
* @event autoplay-play
|
|
205
|
+
* @type {Event}
|
|
206
|
+
*/
|
|
207
|
+
isAutoplaying.value = true;
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
embla?.value?.on('autoplay:stop', () => {
|
|
211
|
+
console.log('autoplay:stop');
|
|
212
|
+
/**
|
|
213
|
+
* Fires when autoplay starts
|
|
214
|
+
* @event autoplay-play
|
|
215
|
+
* @type {Event}
|
|
216
|
+
*/
|
|
217
|
+
isAutoplaying.value = false;
|
|
218
|
+
});
|
|
201
219
|
});
|
|
202
220
|
|
|
203
221
|
onUnmounted(async () => {
|
|
204
222
|
embla?.value?.off('select');
|
|
223
|
+
embla?.value?.off('autoplay:play');
|
|
224
|
+
embla?.value?.off('autoplay:stop');
|
|
205
225
|
embla?.value?.destroy();
|
|
206
226
|
});
|
|
207
227
|
|
|
@@ -29,40 +29,69 @@
|
|
|
29
29
|
<!-- Carousel Controls -->
|
|
30
30
|
<div
|
|
31
31
|
class="kv-carousel__controls tw-flex
|
|
32
|
-
tw-
|
|
33
|
-
tw-mt-2 tw-w-full
|
|
32
|
+
tw-items-center tw-gap-2
|
|
33
|
+
tw-mt-2 tw-w-full
|
|
34
|
+
tw-justify-between md:tw-justify-center"
|
|
34
35
|
>
|
|
35
|
-
<
|
|
36
|
-
class="tw-
|
|
36
|
+
<div
|
|
37
|
+
class="tw-flex tw-gap-2 tw-w-full md:tw-w-auto"
|
|
38
|
+
:class="{'tw-justify-between md:tw-justify-center': !hasAutoplay}"
|
|
39
|
+
>
|
|
40
|
+
<button
|
|
41
|
+
class="tw-text-primary
|
|
37
42
|
tw-rounded-full
|
|
38
43
|
tw-border-2 tw-border-primary
|
|
39
44
|
tw-h-4 tw-w-4
|
|
40
45
|
tw-flex tw-items-center tw-justify-center
|
|
41
46
|
disabled:tw-opacity-low disabled:tw-cursor-default"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
:disabled="embla && !embla.canScrollPrev()"
|
|
48
|
+
@click="handleUserInteraction(previousIndex, 'click-left-arrow')"
|
|
49
|
+
>
|
|
50
|
+
<kv-material-icon
|
|
51
|
+
class="tw-w-4"
|
|
52
|
+
:icon="mdiChevronUp"
|
|
53
|
+
/>
|
|
54
|
+
<span class="tw-sr-only">Show previous slide</span>
|
|
55
|
+
</button>
|
|
56
|
+
<button
|
|
57
|
+
class="tw-text-primary
|
|
58
|
+
tw-rounded-full
|
|
59
|
+
tw-border-2 tw-border-primary
|
|
60
|
+
tw-h-4 tw-w-4
|
|
61
|
+
tw-flex tw-items-center tw-justify-center
|
|
62
|
+
disabled:tw-opacity-low disabled:tw-cursor-default"
|
|
63
|
+
:disabled="embla && !embla.canScrollNext()"
|
|
64
|
+
@click="handleUserInteraction(nextIndex, 'click-right-arrow')"
|
|
65
|
+
>
|
|
66
|
+
<kv-material-icon
|
|
67
|
+
class="tw-w-4"
|
|
68
|
+
:icon="mdiChevronDown"
|
|
69
|
+
/>
|
|
70
|
+
<span class="tw-sr-only">Show next slide</span>
|
|
71
|
+
</button>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
51
74
|
<button
|
|
75
|
+
v-if="hasAutoplay"
|
|
52
76
|
class="tw-text-primary
|
|
53
77
|
tw-rounded-full
|
|
54
78
|
tw-border-2 tw-border-primary
|
|
55
79
|
tw-h-4 tw-w-4
|
|
56
80
|
tw-flex tw-items-center tw-justify-center
|
|
57
81
|
disabled:tw-opacity-low disabled:tw-cursor-default"
|
|
58
|
-
|
|
59
|
-
@click="handleUserInteraction(nextIndex, 'click-right-arrow')"
|
|
82
|
+
@click.native.prevent="toggleAutoPlay()"
|
|
60
83
|
>
|
|
61
84
|
<kv-material-icon
|
|
85
|
+
v-if="isAutoplaying"
|
|
62
86
|
class="tw-w-4"
|
|
63
|
-
:icon="
|
|
87
|
+
:icon="mdiPause"
|
|
64
88
|
/>
|
|
65
|
-
<
|
|
89
|
+
<kv-material-icon
|
|
90
|
+
v-else
|
|
91
|
+
class="tw-w-4"
|
|
92
|
+
:icon="mdiPlay"
|
|
93
|
+
/>
|
|
94
|
+
<span class="tw-sr-only">Show previous slide</span>
|
|
66
95
|
</button>
|
|
67
96
|
</div>
|
|
68
97
|
</div>
|
|
@@ -70,9 +99,15 @@
|
|
|
70
99
|
|
|
71
100
|
<script>
|
|
72
101
|
import {
|
|
102
|
+
toRefs,
|
|
103
|
+
} from 'vue-demi';
|
|
104
|
+
import {
|
|
105
|
+
mdiPause,
|
|
106
|
+
mdiPlay,
|
|
73
107
|
mdiChevronUp,
|
|
74
108
|
mdiChevronDown,
|
|
75
109
|
} from '@mdi/js';
|
|
110
|
+
import { computed } from 'vue';
|
|
76
111
|
import { carouselUtil } from '../utils/carousels';
|
|
77
112
|
import KvMaterialIcon from './KvMaterialIcon.vue';
|
|
78
113
|
|
|
@@ -129,6 +164,10 @@ export default {
|
|
|
129
164
|
'interact-carousel',
|
|
130
165
|
],
|
|
131
166
|
setup(props, { emit, slots }) {
|
|
167
|
+
const {
|
|
168
|
+
autoplayOptions,
|
|
169
|
+
} = toRefs(props);
|
|
170
|
+
|
|
132
171
|
const {
|
|
133
172
|
componentSlotKeys,
|
|
134
173
|
currentIndex,
|
|
@@ -148,7 +187,12 @@ export default {
|
|
|
148
187
|
toggleAutoPlay,
|
|
149
188
|
} = carouselUtil(props, { emit, slots }, { axis: 'y' });
|
|
150
189
|
|
|
190
|
+
const hasAutoplay = computed(() => {
|
|
191
|
+
return Object.keys(autoplayOptions.value).length !== 0;
|
|
192
|
+
});
|
|
193
|
+
|
|
151
194
|
return {
|
|
195
|
+
hasAutoplay,
|
|
152
196
|
componentSlotKeys,
|
|
153
197
|
currentIndex,
|
|
154
198
|
embla,
|
|
@@ -156,6 +200,8 @@ export default {
|
|
|
156
200
|
handleUserInteraction,
|
|
157
201
|
isAriaHidden,
|
|
158
202
|
isAutoplaying,
|
|
203
|
+
mdiPause,
|
|
204
|
+
mdiPlay,
|
|
159
205
|
mdiChevronDown,
|
|
160
206
|
mdiChevronUp,
|
|
161
207
|
nextIndex,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { watch } from 'vue';
|
|
1
2
|
import KvCarousel from '../KvCarousel.vue';
|
|
2
3
|
import KvLoadingSpinner from '../KvLoadingSpinner.vue';
|
|
3
4
|
import KvButton from '../KvButton.vue';
|
|
@@ -444,14 +445,12 @@ export const AutoPlayButton = () => ({
|
|
|
444
445
|
components: {
|
|
445
446
|
KvCarousel,
|
|
446
447
|
},
|
|
447
|
-
data() {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
};
|
|
451
|
-
},
|
|
448
|
+
data: () => ({
|
|
449
|
+
isAutoplaying: false,
|
|
450
|
+
}),
|
|
452
451
|
mounted() {
|
|
453
|
-
this.$
|
|
454
|
-
this.
|
|
452
|
+
watch(() => this.$refs?.sampleCarousel?.isAutoplaying, (newValue) => {
|
|
453
|
+
this.isAutoplaying = newValue;
|
|
455
454
|
});
|
|
456
455
|
},
|
|
457
456
|
template: `
|
|
@@ -461,34 +460,20 @@ export const AutoPlayButton = () => ({
|
|
|
461
460
|
style="max-width: 400px;"
|
|
462
461
|
:embla-options="{ loop: false }"
|
|
463
462
|
:autoplay-options="{ playOnInit: true, delay: 3000 }"
|
|
464
|
-
@interact-carousel="carouselInteraction"
|
|
465
463
|
>
|
|
466
464
|
${defaultCarouselSlides}
|
|
467
465
|
</kv-carousel>
|
|
468
|
-
<a href="#" @click.native.prevent="toggleAutoPlay()" role="toggleAutoPlayButton">Toggle AutoPlay</a>
|
|
466
|
+
<a href="#" @click.native.prevent="$refs.sampleCarousel.toggleAutoPlay()" role="toggleAutoPlayButton">Toggle AutoPlay</a>
|
|
469
467
|
<br/>
|
|
470
|
-
<p>AutoPlay is: {{
|
|
468
|
+
<p>AutoPlay is: {{ isAutoplaying ? 'ON' : 'OFF' }}</p>
|
|
471
469
|
</div>
|
|
472
470
|
`,
|
|
473
|
-
methods: {
|
|
474
|
-
toggleAutoPlay() {
|
|
475
|
-
this.$refs.sampleCarousel.toggleAutoPlay();
|
|
476
|
-
},
|
|
477
|
-
carouselInteraction() {
|
|
478
|
-
this.isPlaying = this.$refs.sampleCarousel.isAutoplaying();
|
|
479
|
-
},
|
|
480
|
-
},
|
|
481
471
|
});
|
|
482
472
|
|
|
483
473
|
export const Fade = () => ({
|
|
484
474
|
components: {
|
|
485
475
|
KvCarousel,
|
|
486
476
|
},
|
|
487
|
-
mounted() {
|
|
488
|
-
this.$nextTick(() => {
|
|
489
|
-
this.isPlaying = this.$refs.sampleCarousel.isAutoplaying();
|
|
490
|
-
});
|
|
491
|
-
},
|
|
492
477
|
template: `
|
|
493
478
|
<div>
|
|
494
479
|
<kv-carousel
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { watch } from 'vue';
|
|
1
2
|
import KvVerticalCarousel from '../KvVerticalCarousel.vue';
|
|
2
3
|
import KvButton from '../KvButton.vue';
|
|
3
4
|
|
|
@@ -186,14 +187,12 @@ export const AutoPlayButton = () => ({
|
|
|
186
187
|
components: {
|
|
187
188
|
KvVerticalCarousel,
|
|
188
189
|
},
|
|
189
|
-
data() {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
};
|
|
193
|
-
},
|
|
190
|
+
data: () => ({
|
|
191
|
+
isAutoplaying: false,
|
|
192
|
+
}),
|
|
194
193
|
mounted() {
|
|
195
|
-
this.$
|
|
196
|
-
this.
|
|
194
|
+
watch(() => this.$refs?.sampleCarousel?.isAutoplaying, (newValue) => {
|
|
195
|
+
this.isAutoplaying = newValue;
|
|
197
196
|
});
|
|
198
197
|
},
|
|
199
198
|
template: `
|
|
@@ -203,34 +202,21 @@ export const AutoPlayButton = () => ({
|
|
|
203
202
|
style="max-width: 400px;"
|
|
204
203
|
:embla-options="{ loop: false }"
|
|
205
204
|
:autoplay-options="{ playOnInit: true, delay: 3000 }"
|
|
206
|
-
@interact-carousel="carouselInteraction"
|
|
207
205
|
>
|
|
208
206
|
${defaultCarouselSlides}
|
|
209
207
|
</kv-vertical-carousel>
|
|
210
|
-
<a href="#" @click.native.prevent="toggleAutoPlay()" role="toggleAutoPlayButton">Toggle AutoPlay</a>
|
|
208
|
+
<a href="#" @click.native.prevent="$refs.sampleCarousel.toggleAutoPlay()" role="toggleAutoPlayButton">Toggle AutoPlay</a>
|
|
211
209
|
<br/>
|
|
212
|
-
<p>AutoPlay is: {{
|
|
210
|
+
<p>AutoPlay is: {{ isAutoplaying ? 'ON' : 'OFF' }}</p>
|
|
213
211
|
</div>
|
|
214
212
|
`,
|
|
215
|
-
methods: {
|
|
216
|
-
toggleAutoPlay() {
|
|
217
|
-
this.$refs.sampleCarousel.toggleAutoPlay();
|
|
218
|
-
},
|
|
219
|
-
carouselInteraction() {
|
|
220
|
-
this.isPlaying = this.$refs.sampleCarousel.isAutoplaying();
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
213
|
});
|
|
224
214
|
|
|
215
|
+
/** Fade really only works when the carousel displays 1 slide at a time, this story is wonky as expected */
|
|
225
216
|
export const Fade = () => ({
|
|
226
217
|
components: {
|
|
227
218
|
KvVerticalCarousel,
|
|
228
219
|
},
|
|
229
|
-
mounted() {
|
|
230
|
-
this.$nextTick(() => {
|
|
231
|
-
this.isPlaying = this.$refs.sampleCarousel.isAutoplaying();
|
|
232
|
-
});
|
|
233
|
-
},
|
|
234
220
|
template: `
|
|
235
221
|
<div>
|
|
236
222
|
<kv-vertical-carousel
|