@zag-js/carousel
Advanced tools
@@ -50,2 +50,3 @@ "use strict"; | ||
| const page = context.get("page"); | ||
| const activePage = pageSnapPoints.length ? (0, import_utils.clampValue)(page, 0, pageSnapPoints.length - 1) : 0; | ||
| const slidesPerPage = prop("slidesPerPage"); | ||
@@ -57,3 +58,3 @@ const padding = prop("padding"); | ||
| isDragging, | ||
| page, | ||
| page: activePage, | ||
| pageSnapPoints, | ||
@@ -63,6 +64,6 @@ canScrollNext, | ||
| getProgress() { | ||
| return page / pageSnapPoints.length; | ||
| return activePage / pageSnapPoints.length; | ||
| }, | ||
| getProgressText() { | ||
| const details = { page: page + 1, totalPages: pageSnapPoints.length }; | ||
| const details = { page: activePage + 1, totalPages: pageSnapPoints.length }; | ||
| return translations.progressText?.(details) ?? ""; | ||
@@ -280,3 +281,3 @@ }, | ||
| "data-readonly": (0, import_dom_query.dataAttr)(props.readOnly), | ||
| "data-current": (0, import_dom_query.dataAttr)(props.index === page), | ||
| "data-current": (0, import_dom_query.dataAttr)(props.index === activePage), | ||
| "aria-label": translations.indicator(props.index), | ||
@@ -283,0 +284,0 @@ onClick(event) { |
| // src/carousel.connect.ts | ||
| import { ariaAttr, contains, dataAttr, getEventKey, getEventTarget, isFocusable, isLeftClick } from "@zag-js/dom-query"; | ||
| import { throttle } from "@zag-js/utils"; | ||
| import { clampValue, throttle } from "@zag-js/utils"; | ||
| import { parts } from "./carousel.anatomy.mjs"; | ||
@@ -16,2 +16,3 @@ import * as dom from "./carousel.dom.mjs"; | ||
| const page = context.get("page"); | ||
| const activePage = pageSnapPoints.length ? clampValue(page, 0, pageSnapPoints.length - 1) : 0; | ||
| const slidesPerPage = prop("slidesPerPage"); | ||
@@ -23,3 +24,3 @@ const padding = prop("padding"); | ||
| isDragging, | ||
| page, | ||
| page: activePage, | ||
| pageSnapPoints, | ||
@@ -29,6 +30,6 @@ canScrollNext, | ||
| getProgress() { | ||
| return page / pageSnapPoints.length; | ||
| return activePage / pageSnapPoints.length; | ||
| }, | ||
| getProgressText() { | ||
| const details = { page: page + 1, totalPages: pageSnapPoints.length }; | ||
| const details = { page: activePage + 1, totalPages: pageSnapPoints.length }; | ||
| return translations.progressText?.(details) ?? ""; | ||
@@ -246,3 +247,3 @@ }, | ||
| "data-readonly": dataAttr(props.readOnly), | ||
| "data-current": dataAttr(props.index === page), | ||
| "data-current": dataAttr(props.index === activePage), | ||
| "aria-label": translations.indicator(props.index), | ||
@@ -249,0 +250,0 @@ onClick(event) { |
+61
-12
@@ -144,3 +144,3 @@ "use strict"; | ||
| "SNAP.REFRESH": { | ||
| actions: ["setSnapPoints", "clampPage"] | ||
| actions: ["setSnapPoints"] | ||
| }, | ||
@@ -204,7 +204,27 @@ "PAGE.SCROLL": { | ||
| "DRAGGING.END": { | ||
| target: "idle", | ||
| actions: ["endDragging", "invokeDraggingEnd"] | ||
| target: "settling", | ||
| actions: ["endDragging"] | ||
| } | ||
| } | ||
| }, | ||
| settling: { | ||
| effects: ["trackSettlingScroll"], | ||
| on: { | ||
| "DRAGGING.START": { | ||
| target: "dragging", | ||
| actions: ["clearScrollEndTimer", "invokeDragStart"] | ||
| }, | ||
| "SCROLL.END": [ | ||
| { | ||
| guard: "isFocused", | ||
| target: "focus", | ||
| actions: ["clearScrollEndTimer", "setClosestPage", "invokeDraggingEnd"] | ||
| }, | ||
| { | ||
| target: "idle", | ||
| actions: ["clearScrollEndTimer", "setClosestPage", "invokeDraggingEnd"] | ||
| } | ||
| ] | ||
| } | ||
| }, | ||
| userScroll: { | ||
@@ -287,3 +307,3 @@ effects: ["trackScroll"], | ||
| itemEls.forEach(exec); | ||
| const cleanups = itemEls.map((el2) => import_dom_query.resizeObserverBorderBox.observe(el2, exec)); | ||
| const cleanups = [import_dom_query.resizeObserverBorderBox.observe(el, exec), ...itemEls.map((el2) => import_dom_query.resizeObserverBorderBox.observe(el2, exec))]; | ||
| return (0, import_utils.callAll)(...cleanups); | ||
@@ -327,2 +347,26 @@ }, | ||
| }, | ||
| trackSettlingScroll({ send, refs, scope }) { | ||
| const el = dom.getItemGroupEl(scope); | ||
| if (!el) return; | ||
| const startTimer = () => { | ||
| clearTimeout(refs.get("timeoutRef")); | ||
| refs.set("timeoutRef", void 0); | ||
| refs.set( | ||
| "timeoutRef", | ||
| setTimeout(() => { | ||
| send({ type: "SCROLL.END" }); | ||
| }, 200) | ||
| ); | ||
| }; | ||
| startTimer(); | ||
| const onScroll = () => { | ||
| startTimer(); | ||
| }; | ||
| const cleanup = (0, import_dom_query.addDomEvent)(el, "scroll", onScroll, { passive: true }); | ||
| return () => { | ||
| cleanup(); | ||
| clearTimeout(refs.get("timeoutRef")); | ||
| refs.set("timeoutRef", void 0); | ||
| }; | ||
| }, | ||
| trackDocumentVisibility({ scope, send }) { | ||
@@ -391,4 +435,9 @@ const doc = scope.getDoc(); | ||
| const scrollPosition = computed("isHorizontal") ? el.scrollLeft : el.scrollTop; | ||
| const page = context.get("pageSnapPoints").findIndex((point) => Math.abs(point - scrollPosition) < 1); | ||
| if (page === -1) return; | ||
| const snapPoints = context.get("pageSnapPoints"); | ||
| if (!snapPoints.length) return; | ||
| const page = snapPoints.reduce((closestIndex, snapPoint, index) => { | ||
| const currentDistance = Math.abs(snapPoint - scrollPosition); | ||
| const closestDistance = Math.abs(snapPoints[closestIndex] - scrollPosition); | ||
| return currentDistance < closestDistance ? index : closestIndex; | ||
| }, 0); | ||
| context.set("page", page); | ||
@@ -422,6 +471,2 @@ }, | ||
| }, | ||
| clampPage({ context }) { | ||
| const index = (0, import_utils.clampValue)(context.get("page"), 0, context.get("pageSnapPoints").length - 1); | ||
| context.set("page", index); | ||
| }, | ||
| setSnapPoints({ context, computed, scope }) { | ||
@@ -431,3 +476,7 @@ const el = dom.getItemGroupEl(scope); | ||
| const scrollSnapPoints = (0, import_scroll_snap.getScrollSnapPositions)(el); | ||
| context.set("pageSnapPoints", computed("isHorizontal") ? scrollSnapPoints.x : scrollSnapPoints.y); | ||
| const pageSnapPoints = computed("isHorizontal") ? scrollSnapPoints.x : scrollSnapPoints.y; | ||
| context.set("pageSnapPoints", pageSnapPoints); | ||
| if (!pageSnapPoints.length) return; | ||
| const index = (0, import_utils.clampValue)(context.get("page"), 0, pageSnapPoints.length - 1); | ||
| context.set("page", index); | ||
| }, | ||
@@ -451,2 +500,3 @@ disableScrollSnap({ scope }) { | ||
| const snapPoints = context.get("pageSnapPoints"); | ||
| if (!snapPoints.length) return; | ||
| const closest = snapPoints.reduce((closest2, curr) => { | ||
@@ -461,3 +511,2 @@ return Math.abs(curr - scrollPos) < Math.abs(closest2 - scrollPos) ? curr : closest2; | ||
| }); | ||
| context.set("page", snapPoints.indexOf(closest)); | ||
| const scrollSnapType = el.dataset.scrollSnapType; | ||
@@ -464,0 +513,0 @@ if (scrollSnapType) { |
@@ -110,3 +110,3 @@ // src/carousel.machine.ts | ||
| "SNAP.REFRESH": { | ||
| actions: ["setSnapPoints", "clampPage"] | ||
| actions: ["setSnapPoints"] | ||
| }, | ||
@@ -170,7 +170,27 @@ "PAGE.SCROLL": { | ||
| "DRAGGING.END": { | ||
| target: "idle", | ||
| actions: ["endDragging", "invokeDraggingEnd"] | ||
| target: "settling", | ||
| actions: ["endDragging"] | ||
| } | ||
| } | ||
| }, | ||
| settling: { | ||
| effects: ["trackSettlingScroll"], | ||
| on: { | ||
| "DRAGGING.START": { | ||
| target: "dragging", | ||
| actions: ["clearScrollEndTimer", "invokeDragStart"] | ||
| }, | ||
| "SCROLL.END": [ | ||
| { | ||
| guard: "isFocused", | ||
| target: "focus", | ||
| actions: ["clearScrollEndTimer", "setClosestPage", "invokeDraggingEnd"] | ||
| }, | ||
| { | ||
| target: "idle", | ||
| actions: ["clearScrollEndTimer", "setClosestPage", "invokeDraggingEnd"] | ||
| } | ||
| ] | ||
| } | ||
| }, | ||
| userScroll: { | ||
@@ -253,3 +273,3 @@ effects: ["trackScroll"], | ||
| itemEls.forEach(exec); | ||
| const cleanups = itemEls.map((el2) => resizeObserverBorderBox.observe(el2, exec)); | ||
| const cleanups = [resizeObserverBorderBox.observe(el, exec), ...itemEls.map((el2) => resizeObserverBorderBox.observe(el2, exec))]; | ||
| return callAll(...cleanups); | ||
@@ -293,2 +313,26 @@ }, | ||
| }, | ||
| trackSettlingScroll({ send, refs, scope }) { | ||
| const el = dom.getItemGroupEl(scope); | ||
| if (!el) return; | ||
| const startTimer = () => { | ||
| clearTimeout(refs.get("timeoutRef")); | ||
| refs.set("timeoutRef", void 0); | ||
| refs.set( | ||
| "timeoutRef", | ||
| setTimeout(() => { | ||
| send({ type: "SCROLL.END" }); | ||
| }, 200) | ||
| ); | ||
| }; | ||
| startTimer(); | ||
| const onScroll = () => { | ||
| startTimer(); | ||
| }; | ||
| const cleanup = addDomEvent(el, "scroll", onScroll, { passive: true }); | ||
| return () => { | ||
| cleanup(); | ||
| clearTimeout(refs.get("timeoutRef")); | ||
| refs.set("timeoutRef", void 0); | ||
| }; | ||
| }, | ||
| trackDocumentVisibility({ scope, send }) { | ||
@@ -357,4 +401,9 @@ const doc = scope.getDoc(); | ||
| const scrollPosition = computed("isHorizontal") ? el.scrollLeft : el.scrollTop; | ||
| const page = context.get("pageSnapPoints").findIndex((point) => Math.abs(point - scrollPosition) < 1); | ||
| if (page === -1) return; | ||
| const snapPoints = context.get("pageSnapPoints"); | ||
| if (!snapPoints.length) return; | ||
| const page = snapPoints.reduce((closestIndex, snapPoint, index) => { | ||
| const currentDistance = Math.abs(snapPoint - scrollPosition); | ||
| const closestDistance = Math.abs(snapPoints[closestIndex] - scrollPosition); | ||
| return currentDistance < closestDistance ? index : closestIndex; | ||
| }, 0); | ||
| context.set("page", page); | ||
@@ -388,6 +437,2 @@ }, | ||
| }, | ||
| clampPage({ context }) { | ||
| const index = clampValue(context.get("page"), 0, context.get("pageSnapPoints").length - 1); | ||
| context.set("page", index); | ||
| }, | ||
| setSnapPoints({ context, computed, scope }) { | ||
@@ -397,3 +442,7 @@ const el = dom.getItemGroupEl(scope); | ||
| const scrollSnapPoints = getScrollSnapPositions(el); | ||
| context.set("pageSnapPoints", computed("isHorizontal") ? scrollSnapPoints.x : scrollSnapPoints.y); | ||
| const pageSnapPoints = computed("isHorizontal") ? scrollSnapPoints.x : scrollSnapPoints.y; | ||
| context.set("pageSnapPoints", pageSnapPoints); | ||
| if (!pageSnapPoints.length) return; | ||
| const index = clampValue(context.get("page"), 0, pageSnapPoints.length - 1); | ||
| context.set("page", index); | ||
| }, | ||
@@ -417,2 +466,3 @@ disableScrollSnap({ scope }) { | ||
| const snapPoints = context.get("pageSnapPoints"); | ||
| if (!snapPoints.length) return; | ||
| const closest = snapPoints.reduce((closest2, curr) => { | ||
@@ -427,3 +477,2 @@ return Math.abs(curr - scrollPos) < Math.abs(closest2 - scrollPos) ? curr : closest2; | ||
| }); | ||
| context.set("page", snapPoints.indexOf(closest)); | ||
| const scrollSnapType = el.dataset.scrollSnapType; | ||
@@ -430,0 +479,0 @@ if (scrollSnapType) { |
@@ -156,3 +156,3 @@ import { Service, EventObject, Machine } from '@zag-js/core'; | ||
| }; | ||
| state: "idle" | "dragging" | "autoplay" | "userScroll" | "focus"; | ||
| state: "idle" | "dragging" | "settling" | "autoplay" | "userScroll" | "focus"; | ||
| effect: string; | ||
@@ -159,0 +159,0 @@ action: string; |
@@ -156,3 +156,3 @@ import { Service, EventObject, Machine } from '@zag-js/core'; | ||
| }; | ||
| state: "idle" | "dragging" | "autoplay" | "userScroll" | "focus"; | ||
| state: "idle" | "dragging" | "settling" | "autoplay" | "userScroll" | "focus"; | ||
| effect: string; | ||
@@ -159,0 +159,0 @@ action: string; |
+7
-7
| { | ||
| "name": "@zag-js/carousel", | ||
| "version": "1.35.2", | ||
| "version": "1.35.3", | ||
| "description": "Core logic for the carousel widget implemented as a state machine", | ||
@@ -30,8 +30,8 @@ "keywords": [ | ||
| "dependencies": { | ||
| "@zag-js/anatomy": "1.35.2", | ||
| "@zag-js/core": "1.35.2", | ||
| "@zag-js/types": "1.35.2", | ||
| "@zag-js/dom-query": "1.35.2", | ||
| "@zag-js/scroll-snap": "1.35.2", | ||
| "@zag-js/utils": "1.35.2" | ||
| "@zag-js/anatomy": "1.35.3", | ||
| "@zag-js/core": "1.35.3", | ||
| "@zag-js/types": "1.35.3", | ||
| "@zag-js/dom-query": "1.35.3", | ||
| "@zag-js/scroll-snap": "1.35.3", | ||
| "@zag-js/utils": "1.35.3" | ||
| }, | ||
@@ -38,0 +38,0 @@ "devDependencies": { |
97195
3.8%2308
4.53%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated
Updated
Updated
Updated
Updated