@destyler/carousel 0.0.7-beta.7 → 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/dist/index.js ADDED
@@ -0,0 +1,718 @@
1
+ import { createAnatomy } from "@destyler/anatomy";
2
+ import { addDomEvent, ariaAttr, createScope, dataAttr, getEventKey, getEventTarget, getTabbables, isFocusable, queryAll, raf, trackPointerMove } from "@destyler/dom";
3
+ import { findSnapPoint, getScrollSnapPositions } from "@destyler/scroll-snap";
4
+ import { add, compact, createSplitProps, isEqual, isObject, nextIndex, prevIndex, remove, uniq } from "@destyler/utils";
5
+ import { createMachine, ref } from "@destyler/xstate";
6
+ import { createProps } from "@destyler/types";
7
+
8
+ //#region src/anatomy.ts
9
+ const anatomy = createAnatomy("carousel").parts("root", "itemGroup", "item", "control", "nextTrigger", "prevTrigger", "indicatorGroup", "indicator", "autoplayTrigger");
10
+ const parts = anatomy.build();
11
+
12
+ //#endregion
13
+ //#region src/dom.ts
14
+ const dom = createScope({
15
+ getRootId: (ctx) => ctx.ids?.root ?? `carousel:${ctx.id}`,
16
+ getItemId: (ctx, index) => ctx.ids?.item?.(index) ?? `carousel:${ctx.id}:item:${index}`,
17
+ getItemGroupId: (ctx) => ctx.ids?.itemGroup ?? `carousel:${ctx.id}:item-group`,
18
+ getNextTriggerId: (ctx) => ctx.ids?.nextTrigger ?? `carousel:${ctx.id}:next-trigger`,
19
+ getPrevTriggerId: (ctx) => ctx.ids?.prevTrigger ?? `carousel:${ctx.id}:prev-trigger`,
20
+ getIndicatorGroupId: (ctx) => ctx.ids?.indicatorGroup ?? `carousel:${ctx.id}:indicator-group`,
21
+ getIndicatorId: (ctx, index) => ctx.ids?.indicator?.(index) ?? `carousel:${ctx.id}:indicator:${index}`,
22
+ getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
23
+ getItemGroupEl: (ctx) => dom.getById(ctx, dom.getItemGroupId(ctx)),
24
+ getItemEl: (ctx, index) => dom.getById(ctx, dom.getItemId(ctx, index)),
25
+ getItemEls: (ctx) => queryAll(dom.getItemGroupEl(ctx), `[data-part=item]`),
26
+ getActiveIndicatorEl: (ctx) => dom.getById(ctx, dom.getIndicatorId(ctx, ctx.page)),
27
+ syncTabIndex(ctx) {
28
+ const el = dom.getItemGroupEl(ctx);
29
+ if (!el) return;
30
+ const tabbables = getTabbables(el);
31
+ if (tabbables.length > 0) el.removeAttribute("tabindex");
32
+ else el.setAttribute("tabindex", "0");
33
+ }
34
+ });
35
+
36
+ //#endregion
37
+ //#region src/connect.ts
38
+ function connect(state, send, normalize) {
39
+ const isPlaying = state.matches("autoplay");
40
+ const isDragging = state.matches("dragging");
41
+ const canScrollNext = state.context.canScrollNext;
42
+ const canScrollPrev = state.context.canScrollPrev;
43
+ const horizontal = state.context.isHorizontal;
44
+ const pageSnapPoints = Array.from(state.context.pageSnapPoints);
45
+ const page = state.context.page;
46
+ const slidesPerPage = state.context.slidesPerPage;
47
+ const padding = state.context.padding;
48
+ const translations = state.context.translations;
49
+ return {
50
+ isPlaying,
51
+ isDragging,
52
+ page,
53
+ pageSnapPoints,
54
+ canScrollNext,
55
+ canScrollPrev,
56
+ getProgress() {
57
+ return page / pageSnapPoints.length;
58
+ },
59
+ scrollToIndex(index, instant) {
60
+ send({
61
+ type: "INDEX.SET",
62
+ index,
63
+ instant
64
+ });
65
+ },
66
+ scrollTo(index, instant) {
67
+ send({
68
+ type: "PAGE.SET",
69
+ index,
70
+ instant
71
+ });
72
+ },
73
+ scrollNext(instant) {
74
+ send({
75
+ type: "PAGE.NEXT",
76
+ instant
77
+ });
78
+ },
79
+ scrollPrev(instant) {
80
+ send({
81
+ type: "PAGE.PREV",
82
+ instant
83
+ });
84
+ },
85
+ play() {
86
+ send("AUTOPLAY.START");
87
+ },
88
+ pause() {
89
+ send("AUTOPLAY.PAUSE");
90
+ },
91
+ isInView(index) {
92
+ return Array.from(state.context.slidesInView).includes(index);
93
+ },
94
+ refresh() {
95
+ send({ type: "SNAP.REFRESH" });
96
+ },
97
+ getRootProps() {
98
+ return normalize.element({
99
+ ...parts.root.attrs,
100
+ "id": dom.getRootId(state.context),
101
+ "role": "region",
102
+ "aria-roledescription": "carousel",
103
+ "data-orientation": state.context.orientation,
104
+ "dir": state.context.dir,
105
+ "style": {
106
+ "--slides-per-page": slidesPerPage,
107
+ "--slide-spacing": state.context.spacing,
108
+ "--slide-item-size": "calc(100% / var(--slides-per-page) - var(--slide-spacing) * (var(--slides-per-page) - 1) / var(--slides-per-page))"
109
+ }
110
+ });
111
+ },
112
+ getItemGroupProps() {
113
+ return normalize.element({
114
+ ...parts.itemGroup.attrs,
115
+ "id": dom.getItemGroupId(state.context),
116
+ "data-orientation": state.context.orientation,
117
+ "data-dragging": dataAttr(isDragging),
118
+ "dir": state.context.dir,
119
+ "aria-live": isPlaying ? "off" : "polite",
120
+ onMouseDown(event) {
121
+ if (!state.context.allowMouseDrag) return;
122
+ if (event.button !== 0) return;
123
+ if (event.defaultPrevented) return;
124
+ const target = getEventTarget(event);
125
+ if (isFocusable(target) && target !== event.currentTarget) return;
126
+ event.preventDefault();
127
+ send({ type: "DRAGGING.START" });
128
+ },
129
+ "style": {
130
+ display: "grid",
131
+ gap: "var(--slide-spacing)",
132
+ scrollSnapType: [horizontal ? "x" : "y", state.context.snapType].join(" "),
133
+ gridAutoFlow: horizontal ? "column" : "row",
134
+ scrollbarWidth: "none",
135
+ overscrollBehavior: "contain",
136
+ [horizontal ? "gridAutoColumns" : "gridAutoRows"]: "var(--slide-item-size)",
137
+ [horizontal ? "scrollPaddingInline" : "scrollPaddingBlock"]: padding,
138
+ [horizontal ? "paddingInline" : "paddingBlock"]: padding,
139
+ [horizontal ? "overflowX" : "overflowY"]: "auto"
140
+ }
141
+ });
142
+ },
143
+ getItemProps(props$1) {
144
+ const isInView = state.context.slidesInView.includes(props$1.index);
145
+ return normalize.element({
146
+ ...parts.item.attrs,
147
+ "id": dom.getItemId(state.context, props$1.index),
148
+ "dir": state.context.dir,
149
+ "role": "group",
150
+ "data-index": props$1.index,
151
+ "data-inview": dataAttr(isInView),
152
+ "aria-roledescription": "slide",
153
+ "data-orientation": state.context.orientation,
154
+ "aria-label": state.context.slideCount ? translations.item(props$1.index, state.context.slideCount) : void 0,
155
+ "aria-hidden": ariaAttr(!isInView),
156
+ "style": { scrollSnapAlign: getSnapAlign(state.context, props$1) }
157
+ });
158
+ },
159
+ getControlProps() {
160
+ return normalize.element({
161
+ ...parts.control.attrs,
162
+ "data-orientation": state.context.orientation
163
+ });
164
+ },
165
+ getPrevTriggerProps() {
166
+ return normalize.button({
167
+ ...parts.prevTrigger.attrs,
168
+ "id": dom.getPrevTriggerId(state.context),
169
+ "type": "button",
170
+ "disabled": !canScrollPrev,
171
+ "dir": state.context.dir,
172
+ "aria-label": translations.prevTrigger,
173
+ "data-orientation": state.context.orientation,
174
+ "aria-controls": dom.getItemGroupId(state.context),
175
+ onClick(event) {
176
+ if (event.defaultPrevented) return;
177
+ send({
178
+ type: "PAGE.PREV",
179
+ src: "trigger"
180
+ });
181
+ }
182
+ });
183
+ },
184
+ getNextTriggerProps() {
185
+ return normalize.button({
186
+ ...parts.nextTrigger.attrs,
187
+ "dir": state.context.dir,
188
+ "id": dom.getNextTriggerId(state.context),
189
+ "type": "button",
190
+ "aria-label": translations.nextTrigger,
191
+ "data-orientation": state.context.orientation,
192
+ "aria-controls": dom.getItemGroupId(state.context),
193
+ "disabled": !canScrollNext,
194
+ onClick(event) {
195
+ if (event.defaultPrevented) return;
196
+ send({
197
+ type: "PAGE.NEXT",
198
+ src: "trigger"
199
+ });
200
+ }
201
+ });
202
+ },
203
+ getIndicatorGroupProps() {
204
+ return normalize.element({
205
+ ...parts.indicatorGroup.attrs,
206
+ "dir": state.context.dir,
207
+ "id": dom.getIndicatorGroupId(state.context),
208
+ "data-orientation": state.context.orientation,
209
+ onKeyDown(event) {
210
+ if (event.defaultPrevented) return;
211
+ const src = "indicator";
212
+ const keyMap = {
213
+ ArrowDown(event$1) {
214
+ if (horizontal) return;
215
+ send({
216
+ type: "PAGE.NEXT",
217
+ src
218
+ });
219
+ event$1.preventDefault();
220
+ },
221
+ ArrowUp(event$1) {
222
+ if (horizontal) return;
223
+ send({
224
+ type: "PAGE.PREV",
225
+ src
226
+ });
227
+ event$1.preventDefault();
228
+ },
229
+ ArrowRight(event$1) {
230
+ if (!horizontal) return;
231
+ send({
232
+ type: "PAGE.NEXT",
233
+ src
234
+ });
235
+ event$1.preventDefault();
236
+ },
237
+ ArrowLeft(event$1) {
238
+ if (!horizontal) return;
239
+ send({
240
+ type: "PAGE.PREV",
241
+ src
242
+ });
243
+ event$1.preventDefault();
244
+ },
245
+ Home(event$1) {
246
+ send({
247
+ type: "PAGE.SET",
248
+ index: 0,
249
+ src
250
+ });
251
+ event$1.preventDefault();
252
+ },
253
+ End(event$1) {
254
+ send({
255
+ type: "PAGE.SET",
256
+ index: pageSnapPoints.length - 1,
257
+ src
258
+ });
259
+ event$1.preventDefault();
260
+ }
261
+ };
262
+ const key = getEventKey(event, {
263
+ dir: state.context.dir,
264
+ orientation: state.context.orientation
265
+ });
266
+ const exec = keyMap[key];
267
+ exec?.(event);
268
+ }
269
+ });
270
+ },
271
+ getIndicatorProps(props$1) {
272
+ return normalize.button({
273
+ ...parts.indicator.attrs,
274
+ "dir": state.context.dir,
275
+ "id": dom.getIndicatorId(state.context, props$1.index),
276
+ "type": "button",
277
+ "data-orientation": state.context.orientation,
278
+ "data-index": props$1.index,
279
+ "data-readonly": dataAttr(props$1.readOnly),
280
+ "data-current": dataAttr(props$1.index === state.context.page),
281
+ "aria-label": translations.indicator(props$1.index),
282
+ onClick(event) {
283
+ if (event.defaultPrevented) return;
284
+ if (props$1.readOnly) return;
285
+ send({
286
+ type: "PAGE.SET",
287
+ index: props$1.index,
288
+ src: "indicator"
289
+ });
290
+ }
291
+ });
292
+ },
293
+ getAutoplayTriggerProps() {
294
+ return normalize.button({
295
+ ...parts.autoplayTrigger.attrs,
296
+ "type": "button",
297
+ "data-orientation": state.context.orientation,
298
+ "data-pressed": dataAttr(isPlaying),
299
+ "aria-label": isPlaying ? translations.autoplayStop : translations.autoplayStart,
300
+ onClick(event) {
301
+ if (event.defaultPrevented) return;
302
+ send({ type: isPlaying ? "AUTOPLAY.PAUSE" : "AUTOPLAY.START" });
303
+ }
304
+ });
305
+ }
306
+ };
307
+ }
308
+ function getSnapAlign(ctx, props$1) {
309
+ const { snapAlign = "start", index } = props$1;
310
+ const perMove = ctx.slidesPerMove === "auto" ? Math.floor(ctx.slidesPerPage) : ctx.slidesPerMove;
311
+ const shouldSnap = (index + perMove) % perMove === 0;
312
+ return shouldSnap ? snapAlign : void 0;
313
+ }
314
+
315
+ //#endregion
316
+ //#region src/machine.ts
317
+ const DEFAULT_SLIDES_PER_PAGE = 1;
318
+ const DEFAULT_SLIDES_PER_MOVE = "auto";
319
+ const invoke = { pageChange: (ctx) => {
320
+ ctx.onPageChange?.({
321
+ page: ctx.page,
322
+ pageSnapPoint: ctx.pageSnapPoints[ctx.page]
323
+ });
324
+ } };
325
+ const set = { page: (ctx, value) => {
326
+ const page = clamp(value, 0, ctx.pageSnapPoints.length - 1);
327
+ if (isEqual(ctx.page, page)) return;
328
+ ctx.page = page;
329
+ invoke.pageChange(ctx);
330
+ } };
331
+ function clamp(value, min, max) {
332
+ return Math.min(Math.max(value, min), max);
333
+ }
334
+ function getPageSnapPoints(totalSlides, slidesPerMove, slidesPerPage) {
335
+ if (totalSlides == null) return [];
336
+ const snapPoints = [];
337
+ const perMove = slidesPerMove === "auto" ? Math.floor(slidesPerPage) : slidesPerMove;
338
+ for (let i = 0; i < totalSlides - 1; i += perMove) snapPoints.push(i);
339
+ return snapPoints;
340
+ }
341
+ function machine(userContext) {
342
+ const ctx = compact(userContext);
343
+ return createMachine({
344
+ id: "carousel",
345
+ initial: ctx.autoplay ? "autoplay" : "idle",
346
+ context: {
347
+ dir: "ltr",
348
+ page: 0,
349
+ orientation: "horizontal",
350
+ snapType: "mandatory",
351
+ loop: false,
352
+ slidesPerPage: DEFAULT_SLIDES_PER_PAGE,
353
+ slidesPerMove: DEFAULT_SLIDES_PER_MOVE,
354
+ spacing: "0px",
355
+ autoplay: false,
356
+ allowMouseDrag: false,
357
+ inViewThreshold: .6,
358
+ ...ctx,
359
+ timeoutRef: ref({ current: void 0 }),
360
+ translations: {
361
+ nextTrigger: "Next slide",
362
+ prevTrigger: "Previous slide",
363
+ indicator: (index) => `Go to slide ${index + 1}`,
364
+ item: (index, count) => `${index + 1} of ${count}`,
365
+ autoplayStart: "Start slide rotation",
366
+ autoplayStop: "Stop slide rotation",
367
+ ...ctx.translations
368
+ },
369
+ pageSnapPoints: getPageSnapPoints(ctx.slideCount, ctx.slidesPerMove ?? DEFAULT_SLIDES_PER_MOVE, ctx.slidesPerPage ?? DEFAULT_SLIDES_PER_PAGE),
370
+ slidesInView: []
371
+ },
372
+ computed: {
373
+ isRtl: (ctx$1) => ctx$1.dir === "rtl",
374
+ isHorizontal: (ctx$1) => ctx$1.orientation === "horizontal",
375
+ canScrollNext: (ctx$1) => ctx$1.loop || ctx$1.page < ctx$1.pageSnapPoints.length - 1,
376
+ canScrollPrev: (ctx$1) => ctx$1.loop || ctx$1.page > 0,
377
+ autoplayInterval: (ctx$1) => isObject(ctx$1.autoplay) ? ctx$1.autoplay.delay : 4e3
378
+ },
379
+ watch: {
380
+ slidesPerPage: ["setSnapPoints"],
381
+ slidesPerMove: ["setSnapPoints"],
382
+ page: ["scrollToPage", "focusIndicatorEl"],
383
+ orientation: ["setSnapPoints", "scrollToPage"]
384
+ },
385
+ on: {
386
+ "PAGE.NEXT": {
387
+ target: "idle",
388
+ actions: ["clearScrollEndTimer", "setNextPage"]
389
+ },
390
+ "PAGE.PREV": {
391
+ target: "idle",
392
+ actions: ["clearScrollEndTimer", "setPrevPage"]
393
+ },
394
+ "PAGE.SET": {
395
+ target: "idle",
396
+ actions: ["clearScrollEndTimer", "setPage"]
397
+ },
398
+ "INDEX.SET": {
399
+ target: "idle",
400
+ actions: ["clearScrollEndTimer", "setMatchingPage"]
401
+ },
402
+ "SNAP.REFRESH": { actions: ["setSnapPoints", "clampPage"] }
403
+ },
404
+ activities: [
405
+ "trackSlideMutation",
406
+ "trackSlideIntersections",
407
+ "trackSlideResize"
408
+ ],
409
+ entry: [
410
+ "resetScrollPosition",
411
+ "setSnapPoints",
412
+ "setPage"
413
+ ],
414
+ exit: ["clearScrollEndTimer"],
415
+ states: {
416
+ idle: {
417
+ activities: ["trackScroll"],
418
+ on: {
419
+ "DRAGGING.START": {
420
+ target: "dragging",
421
+ actions: ["invokeDragStart"]
422
+ },
423
+ "AUTOPLAY.START": {
424
+ target: "autoplay",
425
+ actions: ["invokeAutoplayStart"]
426
+ }
427
+ }
428
+ },
429
+ dragging: {
430
+ activities: ["trackPointerMove"],
431
+ entry: ["disableScrollSnap"],
432
+ on: {
433
+ "DRAGGING": { actions: ["scrollSlides", "invokeDragging"] },
434
+ "DRAGGING.END": {
435
+ target: "idle",
436
+ actions: ["endDragging", "invokeDraggingEnd"]
437
+ }
438
+ }
439
+ },
440
+ autoplay: {
441
+ activities: ["trackDocumentVisibility", "trackScroll"],
442
+ exit: ["invokeAutoplayEnd"],
443
+ every: { AUTOPLAY_INTERVAL: ["setNextPage", "invokeAutoplay"] },
444
+ on: {
445
+ "DRAGGING.START": {
446
+ target: "dragging",
447
+ actions: ["invokeDragStart"]
448
+ },
449
+ "AUTOPLAY.PAUSE": "idle"
450
+ }
451
+ }
452
+ }
453
+ }, {
454
+ activities: {
455
+ trackSlideMutation(ctx$1, _evt, { send }) {
456
+ const el = dom.getItemGroupEl(ctx$1);
457
+ if (!el) return;
458
+ const win = dom.getWin(ctx$1);
459
+ const observer = new win.MutationObserver(() => {
460
+ send({
461
+ type: "SNAP.REFRESH",
462
+ src: "slide.mutation"
463
+ });
464
+ dom.syncTabIndex(ctx$1);
465
+ });
466
+ dom.syncTabIndex(ctx$1);
467
+ observer.observe(el, {
468
+ childList: true,
469
+ subtree: true
470
+ });
471
+ return () => observer.disconnect();
472
+ },
473
+ trackSlideResize(ctx$1, _evt, { send }) {
474
+ const el = dom.getItemGroupEl(ctx$1);
475
+ if (!el) return;
476
+ const win = dom.getWin(ctx$1);
477
+ const observer = new win.ResizeObserver(() => {
478
+ send({
479
+ type: "SNAP.REFRESH",
480
+ src: "slide.resize"
481
+ });
482
+ });
483
+ dom.getItemEls(ctx$1).forEach((slide) => observer.observe(slide));
484
+ return () => observer.disconnect();
485
+ },
486
+ trackSlideIntersections(ctx$1) {
487
+ const el = dom.getItemGroupEl(ctx$1);
488
+ const win = dom.getWin(ctx$1);
489
+ const observer = new win.IntersectionObserver((entries) => {
490
+ const slidesInView = entries.reduce((acc, entry) => {
491
+ const target = entry.target;
492
+ const index = Number(target.dataset.index ?? "-1");
493
+ if (index == null || Number.isNaN(index) || index === -1) return acc;
494
+ return entry.isIntersecting ? add(acc, index) : remove(acc, index);
495
+ }, ctx$1.slidesInView);
496
+ ctx$1.slidesInView = uniq(slidesInView);
497
+ }, {
498
+ root: el,
499
+ threshold: ctx$1.inViewThreshold
500
+ });
501
+ dom.getItemEls(ctx$1).forEach((slide) => observer.observe(slide));
502
+ return () => observer.disconnect();
503
+ },
504
+ trackScroll(ctx$1) {
505
+ const el = dom.getItemGroupEl(ctx$1);
506
+ if (!el) return;
507
+ const onScrollEnd = () => {
508
+ if (ctx$1.slidesInView.length === 0) return;
509
+ const scrollPosition = ctx$1.isHorizontal ? el.scrollLeft : el.scrollTop;
510
+ const page = ctx$1.pageSnapPoints.findIndex((point) => Math.abs(point - scrollPosition) < 1);
511
+ if (page === -1) return;
512
+ set.page(ctx$1, page);
513
+ };
514
+ const onScroll = () => {
515
+ clearTimeout(ctx$1.timeoutRef.current);
516
+ ctx$1.timeoutRef.current = setTimeout(() => {
517
+ onScrollEnd?.();
518
+ }, 150);
519
+ };
520
+ return addDomEvent(el, "scroll", onScroll, { passive: true });
521
+ },
522
+ trackDocumentVisibility(ctx$1, _evt, { send }) {
523
+ const doc = dom.getDoc(ctx$1);
524
+ const onVisibilityChange = () => {
525
+ if (doc.visibilityState === "visible") return;
526
+ send({
527
+ type: "AUTOPLAY.PAUSE",
528
+ src: "doc.hidden"
529
+ });
530
+ };
531
+ return addDomEvent(doc, "visibilitychange", onVisibilityChange);
532
+ },
533
+ trackPointerMove(ctx$1, _evt, { send }) {
534
+ const doc = dom.getDoc(ctx$1);
535
+ return trackPointerMove(doc, {
536
+ onPointerMove({ event }) {
537
+ send({
538
+ type: "DRAGGING",
539
+ left: -event.movementX,
540
+ top: -event.movementY
541
+ });
542
+ },
543
+ onPointerUp() {
544
+ send({ type: "DRAGGING.END" });
545
+ }
546
+ });
547
+ }
548
+ },
549
+ actions: {
550
+ resetScrollPosition(ctx$1) {
551
+ const el = dom.getItemGroupEl(ctx$1);
552
+ el.scrollTo(0, 0);
553
+ },
554
+ clearScrollEndTimer(ctx$1) {
555
+ if (ctx$1.timeoutRef.current == null) return;
556
+ clearTimeout(ctx$1.timeoutRef.current);
557
+ ctx$1.timeoutRef.current = void 0;
558
+ },
559
+ scrollToPage(ctx$1, evt) {
560
+ const behavior = evt.instant ? "instant" : "smooth";
561
+ const index = clamp(evt.index ?? ctx$1.page, 0, ctx$1.pageSnapPoints.length - 1);
562
+ const el = dom.getItemGroupEl(ctx$1);
563
+ const axis = ctx$1.isHorizontal ? "left" : "top";
564
+ el.scrollTo({
565
+ [axis]: ctx$1.pageSnapPoints[index],
566
+ behavior
567
+ });
568
+ },
569
+ setNextPage(ctx$1) {
570
+ const page = nextIndex(ctx$1.pageSnapPoints, ctx$1.page, { loop: ctx$1.loop });
571
+ set.page(ctx$1, page);
572
+ },
573
+ setPrevPage(ctx$1) {
574
+ const page = prevIndex(ctx$1.pageSnapPoints, ctx$1.page, { loop: ctx$1.loop });
575
+ set.page(ctx$1, page);
576
+ },
577
+ setMatchingPage(ctx$1, evt) {
578
+ const snapPoint = findSnapPoint(dom.getItemGroupEl(ctx$1), ctx$1.isHorizontal ? "x" : "y", (node) => node.dataset.index === evt.index.toString());
579
+ if (snapPoint == null) return;
580
+ const page = ctx$1.pageSnapPoints.indexOf(snapPoint);
581
+ set.page(ctx$1, page);
582
+ },
583
+ setPage(ctx$1, evt) {
584
+ set.page(ctx$1, evt.index ?? ctx$1.page);
585
+ },
586
+ clampPage(ctx$1) {
587
+ const index = clamp(ctx$1.page, 0, ctx$1.pageSnapPoints.length - 1);
588
+ set.page(ctx$1, index);
589
+ },
590
+ setSnapPoints(ctx$1) {
591
+ queueMicrotask(() => {
592
+ const el = dom.getItemGroupEl(ctx$1);
593
+ const scrollSnapPoints = getScrollSnapPositions(el);
594
+ ctx$1.pageSnapPoints = ctx$1.isHorizontal ? scrollSnapPoints.x : scrollSnapPoints.y;
595
+ });
596
+ },
597
+ disableScrollSnap(ctx$1) {
598
+ const el = dom.getItemGroupEl(ctx$1);
599
+ const styles = getComputedStyle(el);
600
+ el.dataset.scrollSnapType = styles.getPropertyValue("scroll-snap-type");
601
+ el.style.setProperty("scroll-snap-type", "none");
602
+ },
603
+ scrollSlides(ctx$1, evt) {
604
+ const el = dom.getItemGroupEl(ctx$1);
605
+ el.scrollBy({
606
+ left: evt.left,
607
+ top: evt.top,
608
+ behavior: "instant"
609
+ });
610
+ },
611
+ endDragging(ctx$1) {
612
+ const el = dom.getItemGroupEl(ctx$1);
613
+ const startX = el.scrollLeft;
614
+ const startY = el.scrollTop;
615
+ const snapPositions = getScrollSnapPositions(el);
616
+ const closestX = snapPositions.x.reduce((closest, curr) => {
617
+ return Math.abs(curr - startX) < Math.abs(closest - startX) ? curr : closest;
618
+ }, snapPositions.x[0]);
619
+ const closestY = snapPositions.y.reduce((closest, curr) => {
620
+ return Math.abs(curr - startY) < Math.abs(closest - startY) ? curr : closest;
621
+ }, snapPositions.y[0]);
622
+ raf(() => {
623
+ el.scrollTo({
624
+ left: closestX,
625
+ top: closestY,
626
+ behavior: "smooth"
627
+ });
628
+ const scrollSnapType = el.dataset.scrollSnapType;
629
+ if (scrollSnapType) {
630
+ el.style.removeProperty("scroll-snap-type");
631
+ delete el.dataset.scrollSnapType;
632
+ }
633
+ });
634
+ },
635
+ focusIndicatorEl(ctx$1, evt) {
636
+ if (evt.src !== "indicator") return;
637
+ const el = dom.getActiveIndicatorEl(ctx$1);
638
+ raf(() => el.focus({ preventScroll: true }));
639
+ },
640
+ invokeDragStart(ctx$1) {
641
+ ctx$1.onDragStatusChange?.({
642
+ type: "dragging.start",
643
+ isDragging: true,
644
+ page: ctx$1.page
645
+ });
646
+ },
647
+ invokeDragging(ctx$1) {
648
+ ctx$1.onDragStatusChange?.({
649
+ type: "dragging",
650
+ isDragging: true,
651
+ page: ctx$1.page
652
+ });
653
+ },
654
+ invokeDraggingEnd(ctx$1) {
655
+ ctx$1.onDragStatusChange?.({
656
+ type: "dragging.end",
657
+ isDragging: false,
658
+ page: ctx$1.page
659
+ });
660
+ },
661
+ invokeAutoplay(ctx$1) {
662
+ ctx$1.onAutoplayStatusChange?.({
663
+ type: "autoplay",
664
+ isPlaying: true,
665
+ page: ctx$1.page
666
+ });
667
+ },
668
+ invokeAutoplayStart(ctx$1) {
669
+ ctx$1.onAutoplayStatusChange?.({
670
+ type: "autoplay.start",
671
+ isPlaying: true,
672
+ page: ctx$1.page
673
+ });
674
+ },
675
+ invokeAutoplayEnd(ctx$1) {
676
+ ctx$1.onAutoplayStatusChange?.({
677
+ type: "autoplay.stop",
678
+ isPlaying: false,
679
+ page: ctx$1.page
680
+ });
681
+ }
682
+ },
683
+ delays: { AUTOPLAY_INTERVAL: (ctx$1) => ctx$1.autoplayInterval }
684
+ });
685
+ }
686
+
687
+ //#endregion
688
+ //#region src/props.ts
689
+ const props = createProps()([
690
+ "dir",
691
+ "getRootNode",
692
+ "id",
693
+ "ids",
694
+ "loop",
695
+ "page",
696
+ "onPageChange",
697
+ "orientation",
698
+ "slideCount",
699
+ "slidesPerPage",
700
+ "slidesPerMove",
701
+ "spacing",
702
+ "padding",
703
+ "autoplay",
704
+ "allowMouseDrag",
705
+ "inViewThreshold",
706
+ "translations",
707
+ "snapType",
708
+ "onDragStatusChange",
709
+ "onAutoplayStatusChange"
710
+ ]);
711
+ const splitProps = createSplitProps(props);
712
+ const indicatorProps = createProps()(["index", "readOnly"]);
713
+ const splitIndicatorProps = createSplitProps(indicatorProps);
714
+ const itemProps = createProps()(["index", "snapAlign"]);
715
+ const splitItemProps = createSplitProps(itemProps);
716
+
717
+ //#endregion
718
+ export { anatomy, connect, indicatorProps, itemProps, machine, props, splitIndicatorProps, splitItemProps, splitProps };