@ahrowe/ui 0.24.0 → 0.24.1
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.
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import t from"../interactableDiv/index.mjs";import n from"../actionIcon/actionIcon.mjs";import r from"./carousel.module.mjs";import i,{useEffect as a,useLayoutEffect as o,useRef as s,useState as c}from"react";import l from"classnames";import{faChevronLeft as
|
|
1
|
+
import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import t from"../interactableDiv/index.mjs";import n from"../actionIcon/actionIcon.mjs";import r from"./carousel.module.mjs";import i,{useEffect as a,useLayoutEffect as o,useRef as s,useState as c}from"react";import l from"classnames";import{faChevronLeft as u,faChevronRight as ee}from"@fortawesome/free-solid-svg-icons";import{Fragment as te,jsx as d,jsxs as f}from"react/jsx-runtime";var p=10,ne=.2;function m(m){let{children:re,currentIndex:_,defaultIndex:v=0,onChange:ie=()=>{},loop:ae=!0,autoPlay:y=!1,autoPlayInterval:b=4e3,pauseOnHover:oe=!0,showArrows:se=!0,showDots:ce=!0,swipeable:le=!0,lazyRender:ue=!1,adaptiveHeight:x=!1,className:de,style:S,classNames:C,styles:w,...fe}=e(`Carousel`,m),T=i.Children.toArray(re),E=T.length,D=ae&&E>1,O=+!!D,k=D?[T[E-1],...T,T[0]]:T,A=_!==void 0,[pe,me]=c(()=>g(v,E,D)),j=g(A?_:pe,E,D),[M,N]=c(j+O),[he,P]=c(!0),F=s(j),[I,L]=c(!1),[ge,R]=c(!1),[_e,z]=c(!1),B=s(null),V=s(null),H=k.length>0?100/k.length:100;o(()=>{let e=F.current;if(F.current=j,e===j)return;let t=k.length-1,n=M;D&&M===0?n=E:D&&M===t&&(n=1);let r=D&&e===E-1&&j===0,i=D&&e===0&&j===E-1,a;a=r?n+1:i?n-1:j+O;let o=V.current;n!==M&&o&&(o.style.transition=`none`,o.style.transform=h(n,0,H),o.offsetWidth,o.style.transition=``),P(!0),N(a)},[j]);let[U,ve]=c(()=>({min:j+O-1,max:j+O+1})),ye=Math.min(U.min,M-1),be=Math.max(U.max,M+1),[xe,Se]=c(void 0);o(()=>{if(!x)return;let e=V.current?.children[M];if(!e)return;let t=()=>Se(e.offsetHeight);t();let n=new ResizeObserver(t);return n.observe(e),()=>n.disconnect()},[x,M,E]);function W(e){let t=g(e,E,D);A||me(t),ie(t)}function G(){!D&&j>=E-1||W(j+1)}function K(){!D&&j<=0||W(j-1)}function q(e){e.target===e.currentTarget&&(ve({min:M-1,max:M+1}),D&&(M===0?(P(!1),N(E)):M===k.length-1&&(P(!1),N(1))))}let J=y&&oe,Y=I||ge||_e;a(()=>{if(!y||E<=1||Y)return;let e=setInterval(G,b);return()=>clearInterval(e)},[y,b,Y,j,E]);let X=s(null);function Ce(e){!le||E<=1||(X.current={startX:e.clientX,startY:e.clientY,width:B.current?.getBoundingClientRect().width||1,axisLocked:!1,active:!0,offsetPercent:0},e.currentTarget.setPointerCapture?.(e.pointerId))}function we(e){let t=X.current;if(!t||!t.active)return;let n=e.clientX-t.startX,r=e.clientY-t.startY;if(!t.axisLocked){if(Math.abs(n)<p&&Math.abs(r)<p)return;if(Math.abs(r)>Math.abs(n)){t.active=!1;return}t.axisLocked=!0,z(!0),P(!1)}t.offsetPercent=n/t.width*100,V.current&&(V.current.style.transform=h(M,t.offsetPercent,H))}function Z(){let e=X.current;if(X.current=null,!e||!e.axisLocked){z(!1);return}P(!0),z(!1),V.current&&(V.current.style.transition=``,V.current.style.transform=h(M,0,H)),Math.abs(e.offsetPercent)>=ne*100&&(e.offsetPercent<0?G():K())}function Te(e){e.key===`ArrowLeft`?(e.preventDefault(),K()):e.key===`ArrowRight`&&(e.preventDefault(),G())}let Q=!D&&j<=0,$=!D&&j>=E-1,Ee=h(M,0,H);return f(`div`,{...fe,ref:B,role:`region`,"aria-roledescription":`carousel`,className:l(r.carousel,x&&r.carouselAdaptive,C?.root,de),style:{height:x?xe:void 0,...S,...w?.root},onMouseEnter:J?()=>L(!0):void 0,onMouseLeave:J?()=>L(!1):void 0,onFocus:J?()=>R(!0):void 0,onBlur:J?()=>R(!1):void 0,onKeyDown:Te,children:[d(`div`,{ref:V,className:l(r.carouselTrack,x&&r.carouselTrackAdaptive,C?.track),style:{width:`${k.length*100}%`,transform:Ee,transition:he?void 0:`none`,...w?.track},onTransitionEnd:q,onPointerDown:Ce,onPointerMove:we,onPointerUp:Z,onPointerCancel:Z,children:k.map((e,t)=>{let n=D&&(t===0||t===k.length-1),i=t-O,a=!n&&i===j,o=!ue||t>=ye&&t<=be;return d(`div`,{className:l(r.carouselSlide,C?.slide),style:{width:`${100/k.length}%`,...w?.slide},inert:a?void 0:!0,children:o?e:null},`carousel-slide-${t}`)})}),se&&E>1&&f(te,{children:[d(n,{icon:u,title:`Previous slide`,"aria-label":`Previous slide`,"aria-disabled":Q||void 0,onClick:()=>!Q&&K(),className:l(r.carouselPrevButton,Q&&r.carouselButtonDisabled,C?.prevButton),style:w?.prevButton}),d(n,{icon:ee,title:`Next slide`,"aria-label":`Next slide`,"aria-disabled":$||void 0,onClick:()=>!$&&G(),className:l(r.carouselNextButton,$&&r.carouselButtonDisabled,C?.nextButton),style:w?.nextButton})]}),ce&&E>1&&d(`div`,{className:l(r.carouselDots,C?.dots),style:w?.dots,children:T.map((e,n)=>d(t,{"aria-label":`Go to slide ${n+1}`,"aria-current":n===j,onClick:()=>W(n),className:l(r.carouselDot,n===j&&r.carouselDotActive,C?.dot),style:w?.dot},`carousel-dot-${n}`))})]})}function h(e,t,n){return`translateX(calc(${-e*n}% + ${n/100*t}%))`}function g(e,t,n){return t===0?0:n?(e%t+t)%t:Math.max(0,Math.min(t-1,e))}export{m as default};
|
|
2
2
|
//# sourceMappingURL=carousel.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carousel.mjs","names":[],"sources":["../../../../package/common/carousel/carousel.tsx"],"sourcesContent":["import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport InteractableDiv from '../interactableDiv';\nimport { useComponentDefaults } from '../configProvider';\nimport type { CarouselProps } from './carousel.types';\n\nimport styles from './carousel.module.pcss';\n\nconst AXIS_LOCK_THRESHOLD = 10;\nconst DRAG_COMMIT_RATIO = 0.2;\n\nfunction Carousel(props: CarouselProps) {\n const {\n children,\n currentIndex,\n defaultIndex = 0,\n onChange = () => {},\n loop = true,\n autoPlay = false,\n autoPlayInterval = 4000,\n pauseOnHover = true,\n showArrows = true,\n showDots = true,\n swipeable = true,\n lazyRender = false,\n adaptiveHeight = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Carousel', props);\n\n const slides = React.Children.toArray(children);\n const count = slides.length;\n const canLoop = loop && count > 1;\n const offset = canLoop ? 1 : 0;\n const extendedSlides = canLoop ? [slides[count - 1], ...slides, slides[0]] : slides;\n\n const isControlled = currentIndex !== undefined;\n const [internalIndex, setInternalIndex] = useState(() => clampIndex(defaultIndex, count, canLoop));\n const realIndex = clampIndex(isControlled ? currentIndex! : internalIndex, count, canLoop);\n\n const [displayIndex, setDisplayIndex] = useState(realIndex + offset);\n const [transitionEnabled, setTransitionEnabled] = useState(true);\n const prevRealIndexRef = useRef(realIndex);\n\n const [hovered, setHovered] = useState(false);\n const [focused, setFocused] = useState(false);\n const [dragging, setDragging] = useState(false);\n const [dragOffsetPercent, setDragOffsetPercent] = useState(0);\n\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const prevReal = prevRealIndexRef.current;\n prevRealIndexRef.current = realIndex;\n if (prevReal === realIndex) return;\n\n const forwardWrap = canLoop && prevReal === count - 1 && realIndex === 0;\n const backwardWrap = canLoop && prevReal === 0 && realIndex === count - 1;\n\n setTransitionEnabled(true);\n if (forwardWrap) {\n setDisplayIndex((d) => d + 1);\n } else if (backwardWrap) {\n setDisplayIndex((d) => d - 1);\n } else {\n setDisplayIndex(realIndex + offset);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [realIndex]);\n\n // The window of slides `lazyRender` keeps mounted, as of the last settled position. Slides are\n // rendered for the union of this and the current window, so the ones a multi-step jump slides\n // past stay mounted until the transform transition ends instead of blanking out mid-flight.\n const [settledMountRange, setSettledMountRange] = useState(() => ({\n min: realIndex + offset - 1,\n max: realIndex + offset + 1,\n }));\n const mountMin = Math.min(settledMountRange.min, displayIndex - 1);\n const mountMax = Math.max(settledMountRange.max, displayIndex + 1);\n\n const slideRefs = useRef<(HTMLDivElement | null)[]>([]);\n const [contentHeight, setContentHeight] = useState<number | undefined>(undefined);\n\n useLayoutEffect(() => {\n if (!adaptiveHeight) {\n setContentHeight(undefined);\n return;\n }\n const slideElement = slideRefs.current[displayIndex];\n if (!slideElement) return;\n\n const update = () => setContentHeight(slideElement.offsetHeight);\n update();\n\n const observer = new ResizeObserver(update);\n observer.observe(slideElement);\n return () => observer.disconnect();\n }, [adaptiveHeight, displayIndex, count]);\n\n function goToIndex(nextIndex: number) {\n const clamped = clampIndex(nextIndex, count, canLoop);\n if (!isControlled) setInternalIndex(clamped);\n onChange(clamped);\n }\n\n function goNext() {\n if (!canLoop && realIndex >= count - 1) return;\n goToIndex(realIndex + 1);\n }\n\n function goPrev() {\n if (!canLoop && realIndex <= 0) return;\n goToIndex(realIndex - 1);\n }\n\n function handleTrackTransitionEnd(event: React.TransitionEvent<HTMLDivElement>) {\n if (event.target !== event.currentTarget) return;\n setSettledMountRange({ min: displayIndex - 1, max: displayIndex + 1 });\n\n if (!canLoop) return;\n if (displayIndex === 0) {\n setTransitionEnabled(false);\n setDisplayIndex(count);\n } else if (displayIndex === extendedSlides.length - 1) {\n setTransitionEnabled(false);\n setDisplayIndex(1);\n }\n }\n\n const isPaused = (pauseOnHover && (hovered || focused)) || dragging;\n useEffect(() => {\n if (!autoPlay || count <= 1 || isPaused) return;\n const timer = setInterval(goNext, autoPlayInterval);\n return () => clearInterval(timer);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [autoPlay, autoPlayInterval, isPaused, realIndex, count]);\n\n const dragRef = useRef<{\n startX: number;\n startY: number;\n axisLocked: boolean;\n active: boolean;\n } | null>(null);\n\n function handlePointerDown(event: React.PointerEvent<HTMLDivElement>) {\n if (!swipeable || count <= 1) return;\n dragRef.current = { startX: event.clientX, startY: event.clientY, axisLocked: false, active: true };\n event.currentTarget.setPointerCapture?.(event.pointerId);\n }\n\n function handlePointerMove(event: React.PointerEvent<HTMLDivElement>) {\n const drag = dragRef.current;\n if (!drag || !drag.active) return;\n\n const deltaX = event.clientX - drag.startX;\n const deltaY = event.clientY - drag.startY;\n\n if (!drag.axisLocked) {\n if (Math.abs(deltaX) < AXIS_LOCK_THRESHOLD && Math.abs(deltaY) < AXIS_LOCK_THRESHOLD) return;\n if (Math.abs(deltaY) > Math.abs(deltaX)) {\n drag.active = false;\n return;\n }\n drag.axisLocked = true;\n setDragging(true);\n setTransitionEnabled(false);\n }\n\n const width = containerRef.current?.getBoundingClientRect().width || 1;\n setDragOffsetPercent((deltaX / width) * 100);\n }\n\n function handlePointerUp() {\n const drag = dragRef.current;\n dragRef.current = null;\n if (!drag || !drag.axisLocked) {\n setDragging(false);\n return;\n }\n\n const committed = Math.abs(dragOffsetPercent) >= DRAG_COMMIT_RATIO * 100;\n setDragOffsetPercent(0);\n setTransitionEnabled(true);\n setDragging(false);\n if (committed) {\n if (dragOffsetPercent < 0) goNext();\n else goPrev();\n }\n }\n\n function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n if (event.key === 'ArrowLeft') {\n event.preventDefault();\n goPrev();\n } else if (event.key === 'ArrowRight') {\n event.preventDefault();\n goNext();\n }\n }\n\n const isPrevDisabled = !canLoop && realIndex <= 0;\n const isNextDisabled = !canLoop && realIndex >= count - 1;\n\n const slideWidthPercent = extendedSlides.length > 0 ? 100 / extendedSlides.length : 100;\n const trackTransform = `translateX(calc(${-displayIndex * slideWidthPercent}% + ${dragOffsetPercent * (slideWidthPercent / 100)}%))`;\n\n return (\n <div\n {...rest}\n ref={containerRef}\n role=\"region\"\n aria-roledescription=\"carousel\"\n className={cx(styles.carousel, adaptiveHeight && styles.carouselAdaptive, classNames?.root, className)}\n style={{ height: contentHeight, ...style, ...slotStyles?.root }}\n onMouseEnter={pauseOnHover ? () => setHovered(true) : undefined}\n onMouseLeave={pauseOnHover ? () => setHovered(false) : undefined}\n onFocus={pauseOnHover ? () => setFocused(true) : undefined}\n onBlur={pauseOnHover ? () => setFocused(false) : undefined}\n onKeyDown={handleKeyDown}\n >\n <div\n className={cx(styles.carouselTrack, adaptiveHeight && styles.carouselTrackAdaptive, classNames?.track)}\n style={{\n width: `${extendedSlides.length * 100}%`,\n transform: trackTransform,\n transition: transitionEnabled ? undefined : 'none',\n ...slotStyles?.track,\n }}\n onTransitionEnd={handleTrackTransitionEnd}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n >\n {extendedSlides.map((slide, idx) => {\n const isClonePosition = canLoop && (idx === 0 || idx === extendedSlides.length - 1);\n const logicalIndex = idx - offset;\n const isActive = !isClonePosition && logicalIndex === realIndex;\n const isRendered = !lazyRender || (idx >= mountMin && idx <= mountMax);\n\n return (\n <div\n key={`carousel-slide-${idx}`}\n ref={(el) => {\n slideRefs.current[idx] = el;\n }}\n className={cx(styles.carouselSlide, classNames?.slide)}\n style={{ width: `${100 / extendedSlides.length}%`, ...slotStyles?.slide }}\n inert={isActive ? undefined : true}\n >\n {isRendered ? slide : null}\n </div>\n );\n })}\n </div>\n\n {showArrows && count > 1 && (\n <>\n <ActionIcon\n icon={faChevronLeft}\n title=\"Previous slide\"\n aria-label=\"Previous slide\"\n aria-disabled={isPrevDisabled || undefined}\n onClick={() => !isPrevDisabled && goPrev()}\n className={cx(styles.carouselPrevButton, isPrevDisabled && styles.carouselButtonDisabled, classNames?.prevButton)}\n style={slotStyles?.prevButton}\n />\n <ActionIcon\n icon={faChevronRight}\n title=\"Next slide\"\n aria-label=\"Next slide\"\n aria-disabled={isNextDisabled || undefined}\n onClick={() => !isNextDisabled && goNext()}\n className={cx(styles.carouselNextButton, isNextDisabled && styles.carouselButtonDisabled, classNames?.nextButton)}\n style={slotStyles?.nextButton}\n />\n </>\n )}\n\n {showDots && count > 1 && (\n <div className={cx(styles.carouselDots, classNames?.dots)} style={slotStyles?.dots}>\n {slides.map((_, index) => (\n <InteractableDiv\n key={`carousel-dot-${index}`}\n aria-label={`Go to slide ${index + 1}`}\n aria-current={index === realIndex}\n onClick={() => goToIndex(index)}\n className={cx(styles.carouselDot, index === realIndex && styles.carouselDotActive, classNames?.dot)}\n style={slotStyles?.dot}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction clampIndex(index: number, count: number, canLoop: boolean): number {\n if (count === 0) return 0;\n if (canLoop) return ((index % count) + count) % count;\n return Math.max(0, Math.min(count - 1, index));\n}\n\nexport default Carousel;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"carousel.mjs","names":[],"sources":["../../../../package/common/carousel/carousel.tsx"],"sourcesContent":["import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport InteractableDiv from '../interactableDiv';\nimport { useComponentDefaults } from '../configProvider';\nimport type { CarouselProps } from './carousel.types';\n\nimport styles from './carousel.module.pcss';\n\nconst AXIS_LOCK_THRESHOLD = 10;\nconst DRAG_COMMIT_RATIO = 0.2;\n\nfunction Carousel(props: CarouselProps) {\n const {\n children,\n currentIndex,\n defaultIndex = 0,\n onChange = () => {},\n loop = true,\n autoPlay = false,\n autoPlayInterval = 4000,\n pauseOnHover = true,\n showArrows = true,\n showDots = true,\n swipeable = true,\n lazyRender = false,\n adaptiveHeight = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Carousel', props);\n\n const slides = React.Children.toArray(children);\n const count = slides.length;\n const canLoop = loop && count > 1;\n const offset = canLoop ? 1 : 0;\n const extendedSlides = canLoop ? [slides[count - 1], ...slides, slides[0]] : slides;\n\n const isControlled = currentIndex !== undefined;\n const [internalIndex, setInternalIndex] = useState(() => clampIndex(defaultIndex, count, canLoop));\n const realIndex = clampIndex(isControlled ? currentIndex! : internalIndex, count, canLoop);\n\n const [displayIndex, setDisplayIndex] = useState(realIndex + offset);\n const [transitionEnabled, setTransitionEnabled] = useState(true);\n const prevRealIndexRef = useRef(realIndex);\n\n const [hovered, setHovered] = useState(false);\n const [focused, setFocused] = useState(false);\n const [dragging, setDragging] = useState(false);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const trackRef = useRef<HTMLDivElement>(null);\n\n const slideWidthPercent = extendedSlides.length > 0 ? 100 / extendedSlides.length : 100;\n\n useLayoutEffect(() => {\n const prevReal = prevRealIndexRef.current;\n prevRealIndexRef.current = realIndex;\n if (prevReal === realIndex) return;\n\n // A wrap parks the track on a clone until transitionEnd swaps it back, so a change arriving\n // before that has to animate from the normalised position rather than the clone.\n const lastExtendedIndex = extendedSlides.length - 1;\n let fromIndex = displayIndex;\n if (canLoop && displayIndex === 0) fromIndex = count;\n else if (canLoop && displayIndex === lastExtendedIndex) fromIndex = 1;\n\n const forwardWrap = canLoop && prevReal === count - 1 && realIndex === 0;\n const backwardWrap = canLoop && prevReal === 0 && realIndex === count - 1;\n\n let target: number;\n if (forwardWrap) target = fromIndex + 1;\n else if (backwardWrap) target = fromIndex - 1;\n else target = realIndex + offset;\n\n // Written straight to the node: the normalised position has to reach style recalculation on its\n // own, or it and the animated position collapse into one jump with no transition.\n const track = trackRef.current;\n if (fromIndex !== displayIndex && track) {\n track.style.transition = 'none';\n track.style.transform = buildTrackTransform(fromIndex, 0, slideWidthPercent);\n void track.offsetWidth;\n track.style.transition = '';\n }\n\n setTransitionEnabled(true);\n setDisplayIndex(target);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [realIndex]);\n\n // The window of slides `lazyRender` keeps mounted, as of the last settled position. Slides are\n // rendered for the union of this and the current window, so the ones a multi-step jump slides\n // past stay mounted until the transform transition ends instead of blanking out mid-flight.\n const [settledMountRange, setSettledMountRange] = useState(() => ({\n min: realIndex + offset - 1,\n max: realIndex + offset + 1,\n }));\n const mountMin = Math.min(settledMountRange.min, displayIndex - 1);\n const mountMax = Math.max(settledMountRange.max, displayIndex + 1);\n\n const [contentHeight, setContentHeight] = useState<number | undefined>(undefined);\n\n useLayoutEffect(() => {\n if (!adaptiveHeight) return;\n const slideElement = trackRef.current?.children[displayIndex] as HTMLElement | undefined;\n if (!slideElement) return;\n\n const update = () => setContentHeight(slideElement.offsetHeight);\n update();\n\n const observer = new ResizeObserver(update);\n observer.observe(slideElement);\n return () => observer.disconnect();\n }, [adaptiveHeight, displayIndex, count]);\n\n function goToIndex(nextIndex: number) {\n const clamped = clampIndex(nextIndex, count, canLoop);\n if (!isControlled) setInternalIndex(clamped);\n onChange(clamped);\n }\n\n function goNext() {\n if (!canLoop && realIndex >= count - 1) return;\n goToIndex(realIndex + 1);\n }\n\n function goPrev() {\n if (!canLoop && realIndex <= 0) return;\n goToIndex(realIndex - 1);\n }\n\n function handleTrackTransitionEnd(event: React.TransitionEvent<HTMLDivElement>) {\n if (event.target !== event.currentTarget) return;\n setSettledMountRange({ min: displayIndex - 1, max: displayIndex + 1 });\n\n if (!canLoop) return;\n if (displayIndex === 0) {\n setTransitionEnabled(false);\n setDisplayIndex(count);\n } else if (displayIndex === extendedSlides.length - 1) {\n setTransitionEnabled(false);\n setDisplayIndex(1);\n }\n }\n\n // Hover and focus only ever pause the timer, so without one they are not worth tracking.\n const tracksPointerPause = autoPlay && pauseOnHover;\n const isPaused = hovered || focused || dragging;\n useEffect(() => {\n if (!autoPlay || count <= 1 || isPaused) return;\n const timer = setInterval(goNext, autoPlayInterval);\n return () => clearInterval(timer);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [autoPlay, autoPlayInterval, isPaused, realIndex, count]);\n\n // A drag follows the pointer through the node, not through state: a render per move event would\n // rebuild every slide and dot for a change only the track's transform sees.\n const dragRef = useRef<{\n startX: number;\n startY: number;\n width: number;\n axisLocked: boolean;\n active: boolean;\n offsetPercent: number;\n } | null>(null);\n\n function handlePointerDown(event: React.PointerEvent<HTMLDivElement>) {\n if (!swipeable || count <= 1) return;\n dragRef.current = {\n startX: event.clientX,\n startY: event.clientY,\n // Measured once: measuring per move would force a layout between the transform writes.\n width: containerRef.current?.getBoundingClientRect().width || 1,\n axisLocked: false,\n active: true,\n offsetPercent: 0,\n };\n event.currentTarget.setPointerCapture?.(event.pointerId);\n }\n\n function handlePointerMove(event: React.PointerEvent<HTMLDivElement>) {\n const drag = dragRef.current;\n if (!drag || !drag.active) return;\n\n const deltaX = event.clientX - drag.startX;\n const deltaY = event.clientY - drag.startY;\n\n if (!drag.axisLocked) {\n if (Math.abs(deltaX) < AXIS_LOCK_THRESHOLD && Math.abs(deltaY) < AXIS_LOCK_THRESHOLD) return;\n if (Math.abs(deltaY) > Math.abs(deltaX)) {\n drag.active = false;\n return;\n }\n drag.axisLocked = true;\n setDragging(true);\n setTransitionEnabled(false);\n }\n\n drag.offsetPercent = (deltaX / drag.width) * 100;\n if (trackRef.current) {\n trackRef.current.style.transform = buildTrackTransform(displayIndex, drag.offsetPercent, slideWidthPercent);\n }\n }\n\n function handlePointerUp() {\n const drag = dragRef.current;\n dragRef.current = null;\n if (!drag || !drag.axisLocked) {\n setDragging(false);\n return;\n }\n\n setTransitionEnabled(true);\n setDragging(false);\n\n // React never saw the dragged transform, so it has to be handed back by hand. Unconditionally:\n // a drag that changes no index (either end of a non-looping carousel, a controlled owner that\n // ignores the change) would otherwise strand the track off-screen. One that does change it\n // overwrites this in the same tick, and still animates on from where the pointer left off.\n if (trackRef.current) {\n trackRef.current.style.transition = '';\n trackRef.current.style.transform = buildTrackTransform(displayIndex, 0, slideWidthPercent);\n }\n\n if (Math.abs(drag.offsetPercent) >= DRAG_COMMIT_RATIO * 100) {\n if (drag.offsetPercent < 0) goNext();\n else goPrev();\n }\n }\n\n function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n if (event.key === 'ArrowLeft') {\n event.preventDefault();\n goPrev();\n } else if (event.key === 'ArrowRight') {\n event.preventDefault();\n goNext();\n }\n }\n\n const isPrevDisabled = !canLoop && realIndex <= 0;\n const isNextDisabled = !canLoop && realIndex >= count - 1;\n\n const trackTransform = buildTrackTransform(displayIndex, 0, slideWidthPercent);\n\n return (\n <div\n {...rest}\n ref={containerRef}\n role=\"region\"\n aria-roledescription=\"carousel\"\n className={cx(styles.carousel, adaptiveHeight && styles.carouselAdaptive, classNames?.root, className)}\n style={{ height: adaptiveHeight ? contentHeight : undefined, ...style, ...slotStyles?.root }}\n onMouseEnter={tracksPointerPause ? () => setHovered(true) : undefined}\n onMouseLeave={tracksPointerPause ? () => setHovered(false) : undefined}\n onFocus={tracksPointerPause ? () => setFocused(true) : undefined}\n onBlur={tracksPointerPause ? () => setFocused(false) : undefined}\n onKeyDown={handleKeyDown}\n >\n <div\n ref={trackRef}\n className={cx(styles.carouselTrack, adaptiveHeight && styles.carouselTrackAdaptive, classNames?.track)}\n style={{\n width: `${extendedSlides.length * 100}%`,\n transform: trackTransform,\n transition: transitionEnabled ? undefined : 'none',\n ...slotStyles?.track,\n }}\n onTransitionEnd={handleTrackTransitionEnd}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n >\n {extendedSlides.map((slide, idx) => {\n const isClonePosition = canLoop && (idx === 0 || idx === extendedSlides.length - 1);\n const logicalIndex = idx - offset;\n const isActive = !isClonePosition && logicalIndex === realIndex;\n const isRendered = !lazyRender || (idx >= mountMin && idx <= mountMax);\n\n return (\n <div\n key={`carousel-slide-${idx}`}\n className={cx(styles.carouselSlide, classNames?.slide)}\n style={{ width: `${100 / extendedSlides.length}%`, ...slotStyles?.slide }}\n inert={isActive ? undefined : true}\n >\n {isRendered ? slide : null}\n </div>\n );\n })}\n </div>\n\n {showArrows && count > 1 && (\n <>\n <ActionIcon\n icon={faChevronLeft}\n title=\"Previous slide\"\n aria-label=\"Previous slide\"\n aria-disabled={isPrevDisabled || undefined}\n onClick={() => !isPrevDisabled && goPrev()}\n className={cx(styles.carouselPrevButton, isPrevDisabled && styles.carouselButtonDisabled, classNames?.prevButton)}\n style={slotStyles?.prevButton}\n />\n <ActionIcon\n icon={faChevronRight}\n title=\"Next slide\"\n aria-label=\"Next slide\"\n aria-disabled={isNextDisabled || undefined}\n onClick={() => !isNextDisabled && goNext()}\n className={cx(styles.carouselNextButton, isNextDisabled && styles.carouselButtonDisabled, classNames?.nextButton)}\n style={slotStyles?.nextButton}\n />\n </>\n )}\n\n {showDots && count > 1 && (\n <div className={cx(styles.carouselDots, classNames?.dots)} style={slotStyles?.dots}>\n {slides.map((_, index) => (\n <InteractableDiv\n key={`carousel-dot-${index}`}\n aria-label={`Go to slide ${index + 1}`}\n aria-current={index === realIndex}\n onClick={() => goToIndex(index)}\n className={cx(styles.carouselDot, index === realIndex && styles.carouselDotActive, classNames?.dot)}\n style={slotStyles?.dot}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction buildTrackTransform(position: number, dragPercent: number, slideWidthPercent: number): string {\n return `translateX(calc(${-position * slideWidthPercent}% + ${dragPercent * (slideWidthPercent / 100)}%))`;\n}\n\nfunction clampIndex(index: number, count: number, canLoop: boolean): number {\n if (count === 0) return 0;\n if (canLoop) return ((index % count) + count) % count;\n return Math.max(0, Math.min(count - 1, index));\n}\n\nexport default Carousel;\n"],"mappings":"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"}
|