UNPKG

react-carousel-latest

Version:

A headless, accessible, tree-shakeable React carousel with a compound-component API (and a backwards-compatible CardSlider preset).

991 lines (980 loc) 47.3 kB
"use client"; 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var react = require('react'); var jsxRuntime = require('react/jsx-runtime'); var framerMotion = require('framer-motion'); // src/components/Carousel.tsx var CarouselContext = react.createContext(null); function useCarouselContext() { const api = react.useContext(CarouselContext); if (api === null) { throw new Error( "Carousel compound components must be rendered inside <Carousel>. Did you forget to wrap them, or import the part from a different package version?" ); } return api; } // src/utils/clamp.ts function clamp(value, min, max) { if (max < min) return min; return Math.min(Math.max(value, min), max); } function wrapIndex(index, count) { if (count <= 0) return 0; return (index % count + count) % count; } // src/core/carouselReducer.ts function carouselReducer(state, action) { const maxIndex = Math.max(0, state.slidesCount - state.slidesPerView); switch (action.type) { case "NEXT": { const target = state.activeIndex + action.step; const next = action.loop ? wrapIndex(target, state.slidesCount) : clamp(target, 0, maxIndex); return next === state.activeIndex ? state : { ...state, activeIndex: next }; } case "PREV": { const target = state.activeIndex - action.step; const next = action.loop ? wrapIndex(target, state.slidesCount) : clamp(target, 0, maxIndex); return next === state.activeIndex ? state : { ...state, activeIndex: next }; } case "GO_TO": { const next = clamp(action.index, 0, maxIndex); return next === state.activeIndex ? state : { ...state, activeIndex: next }; } case "SET_COUNT": { if (action.slidesCount === state.slidesCount) return state; const activeIndex = clamp(state.activeIndex, 0, Math.max(0, action.slidesCount - state.slidesPerView)); return { ...state, slidesCount: action.slidesCount, activeIndex }; } case "SET_SLIDES_PER_VIEW": { if (action.slidesPerView === state.slidesPerView) return state; const activeIndex = clamp(state.activeIndex, 0, Math.max(0, state.slidesCount - action.slidesPerView)); return { ...state, slidesPerView: action.slidesPerView, activeIndex }; } case "SET_PLAYING": { return action.isPlaying === state.isPlaying ? state : { ...state, isPlaying: action.isPlaying }; } default: return state; } } function useAutoplay({ enabled, interval, onTick, rootRef }) { const onTickRef = react.useRef(onTick); onTickRef.current = onTick; react.useEffect(() => { if (!enabled || typeof window === "undefined") return; const prefersReducedMotion = window.matchMedia?.( "(prefers-reduced-motion: reduce)" ).matches; if (prefersReducedMotion) return; const root = rootRef.current; let paused = false; const pause = () => paused = true; const resume = () => paused = false; const timer = window.setInterval(() => { if (!paused && !document.hidden) onTickRef.current(); }, interval); root?.addEventListener("pointerenter", pause); root?.addEventListener("pointerleave", resume); root?.addEventListener("focusin", pause); root?.addEventListener("focusout", resume); return () => { window.clearInterval(timer); root?.removeEventListener("pointerenter", pause); root?.removeEventListener("pointerleave", resume); root?.removeEventListener("focusin", pause); root?.removeEventListener("focusout", resume); }; }, [enabled, interval, rootRef]); } function useBreakpoints(base, breakpoints) { const [resolved, setResolved] = react.useState(base); const bpKey = breakpoints ? JSON.stringify(breakpoints) : ""; react.useEffect(() => { if (!breakpoints || typeof window === "undefined") return; const resolve = () => { const next = { ...base }; for (const width of Object.keys(breakpoints).map(Number).sort((a, b) => a - b)) { if (window.matchMedia(`(min-width: ${width}px)`).matches) { const over = breakpoints[width]; if (over.slidesPerView != null) next.slidesPerView = over.slidesPerView; if (over.slidesToScroll != null) next.slidesToScroll = over.slidesToScroll; } } return next; }; const update = () => setResolved(resolve()); update(); window.addEventListener("resize", update); return () => window.removeEventListener("resize", update); }, [bpKey, base.slidesPerView, base.slidesToScroll]); return breakpoints ? resolved : base; } function useKeyboard({ rootRef, orientation, onPrev, onNext, onFirst, onLast }) { const handlers = react.useRef({ onPrev, onNext, onFirst, onLast }); handlers.current = { onPrev, onNext, onFirst, onLast }; react.useEffect(() => { const root = rootRef.current; if (!root) return; const prevKey = orientation === "horizontal" ? "ArrowLeft" : "ArrowUp"; const nextKey = orientation === "horizontal" ? "ArrowRight" : "ArrowDown"; const onKeyDown = (event) => { const { onPrev: onPrev2, onNext: onNext2, onFirst: onFirst2, onLast: onLast2 } = handlers.current; switch (event.key) { case prevKey: event.preventDefault(); onPrev2(); break; case nextKey: event.preventDefault(); onNext2(); break; case "Home": event.preventDefault(); onFirst2(); break; case "End": event.preventDefault(); onLast2(); break; } }; root.addEventListener("keydown", onKeyDown); return () => root.removeEventListener("keydown", onKeyDown); }, [rootRef, orientation]); } function useSwipe({ trackRef, orientation, onPrev, onNext, threshold = 50, onSwipeStart, onSwipeEnd }) { const handlers = react.useRef({ onPrev, onNext, onSwipeStart, onSwipeEnd }); handlers.current = { onPrev, onNext, onSwipeStart, onSwipeEnd }; react.useEffect(() => { const track = trackRef.current; if (!track) return; const isHorizontal = orientation === "horizontal"; let startPos = 0; let delta = 0; let dragging = false; let frame = 0; const axis = (event) => isHorizontal ? event.clientX : event.clientY; const paint = () => { frame = 0; track.style.setProperty("--rc-drag", `${delta}px`); }; const onPointerDown = (event) => { if (event.button !== 0) return; dragging = true; startPos = axis(event); delta = 0; track.setAttribute("data-dragging", "true"); track.setPointerCapture(event.pointerId); handlers.current.onSwipeStart?.(); }; const onPointerMove = (event) => { if (!dragging) return; delta = axis(event) - startPos; if (!frame) frame = window.requestAnimationFrame(paint); }; const onPointerUp = (event) => { if (!dragging) return; dragging = false; if (frame) window.cancelAnimationFrame(frame), frame = 0; track.removeAttribute("data-dragging"); track.style.setProperty("--rc-drag", "0px"); if (track.hasPointerCapture(event.pointerId)) { track.releasePointerCapture(event.pointerId); } const committed = Math.abs(delta) > threshold; handlers.current.onSwipeEnd?.({ delta, direction: committed ? delta < 0 ? "next" : "prev" : "none" }); if (committed) { delta < 0 ? handlers.current.onNext() : handlers.current.onPrev(); } }; track.addEventListener("pointerdown", onPointerDown); track.addEventListener("pointermove", onPointerMove); track.addEventListener("pointerup", onPointerUp); track.addEventListener("pointercancel", onPointerUp); return () => { if (frame) window.cancelAnimationFrame(frame); track.removeEventListener("pointerdown", onPointerDown); track.removeEventListener("pointermove", onPointerMove); track.removeEventListener("pointerup", onPointerUp); track.removeEventListener("pointercancel", onPointerUp); }; }, [trackRef, orientation, threshold]); } // src/core/useCarousel.ts function useCarousel(options) { const { slidesCount, initialIndex = 0, loop = false, autoplay = false, autoplayInterval = 4e3, slidesToScroll = 1, slidesPerView = 1, breakpoints, orientation = "horizontal", onIndexChange, onSettle, onSwipeStart, onSwipeEnd } = options; const effective = useBreakpoints({ slidesPerView, slidesToScroll }, breakpoints); const trackRef = react.useRef(null); const rootRef = react.useRef(null); const [state, dispatch] = react.useReducer( carouselReducer, void 0, () => ({ activeIndex: clamp(initialIndex, 0, Math.max(0, slidesCount - slidesPerView)), slidesCount, slidesPerView, isPlaying: autoplay }) ); react.useEffect(() => { dispatch({ type: "SET_COUNT", slidesCount }); }, [slidesCount]); react.useEffect(() => { dispatch({ type: "SET_SLIDES_PER_VIEW", slidesPerView: effective.slidesPerView }); }, [effective.slidesPerView]); const onIndexChangeRef = react.useRef(onIndexChange); onIndexChangeRef.current = onIndexChange; react.useEffect(() => { onIndexChangeRef.current?.(state.activeIndex); }, [state.activeIndex]); const onSettleRef = react.useRef(onSettle); onSettleRef.current = onSettle; const indexRef = react.useRef(state.activeIndex); indexRef.current = state.activeIndex; react.useEffect(() => { const track = trackRef.current; if (!track) return; const handle = (event) => { if (event.target === track && event.propertyName === "transform") { onSettleRef.current?.(indexRef.current); } }; track.addEventListener("transitionend", handle); return () => track.removeEventListener("transitionend", handle); }, []); const step = effective.slidesToScroll; const next = react.useCallback( () => dispatch({ type: "NEXT", step, loop }), [step, loop] ); const prev = react.useCallback( () => dispatch({ type: "PREV", step, loop }), [step, loop] ); const goTo = react.useCallback((index) => dispatch({ type: "GO_TO", index }), []); const play = react.useCallback(() => dispatch({ type: "SET_PLAYING", isPlaying: true }), []); const pause = react.useCallback(() => dispatch({ type: "SET_PLAYING", isPlaying: false }), []); const first = react.useCallback(() => dispatch({ type: "GO_TO", index: 0 }), []); const last = react.useCallback( () => dispatch({ type: "GO_TO", index: slidesCount - 1 }), [slidesCount] ); useKeyboard({ rootRef, orientation, onPrev: prev, onNext: next, onFirst: first, onLast: last }); useSwipe({ trackRef, orientation, onPrev: prev, onNext: next, onSwipeStart, onSwipeEnd }); useAutoplay({ enabled: state.isPlaying, interval: autoplayInterval, onTick: next, rootRef }); const maxIndex = Math.max(0, state.slidesCount - state.slidesPerView); const canPrev = loop || state.activeIndex > 0; const canNext = loop || state.activeIndex < maxIndex; return react.useMemo( () => ({ activeIndex: state.activeIndex, slidesCount: state.slidesCount, slidesPerView: state.slidesPerView, isPlaying: state.isPlaying, canPrev, canNext, orientation, next, prev, goTo, play, pause, trackRef, rootRef }), [state, canPrev, canNext, orientation, next, prev, goTo, play, pause] ); } // src/utils/cx.ts function cx(...parts) { return parts.filter(Boolean).join(" "); } var Carousel = react.forwardRef(function Carousel2({ slidesCount, initialIndex, loop, autoplay, autoplayInterval, slidesToScroll, slidesPerView, breakpoints, orientation = "horizontal", onIndexChange, onSettle, onSwipeStart, onSwipeEnd, label = "Carousel", className, style, children, ...rest }, ref) { const api = useCarousel({ slidesCount, initialIndex, loop, autoplay, autoplayInterval, slidesToScroll, slidesPerView, breakpoints, orientation, onIndexChange, onSettle, onSwipeStart, onSwipeEnd }); react.useImperativeHandle( ref, () => ({ activeIndex: api.activeIndex, canPrev: api.canPrev, canNext: api.canNext, next: api.next, prev: api.prev, goTo: api.goTo, play: api.play, pause: api.pause }), [api] ); const sizedStyle = api.slidesPerView > 1 ? { ...style, "--rc-slide-size": `calc((100% - ${api.slidesPerView - 1} * var(--rc-slide-gap)) / ${api.slidesPerView})` } : style; return /* @__PURE__ */ jsxRuntime.jsx(CarouselContext.Provider, { value: api, children: /* @__PURE__ */ jsxRuntime.jsx( "div", { ref: api.rootRef, className: cx("rc-root", className), role: "region", "aria-roledescription": "carousel", "aria-label": label, "data-orientation": orientation, tabIndex: 0, style: sizedStyle, ...rest, children } ) }); }); function Track({ children, className, style, ...rest }) { const { activeIndex, isPlaying, orientation, trackRef } = useCarouselContext(); return /* @__PURE__ */ jsxRuntime.jsx( "div", { className: "rc-viewport", "data-orientation": orientation, "aria-live": isPlaying ? "off" : "polite", children: /* @__PURE__ */ jsxRuntime.jsx( "div", { ref: trackRef, className: cx("rc-track", className), "data-orientation": orientation, style: { "--rc-active-index": activeIndex, ...style }, ...rest, children } ) } ); } function Slide({ index, children, className, ...rest }) { const { activeIndex, slidesCount } = useCarouselContext(); const isActive = index === activeIndex; return /* @__PURE__ */ jsxRuntime.jsx( "div", { className: cx("rc-slide", isActive && "rc-slide--active", className), role: "group", "aria-roledescription": "slide", "aria-label": `${index + 1} of ${slidesCount}`, "aria-hidden": !isActive || void 0, "data-active": isActive || void 0, ...rest, children } ); } var DEFAULT_LABELS = { prev: "Previous slide", next: "Next slide", first: "First slide", last: "Last slide" }; function Icon({ dir }) { const lines = { prev: ["15 18 9 12 15 6"], next: ["9 18 15 12 9 6"], first: ["18 18 12 12 18 6", "11 18 5 12 11 6"], last: ["13 18 19 12 13 6", "6 18 12 12 6 6"] }; return /* @__PURE__ */ jsxRuntime.jsx( "svg", { className: "rc-button__icon", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", focusable: "false", children: lines[dir].map((points) => /* @__PURE__ */ jsxRuntime.jsx("polyline", { points }, points)) } ); } function Button({ dir, className, children, disabled, "aria-label": ariaLabel, ...rest }) { const { prev, next, goTo, slidesCount, canPrev, canNext } = useCarouselContext(); const actions = { prev, next, first: () => goTo(0), last: () => goTo(slidesCount - 1) }; const enabled = dir === "prev" || dir === "first" ? canPrev : canNext; return /* @__PURE__ */ jsxRuntime.jsx( "button", { type: "button", className: cx("rc-button", `rc-button--${dir}`, className), "aria-label": ariaLabel ?? DEFAULT_LABELS[dir], onClick: actions[dir], disabled: disabled ?? !enabled, ...rest, children: children ?? /* @__PURE__ */ jsxRuntime.jsx(Icon, { dir }) } ); } function Dots({ className, dotLabel, ...rest }) { const { slidesCount, activeIndex, goTo } = useCarouselContext(); return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cx("rc-dots", className), role: "tablist", ...rest, children: Array.from({ length: slidesCount }, (_, index) => { const isActive = index === activeIndex; return /* @__PURE__ */ jsxRuntime.jsx( "button", { type: "button", role: "tab", "aria-selected": isActive, "aria-current": isActive || void 0, "aria-label": dotLabel ? dotLabel(index) : `Go to slide ${index + 1}`, className: cx("rc-dot", isActive && "rc-dot--active"), onClick: () => goTo(index) }, index ); }) }); } function Icon2({ playing }) { return /* @__PURE__ */ jsxRuntime.jsx( "svg", { className: "rc-button__icon", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "currentColor", "aria-hidden": "true", focusable: "false", children: playing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "6", y: "5", width: "4", height: "14", rx: "1" }), /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "5", width: "4", height: "14", rx: "1" }) ] }) : /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "7 4 20 12 7 20 7 4" }) } ); } function PlayPause({ className, children, "aria-label": ariaLabel, ...rest }) { const { isPlaying, play, pause } = useCarouselContext(); return /* @__PURE__ */ jsxRuntime.jsx( "button", { type: "button", className: cx("rc-button", "rc-button--playpause", className), "aria-label": ariaLabel ?? (isPlaying ? "Pause" : "Play"), "aria-pressed": isPlaying, onClick: isPlaying ? pause : play, ...rest, children: children ?? /* @__PURE__ */ jsxRuntime.jsx(Icon2, { playing: isPlaying }) } ); } // src/components/index.ts var Carousel3 = Object.assign(Carousel, { Track, Slide, Button, Dots, PlayPause }); function Icon3({ size = 24, name, children, ...rest }) { return /* @__PURE__ */ jsxRuntime.jsx( "svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className: `lucide lucide-${name}`, ...rest, children } ); } function ChevronLeft(props) { return /* @__PURE__ */ jsxRuntime.jsx(Icon3, { name: "chevron-left", ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) }); } function ChevronRight(props) { return /* @__PURE__ */ jsxRuntime.jsx(Icon3, { name: "chevron-right", ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) }); } function ArrowUpRight(props) { return /* @__PURE__ */ jsxRuntime.jsxs(Icon3, { name: "arrow-up-right", ...props, children: [ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 7h10v10" }), /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 17 17 7" }) ] }); } var shapePaths = { blob: [ "M53.3,-56.6C68.8,-42.1,81.5,-21.1,78.6,-4.5C75.6,12.1,57,24.2,41.5,38C26,51.8,13,67.3,-1,68.6C-15,69.8,-30,56.8,-41.3,42.7C-52.6,28.6,-60.2,13.3,-61.8,-3.4C-63.3,-20.1,-58.9,-38.2,-47.3,-52.6C-35.7,-67.1,-17.9,-77.9,2,-80.3C21.9,-82.7,43.8,-76.8,53.3,-56.6Z", "M40.6,-64.2C50.5,-51.2,55.3,-38,61.2,-26C67.2,-14,74.3,-3.1,74.8,8.7C75.3,20.6,69.2,33.4,60.1,41.8C50.9,50.3,38.7,54.5,26.1,63.4C13.4,72.3,0.3,86,-16.3,89.5C-32.8,93,-52.9,86.3,-60.6,71.8C-68.2,57.2,-63.4,34.8,-58,16.6C-52.7,-1.7,-46.7,-15.7,-39.3,-29.6C-31.9,-43.5,-23.1,-57.3,-10.2,-66.4C2.7,-75.5,27.8,-79.8,40.6,-64.2Z", "M44.7,-61.6C55.7,-52,61.7,-38.4,64.4,-24.9C67.1,-11.4,66.5,2,62.3,14.5C58.2,27,50.6,38.6,40.8,49.2C31,59.8,19,69.3,5.3,71.5C-8.5,73.7,-17,68.7,-29.2,62.5C-41.3,56.2,-57.1,48.7,-65.3,36.2C-73.6,23.6,-74.3,6.1,-68.9,-8.1C-63.5,-22.3,-52,-33.3,-40.3,-43.7C-28.6,-54,-16.8,-63.6,-2.9,-61.3C11,-59,22,-44.9,44.7,-61.6Z", "M62.1,-47.5C75.2,-32.4,78.7,-8.5,75.7,13.8C72.7,36.1,63.3,56.7,47.3,65.8C31.3,74.9,8.8,72.5,-11.8,66.2C-32.5,60,-51.2,49.8,-61.6,34.5C-72,19.1,-74.1,-1.5,-66.9,-17.5C-59.7,-33.5,-43.3,-44.8,-27.7,-58.2C-12.2,-71.6,2.5,-87.2,20.1,-87.4C37.8,-87.6,58.3,-72.5,62.1,-47.5Z" ], heart: [ "M60.83,17.18c8-8.35,13.62-15.57,26-17C110-2.46,131.27,21.26,119.57,44.61c-3.33,6.65-10.11,14.56-17.61,22.32-8.23,8.52-17.34,16.87-23.72,23.2l-17.4,17.26L46.46,93.55C29.16,76.89,1,55.92,0,29.94-.63,11.74,13.73.08,30.25.29c14.76.2,21,7.54,30.58,16.89Z" ], star: [ "M63.09,1.11l16,39.1l42.14,3.13c0.98,0.07,1.72,0.92,1.65,1.9c-0.04,0.52-0.3,0.98-0.68,1.28L90,73.79l10.04,41.05 c0.23,0.95-0.36,1.92-1.31,2.15c-0.5,0.12-1,0.02-1.39-0.24l-35.9-22.21L25.5,116.77c-0.84,0.52-1.93,0.26-2.45-0.58 c-0.26-0.42-0.32-0.91-0.22-1.35l0,0l10.04-41.05L0.63,46.48c-0.75-0.63-0.84-1.76-0.21-2.51c0.32-0.38,0.77-0.59,1.23-0.63v0 l42.14-3.13l16-39.1c0.37-0.91,1.41-1.35,2.31-0.98C62.57,0.32,62.91,0.68,63.09,1.11L63.09,1.11L63.09,1.11z M64.1,39.66 l5.71,13.96l15.05,1.12c0.27,0.02,0.52,0.08,0.76,0.17l29.73-8.43l-37.62-2.8l0-0.01c-0.65-0.05-1.26-0.45-1.52-1.1L63.16,10.66 l0.3,28.08C63.74,39,63.96,39.31,64.1,39.66L64.1,39.66L64.1,39.66z M111.1,51.25l-23.95,6.79c-0.15,0.52-0.47,0.97-0.88,1.29 l-11.45,9.7l3.59,14.67c0.07,0.29,0.09,0.58,0.06,0.86l15.86,21.9L86.3,73.65c-0.2-0.66,0-1.4,0.56-1.87L111.1,51.25L111.1,51.25z M92.21,109.39l-16.3-22.51c-0.51,0-0.99-0.15-1.4-0.42L63.6,79.7v11.17c0,0.25-0.05,0.49-0.15,0.71L92.21,109.39L92.21,109.39z M60.18,91.13c-0.01-0.08-0.02-0.17-0.02-0.25V79.51l-11.28,6.98c-0.34,0.21-0.71,0.33-1.09,0.37L30.65,109.4L60.18,91.13 L60.18,91.13z M28.53,106.54l16.49-21.68c-0.08-0.38-0.08-0.78,0.01-1.15l0,0l3.59-14.67L37.1,59.27c-0.43-0.36-0.7-0.83-0.83-1.33 L8.71,48.66l27.31,23.12l0,0c0.5,0.42,0.74,1.1,0.58,1.78L28.53,106.54L28.53,106.54z M12,46.15l25.65,8.65 c0.08,0.03,0.16,0.06,0.23,0.1c0.22-0.08,0.46-0.13,0.7-0.15l0,0l15.06-1.12l5.71-13.96c0.16-0.39,0.4-0.71,0.69-0.97l-0.3-28.05 l-13.01,31.8c-0.21,0.68-0.82,1.19-1.58,1.25L12,46.15L12,46.15z M60.1,44.59l-4.7,11.48l-16.64,1.24l12.74,10.79l-3.97,16.21 l0.61-0.38l2.88-1.78l10.7-6.62l4.71,2.92l9.11,5.64l0.37,0.23l-3.97-16.21l12.74-10.79l-0.26-0.02v0l-16.38-1.22l-4.51-11.03v0 l-1.81-4.42L60.1,44.59L60.1,44.59z" ], bear: [ "M101.1,19.08c-0.82,0.09-1.56-0.51-1.64-1.33c-0.09-0.82,0.51-1.56,1.33-1.64c0.8-0.09,1.6-0.06,2.4,0.07 c0.78,0.13,1.56,0.37,2.34,0.71c0.76,0.33,1.1,1.2,0.78,1.96c-0.33,0.76-1.2,1.1-1.96,0.78c-0.55-0.24-1.1-0.4-1.65-0.49 C102.16,19.04,101.63,19.03,101.1,19.08L101.1,19.08z M115.43,17.02c-1.16,0.44-1.55,1.27-1.31,3.62c0.24,2.36,0.36,4.57,2.91,5.48 c0.22,0.08,0.45,0.14,0.69,0.19c-1.2,0.84-2.7,1.21-4.31,1.6c-0.73,0.18-1.47,0.36-2.27,0.6c-0.06,0.01-0.12,0.03-0.18,0.06 L80.61,40.06c0.04-1.42,0-2.75-0.15-3.92c-0.13-1.02-0.31-1.98-0.55-2.89c-0.24-0.92-0.54-1.8-0.89-2.63 c-0.32-0.76-1.2-1.12-1.96-0.8c-0.76,0.32-1.12,1.2-0.8,1.96c0.29,0.7,0.54,1.44,0.75,2.22c0.21,0.8,0.37,1.64,0.48,2.51 c0.18,1.4,0.18,3.08,0.06,4.91c-0.33,0.4-0.44,0.96-0.24,1.47c0.03,0.08,0.06,0.15,0.1,0.22c-0.48,4.95-1.68,10.79-2.7,15.77 c-0.47,2.29-0.9,4.42-1.19,6.02l0,0c-0.01,0.07-0.02,0.15-0.02,0.23c-0.03,1.32,0.03,2.48,0.2,3.49c0.18,1.1,0.48,2.03,0.9,2.78 c0.88,1.55,2.13,1.94,3.4,2.34c0.83,0.26,1.68,0.53,2.06,1.46c0.06,0.15,0.08,0.31,0.05,0.47c-0.03,0.19-0.12,0.4-0.27,0.63 c-2.4,1.55-4.8,2.45-7.03,2.67c-2.19,0.22-4.23-0.21-5.95-1.33c-2.04-1.33-3.14-2.87-3.76-4.6c-0.65-1.84-0.8-3.98-0.91-6.34 l-0.1-2.09c0-0.04,0-0.08,0-0.12c-0.22-2.8-1.08-4.6-2.35-5.76c-0.84-0.77-1.82-1.22-2.88-1.48c0.18-0.74,0.33-1.45,0.43-2.16 c0.18-1.24,0.25-2.43,0.19-3.6c-0.09-1.7-0.43-3.31-1.04-4.85c-0.6-1.52-1.47-3-2.6-4.45c-0.51-0.65-1.45-0.77-2.1-0.26 c-0.65,0.51-0.77,1.45-0.26,2.1c0.94,1.21,1.67,2.43,2.17,3.71c0.37,0.94,0.62,1.91,0.75,2.9c-4.52,2.23-7.53,3.49-10.63,4.3 c-0.64,0.17-1.29,0.31-1.96,0.45c-0.21,0-0.41,0.04-0.61,0.12c-1.71,0.31-3.59,0.55-5.86,0.78c1.43-1.71,2.58-3.59,3.44-5.65 c1.79-4.31,2.29-9.37,1.4-15.24c-0.12-0.82-0.89-1.38-1.7-1.26c-0.82,0.12-1.38,0.89-1.26,1.7c0.81,5.32,0.38,9.85-1.2,13.65 c-1.2,2.88-3.06,5.36-5.56,7.47c-0.05,0.04-0.09,0.07-0.14,0.11c-0.72,0.6-1.49,1.17-2.31,1.71c-0.12,0.07-0.23,0.16-0.33,0.26 c-1.23,1.31-2.31,2.69-3.23,4.16c-0.9,1.45-1.64,2.98-2.2,4.62c-0.11,0.26-0.15,0.56-0.09,0.86c0.36,1.83,1.1,3.1,2.15,3.88 c1.03,0.77,2.29,1.03,3.72,0.88c1.26,0.22,2.07,0.88,2.38,1.64c0.12,0.29,0.16,0.6,0.12,0.91c-0.04,0.29-0.15,0.59-0.35,0.85 c-0.45,0.59-1.29,1.05-2.59,1.2h-3.18c-0.07,0-0.13,0-0.19,0.01H14.08L7.02,64.93c-0.14-1.3-0.04-2.35,0.26-3.21 c0.29-0.86,0.79-1.55,1.43-2.12l0,0c0.18-0.17,0.33-0.38,0.41-0.63c0.71-2.14,0.99-4.78,0.83-7.92c-0.15-3.02-0.71-6.54-1.66-10.53 c-0.03-0.18-0.1-0.36-0.21-0.53c-0.44-0.7-1.36-0.91-2.06-0.47c-1.23,0.77-2.04,1.06-2.4,0.84c-0.43-0.27-0.64-1.27-0.63-3.05 l0-0.01c0.18-4.42,1.2-8.16,2.91-11.32c1.71-3.15,4.12-5.75,7.09-7.89v0c0.04-0.03,0.08-0.06,0.12-0.09 c3.87-3.42,8.86-6,14.87-7.78c6.08-1.8,13.2-2.78,21.29-3.01c0.25,0.01,0.51-0.05,0.75-0.18c4.59-2.49,8.94-4.27,12.58-4 c3.39,0.25,6.28,2.44,8.34,7.82c0.29,0.77,1.16,1.16,1.93,0.87c0.77-0.29,1.16-1.16,0.87-1.93c-0.24-0.64-0.5-1.24-0.77-1.8 l15.8,1.51c0.76,0.11,1.5-0.38,1.67-1.15c0.43-1.9,1.56-3.26,2.89-3.95c0.69-0.36,1.43-0.54,2.14-0.52 c0.68,0.02,1.36,0.22,1.95,0.63c1.04,0.71,1.85,2.08,2.12,4.23h0c0.07,0.58,0.48,1.09,1.08,1.26c3.44,0.99,6.61,2.15,9.38,3.55 C112.04,14.55,113.86,15.71,115.43,17.02L115.43,17.02z M71.43,5.23c0.29-0.23,0.66-0.35,1.06-0.31L87.92,6.4 c0.81-2.16,2.31-3.76,4.04-4.66c1.13-0.59,2.37-0.89,3.6-0.86c1.25,0.03,2.49,0.4,3.56,1.14c1.52,1.04,2.73,2.8,3.24,5.35 c3.25,0.98,6.28,2.12,8.99,3.49c2.97,1.5,5.56,3.28,7.67,5.4c1.85,1.38,2.98,2.86,3.51,4.38c0.61,1.77,0.4,3.51-0.5,5.18 c-1.9,3.54-4.73,4.23-7.91,5c-0.7,0.17-1.43,0.35-2.12,0.55L80.4,43.33c-0.5,5.15-1.71,11.09-2.75,16.15 c-0.43,2.09-0.82,4.02-1.15,5.85c-0.02,1.08,0.04,2.02,0.16,2.82c0.12,0.74,0.3,1.34,0.55,1.77c0.3,0.52,0.99,0.74,1.69,0.96 c1.49,0.47,3.03,0.95,3.94,3.19c0.28,0.68,0.35,1.4,0.21,2.15c-0.12,0.66-0.41,1.32-0.88,1.98c-0.11,0.17-0.25,0.31-0.43,0.43 c-2.89,1.91-5.84,3.03-8.64,3.31c-2.87,0.29-5.56-0.3-7.87-1.8c-2.68-1.75-4.13-3.79-4.95-6.11c-0.78-2.21-0.95-4.59-1.08-7.19 l-0.1-2.08l0-0.05c-0.15-1.94-0.65-3.1-1.38-3.77c-0.7-0.64-1.7-0.89-2.84-0.97c-0.12-0.01-0.25-0.03-0.37-0.07 c-0.79-0.25-1.23-1.08-0.98-1.87c0.37-1.18,0.63-2.3,0.79-3.37c0.03-0.23,0.06-0.46,0.09-0.69c-3.99,1.92-6.86,3.08-9.9,3.86 c-0.67,0.17-1.34,0.33-2.03,0.47l-4.88,5.14c-0.28,0.34-0.5,0.59-0.7,0.83c-1.22,1.4-2.19,2.53-2.04,4.5 c0.03,0.34,0.1,0.66,0.21,0.95c0.02,0.06,0.05,0.12,0.08,0.18c2.88-0.22,5.13,0.91,6.4,2.5c0.7,0.87,1.11,1.88,1.2,2.9 c0.09,1.07-0.17,2.14-0.83,3.09c-1.17,1.66-3.59,2.85-7.53,2.64v0h-6.73c-0.6,0.05-1.24,0.06-1.94,0.01H13.18v0 c-0.53,0-1.05-0.29-1.32-0.79L4.25,66.1l0,0c-0.08-0.16-0.14-0.33-0.17-0.51c-0.26-1.92-0.1-3.5,0.35-4.83 c0.43-1.24,1.1-2.25,1.95-3.09c0.51-1.73,0.7-3.89,0.57-6.49c-0.12-2.39-0.51-5.13-1.18-8.2c-1.48,0.57-2.74,0.55-3.77-0.11 c-1.35-0.86-2.03-2.7-2.01-5.6c0-0.03,0-0.07,0-0.1c0.2-4.92,1.34-9.09,3.26-12.63c1.92-3.53,4.61-6.44,7.92-8.85 c4.21-3.7,9.55-6.46,15.95-8.36c6.25-1.85,13.53-2.87,21.78-3.12c4.92-2.64,9.67-4.5,13.9-4.19C66.15,0.28,69.09,1.81,71.43,5.23 L71.43,5.23z M31.93,59.63c-0.69,0.56-1.42,1.09-2.19,1.6c-1.05,1.13-1.97,2.31-2.75,3.57c-0.73,1.18-1.34,2.41-1.81,3.7 c0.21,0.84,0.52,1.39,0.92,1.68c0.41,0.3,0.99,0.39,1.71,0.3c0.15-0.02,0.3-0.03,0.45-0.01c2.53,0.35,4.21,1.8,4.91,3.51 c0.32,0.77,0.43,1.59,0.34,2.39c-0.07,0.58-0.25,1.16-0.54,1.7h1.43v0c0.03,0,0.06,0,0.09,0c2.79,0.16,4.36-0.47,4.99-1.37 c0.24-0.33,0.33-0.72,0.29-1.11c-0.04-0.44-0.23-0.89-0.55-1.28c-0.81-1-2.38-1.68-4.48-1.32c-0.55,0.13-1.15-0.05-1.52-0.52 c-0.4-0.5-0.72-1.05-0.94-1.62c-0.23-0.58-0.36-1.18-0.41-1.82c-0.25-3.2,1.09-4.75,2.77-6.68c0.24-0.27,0.49-0.56,0.67-0.78 c0.04-0.05,0.08-0.1,0.12-0.14l2.23-2.34C35.98,59.27,34.11,59.44,31.93,59.63L31.93,59.63z" ], music: [ "M11.7,0h6.19V2.07c15.49,3.54,17.26,11,8.28,22.7.95-11.63-.22-14.12-8.28-14.66v29.4a3.62,3.62,0,0,1,0,.47c0,3.82-4,7.61-8.95,8.47S0,46.9,0,43.07c0-5.21,7.16-9.74,11.7-8.14V0ZM103,0h6.19V2.07c15.48,3.54,17.25,11,8.27,22.7,1-11.63-.22-14.12-8.27-14.66v29.4c0,.15,0,.31,0,.47,0,3.82-4,7.61-9,8.47s-9-1.55-9-5.38c0-5.21,7.16-9.74,11.7-8.14V0ZM70.51,68.64a11.26,11.26,0,0,1,4.5.08V37.13L41.58,46.72q0,18.66,0,37.3c0,5.82-6.42,10.06-11.57,11-6.39,1.1-11.58-2-11.58-7S23.65,78.18,30,77.08a13,13,0,0,1,6.49.42V32.34l43.54-9.91V73.31c.48,5.4-5,9.49-9.56,10.28-5.34.92-9.66-1.68-9.66-5.81s4.32-8.22,9.66-9.14Z" ], trophy: [ "M89.43,45.54c3.38-1,6.39-2.61,8.84-4.65c4.02-3.35,6.5-7.9,6.5-12.87c0-2.78-0.77-5.42-2.15-7.78l0.01,0 c-0.62-1.06-1.36-2.07-2.21-3.01c-0.44,6.2-1.96,12.08-4.34,17.43C94.32,38.61,92.07,42.27,89.43,45.54L89.43,45.54L89.43,45.54z M56.4,91.21l2.83,7.93l8.42,0.24l-6.67,5.14l2.37,8.08l-6.95-4.76l-6.95,4.76l2.37-8.08l-6.67-5.14l8.42-0.24L56.4,91.21 L56.4,91.21z M20.63,80.94h71.55v41.94H20.63V80.94L20.63,80.94z M60.73,60.07v6.55h0.49v4.58l-12.42,0v-4.58l0.49,0v-6.59 c-7.57-1.17-14.49-4.59-20.14-9.59l-0.67,1.85c-7.79-0.13-14.84-2.82-19.95-7.08C3.26,40.83,0,34.75,0,28.01 c0-3.8,1.05-7.4,2.93-10.63l-0.01-0.01c1.9-3.27,4.66-6.13,8.03-8.37L14,6.97l-3.53,0V0h88.61v6.97h-2.82L99.31,9 c3.36,2.24,6.11,5.1,8.02,8.37h0.01c1.87,3.22,2.92,6.82,2.92,10.64c0,6.74-3.26,12.81-8.54,17.21 c-5.11,4.26-12.16,6.95-19.95,7.08l-0.67-1.86C75.39,55.5,68.39,58.94,60.73,60.07L60.73,60.07L60.73,60.07z M42.16,75.79h25.71 v4.58H42.16V75.79L42.16,75.79z M46.08,71.2h17.87v4.58H46.08V71.2L46.08,71.2z M11.99,40.89c2.45,2.05,5.47,3.65,8.85,4.66 c-2.64-3.27-4.89-6.93-6.66-10.9c-2.38-5.34-3.9-11.23-4.34-17.43c-0.83,0.92-1.57,1.94-2.2,3.01l-0.01,0 c-1.37,2.35-2.14,5-2.14,7.78C5.49,32.99,7.97,37.53,11.99,40.89L11.99,40.89z" ], ring: [ "M10.94,31.01c-0.05-0.25-0.03-0.51,0.05-0.74l3.48-11.06c0.16-0.53,0.6-0.9,1.1-1l18.7-5.39c0.5-0.14,1.01-0.01,1.37,0.31 l0,0l8.52,7.54c0.15,0.11,0.27,0.26,0.37,0.42c0.23,0.39,0.26,0.86,0.1,1.28l-4.76,13.26c6.32-0.29,12.49,1,18.02,3.61 c2.1-2.01,4.44-3.8,6.99-5.31c2.73-1.61,5.72-2.92,8.93-3.84c10.19-2.94,20.61-1.47,29.2,3.28c8.6,4.75,15.39,12.79,18.33,22.99 c2.94,10.19,1.47,20.61-3.28,29.2c-4.75,8.6-12.79,15.39-22.99,18.33c-9.32,2.69-18.82,1.69-26.95-2.13 c-2.11,2.02-4.46,3.81-7.02,5.32c-2.72,1.61-5.7,2.9-8.9,3.83c-10.19,2.94-20.61,1.47-29.2-3.28c-8.6-4.75-15.39-12.79-18.33-22.99 c-2.94-10.19-1.47-20.61,3.28-29.2c3.4-6.16,8.48-11.39,14.84-14.94l-11.31-8.6C11.19,31.68,11,31.35,10.94,31.01L10.94,31.01z M6.69,31.24l-0.16,0.05C6.13,29.94,5.29,28.92,4,28.2c-1.29-0.71-2.61-0.88-3.95-0.49L0,27.55c1.34-0.39,2.37-1.23,3.09-2.52 c0.71-1.3,0.88-2.61,0.49-3.95l0.16-0.05c0.39,1.34,1.23,2.37,2.52,3.09c1.29,0.71,2.61,0.88,3.95,0.49l0.05,0.16 c-1.34,0.39-2.37,1.23-3.09,2.52C6.46,28.58,6.3,29.9,6.69,31.24L6.69,31.24L6.69,31.24z M17.03,12l-0.16,0.05 c-0.39-1.34-1.23-2.37-2.52-3.09c-1.29-0.71-2.61-0.88-3.95-0.49l-0.05-0.16c1.34-0.39,2.37-1.23,3.09-2.52 c0.71-1.3,0.88-2.61,0.49-3.95l0.16-0.05c0.39,1.34,1.23,2.37,2.52,3.09s2.61,0.88,3.95,0.49l0.05,0.16 c-1.34,0.39-2.37,1.23-3.09,2.52C16.8,9.34,16.64,10.66,17.03,12L17.03,12L17.03,12z M40.83,10.22l-0.16,0.05 c-0.39-1.34-1.23-2.37-2.52-3.09c-1.29-0.71-2.61-0.88-3.95-0.49l-0.05-0.16c1.34-0.39,2.37-1.23,3.09-2.52 c0.71-1.3,0.88-2.61,0.49-3.95L37.89,0c0.39,1.34,1.23,2.37,2.52,3.09c1.29,0.71,2.61,0.88,3.95,0.49l0.05,0.16 c-1.34,0.39-2.37,1.23-3.09,2.52C40.61,7.55,40.45,8.87,40.83,10.22L40.83,10.22L40.83,10.22z M60.66,40.68 c2.31,1.32,4.48,2.88,6.48,4.66c1.26-1,2.61-1.91,4.05-2.69c1.74-0.95,3.61-1.72,5.6-2.29c7.36-2.12,14.88-1.06,21.09,2.37 c6.21,3.43,11.12,9.24,13.24,16.6c2.12,7.36,1.06,14.88-2.37,21.09c-3.43,6.21-9.24,11.12-16.6,13.24 c-3.08,0.89-6.19,1.22-9.22,1.05c-3.14-0.17-6.2-0.89-9.05-2.07c-1.79-0.74-3.5-1.67-5.09-2.75c-1.59-1.09-3.06-2.34-4.41-3.74 c-1.52-1.59-2.86-3.37-3.97-5.32c-1.08-1.88-1.95-3.93-2.59-6.14c-0.93-3.24-1.25-6.5-1.03-9.67c0.22-3.05,0.94-6.01,2.11-8.77 c-1.59-1.55-3.38-2.87-5.31-3.94c-0.37-0.21-0.75-0.4-1.14-0.59c-1.77,3.7-2.9,7.71-3.31,11.86c-0.42,4.34-0.05,8.82,1.23,13.26 c2.71,9.41,8.99,16.83,16.94,21.22c7.95,4.39,17.58,5.75,26.99,3.04c9.41-2.71,16.83-8.99,21.22-16.94 c4.39-7.95,5.75-17.58,3.04-26.99c-2.71-9.41-8.99-16.83-16.94-21.22c-7.95-4.39-17.58-5.75-26.99-3.04 c-2.94,0.85-5.7,2.05-8.24,3.55C64.32,37.68,62.4,39.1,60.66,40.68L60.66,40.68z M69.27,47.38c4.2,4.36,7.43,9.78,9.22,16 c1.39,4.82,1.79,9.68,1.33,14.38c-0.44,4.43-1.64,8.71-3.51,12.67c2.16,0.75,4.44,1.21,6.78,1.34c2.72,0.15,5.5-0.14,8.26-0.94 c6.58-1.9,11.76-6.28,14.83-11.84c3.07-5.56,4.02-12.29,2.13-18.88c-1.9-6.58-6.28-11.76-11.84-14.84 c-5.56-3.07-12.29-4.02-18.88-2.13c-1.77,0.51-3.44,1.2-5,2.05C71.41,45.85,70.3,46.58,69.27,47.38L69.27,47.38z M73.6,89.3 c1.76-3.69,2.9-7.69,3.3-11.83c0.43-4.35,0.05-8.85-1.23-13.3c-2.71-9.41-8.99-16.83-16.94-21.22c-7.07-3.9-15.46-5.41-23.84-3.8 c-1.04,0.23-2.05,0.48-3.05,0.77c-1.34,0.39-2.67,0.84-3.96,1.34c-7.58,3.16-13.59,8.75-17.36,15.58 c-4.39,7.95-5.75,17.58-3.04,26.99c2.71,9.41,8.99,16.83,16.94,21.22c7.95,4.39,17.58,5.75,26.99,3.04 c2.93-0.85,5.68-2.05,8.22-3.54c2.08-1.23,4.01-2.65,5.76-4.23c-2.31-1.32-4.48-2.88-6.48-4.66c-1.27,1.02-2.63,1.93-4.07,2.71 c-1.72,0.93-3.58,1.7-5.57,2.27c-7.36,2.12-14.88,1.06-21.09-2.37c-6.21-3.43-11.12-9.24-13.24-16.6l0-0.01 c-2.12-7.36-1.06-14.87,2.37-21.08c3.43-6.21,9.24-11.12,16.6-13.24l0.01,0c7.36-2.12,14.87-1.06,21.08,2.37 c6.21,3.43,11.12,9.24,13.24,16.6l0,0c0.94,3.25,1.25,6.53,1.02,9.7c-0.22,3.03-0.94,5.98-2.11,8.73c1.02,0.99,2.12,1.89,3.29,2.69 C71.45,88.15,72.51,88.77,73.6,89.3L73.6,89.3z M56.78,93.63c-4.2-4.36-7.43-9.78-9.22-16c-1.38-4.8-1.79-9.65-1.34-14.34 c0.43-4.45,1.64-8.74,3.51-12.71c-4.64-1.62-9.81-1.88-14.9-0.45c-0.08,0.03-0.17,0.06-0.26,0.08c-6.52,1.92-11.66,6.28-14.71,11.8 c-3.05,5.52-4.01,12.2-2.16,18.74c0.03,0.08,0.06,0.17,0.08,0.26c1.92,6.52,6.28,11.66,11.8,14.71c5.56,3.07,12.29,4.02,18.88,2.13 c1.74-0.5,3.41-1.19,4.98-2.04C54.63,95.17,55.74,94.44,56.78,93.63L56.78,93.63z M61.09,58.68c-0.75,2.09-1.22,4.29-1.38,6.54 c-0.2,2.85,0.08,5.77,0.91,8.66c0.56,1.94,1.35,3.78,2.33,5.48c0.6,1.05,1.28,2.05,2.01,2.98c0.74-2.08,1.21-4.26,1.37-6.5 c0.21-2.81-0.06-5.7-0.87-8.56c-0.03-0.08-0.06-0.17-0.08-0.26C64.47,63.89,62.99,61.09,61.09,58.68L61.09,58.68z M27.02,38.48 c1.27-0.52,2.58-0.98,3.93-1.37c1.03-0.3,2.05-0.55,3.08-0.75c0.89-0.2,1.78-0.38,2.68-0.53l4.24-11.81l-25.38,7.32l10.11,7.68 C26.11,38.83,26.56,38.65,27.02,38.48L27.02,38.48z M14.59,28.58l25.72-7.42l-6-5.31l-17.27,4.98L14.59,28.58L14.59,28.58z" ] }; function Blobs({ seed, shape = "blob" }) { const blobShapes = shapePaths[shape]; const selectedBlobs = react.useMemo( () => [ { shape: blobShapes[Math.floor(Math.random() * blobShapes.length)], top: -Math.random() * 50, left: Math.random(), opacity: 20 }, { shape: blobShapes[Math.floor(Math.random() * blobShapes.length)], top: Math.random() * 50, left: 50 + Math.random() * 20, opacity: 30 } ], // Recompute only when the seed (per-card) changes. [seed, shape] ); return /* @__PURE__ */ jsxRuntime.jsx("div", { children: selectedBlobs.map((blob, index) => /* @__PURE__ */ jsxRuntime.jsx( "svg", { className: "rc-card__blob", viewBox: "0 0 300 200", xmlns: "http://www.w3.org/2000/svg", style: { top: `${blob.top}%`, left: `${blob.left}%`, opacity: `${blob.opacity}%` }, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx( "path", { fill: "var(--rc-blob-fill, #ffffff)", d: blob.shape, transform: "translate(100 100)" } ) }, index )) }); } function Card({ title, category, description, from, to, shape, variant = "gradient" }) { const seed = react.useMemo(() => Math.random(), []); return /* @__PURE__ */ jsxRuntime.jsxs( framerMotion.motion.div, { className: `rc-card rc-card--${variant}`, style: { "--rc-from": from, "--rc-to": to }, whileTap: { scale: 0.95 }, whileHover: { scale: 1.05, boxShadow: "10px 8px 20px rgba(0, 0, 0, 0.35)" }, transition: { type: "spring", stiffness: 200 }, children: [ /* @__PURE__ */ jsxRuntime.jsx(Blobs, { seed, shape }), /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rc-card__tag", children: category }), /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "rc-card__title", children: title }), /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rc-card__progress", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rc-card__progress-fill" }) }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "rc-card__desc", children: description }), /* @__PURE__ */ jsxRuntime.jsx( framerMotion.motion.button, { type: "button", className: "rc-card__button", whileHover: { scale: 1.2 }, "aria-hidden": "true", tabIndex: -1, children: /* @__PURE__ */ jsxRuntime.jsx(ArrowUpRight, { size: 18 }) } ) ] } ); } // src/utils/shuffle.ts function shuffle(input) { const result = input.slice(); for (let i = result.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [result[i], result[j]] = [result[j], result[i]]; } return result; } // src/presets/gradient.ts var palettes = [ { from: "#4A90E2", to: "#5F9EE7" }, { from: "#D35400", to: "#E67E22" }, { from: "#8E44AD", to: "#9B59B6" }, { from: "#27AE60", to: "#2ECC71" }, { from: "#F39C12", to: "#F1C40F" }, { from: "#E74C3C", to: "#EC7063" }, { from: "#9B59B6", to: "#8E44AD" }, { from: "#16A085", to: "#1ABC9C" }, { from: "#00C9A7", to: "#02AABD" }, { from: "#FF4E50", to: "#FC913A" }, { from: "#6A0572", to: "#AB83A1" }, { from: "#D946EF", to: "#F472B6" }, { from: "#8E2DE2", to: "#4A00E0" }, { from: "#FFD700", to: "#FFA500" } ]; function gradientCss({ from, to }) { return `linear-gradient(135deg, ${from}, ${to})`; } function getPalettes(randomBackground) { return randomBackground ? shuffle(palettes) : palettes.slice(); } palettes.map(gradientCss); function CardSlider({ slides, shape, randomBackground = false, variant = "gradient" }) { const sliderRef = react.useRef(null); const scrollByHalf = (direction) => { const el = sliderRef.current; if (el) { el.scrollBy({ left: direction * el.clientWidth / 2, behavior: "smooth" }); } }; const palettes2 = getPalettes(randomBackground); return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rc-cardslider", children: [ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rc-cardslider__overlay rc-cardslider__overlay--left" }), /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rc-cardslider__overlay rc-cardslider__overlay--right" }), /* @__PURE__ */ jsxRuntime.jsx( "button", { type: "button", className: "rc-cardslider__arrow rc-cardslider__arrow--left", "aria-label": "Scroll left", onClick: () => scrollByHalf(-1), children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeft, {}) } ), /* @__PURE__ */ jsxRuntime.jsx("div", { ref: sliderRef, className: "rc-cardslider__track", children: slides.map((slide, index) => { const palette = palettes2[index % palettes2.length]; const card = /* @__PURE__ */ jsxRuntime.jsx( Card, { title: slide.title, category: slide.category, description: slide.description, from: palette.from, to: palette.to, shape, variant } ); return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rc-cardslider__item", children: slide.link ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: slide.link, target: "_blank", rel: "noreferrer", children: card }) : card }, slide.title + index); }) }), /* @__PURE__ */ jsxRuntime.jsx( "button", { type: "button", className: "rc-cardslider__arrow rc-cardslider__arrow--right", "aria-label": "Scroll right", onClick: () => scrollByHalf(1), children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRight, {}) } ) ] }); } function ImageSlider({ slides, loop = true, autoplay = false, autoplayInterval, height = 460, showArrows = true, showDots = true, className, label = "Image carousel" }) { return /* @__PURE__ */ jsxRuntime.jsxs( Carousel3, { slidesCount: slides.length, loop, autoplay, autoplayInterval, label, className: cx("rc-image", className), style: { "--rc-image-height": typeof height === "number" ? `${height}px` : height }, children: [ showArrows && /* @__PURE__ */ jsxRuntime.jsx(Carousel3.Button, { dir: "prev" }), /* @__PURE__ */ jsxRuntime.jsx(Carousel3.Track, { children: slides.map((slide, i) => { const inner = /* @__PURE__ */ jsxRuntime.jsx( "div", { className: "rc-image__slide", style: { backgroundImage: `url(${slide.src})` }, role: "img", "aria-label": slide.alt, children: slide.caption != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rc-image__caption", children: slide.caption }) } ); return /* @__PURE__ */ jsxRuntime.jsx(Carousel3.Slide, { index: i, children: slide.href ? /* @__PURE__ */ jsxRuntime.jsx("a", { className: "rc-image__link", href: slide.href, target: "_blank", rel: "noreferrer", children: inner }) : inner }, i); }) }), showArrows && /* @__PURE__ */ jsxRuntime.jsx(Carousel3.Button, { dir: "next" }), showDots && /* @__PURE__ */ jsxRuntime.jsx(Carousel3.Dots, {}) ] } ); } function SlicerSlider({ slides, loop = true, autoplay = false, autoplayInterval, height = 460, slices = 6, showArrows = true, showDots = true, className, label = "Slicer carousel" }) { const api = useCarousel({ slidesCount: slides.length, loop, autoplay, autoplayInterval }); const strips = Array.from({ length: slices }, (_, k) => k); return /* @__PURE__ */ jsxRuntime.jsx(CarouselContext.Provider, { value: api, children: /* @__PURE__ */ jsxRuntime.jsxs( "div", { ref: api.rootRef, className: cx("rc-slicer", className), role: "region", "aria-roledescription": "carousel", "aria-label": label, tabIndex: 0, style: { "--rc-image-height": `${height}px`, "--rc-slices": slices }, children: [ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: api.trackRef, className: "rc-slicer__viewport", children: slides.map((slide, i) => { const active = i === api.activeIndex; return /* @__PURE__ */ jsxRuntime.jsxs( "div", { className: "rc-slicer__slide", "data-active": active || void 0, "aria-hidden": !active || void 0, role: "group", "aria-roledescription": "slide", "aria-label": `${i + 1} of ${slides.length}`, children: [ strips.map((k) => /* @__PURE__ */ jsxRuntime.jsx( "span", { className: "rc-slicer__strip", style: { "--k": k, backgroundImage: `url(${slide.src})` } }, k )), slide.caption != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rc-slicer__caption", children: slide.caption }) ] }, i ); }) }), showArrows && /* @__PURE__ */ jsxRuntime.jsx(Button, { dir: "prev" }), showArrows && /* @__PURE__ */ jsxRuntime.jsx(Button, { dir: "next" }), showDots && /* @__PURE__ */ jsxRuntime.jsx(Dots, {}) ] } ) }); } function CubeSlider({ slides, loop = true, autoplay = false, autoplayInterval, height = 460, vertical = false, shadow = true, showArrows = true, showDots = true, className, label = "Cube carousel" }) { const api = useCarousel({ slidesCount: slides.length, loop, autoplay, autoplayInterval, orientation: vertical ? "vertical" : "horizontal" }); const count = slides.length; const [depth, setDepth] = react.useState(0); react.useEffect(() => { const el = api.trackRef.current; if (!el) return; const measure = () => setDepth((vertical ? el.clientHeight : el.clientWidth) / 2); measure(); if (typeof ResizeObserver === "undefined") return; const observer = new ResizeObserver(measure); observer.observe(el); return () => observer.disconnect(); }, [api.trackRef, vertical]); const offsetOf = (i) => { let off = i - api.activeIndex; if (loop && count > 1) { if (off > count / 2) off -= count; else if (off < -count / 2) off += count; } return off; }; return /* @__PURE__ */ jsxRuntime.jsx(CarouselContext.Provider, { value: api, children: /* @__PURE__ */ jsxRuntime.jsxs( "div", { ref: api.rootRef, className: cx("rc-cube", className), role: "region", "aria-roledescription": "carousel", "aria-label": label, tabIndex: 0, "data-orientation": vertical ? "vertical" : "horizontal", "data-shadow": shadow || void 0, style: { "--rc-image-height": `${height}px`, "--rc-cube-depth": `${depth}px` }, children: [ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: api.trackRef, className: "rc-cube__viewport", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rc-cube__cage", children: slides.map((slide, i) => { const off = offsetOf(i); const active = off === 0; return /* @__PURE__ */ jsxRuntime.jsx( "div", { className: "rc-cube__face", "data-active": active || void 0, "aria-hidden": !active || void 0, role: "group", "aria-roledescription": "slide", "aria-label": `${i + 1} of ${count}`, style: { "--off": off, // Only the active face and its two neighbours form the cube. visibility: Math.abs(off) <= 1 ? void 0 : "hidden", backgroundImage: `url(${slide.src})` }, children: slide.caption != null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rc-cube__caption", children: slide.caption }) }, i ); }) }) }), shadow && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rc-cube__shadow", "aria-hidden": "true" }), showArrows && /* @__PURE__ */ jsxRuntime.jsx(Button, { dir: "prev" }), showArrows && /* @__PURE__ */ jsxRuntime.jsx(Button, { dir: "next" }), showDots && /* @__PURE__ */ jsxRuntime.jsx(Dots, {}) ] } ) }); } exports.Button = Button; exports.CardSlider = CardSlider; exports.Carousel = Carousel3; exports.CubeSlider = CubeSlider; exports.Dots = Dots; exports.ImageSlider = ImageSlider; exports.PlayPause = PlayPause; exports.SlicerSlider = SlicerSlider; exports.Slide = Slide; exports.Track = Track; exports.default = CardSlider; exports.useCarousel = useCarousel; //# sourceMappingURL=index.cjs.map //# sourceMappingURL=index.cjs.map