@ailuracode/alpine-carousel 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) ailuracode
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # @ailuracode/alpine-carousel
2
+
3
+ Headless accessible carousel store for Alpine.js, powered by [Embla Carousel](https://www.embla-carousel.com/).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @ailuracode/alpine-carousel alpinejs
9
+ ```
10
+
11
+ Peer dependencies: `embla-carousel` and `embla-carousel-autoplay` are bundled as direct dependencies.
12
+
13
+ ## Setup
14
+
15
+ ```js
16
+ import Alpine from "alpinejs";
17
+ import carousel from "@ailuracode/alpine-carousel";
18
+
19
+ Alpine.plugin(carousel());
20
+ Alpine.start();
21
+ ```
22
+
23
+ ## Basic markup
24
+
25
+ ```html
26
+ <div
27
+ x-data
28
+ x-init="
29
+ $store.carousel.create('gallery');
30
+ $nextTick(() => $store.carousel.bindViewport('gallery', $refs.viewport))
31
+ "
32
+ @keydown="$store.carousel.handleKeydown('gallery', $event)"
33
+ >
34
+ <section x-bind="$store.carousel.carouselProps('gallery', { label: 'Featured gallery' })">
35
+ <div x-ref="viewport" x-bind="$store.carousel.viewportProps('gallery')" class="min-w-0 w-full overflow-hidden">
36
+ <div class="flex touch-pan-y pinch-zoom">
37
+ <div class="min-w-0 shrink-0 grow-0 [flex:0_0_var(--slide-size,100%)]" x-bind="$store.carousel.slideProps('gallery', 0)">Slide 1</div>
38
+ <div class="min-w-0 shrink-0 grow-0 [flex:0_0_var(--slide-size,100%)]" x-bind="$store.carousel.slideProps('gallery', 1)">Slide 2</div>
39
+ </div>
40
+ </div>
41
+
42
+ <button type="button" @click="$store.carousel.previous('gallery')">Previous</button>
43
+ <button type="button" @click="$store.carousel.next('gallery')">Next</button>
44
+ </section>
45
+ </div>
46
+ ```
47
+
48
+ Embla expects the **viewport** element (overflow hidden) with a **container** child and **slides** as descendants of the container. `viewportProps()` sets `--slide-size: 100%` on the viewport; size slides with `flex: 0 0 var(--slide-size)` and `min-width: 0`. Avoid `width: 100%` on slides — it resolves against the flex container and overflows on mobile.
49
+
50
+ ## Store API
51
+
52
+ | Method | Description |
53
+ |--------|-------------|
54
+ | `create(id, options?)` | Register a carousel instance |
55
+ | `bindViewport(id, element)` | Mount Embla on the viewport element |
56
+ | `destroy(id)` | Destroy Embla and remove the instance |
57
+ | `next(id)` / `previous(id)` | Navigate slides |
58
+ | `goTo(id, index)` | Jump to a slide |
59
+ | `current(id)` / `count(id)` | Current index and total slides |
60
+ | `canNext(id)` / `canPrevious(id)` | Scroll availability |
61
+ | `play(id)` / `pause(id)` / `isPlaying(id)` | Autoplay controls |
62
+ | `instance(id)` | Raw Embla API (advanced) |
63
+ | `handleKeydown(id, event)` | Arrow keys, Home, End |
64
+ | `carouselProps(id, options?)` | ARIA region props |
65
+ | `viewportProps(id, options?)` | Focusable viewport props; sets `--slide-size` (default `100%`, pass `{ slideSize: false }` to use CSS classes instead) |
66
+ | `slideProps(id, index)` | Per-slide ARIA props |
67
+ | `indicatorProps(id, index)` | Dot/thumbnail button props |
68
+
69
+ ### Reactive state
70
+
71
+ Each instance in `$store.carousel.instances[id]` exposes:
72
+
73
+ - `currentIndex`, `totalSlides`, `progress`
74
+ - `isFirst`, `isLast`, `isPlaying`
75
+ - `canNext`, `canPrevious`, `slidesInView`
76
+
77
+ ## Options
78
+
79
+ | Option | Default | Maps to Embla |
80
+ |--------|---------|---------------|
81
+ | `loop` | `false` | `loop` |
82
+ | `axis` | `'x'` | `axis` |
83
+ | `align` | `'start'` | `align` |
84
+ | `containScroll` | `'trimSnaps'` | `containScroll` |
85
+ | `dragFree` | `false` | `dragFree` |
86
+ | `duration` | `25` | `duration` |
87
+ | `autoplay` | `false` | `embla-carousel-autoplay` |
88
+ | `autoplayOptions.delay` | `4000` | autoplay delay |
89
+ | `autoplayOptions.stopOnMouseEnter` | `false` | Pause on hover |
90
+ | `autoplayOptions.stopOnInteraction` | `true` (`false` when hover pause is on) | Pause on drag/click; must be `false` for hover resume |
91
+ | `autoplayOptions.stopWhenHidden` | `true` | Pause when the document is hidden (plugin-managed) |
92
+ | `ariaLive` | `'polite'` | `aria-live` on carousel region |
93
+ | `onChange` | — | Callback when slide index changes |
94
+
95
+ ## License
96
+
97
+ MIT
@@ -0,0 +1,67 @@
1
+ /// <reference types="@types/alpinejs" />
2
+
3
+ export type CarouselAutoplayOptions = {
4
+ delay?: number;
5
+ stopOnInteraction?: boolean;
6
+ stopOnMouseEnter?: boolean;
7
+ stopOnFocusIn?: boolean;
8
+ stopWhenHidden?: boolean;
9
+ };
10
+
11
+ export type CarouselOptions = {
12
+ loop?: boolean;
13
+ autoplay?: boolean;
14
+ autoplayOptions?: CarouselAutoplayOptions;
15
+ axis?: "x" | "y";
16
+ align?: import("embla-carousel").EmblaOptionsType["align"];
17
+ containScroll?: import("embla-carousel").EmblaOptionsType["containScroll"];
18
+ dragFree?: boolean;
19
+ duration?: number;
20
+ ariaLive?: "off" | "polite" | "assertive";
21
+ onChange?: (index: number) => void;
22
+ };
23
+
24
+ export interface CarouselStore {
25
+ instances: Record<string, import("./store.js").CarouselInstance>;
26
+ create(id: string, options?: CarouselOptions): void;
27
+ destroy(id: string): void;
28
+ bindViewport(id: string, viewport: HTMLElement | null): void;
29
+ next(id: string): void;
30
+ previous(id: string): void;
31
+ goTo(id: string, index: number): void;
32
+ current(id: string): number;
33
+ count(id: string): number;
34
+ canNext(id: string): boolean;
35
+ canPrevious(id: string): boolean;
36
+ play(id: string): void;
37
+ pause(id: string): void;
38
+ isPlaying(id: string): boolean;
39
+ instance(id: string): import("embla-carousel").EmblaCarouselType | null;
40
+ handleKeydown(id: string, event: KeyboardEvent): void;
41
+ carouselProps(
42
+ id: string,
43
+ options?: { label?: string }
44
+ ): Record<string, string | boolean | undefined>;
45
+ viewportProps(
46
+ id: string,
47
+ options?: { slideSize?: string | false }
48
+ ): Record<string, string | number | boolean | undefined>;
49
+ slideProps(id: string, index: number): Record<string, string | boolean | undefined>;
50
+ indicatorProps(id: string, index: number): Record<string, string | boolean | undefined>;
51
+ destroyAll(): void;
52
+ }
53
+
54
+ export function createCarouselStore(): CarouselStore;
55
+
56
+ export default function carouselPlugin(): import("alpinejs").PluginCallback;
57
+
58
+ declare global {
59
+ namespace Alpine {
60
+ interface Stores {
61
+ carousel: CarouselStore;
62
+ }
63
+ interface Magics<T> {
64
+ $carousel: CarouselStore;
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,83 @@
1
+ import AlpineType from 'alpinejs';
2
+ import { EmblaOptionsType, EmblaCarouselType } from 'embla-carousel';
3
+ import { AutoplayType } from 'embla-carousel-autoplay';
4
+
5
+ type CarouselAutoplayOptions = {
6
+ delay?: number;
7
+ stopOnInteraction?: boolean;
8
+ stopOnMouseEnter?: boolean;
9
+ stopOnFocusIn?: boolean;
10
+ stopWhenHidden?: boolean;
11
+ };
12
+ type CarouselOptions = {
13
+ loop?: boolean;
14
+ autoplay?: boolean;
15
+ autoplayOptions?: CarouselAutoplayOptions;
16
+ axis?: "x" | "y";
17
+ align?: EmblaOptionsType["align"];
18
+ containScroll?: EmblaOptionsType["containScroll"];
19
+ dragFree?: boolean;
20
+ duration?: number;
21
+ ariaLive?: "off" | "polite" | "assertive";
22
+ onChange?: (index: number) => void;
23
+ };
24
+ type CarouselInstance = {
25
+ currentIndex: number;
26
+ totalSlides: number;
27
+ progress: number;
28
+ isFirst: boolean;
29
+ isLast: boolean;
30
+ isPlaying: boolean;
31
+ canNext: boolean;
32
+ canPrevious: boolean;
33
+ slidesInView: number[];
34
+ options: CarouselOptions;
35
+ ariaLive: "off" | "polite" | "assertive";
36
+ viewport: HTMLElement | null;
37
+ embla: EmblaCarouselType | null;
38
+ autoplay: AutoplayType | null;
39
+ };
40
+ type CarouselStore = {
41
+ instances: Record<string, CarouselInstance>;
42
+ create(id: string, options?: CarouselOptions): void;
43
+ destroy(id: string): void;
44
+ bindViewport(id: string, viewport: HTMLElement | null): void;
45
+ next(id: string): void;
46
+ previous(id: string): void;
47
+ goTo(id: string, index: number): void;
48
+ current(id: string): number;
49
+ count(id: string): number;
50
+ canNext(id: string): boolean;
51
+ canPrevious(id: string): boolean;
52
+ play(id: string): void;
53
+ pause(id: string): void;
54
+ isPlaying(id: string): boolean;
55
+ instance(id: string): EmblaCarouselType | null;
56
+ handleKeydown(id: string, event: KeyboardEvent): void;
57
+ carouselProps(id: string, options?: {
58
+ label?: string;
59
+ }): Record<string, string | boolean | undefined>;
60
+ viewportProps(id: string, options?: {
61
+ slideSize?: string | false;
62
+ }): Record<string, string | number | boolean | undefined>;
63
+ slideProps(id: string, index: number): Record<string, string | boolean | undefined>;
64
+ indicatorProps(id: string, index: number): Record<string, string | boolean | undefined>;
65
+ destroyAll(): void;
66
+ };
67
+ /** Creates the headless carousel store powered by Embla Carousel. */
68
+ declare function createCarouselStore(): CarouselStore;
69
+
70
+ /** Alpine.js carousel plugin. Registers `$store.carousel`. */
71
+ declare function carouselPlugin(): AlpineType.PluginCallback;
72
+ declare global {
73
+ namespace Alpine {
74
+ interface Stores {
75
+ carousel: CarouselStore;
76
+ }
77
+ interface Magics<T> {
78
+ $carousel: CarouselStore;
79
+ }
80
+ }
81
+ }
82
+
83
+ export { type CarouselAutoplayOptions, type CarouselInstance, type CarouselOptions, type CarouselStore, createCarouselStore, carouselPlugin as default };
package/dist/index.js ADDED
@@ -0,0 +1,312 @@
1
+ // src/store.ts
2
+ import EmblaCarousel from "embla-carousel";
3
+ import Autoplay from "embla-carousel-autoplay";
4
+ function createInstance(options = {}) {
5
+ return {
6
+ currentIndex: 0,
7
+ totalSlides: 0,
8
+ progress: 0,
9
+ isFirst: true,
10
+ isLast: false,
11
+ isPlaying: false,
12
+ canNext: false,
13
+ canPrevious: false,
14
+ slidesInView: [],
15
+ options,
16
+ ariaLive: options.ariaLive ?? "polite",
17
+ viewport: null,
18
+ embla: null,
19
+ autoplay: null
20
+ };
21
+ }
22
+ function toEmblaOptions(options) {
23
+ return {
24
+ loop: options.loop ?? false,
25
+ axis: options.axis ?? "x",
26
+ align: options.align ?? "start",
27
+ containScroll: options.containScroll ?? "trimSnaps",
28
+ dragFree: options.dragFree ?? false,
29
+ duration: options.duration ?? 25
30
+ };
31
+ }
32
+ function createAutoplayPlugin(options) {
33
+ if (!options.autoplay) {
34
+ return null;
35
+ }
36
+ const autoplayOptions = options.autoplayOptions ?? {};
37
+ const stopOnMouseEnter = autoplayOptions.stopOnMouseEnter ?? false;
38
+ const stopOnInteraction = autoplayOptions.stopOnInteraction ?? !stopOnMouseEnter;
39
+ return Autoplay({
40
+ delay: autoplayOptions.delay ?? 4e3,
41
+ stopOnInteraction,
42
+ stopOnMouseEnter,
43
+ stopOnFocusIn: autoplayOptions.stopOnFocusIn ?? true,
44
+ playOnInit: true
45
+ });
46
+ }
47
+ function syncFromEmbla(store, id) {
48
+ const instance = store.instances[id];
49
+ const embla = instance?.embla;
50
+ if (!(instance && embla)) {
51
+ return;
52
+ }
53
+ const previousIndex = instance.currentIndex;
54
+ instance.currentIndex = embla.selectedScrollSnap();
55
+ instance.totalSlides = embla.scrollSnapList().length;
56
+ instance.progress = embla.scrollProgress();
57
+ instance.canNext = embla.canScrollNext();
58
+ instance.canPrevious = embla.canScrollPrev();
59
+ instance.slidesInView = embla.slidesInView();
60
+ instance.isFirst = instance.currentIndex === 0;
61
+ instance.isLast = instance.totalSlides > 0 && instance.currentIndex === instance.totalSlides - 1;
62
+ instance.isPlaying = instance.autoplay?.isPlaying() ?? false;
63
+ if (previousIndex !== instance.currentIndex) {
64
+ instance.options.onChange?.(instance.currentIndex);
65
+ }
66
+ }
67
+ function destroyEmbla(instance, id, cleanups) {
68
+ cleanups.get(id)?.();
69
+ cleanups.delete(id);
70
+ instance.embla?.destroy();
71
+ instance.embla = null;
72
+ instance.autoplay = null;
73
+ instance.viewport = null;
74
+ }
75
+ function addCleanup(id, cleanups, cleanup) {
76
+ const previous = cleanups.get(id);
77
+ cleanups.set(id, () => {
78
+ previous?.();
79
+ cleanup();
80
+ });
81
+ }
82
+ function setupVisibilityAutoplay(id, instance, cleanups) {
83
+ const stopWhenHidden = instance.options.autoplayOptions?.stopWhenHidden ?? true;
84
+ if (!(instance.options.autoplay && stopWhenHidden)) {
85
+ return;
86
+ }
87
+ const onVisibilityChange = () => {
88
+ if (document.hidden) {
89
+ instance.autoplay?.stop();
90
+ } else {
91
+ instance.autoplay?.play();
92
+ }
93
+ instance.isPlaying = instance.autoplay?.isPlaying() ?? false;
94
+ };
95
+ document.addEventListener("visibilitychange", onVisibilityChange);
96
+ addCleanup(
97
+ id,
98
+ cleanups,
99
+ () => document.removeEventListener("visibilitychange", onVisibilityChange)
100
+ );
101
+ }
102
+ function setupResizeObserver(viewport, store, id, cleanups) {
103
+ if (typeof ResizeObserver === "undefined") {
104
+ return;
105
+ }
106
+ const observer = new ResizeObserver(() => {
107
+ store.instances[id]?.embla?.reInit();
108
+ syncFromEmbla(store, id);
109
+ });
110
+ observer.observe(viewport);
111
+ addCleanup(id, cleanups, () => observer.disconnect());
112
+ }
113
+ function getOrCreate(store, id, options) {
114
+ if (!store.instances[id]) {
115
+ store.instances[id] = createInstance(options);
116
+ } else if (options) {
117
+ store.instances[id].options = { ...store.instances[id].options, ...options };
118
+ store.instances[id].ariaLive = options.ariaLive ?? store.instances[id].ariaLive;
119
+ }
120
+ return store.instances[id];
121
+ }
122
+ function initEmbla(store, id, viewport, cleanups) {
123
+ const instance = store.instances[id];
124
+ if (!instance) {
125
+ return;
126
+ }
127
+ destroyEmbla(instance, id, cleanups);
128
+ instance.viewport = viewport;
129
+ const plugins = [];
130
+ const autoplay = createAutoplayPlugin(instance.options);
131
+ if (autoplay) {
132
+ plugins.push(autoplay);
133
+ instance.autoplay = autoplay;
134
+ }
135
+ const embla = EmblaCarousel(viewport, toEmblaOptions(instance.options), plugins);
136
+ instance.embla = embla;
137
+ const sync = () => syncFromEmbla(store, id);
138
+ embla.on("select", sync);
139
+ embla.on("scroll", sync);
140
+ embla.on("reInit", sync);
141
+ embla.on("autoplay:play", sync);
142
+ embla.on("autoplay:stop", sync);
143
+ sync();
144
+ setupResizeObserver(viewport, store, id, cleanups);
145
+ setupVisibilityAutoplay(id, instance, cleanups);
146
+ if (typeof requestAnimationFrame !== "undefined") {
147
+ requestAnimationFrame(() => {
148
+ instance.embla?.reInit();
149
+ syncFromEmbla(store, id);
150
+ });
151
+ }
152
+ }
153
+ function createCarouselStore() {
154
+ const cleanups = /* @__PURE__ */ new Map();
155
+ const store = {
156
+ instances: {},
157
+ create(id, options = {}) {
158
+ getOrCreate(this, id, options);
159
+ },
160
+ destroy(id) {
161
+ const instance = this.instances[id];
162
+ if (!instance) {
163
+ return;
164
+ }
165
+ destroyEmbla(instance, id, cleanups);
166
+ delete this.instances[id];
167
+ },
168
+ bindViewport(id, viewport) {
169
+ if (typeof window === "undefined" || typeof document === "undefined") {
170
+ return;
171
+ }
172
+ if (!viewport) {
173
+ const instance = this.instances[id];
174
+ if (instance) {
175
+ destroyEmbla(instance, id, cleanups);
176
+ }
177
+ return;
178
+ }
179
+ getOrCreate(this, id);
180
+ initEmbla(this, id, viewport, cleanups);
181
+ },
182
+ next(id) {
183
+ this.instances[id]?.embla?.scrollNext();
184
+ },
185
+ previous(id) {
186
+ this.instances[id]?.embla?.scrollPrev();
187
+ },
188
+ goTo(id, index) {
189
+ this.instances[id]?.embla?.scrollTo(index);
190
+ },
191
+ current(id) {
192
+ return this.instances[id]?.currentIndex ?? 0;
193
+ },
194
+ count(id) {
195
+ return this.instances[id]?.totalSlides ?? 0;
196
+ },
197
+ canNext(id) {
198
+ return this.instances[id]?.canNext ?? false;
199
+ },
200
+ canPrevious(id) {
201
+ return this.instances[id]?.canPrevious ?? false;
202
+ },
203
+ play(id) {
204
+ this.instances[id]?.autoplay?.play();
205
+ const instance = this.instances[id];
206
+ if (instance) {
207
+ instance.isPlaying = instance.autoplay?.isPlaying() ?? false;
208
+ }
209
+ },
210
+ pause(id) {
211
+ this.instances[id]?.autoplay?.stop();
212
+ const instance = this.instances[id];
213
+ if (instance) {
214
+ instance.isPlaying = instance.autoplay?.isPlaying() ?? false;
215
+ }
216
+ },
217
+ isPlaying(id) {
218
+ return this.instances[id]?.isPlaying ?? false;
219
+ },
220
+ instance(id) {
221
+ return this.instances[id]?.embla ?? null;
222
+ },
223
+ handleKeydown(id, event) {
224
+ const instance = this.instances[id];
225
+ if (!instance?.embla) {
226
+ return;
227
+ }
228
+ switch (event.key) {
229
+ case "ArrowLeft":
230
+ case "ArrowUp":
231
+ event.preventDefault();
232
+ this.previous(id);
233
+ break;
234
+ case "ArrowRight":
235
+ case "ArrowDown":
236
+ event.preventDefault();
237
+ this.next(id);
238
+ break;
239
+ case "Home":
240
+ event.preventDefault();
241
+ this.goTo(id, 0);
242
+ break;
243
+ case "End": {
244
+ event.preventDefault();
245
+ const last = this.count(id) - 1;
246
+ if (last >= 0) {
247
+ this.goTo(id, last);
248
+ }
249
+ break;
250
+ }
251
+ default:
252
+ break;
253
+ }
254
+ },
255
+ carouselProps(id, options = {}) {
256
+ const instance = this.instances[id];
257
+ return {
258
+ role: "region",
259
+ "aria-roledescription": "carousel",
260
+ "aria-live": instance?.ariaLive ?? "polite",
261
+ "aria-label": options.label
262
+ };
263
+ },
264
+ viewportProps(_id, options = {}) {
265
+ const props = {
266
+ tabindex: 0
267
+ };
268
+ if (options.slideSize !== false) {
269
+ props.style = `--slide-size: ${options.slideSize ?? "100%"}`;
270
+ }
271
+ return props;
272
+ },
273
+ slideProps(id, index) {
274
+ const current = this.current(id);
275
+ const total = this.count(id);
276
+ return {
277
+ role: "group",
278
+ "aria-roledescription": "slide",
279
+ "aria-label": `${index + 1} of ${total}`,
280
+ "aria-hidden": current !== index ? true : void 0
281
+ };
282
+ },
283
+ indicatorProps(id, index) {
284
+ const selected = this.current(id) === index;
285
+ return {
286
+ type: "button",
287
+ "aria-label": `Go to slide ${index + 1}`,
288
+ "aria-current": selected ? "true" : void 0
289
+ };
290
+ },
291
+ destroyAll() {
292
+ for (const id of Object.keys(this.instances)) {
293
+ this.destroy(id);
294
+ }
295
+ }
296
+ };
297
+ return store;
298
+ }
299
+
300
+ // src/index.ts
301
+ function carouselPlugin() {
302
+ return function registerCarousel(Alpine) {
303
+ const store = createCarouselStore();
304
+ Alpine.store("carousel", store);
305
+ Alpine.magic("carousel", () => Alpine.store("carousel"));
306
+ };
307
+ }
308
+ export {
309
+ createCarouselStore,
310
+ carouselPlugin as default
311
+ };
312
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/store.ts","../src/index.ts"],"sourcesContent":["import EmblaCarousel, { type EmblaCarouselType, type EmblaOptionsType } from \"embla-carousel\";\nimport Autoplay, { type AutoplayType } from \"embla-carousel-autoplay\";\n\nexport type CarouselAutoplayOptions = {\n delay?: number;\n stopOnInteraction?: boolean;\n stopOnMouseEnter?: boolean;\n stopOnFocusIn?: boolean;\n stopWhenHidden?: boolean;\n};\n\nexport type CarouselOptions = {\n loop?: boolean;\n autoplay?: boolean;\n autoplayOptions?: CarouselAutoplayOptions;\n axis?: \"x\" | \"y\";\n align?: EmblaOptionsType[\"align\"];\n containScroll?: EmblaOptionsType[\"containScroll\"];\n dragFree?: boolean;\n duration?: number;\n ariaLive?: \"off\" | \"polite\" | \"assertive\";\n onChange?: (index: number) => void;\n};\n\nexport type CarouselInstance = {\n currentIndex: number;\n totalSlides: number;\n progress: number;\n isFirst: boolean;\n isLast: boolean;\n isPlaying: boolean;\n canNext: boolean;\n canPrevious: boolean;\n slidesInView: number[];\n options: CarouselOptions;\n ariaLive: \"off\" | \"polite\" | \"assertive\";\n viewport: HTMLElement | null;\n embla: EmblaCarouselType | null;\n autoplay: AutoplayType | null;\n};\n\nexport type CarouselStore = {\n instances: Record<string, CarouselInstance>;\n create(id: string, options?: CarouselOptions): void;\n destroy(id: string): void;\n bindViewport(id: string, viewport: HTMLElement | null): void;\n next(id: string): void;\n previous(id: string): void;\n goTo(id: string, index: number): void;\n current(id: string): number;\n count(id: string): number;\n canNext(id: string): boolean;\n canPrevious(id: string): boolean;\n play(id: string): void;\n pause(id: string): void;\n isPlaying(id: string): boolean;\n instance(id: string): EmblaCarouselType | null;\n handleKeydown(id: string, event: KeyboardEvent): void;\n carouselProps(\n id: string,\n options?: { label?: string }\n ): Record<string, string | boolean | undefined>;\n viewportProps(\n id: string,\n options?: { slideSize?: string | false }\n ): Record<string, string | number | boolean | undefined>;\n slideProps(id: string, index: number): Record<string, string | boolean | undefined>;\n indicatorProps(id: string, index: number): Record<string, string | boolean | undefined>;\n destroyAll(): void;\n};\n\nfunction createInstance(options: CarouselOptions = {}): CarouselInstance {\n return {\n currentIndex: 0,\n totalSlides: 0,\n progress: 0,\n isFirst: true,\n isLast: false,\n isPlaying: false,\n canNext: false,\n canPrevious: false,\n slidesInView: [],\n options,\n ariaLive: options.ariaLive ?? \"polite\",\n viewport: null,\n embla: null,\n autoplay: null,\n };\n}\n\nfunction toEmblaOptions(options: CarouselOptions): EmblaOptionsType {\n return {\n loop: options.loop ?? false,\n axis: options.axis ?? \"x\",\n align: options.align ?? \"start\",\n containScroll: options.containScroll ?? \"trimSnaps\",\n dragFree: options.dragFree ?? false,\n duration: options.duration ?? 25,\n };\n}\n\nfunction createAutoplayPlugin(options: CarouselOptions): AutoplayType | null {\n if (!options.autoplay) {\n return null;\n }\n\n const autoplayOptions = options.autoplayOptions ?? {};\n const stopOnMouseEnter = autoplayOptions.stopOnMouseEnter ?? false;\n const stopOnInteraction = autoplayOptions.stopOnInteraction ?? !stopOnMouseEnter;\n\n return Autoplay({\n delay: autoplayOptions.delay ?? 4000,\n stopOnInteraction,\n stopOnMouseEnter,\n stopOnFocusIn: autoplayOptions.stopOnFocusIn ?? true,\n playOnInit: true,\n });\n}\n\nfunction syncFromEmbla(store: CarouselStore, id: string): void {\n const instance = store.instances[id];\n const embla = instance?.embla;\n if (!(instance && embla)) {\n return;\n }\n\n const previousIndex = instance.currentIndex;\n instance.currentIndex = embla.selectedScrollSnap();\n instance.totalSlides = embla.scrollSnapList().length;\n instance.progress = embla.scrollProgress();\n instance.canNext = embla.canScrollNext();\n instance.canPrevious = embla.canScrollPrev();\n instance.slidesInView = embla.slidesInView();\n instance.isFirst = instance.currentIndex === 0;\n instance.isLast = instance.totalSlides > 0 && instance.currentIndex === instance.totalSlides - 1;\n instance.isPlaying = instance.autoplay?.isPlaying() ?? false;\n\n if (previousIndex !== instance.currentIndex) {\n instance.options.onChange?.(instance.currentIndex);\n }\n}\n\nfunction destroyEmbla(\n instance: CarouselInstance,\n id: string,\n cleanups: Map<string, () => void>\n): void {\n cleanups.get(id)?.();\n cleanups.delete(id);\n instance.embla?.destroy();\n instance.embla = null;\n instance.autoplay = null;\n instance.viewport = null;\n}\n\nfunction addCleanup(id: string, cleanups: Map<string, () => void>, cleanup: () => void): void {\n const previous = cleanups.get(id);\n cleanups.set(id, () => {\n previous?.();\n cleanup();\n });\n}\n\nfunction setupVisibilityAutoplay(\n id: string,\n instance: CarouselInstance,\n cleanups: Map<string, () => void>\n): void {\n const stopWhenHidden = instance.options.autoplayOptions?.stopWhenHidden ?? true;\n if (!(instance.options.autoplay && stopWhenHidden)) {\n return;\n }\n\n const onVisibilityChange = () => {\n if (document.hidden) {\n instance.autoplay?.stop();\n } else {\n instance.autoplay?.play();\n }\n instance.isPlaying = instance.autoplay?.isPlaying() ?? false;\n };\n\n document.addEventListener(\"visibilitychange\", onVisibilityChange);\n addCleanup(id, cleanups, () =>\n document.removeEventListener(\"visibilitychange\", onVisibilityChange)\n );\n}\n\nfunction setupResizeObserver(\n viewport: HTMLElement,\n store: CarouselStore,\n id: string,\n cleanups: Map<string, () => void>\n): void {\n if (typeof ResizeObserver === \"undefined\") {\n return;\n }\n\n const observer = new ResizeObserver(() => {\n store.instances[id]?.embla?.reInit();\n syncFromEmbla(store, id);\n });\n observer.observe(viewport);\n addCleanup(id, cleanups, () => observer.disconnect());\n}\n\nfunction getOrCreate(\n store: CarouselStore,\n id: string,\n options?: CarouselOptions\n): CarouselInstance {\n if (!store.instances[id]) {\n store.instances[id] = createInstance(options);\n } else if (options) {\n store.instances[id].options = { ...store.instances[id].options, ...options };\n store.instances[id].ariaLive = options.ariaLive ?? store.instances[id].ariaLive;\n }\n return store.instances[id];\n}\n\nfunction initEmbla(\n store: CarouselStore,\n id: string,\n viewport: HTMLElement,\n cleanups: Map<string, () => void>\n): void {\n const instance = store.instances[id];\n if (!instance) {\n return;\n }\n\n destroyEmbla(instance, id, cleanups);\n instance.viewport = viewport;\n\n const plugins = [];\n const autoplay = createAutoplayPlugin(instance.options);\n if (autoplay) {\n plugins.push(autoplay);\n instance.autoplay = autoplay;\n }\n\n const embla = EmblaCarousel(viewport, toEmblaOptions(instance.options), plugins);\n instance.embla = embla;\n\n const sync = () => syncFromEmbla(store, id);\n embla.on(\"select\", sync);\n embla.on(\"scroll\", sync);\n embla.on(\"reInit\", sync);\n embla.on(\"autoplay:play\", sync);\n embla.on(\"autoplay:stop\", sync);\n sync();\n setupResizeObserver(viewport, store, id, cleanups);\n setupVisibilityAutoplay(id, instance, cleanups);\n\n if (typeof requestAnimationFrame !== \"undefined\") {\n requestAnimationFrame(() => {\n instance.embla?.reInit();\n syncFromEmbla(store, id);\n });\n }\n}\n\n/** Creates the headless carousel store powered by Embla Carousel. */\nexport function createCarouselStore(): CarouselStore {\n const cleanups = new Map<string, () => void>();\n\n const store: CarouselStore = {\n instances: {},\n\n create(id, options = {}) {\n getOrCreate(this, id, options);\n },\n\n destroy(id) {\n const instance = this.instances[id];\n if (!instance) {\n return;\n }\n destroyEmbla(instance, id, cleanups);\n delete this.instances[id];\n },\n\n bindViewport(id, viewport) {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n if (!viewport) {\n const instance = this.instances[id];\n if (instance) {\n destroyEmbla(instance, id, cleanups);\n }\n return;\n }\n\n getOrCreate(this, id);\n initEmbla(this, id, viewport, cleanups);\n },\n\n next(id) {\n this.instances[id]?.embla?.scrollNext();\n },\n\n previous(id) {\n this.instances[id]?.embla?.scrollPrev();\n },\n\n goTo(id, index) {\n this.instances[id]?.embla?.scrollTo(index);\n },\n\n current(id) {\n return this.instances[id]?.currentIndex ?? 0;\n },\n\n count(id) {\n return this.instances[id]?.totalSlides ?? 0;\n },\n\n canNext(id) {\n return this.instances[id]?.canNext ?? false;\n },\n\n canPrevious(id) {\n return this.instances[id]?.canPrevious ?? false;\n },\n\n play(id) {\n this.instances[id]?.autoplay?.play();\n const instance = this.instances[id];\n if (instance) {\n instance.isPlaying = instance.autoplay?.isPlaying() ?? false;\n }\n },\n\n pause(id) {\n this.instances[id]?.autoplay?.stop();\n const instance = this.instances[id];\n if (instance) {\n instance.isPlaying = instance.autoplay?.isPlaying() ?? false;\n }\n },\n\n isPlaying(id) {\n return this.instances[id]?.isPlaying ?? false;\n },\n\n instance(id) {\n return this.instances[id]?.embla ?? null;\n },\n\n handleKeydown(id, event) {\n const instance = this.instances[id];\n if (!instance?.embla) {\n return;\n }\n\n switch (event.key) {\n case \"ArrowLeft\":\n case \"ArrowUp\":\n event.preventDefault();\n this.previous(id);\n break;\n case \"ArrowRight\":\n case \"ArrowDown\":\n event.preventDefault();\n this.next(id);\n break;\n case \"Home\":\n event.preventDefault();\n this.goTo(id, 0);\n break;\n case \"End\": {\n event.preventDefault();\n const last = this.count(id) - 1;\n if (last >= 0) {\n this.goTo(id, last);\n }\n break;\n }\n default:\n break;\n }\n },\n\n carouselProps(id, options = {}) {\n const instance = this.instances[id];\n return {\n role: \"region\",\n \"aria-roledescription\": \"carousel\",\n \"aria-live\": instance?.ariaLive ?? \"polite\",\n \"aria-label\": options.label,\n };\n },\n\n viewportProps(_id, options = {}) {\n const props: Record<string, string | number | boolean | undefined> = {\n tabindex: 0,\n };\n\n if (options.slideSize !== false) {\n props.style = `--slide-size: ${options.slideSize ?? \"100%\"}`;\n }\n\n return props;\n },\n\n slideProps(id, index) {\n const current = this.current(id);\n const total = this.count(id);\n return {\n role: \"group\",\n \"aria-roledescription\": \"slide\",\n \"aria-label\": `${index + 1} of ${total}`,\n \"aria-hidden\": current !== index ? true : undefined,\n };\n },\n\n indicatorProps(id, index) {\n const selected = this.current(id) === index;\n return {\n type: \"button\",\n \"aria-label\": `Go to slide ${index + 1}`,\n \"aria-current\": selected ? \"true\" : undefined,\n };\n },\n\n destroyAll() {\n for (const id of Object.keys(this.instances)) {\n this.destroy(id);\n }\n },\n };\n\n return store;\n}\n","import type AlpineType from \"alpinejs\";\nimport { type CarouselStore, createCarouselStore } from \"./store.js\";\n\nexport {\n type CarouselAutoplayOptions,\n type CarouselInstance,\n type CarouselOptions,\n type CarouselStore,\n createCarouselStore,\n} from \"./store.js\";\n\n/** Alpine.js carousel plugin. Registers `$store.carousel`. */\nexport default function carouselPlugin(): AlpineType.PluginCallback {\n return function registerCarousel(Alpine) {\n const store = createCarouselStore();\n Alpine.store(\"carousel\", store);\n Alpine.magic(\"carousel\", () => Alpine.store(\"carousel\"));\n };\n}\n\ndeclare global {\n namespace Alpine {\n interface Stores {\n carousel: CarouselStore;\n }\n interface Magics<T> {\n $carousel: CarouselStore;\n }\n }\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@ailuracode/alpine-carousel",
3
+ "version": "0.1.0",
4
+ "description": "Alpine.js headless accessible carousel store powered by Embla Carousel",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "ailuracode",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/ailuracode/alpinejs-toolkit.git",
14
+ "directory": "packages/carousel"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/ailuracode/alpinejs-toolkit/issues"
18
+ },
19
+ "homepage": "https://github.com/ailuracode/alpinejs-toolkit/tree/master/packages/carousel#readme",
20
+ "files": [
21
+ "dist",
22
+ "README.md"
23
+ ],
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "default": "./dist/index.js"
28
+ },
29
+ "./global": {
30
+ "types": "./dist/global.d.ts"
31
+ }
32
+ },
33
+ "types": "./dist/global.d.ts",
34
+ "dependencies": {
35
+ "embla-carousel": "^8.6.0",
36
+ "embla-carousel-autoplay": "^8.6.0"
37
+ },
38
+ "peerDependencies": {
39
+ "alpinejs": "^3.0.0",
40
+ "@types/alpinejs": "^3.13.11"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "@types/alpinejs": {
44
+ "optional": true
45
+ }
46
+ },
47
+ "keywords": [
48
+ "alpinejs",
49
+ "alpine",
50
+ "plugin",
51
+ "carousel",
52
+ "slider",
53
+ "embla",
54
+ "accessibility",
55
+ "headless"
56
+ ],
57
+ "scripts": {
58
+ "build": "tsup src/index.ts --format esm --dts --clean --sourcemap --out-dir dist && cp src/global.d.ts dist/global.d.ts",
59
+ "test": "vitest run --config ../../vitest.config.ts test"
60
+ }
61
+ }