{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "box-carousel",
  "type": "registry:block",
  "title": "Box carousel",
  "description": "Box carousel",
  "files": [
    {
      "path": "components/usages/boxcarouselusage.tsx",
      "content": "\"use client\";\r\n\r\nimport { useRef, useState } from \"react\";\r\n\r\nimport BoxCarousel, { CarouselItem } from \"@/registry/open-source/box-carousel\";\r\nimport { useIsMobile } from \"@/registry/open-source/skeleton\";\r\nimport { Bug, BugOff } from \"lucide-react\";\r\n\r\n// Sample carousel items with mix of images and videos\r\nconst carouselItems: CarouselItem[] = [\r\n\t{\r\n\t\tid: \"1\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/778d0640-d4b8-45b4-8bbe-862e759c231d?format=jpeg\",\r\n\t\talt: \"Blurry poster\",\r\n\t},\r\n\t{\r\n\t\tid: \"2\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/27ac2696-1f2b-498e-8d3d-11f2dd358ab9?format=jpeg\",\r\n\t\talt: \"Abstract blurry figure\",\r\n\t},\r\n\t{\r\n\t\tid: \"3\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/c48b739d-202d-4340-ab6b-afa34f0d7142?format=jpeg\",\r\n\t\talt: \"Long exposure photo of a person\",\r\n\t},\r\n\t{\r\n\t\tid: \"4\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/5332f9ac-7823-4635-871d-d4b3032e1c62?format=jpeg\",\r\n\t\talt: \"Blurry portrait photo of a person\",\r\n\t},\r\n\t{\r\n\t\tid: \"5\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/d9ed937e-7c3b-4f64-a4f3-708d639f13a1?format=jpeg\",\r\n\t\talt: \"Long exposure shots with multiple people\",\r\n\t},\r\n\t{\r\n\t\tid: \"6\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/33b43e2a-da66-42d9-a0b1-08165d80b0aa?format=jpeg\",\r\n\t\talt: \"Close up blurry photo of a person poster\",\r\n\t},\r\n\t{\r\n\t\tid: \"7\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/40342df7-2ea2-4297-add2-fe17cdc62551?format=jpeg\",\r\n\t\talt: \"Long exposure shot of a motorcyclist\",\r\n\t},\r\n];\r\n\r\nexport default function BoxCarouselDemo() {\r\n\tconst carouselRef = useRef<BoxCarouselRef>(null);\r\n\tconst [debug, setDebug] = useState(false);\r\n\tconst isMobile = useIsMobile();\r\n\r\n\t// Responsive dimensions based on screen size\r\n\tconst getCarouselDimensions = () => {\r\n\t\tif (isMobile) {\r\n\t\t\treturn { width: 200, height: 150 };\r\n\t\t}\r\n\t\treturn { width: 350, height: 250 };\r\n\t};\r\n\r\n\tconst { width, height } = getCarouselDimensions();\r\n\r\n\tconst handleNext = () => {\r\n\t\tcarouselRef.current?.next();\r\n\t};\r\n\r\n\tconst handlePrev = () => {\r\n\t\tcarouselRef.current?.prev();\r\n\t};\r\n\r\n\tconst handleIndexChange = (index: number) => {\r\n\t\tconsole.log(\"Index changed:\", index);\r\n\t};\r\n\r\n\tconst toggleDebug = () => {\r\n\t\tsetDebug(!debug);\r\n\t};\r\n\r\n\treturn (\r\n\t\t<div className=\"w-full max-w-4xl h-full p-6 flex justify-items-center justify-center items-center text-muted-foreground bg-[#fefefe]\">\r\n\t\t\t<button\r\n\t\t\t\tonClick={toggleDebug}\r\n\t\t\t\tclassName=\"absolute top-4 left-4 p-1.5 border border-black text-black rounded-full cursor-pointer transition-all duration-300 ease-out hover:bg-gray-100 active:scale-95\"\r\n\t\t\t\ttitle={debug ? \"Debug Mode: ON\" : \"Debug Mode: OFF\"}\r\n\t\t\t>\r\n\t\t\t\t{debug ? <Bug size={10} /> : <BugOff size={10} />}\r\n\t\t\t</button>\r\n\r\n\t\t\t<div className=\"space-y-24\">\r\n\t\t\t\t<div className=\"flex justify-center pt-20\">\r\n\t\t\t\t\t<BoxCarousel\r\n\t\t\t\t\t\tref={carouselRef}\r\n\t\t\t\t\t\titems={carouselItems}\r\n\t\t\t\t\t\twidth={width}\r\n\t\t\t\t\t\theight={height}\r\n\t\t\t\t\t\tdirection=\"right\"\r\n\t\t\t\t\t\tonIndexChange={handleIndexChange}\r\n\t\t\t\t\t\tdebug={debug}\r\n\t\t\t\t\t\tenableDrag\r\n\t\t\t\t\t\tperspective={1000}\r\n\t\t\t\t\t/>\r\n\t\t\t\t</div>\r\n\r\n\t\t\t\t<div className=\"flex gap-2 justify-center\">\r\n\t\t\t\t\t<button\r\n\t\t\t\t\t\tonClick={handlePrev}\r\n\t\t\t\t\t\tclassName=\"px-2 py-0.5 text-xs border border-black text-black rounded-full cursor-pointer transition-all duration-300 ease-out hover:bg-gray-100 active:scale-95\"\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\tPrev\r\n\t\t\t\t\t</button>\r\n\t\t\t\t\t<button\r\n\t\t\t\t\t\tonClick={handleNext}\r\n\t\t\t\t\t\tclassName=\"px-2 py-0.5 text-xs border border-black text-black rounded-full cursor-pointer transition-all duration-300 ease-out hover:bg-gray-100 active:scale-95\"\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\tNext\r\n\t\t\t\t\t</button>\r\n\t\t\t\t</div>\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t);\r\n}\r\n",
      "type": "registry:block",
      "target": "~/example.tsx"
    },
    {
      "path": "components/usages/boxcarouselusage.tsx",
      "content": "\"use client\";\r\n\r\nimport { useRef, useState } from \"react\";\r\n\r\nimport BoxCarousel, { CarouselItem } from \"@/registry/open-source/box-carousel\";\r\nimport { useIsMobile } from \"@/registry/open-source/skeleton\";\r\nimport { Bug, BugOff } from \"lucide-react\";\r\n\r\n// Sample carousel items with mix of images and videos\r\nconst carouselItems: CarouselItem[] = [\r\n\t{\r\n\t\tid: \"1\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/778d0640-d4b8-45b4-8bbe-862e759c231d?format=jpeg\",\r\n\t\talt: \"Blurry poster\",\r\n\t},\r\n\t{\r\n\t\tid: \"2\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/27ac2696-1f2b-498e-8d3d-11f2dd358ab9?format=jpeg\",\r\n\t\talt: \"Abstract blurry figure\",\r\n\t},\r\n\t{\r\n\t\tid: \"3\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/c48b739d-202d-4340-ab6b-afa34f0d7142?format=jpeg\",\r\n\t\talt: \"Long exposure photo of a person\",\r\n\t},\r\n\t{\r\n\t\tid: \"4\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/5332f9ac-7823-4635-871d-d4b3032e1c62?format=jpeg\",\r\n\t\talt: \"Blurry portrait photo of a person\",\r\n\t},\r\n\t{\r\n\t\tid: \"5\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/d9ed937e-7c3b-4f64-a4f3-708d639f13a1?format=jpeg\",\r\n\t\talt: \"Long exposure shots with multiple people\",\r\n\t},\r\n\t{\r\n\t\tid: \"6\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/33b43e2a-da66-42d9-a0b1-08165d80b0aa?format=jpeg\",\r\n\t\talt: \"Close up blurry photo of a person poster\",\r\n\t},\r\n\t{\r\n\t\tid: \"7\",\r\n\t\ttype: \"image\",\r\n\t\tsrc: \"https://cdn.cosmos.so/40342df7-2ea2-4297-add2-fe17cdc62551?format=jpeg\",\r\n\t\talt: \"Long exposure shot of a motorcyclist\",\r\n\t},\r\n];\r\n\r\nexport default function BoxCarouselDemo() {\r\n\tconst carouselRef = useRef<BoxCarouselRef>(null);\r\n\tconst [debug, setDebug] = useState(false);\r\n\tconst isMobile = useIsMobile();\r\n\r\n\t// Responsive dimensions based on screen size\r\n\tconst getCarouselDimensions = () => {\r\n\t\tif (isMobile) {\r\n\t\t\treturn { width: 200, height: 150 };\r\n\t\t}\r\n\t\treturn { width: 350, height: 250 };\r\n\t};\r\n\r\n\tconst { width, height } = getCarouselDimensions();\r\n\r\n\tconst handleNext = () => {\r\n\t\tcarouselRef.current?.next();\r\n\t};\r\n\r\n\tconst handlePrev = () => {\r\n\t\tcarouselRef.current?.prev();\r\n\t};\r\n\r\n\tconst handleIndexChange = (index: number) => {\r\n\t\tconsole.log(\"Index changed:\", index);\r\n\t};\r\n\r\n\tconst toggleDebug = () => {\r\n\t\tsetDebug(!debug);\r\n\t};\r\n\r\n\treturn (\r\n\t\t<div className=\"w-full max-w-4xl h-full p-6 flex justify-items-center justify-center items-center text-muted-foreground bg-[#fefefe]\">\r\n\t\t\t<button\r\n\t\t\t\tonClick={toggleDebug}\r\n\t\t\t\tclassName=\"absolute top-4 left-4 p-1.5 border border-black text-black rounded-full cursor-pointer transition-all duration-300 ease-out hover:bg-gray-100 active:scale-95\"\r\n\t\t\t\ttitle={debug ? \"Debug Mode: ON\" : \"Debug Mode: OFF\"}\r\n\t\t\t>\r\n\t\t\t\t{debug ? <Bug size={10} /> : <BugOff size={10} />}\r\n\t\t\t</button>\r\n\r\n\t\t\t<div className=\"space-y-24\">\r\n\t\t\t\t<div className=\"flex justify-center pt-20\">\r\n\t\t\t\t\t<BoxCarousel\r\n\t\t\t\t\t\tref={carouselRef}\r\n\t\t\t\t\t\titems={carouselItems}\r\n\t\t\t\t\t\twidth={width}\r\n\t\t\t\t\t\theight={height}\r\n\t\t\t\t\t\tdirection=\"right\"\r\n\t\t\t\t\t\tonIndexChange={handleIndexChange}\r\n\t\t\t\t\t\tdebug={debug}\r\n\t\t\t\t\t\tenableDrag\r\n\t\t\t\t\t\tperspective={1000}\r\n\t\t\t\t\t/>\r\n\t\t\t\t</div>\r\n\r\n\t\t\t\t<div className=\"flex gap-2 justify-center\">\r\n\t\t\t\t\t<button\r\n\t\t\t\t\t\tonClick={handlePrev}\r\n\t\t\t\t\t\tclassName=\"px-2 py-0.5 text-xs border border-black text-black rounded-full cursor-pointer transition-all duration-300 ease-out hover:bg-gray-100 active:scale-95\"\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\tPrev\r\n\t\t\t\t\t</button>\r\n\t\t\t\t\t<button\r\n\t\t\t\t\t\tonClick={handleNext}\r\n\t\t\t\t\t\tclassName=\"px-2 py-0.5 text-xs border border-black text-black rounded-full cursor-pointer transition-all duration-300 ease-out hover:bg-gray-100 active:scale-95\"\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\tNext\r\n\t\t\t\t\t</button>\r\n\t\t\t\t</div>\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t);\r\n}\r\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/box-carousel.tsx",
      "content": "\"use client\"\r\n\r\nimport React, {\r\n\tforwardRef,\r\n\tmemo,\r\n\tReactNode,\r\n\tuseCallback,\r\n\tuseEffect,\r\n\tuseImperativeHandle,\r\n\tuseMemo,\r\n\tuseRef,\r\n\tuseState,\r\n} from \"react\"\r\nimport {\r\n\tanimate,\r\n\tmotion,\r\n\tuseMotionValue,\r\n\tuseReducedMotion,\r\n\tuseSpring,\r\n\tuseTransform,\r\n\tValueAnimationOptions,\r\n} from \"motion/react\"\r\nimport { cn } from \"@/registry/utilities/cn\";\r\n\r\n\r\ninterface CarouselItem {\r\n\t/**\r\n\t * Unique identifier for the carousel item\r\n\t */\r\n\tid: string\r\n\t/**\r\n\t * The type of media: \"image\" or \"video\"\r\n\t */\r\n\ttype: \"image\" | \"video\"\r\n\t/**\r\n\t * Source URL for the image or video\r\n\t */\r\n\tsrc: string\r\n\t/**\r\n\t * (Optional) Alternative text for images\r\n\t */\r\n\talt?: string\r\n\t/**\r\n\t * (Optional) Poster image for videos (displayed before playback)\r\n\t */\r\n\tposter?: string\r\n}\r\n\r\n/**\r\n * Props for a single face of the cube in the BoxCarousel.\r\n */\r\ninterface FaceProps {\r\n\t/**\r\n\t * The CSS transform string to position and rotate the face in 3D space.\r\n\t */\r\n\ttransform: string\r\n\t/**\r\n\t * Optional additional CSS class names for the face.\r\n\t */\r\n\tclassName?: string\r\n\t/**\r\n\t * Optional React children to render inside the face.\r\n\t */\r\n\tchildren?: ReactNode\r\n\t/**\r\n\t * Optional inline styles for the face.\r\n\t */\r\n\tstyle?: React.CSSProperties\r\n\t/**\r\n\t * If true, enables debug mode (e.g., shows backface and opacity).\r\n\t */\r\n\tdebug?: boolean\r\n}\r\n\r\nconst CubeFace = memo(\r\n\t({ transform, className, children, style, debug }: FaceProps) => (\r\n\t\t<div\r\n\t\t\tclassName={cn(\r\n\t\t\t\t\"absolute overflow-hidden\",\r\n\t\t\t\tdebug && \"backface-visible opacity-50\",\r\n\t\t\t\tclassName\r\n\t\t\t)}\r\n\t\t\tstyle={{ transform, ...style }}\r\n\t\t>\r\n\t\t\t{children}\r\n\t\t</div>\r\n\t)\r\n)\r\n\r\nCubeFace.displayName = \"CubeFace\"\r\n\r\nconst MediaRenderer = memo(\r\n\t({\r\n\t\titem,\r\n\t\tclassName,\r\n\t\tdebug = false,\r\n\t}: {\r\n\t\titem: CarouselItem\r\n\t\tclassName?: string\r\n\t\tdebug?: boolean\r\n\t}) => {\r\n\t\tif (!debug) {\r\n\t\t\tif (item.type === \"video\") {\r\n\t\t\t\treturn (\r\n\t\t\t\t\t<video\r\n\t\t\t\t\t\tsrc={item.src}\r\n\t\t\t\t\t\tposter={item.poster}\r\n\t\t\t\t\t\tclassName={cn(\"w-full h-full object-cover\", className)}\r\n\t\t\t\t\t\tmuted\r\n\t\t\t\t\t\tloop\r\n\t\t\t\t\t\tautoPlay\r\n\t\t\t\t\t/>\r\n\t\t\t\t)\r\n\t\t\t}\r\n\r\n\t\t\treturn (\r\n\t\t\t\t<img\r\n\t\t\t\t\tsrc={item.src}\r\n\t\t\t\t\talt={item.alt || \"\"}\r\n\t\t\t\t\tdraggable={false}\r\n\t\t\t\t\tclassName={cn(\"w-full h-full object-cover\", className)}\r\n\t\t\t\t/>\r\n\t\t\t)\r\n\t\t}\r\n\r\n\t\treturn (\r\n\t\t\t<div\r\n\t\t\t\tclassName={cn(\r\n\t\t\t\t\t\"w-full h-full flex items-center justify-center border text-2xl\",\r\n\t\t\t\t\tclassName\r\n\t\t\t\t)}\r\n\t\t\t>\r\n\t\t\t\t{item.id}\r\n\t\t\t</div>\r\n\t\t)\r\n\t}\r\n)\r\n\r\nMediaRenderer.displayName = \"MediaRenderer\"\r\n\r\nexport interface BoxCarouselRef {\r\n\t/**\r\n\t * Advance to the next item in the carousel.\r\n\t */\r\n\tnext: () => void\r\n\r\n\t/**\r\n\t * Go back to the previous item in the carousel.\r\n\t */\r\n\tprev: () => void\r\n\r\n\t/**\r\n\t * Get the index of the currently visible item.\r\n\t */\r\n\tgetCurrentItemIndex: () => number\r\n}\r\n\r\ntype RotationDirection = \"top\" | \"bottom\" | \"left\" | \"right\"\r\n\r\ninterface SpringConfig {\r\n\tstiffness?: number\r\n\tdamping?: number\r\n\tmass?: number\r\n}\r\n\r\n/**\r\n * Props for the BoxCarousel component\r\n */\r\ninterface BoxCarouselProps extends React.HTMLProps<HTMLDivElement> {\r\n\t/**\r\n\t * Array of items to display in the carousel\r\n\t */\r\n\titems: CarouselItem[]\r\n\r\n\t/**\r\n\t * Width of the carousel in pixels\r\n\t */\r\n\twidth: number\r\n\r\n\t/**\r\n\t * Height of the carousel in pixels\r\n\t */\r\n\theight: number\r\n\r\n\t/**\r\n\t * Additional CSS classes for the container\r\n\t */\r\n\tclassName?: string\r\n\r\n\t/**\r\n\t * Enable debug mode (shows extra info/overlays)\r\n\t */\r\n\tdebug?: boolean\r\n\r\n\t/**\r\n\t * Perspective value for 3D effect (in px)\r\n\t * @default 600\r\n\t */\r\n\tperspective?: number\r\n\r\n\t/**\r\n\t * The axis and direction of rotation\r\n\t * @default \"vertical\"\r\n\t * \"top\" | \"bottom\" | \"left\" | \"right\"\r\n\t */\r\n\tdirection?: RotationDirection\r\n\r\n\t/**\r\n\t * Transition configuration for rotation animation\r\n\t * @default { duration: 1.25, ease: [0.953, 0.001, 0.019, 0.995] }\r\n\t */\r\n\ttransition?: ValueAnimationOptions\r\n\r\n\t/**\r\n\t * Transition configuration for snapping after drag\r\n\t * @default { type: \"spring\", damping: 30, stiffness: 200 }\r\n\t */\r\n\tsnapTransition?: ValueAnimationOptions\r\n\r\n\t/**\r\n\t * Spring physics config for drag interaction\r\n\t * @default { stiffness: 200, damping: 30 }\r\n\t */\r\n\tdragSpring?: SpringConfig\r\n\r\n\t/**\r\n\t * Enable auto-play mode\r\n\t * @default false\r\n\t */\r\n\tautoPlay?: boolean\r\n\r\n\t/**\r\n\t * Interval (ms) between auto-play transitions\r\n\t * @default 3000\r\n\t */\r\n\tautoPlayInterval?: number\r\n\r\n\t/**\r\n\t * Callback when the current item index changes\r\n\t */\r\n\tonIndexChange?: (index: number) => void\r\n\r\n\t/**\r\n\t * Enable drag interaction\r\n\t * @default true\r\n\t */\r\n\tenableDrag?: boolean\r\n\r\n\t/**\r\n\t * Sensitivity of drag (higher = more rotation per pixel)\r\n\t * @default 0.5\r\n\t */\r\n\tdragSensitivity?: number\r\n}\r\n\r\nconst BoxCarousel = forwardRef<BoxCarouselRef, BoxCarouselProps>(\r\n\t(\r\n\t\t{\r\n\t\t\titems,\r\n\t\t\twidth,\r\n\t\t\theight,\r\n\t\t\tclassName,\r\n\t\t\tperspective = 600,\r\n\t\t\tdebug = false,\r\n\t\t\tdirection = \"left\",\r\n\t\t\ttransition = { duration: 1.25, ease: [0.953, 0.001, 0.019, 0.995] },\r\n\t\t\tsnapTransition = { type: \"spring\", damping: 30, stiffness: 200 },\r\n\t\t\tdragSpring = { stiffness: 200, damping: 30 },\r\n\t\t\tautoPlay = false,\r\n\t\t\tautoPlayInterval = 3000,\r\n\t\t\tonIndexChange,\r\n\t\t\tenableDrag = true,\r\n\t\t\tdragSensitivity = 0.5,\r\n\t\t\t...props\r\n\t\t},\r\n\t\tref\r\n\t) => {\r\n\t\tconst [currentItemIndex, setCurrentItemIndex] = useState(0)\r\n\t\tconst [currentFrontFaceIndex, setCurrentFrontFaceIndex] = useState(1)\r\n\r\n\t\tconst prefersReducedMotion = useReducedMotion()\r\n\r\n\t\tconst _transition = prefersReducedMotion ? { duration: 0 } : transition\r\n\r\n\t\t// 0 ⇢ will be shown if the user presses \"prev\"\r\n\t\tconst [prevIndex, setPrevIndex] = useState(items.length - 1)\r\n\r\n\t\t// 1 ⇢ item that is currently visible\r\n\t\tconst [currentIndex, setCurrentIndex] = useState(0)\r\n\r\n\t\t// 2 ⇢ will be shown on the next \"next\"\r\n\t\tconst [nextIndex, setNextIndex] = useState(1)\r\n\r\n\t\t// 3 ⇢ two steps ahead (the face that is at the back right now)\r\n\t\tconst [afterNextIndex, setAfterNextIndex] = useState(2)\r\n\r\n\t\tconst [currentRotation, setCurrentRotation] = useState(0)\r\n\r\n\t\tconst rotationCount = useRef(1)\r\n\t\tconst isRotating = useRef(false)\r\n\t\tconst pendingIndexChange = useRef<number | null>(null)\r\n\t\tconst isDragging = useRef(false)\r\n\t\tconst startPosition = useRef({ x: 0, y: 0 })\r\n\t\tconst startRotation = useRef(0)\r\n\r\n\t\tconst baseRotateX = useMotionValue(0)\r\n\t\tconst baseRotateY = useMotionValue(0)\r\n\r\n\t\t// Use springs for smoother animation during drag\r\n\t\tconst springRotateX = useSpring(baseRotateX, dragSpring)\r\n\t\tconst springRotateY = useSpring(baseRotateY, dragSpring)\r\n\r\n\t\tconst handleAnimationComplete = useCallback(\r\n\t\t\t(triggeredBy: string) => {\r\n\t\t\t\tif (isRotating.current && pendingIndexChange.current !== null) {\r\n\t\t\t\t\tisRotating.current = false\r\n\r\n\t\t\t\t\tlet newFrontFaceIndex: number\r\n\t\t\t\t\tlet currentBackFaceIndex: number\r\n\r\n\t\t\t\t\tif (triggeredBy === \"next\") {\r\n\t\t\t\t\t\tnewFrontFaceIndex = (currentFrontFaceIndex + 1) % 4\r\n\t\t\t\t\t\tcurrentBackFaceIndex = (newFrontFaceIndex + 2) % 4\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tnewFrontFaceIndex = (currentFrontFaceIndex - 1 + 4) % 4\r\n\t\t\t\t\t\tcurrentBackFaceIndex = (newFrontFaceIndex + 3) % 4\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tsetCurrentItemIndex(pendingIndexChange.current)\r\n\t\t\t\t\tonIndexChange?.(pendingIndexChange.current)\r\n\r\n\t\t\t\t\tconst indexOffset = triggeredBy === \"next\" ? 2 : -1\r\n\r\n\t\t\t\t\tif (currentBackFaceIndex === 0) {\r\n\t\t\t\t\t\tsetPrevIndex(\r\n\t\t\t\t\t\t\t(pendingIndexChange.current + indexOffset + items.length) %\r\n\t\t\t\t\t\t\titems.length\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t} else if (currentBackFaceIndex === 1) {\r\n\t\t\t\t\t\tsetCurrentIndex(\r\n\t\t\t\t\t\t\t(pendingIndexChange.current + indexOffset + items.length) %\r\n\t\t\t\t\t\t\titems.length\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t} else if (currentBackFaceIndex === 2) {\r\n\t\t\t\t\t\tsetNextIndex(\r\n\t\t\t\t\t\t\t(pendingIndexChange.current + indexOffset + items.length) %\r\n\t\t\t\t\t\t\titems.length\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t} else if (currentBackFaceIndex === 3) {\r\n\t\t\t\t\t\tsetAfterNextIndex(\r\n\t\t\t\t\t\t\t(pendingIndexChange.current + indexOffset + items.length) %\r\n\t\t\t\t\t\t\titems.length\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tpendingIndexChange.current = null\r\n\t\t\t\t\trotationCount.current++\r\n\r\n\t\t\t\t\tsetCurrentFrontFaceIndex(newFrontFaceIndex)\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\t[currentFrontFaceIndex, items.length, onIndexChange]\r\n\t\t)\r\n\r\n\t\t// Drag functionality - using direct event handlers like css-box\r\n\t\tconst handleDragStart = useCallback(\r\n\t\t\t(e: React.MouseEvent | React.TouchEvent) => {\r\n\t\t\t\tif (!enableDrag || isRotating.current) return\r\n\r\n\t\t\t\tisDragging.current = true\r\n\t\t\t\tconst point = \"touches\" in e ? e.touches[0] : e\r\n\t\t\t\tstartPosition.current = { x: point.clientX, y: point.clientY }\r\n\t\t\t\tstartRotation.current = currentRotation\r\n\r\n\t\t\t\t// Prevent default to avoid text selection\r\n\t\t\t\te.preventDefault()\r\n\t\t\t},\r\n\t\t\t[enableDrag, currentRotation]\r\n\t\t)\r\n\r\n\t\tconst handleDragMove = useCallback(\r\n\t\t\t(e: MouseEvent | TouchEvent) => {\r\n\t\t\t\tif (!isDragging.current || isRotating.current) return\r\n\r\n\t\t\t\tconst point = \"touches\" in e ? e.touches[0] : e\r\n\t\t\t\tconst deltaX = point.clientX - startPosition.current.x\r\n\t\t\t\tconst deltaY = point.clientY - startPosition.current.y\r\n\r\n\t\t\t\tconst isVertical = direction === \"top\" || direction === \"bottom\"\r\n\t\t\t\tconst delta = isVertical ? deltaY : deltaX\r\n\t\t\t\tconst rotationDelta = (delta * dragSensitivity) / 2\r\n\r\n\t\t\t\tlet newRotation = startRotation.current\r\n\r\n\t\t\t\tif (direction === \"top\" || direction === \"right\") {\r\n\t\t\t\t\tnewRotation += rotationDelta\r\n\t\t\t\t} else {\r\n\t\t\t\t\tnewRotation -= rotationDelta\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Constrain rotation to ±120 degrees from start position. Otherwise the index recalculation will be off. TBD - find a better solution\r\n\t\t\t\tconst minRotation = startRotation.current - 120\r\n\t\t\t\tconst maxRotation = startRotation.current + 120\r\n\t\t\t\tnewRotation = Math.max(minRotation, Math.min(maxRotation, newRotation))\r\n\r\n\t\t\t\t// Apply the rotation immediately during drag\r\n\t\t\t\tif (isVertical) {\r\n\t\t\t\t\tbaseRotateX.set(newRotation)\r\n\t\t\t\t} else {\r\n\t\t\t\t\tbaseRotateY.set(newRotation)\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\t[enableDrag, direction, dragSensitivity]\r\n\t\t)\r\n\r\n\t\tconst handleDragEnd = useCallback(() => {\r\n\t\t\tif (!isDragging.current) return\r\n\r\n\t\t\tisDragging.current = false\r\n\r\n\t\t\tconst isVertical = direction === \"top\" || direction === \"bottom\"\r\n\t\t\tconst currentValue = isVertical ? baseRotateX.get() : baseRotateY.get()\r\n\r\n\t\t\t// Calculate the nearest quarter rotation (90-degree increment)\r\n\t\t\tconst quarterRotations = Math.round(currentValue / 90)\r\n\t\t\tconst snappedRotation = quarterRotations * 90\r\n\r\n\t\t\t// Calculate how many steps we've moved from the original position\r\n\t\t\tconst rotationDifference = snappedRotation - currentRotation\r\n\t\t\tconst steps = Math.round(rotationDifference / 90)\r\n\r\n\t\t\tif (steps !== 0) {\r\n\t\t\t\tisRotating.current = true\r\n\r\n\t\t\t\t// Calculate new item index\r\n\t\t\t\tlet newItemIndex = currentItemIndex\r\n\t\t\t\tfor (let i = 0; i < Math.abs(steps); i++) {\r\n\t\t\t\t\tif (steps > 0) {\r\n\t\t\t\t\t\tnewItemIndex = (newItemIndex + 1) % items.length\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tnewItemIndex =\r\n\t\t\t\t\t\t\tnewItemIndex === 0 ? items.length - 1 : newItemIndex - 1\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tpendingIndexChange.current = newItemIndex\r\n\r\n\t\t\t\t// Animate to the snapped position\r\n\t\t\t\tconst targetMotionValue = isVertical ? baseRotateX : baseRotateY\r\n\t\t\t\tanimate(targetMotionValue, snappedRotation, {\r\n\t\t\t\t\t...snapTransition,\r\n\t\t\t\t\tonComplete: () => {\r\n\t\t\t\t\t\thandleAnimationComplete(steps > 0 ? \"next\" : \"prev\")\r\n\t\t\t\t\t\tsetCurrentRotation(snappedRotation)\r\n\t\t\t\t\t},\r\n\t\t\t\t})\r\n\t\t\t} else {\r\n\t\t\t\t// Snap back to current position\r\n\t\t\t\tconst targetMotionValue = isVertical ? baseRotateX : baseRotateY\r\n\t\t\t\tanimate(targetMotionValue, currentRotation, snapTransition)\r\n\t\t\t}\r\n\t\t}, [\r\n\t\t\tdirection,\r\n\t\t\tbaseRotateX,\r\n\t\t\tbaseRotateY,\r\n\t\t\tcurrentRotation,\r\n\t\t\tcurrentItemIndex,\r\n\t\t\titems.length,\r\n\t\t\ttransition,\r\n\t\t\thandleAnimationComplete,\r\n\t\t])\r\n\r\n\t\t// Set up global event listeners for drag\r\n\t\tuseEffect(() => {\r\n\t\t\tif (enableDrag) {\r\n\t\t\t\twindow.addEventListener(\"mousemove\", handleDragMove)\r\n\t\t\t\twindow.addEventListener(\"mouseup\", handleDragEnd)\r\n\t\t\t\twindow.addEventListener(\"touchmove\", handleDragMove)\r\n\t\t\t\twindow.addEventListener(\"touchend\", handleDragEnd)\r\n\r\n\t\t\t\treturn () => {\r\n\t\t\t\t\twindow.removeEventListener(\"mousemove\", handleDragMove)\r\n\t\t\t\t\twindow.removeEventListener(\"mouseup\", handleDragEnd)\r\n\t\t\t\t\twindow.removeEventListener(\"touchmove\", handleDragMove)\r\n\t\t\t\t\twindow.removeEventListener(\"touchend\", handleDragEnd)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}, [enableDrag, handleDragMove, handleDragEnd])\r\n\r\n\t\tconst next = useCallback(() => {\r\n\t\t\tif (items.length === 0 || isRotating.current) return\r\n\r\n\t\t\tisRotating.current = true\r\n\t\t\tconst newIndex = (currentItemIndex + 1) % items.length\r\n\t\t\tpendingIndexChange.current = newIndex\r\n\r\n\t\t\tif (direction === \"top\") {\r\n\t\t\t\tanimate(baseRotateX, currentRotation + 90, {\r\n\t\t\t\t\t..._transition,\r\n\t\t\t\t\tonComplete: () => {\r\n\t\t\t\t\t\thandleAnimationComplete(\"next\")\r\n\t\t\t\t\t\tsetCurrentRotation(currentRotation + 90)\r\n\t\t\t\t\t},\r\n\t\t\t\t})\r\n\t\t\t} else if (direction === \"bottom\") {\r\n\t\t\t\tanimate(baseRotateX, currentRotation - 90, {\r\n\t\t\t\t\t..._transition,\r\n\t\t\t\t\tonComplete: () => {\r\n\t\t\t\t\t\thandleAnimationComplete(\"next\")\r\n\t\t\t\t\t\tsetCurrentRotation(currentRotation - 90)\r\n\t\t\t\t\t},\r\n\t\t\t\t})\r\n\t\t\t} else if (direction === \"left\") {\r\n\t\t\t\tanimate(baseRotateY, currentRotation - 90, {\r\n\t\t\t\t\t..._transition,\r\n\t\t\t\t\tonComplete: () => {\r\n\t\t\t\t\t\thandleAnimationComplete(\"next\")\r\n\t\t\t\t\t\tsetCurrentRotation(currentRotation - 90)\r\n\t\t\t\t\t},\r\n\t\t\t\t})\r\n\t\t\t} else if (direction === \"right\") {\r\n\t\t\t\tanimate(baseRotateY, currentRotation + 90, {\r\n\t\t\t\t\t..._transition,\r\n\t\t\t\t\tonComplete: () => {\r\n\t\t\t\t\t\thandleAnimationComplete(\"next\")\r\n\t\t\t\t\t\tsetCurrentRotation(currentRotation + 90)\r\n\t\t\t\t\t},\r\n\t\t\t\t})\r\n\t\t\t}\r\n\t\t}, [items.length, direction, transition, currentRotation])\r\n\r\n\t\tconst prev = useCallback(() => {\r\n\t\t\tif (items.length === 0 || isRotating.current) return\r\n\r\n\t\t\tisRotating.current = true\r\n\t\t\tconst newIndex =\r\n\t\t\t\tcurrentItemIndex === 0 ? items.length - 1 : currentItemIndex - 1\r\n\t\t\tpendingIndexChange.current = newIndex\r\n\r\n\t\t\tif (direction === \"top\") {\r\n\t\t\t\tanimate(baseRotateX, currentRotation - 90, {\r\n\t\t\t\t\t..._transition,\r\n\t\t\t\t\tonComplete: () => {\r\n\t\t\t\t\t\thandleAnimationComplete(\"prev\")\r\n\t\t\t\t\t\tsetCurrentRotation(currentRotation - 90)\r\n\t\t\t\t\t},\r\n\t\t\t\t})\r\n\t\t\t} else if (direction === \"bottom\") {\r\n\t\t\t\tanimate(baseRotateX, currentRotation + 90, {\r\n\t\t\t\t\t..._transition,\r\n\t\t\t\t\tonComplete: () => {\r\n\t\t\t\t\t\thandleAnimationComplete(\"prev\")\r\n\t\t\t\t\t\tsetCurrentRotation(currentRotation + 90)\r\n\t\t\t\t\t},\r\n\t\t\t\t})\r\n\t\t\t} else if (direction === \"left\") {\r\n\t\t\t\tanimate(baseRotateY, currentRotation + 90, {\r\n\t\t\t\t\t..._transition,\r\n\t\t\t\t\tonComplete: () => {\r\n\t\t\t\t\t\thandleAnimationComplete(\"prev\")\r\n\t\t\t\t\t\tsetCurrentRotation(currentRotation + 90)\r\n\t\t\t\t\t},\r\n\t\t\t\t})\r\n\t\t\t} else if (direction === \"right\") {\r\n\t\t\t\tanimate(baseRotateY, currentRotation - 90, {\r\n\t\t\t\t\t..._transition,\r\n\t\t\t\t\tonComplete: () => {\r\n\t\t\t\t\t\thandleAnimationComplete(\"prev\")\r\n\t\t\t\t\t\tsetCurrentRotation(currentRotation - 90)\r\n\t\t\t\t\t},\r\n\t\t\t\t})\r\n\t\t\t}\r\n\t\t}, [items.length, direction, transition])\r\n\r\n\t\tuseImperativeHandle(\r\n\t\t\tref,\r\n\t\t\t() => ({\r\n\t\t\t\tnext,\r\n\t\t\t\tprev,\r\n\t\t\t\tgetCurrentItemIndex: () => currentItemIndex,\r\n\t\t\t}),\r\n\t\t\t[next, prev, currentItemIndex]\r\n\t\t)\r\n\r\n\t\tconst depth = useMemo(\r\n\t\t\t() => (direction === \"top\" || direction === \"bottom\" ? height : width),\r\n\t\t\t[direction, width, height]\r\n\t\t)\r\n\r\n\t\tconst transform = useTransform(\r\n\t\t\tisDragging.current\r\n\t\t\t\t? [springRotateX, springRotateY]\r\n\t\t\t\t: [baseRotateX, baseRotateY],\r\n\t\t\t([x, y]) =>\r\n\t\t\t\t`translateZ(-${depth / 2}px) rotateX(${x}deg) rotateY(${y}deg)`\r\n\t\t)\r\n\r\n\t\t// Determine face transforms based on the desired rotation axis\r\n\t\tconst faceTransforms = (() => {\r\n\t\t\tswitch (direction) {\r\n\t\t\t\tcase \"left\":\r\n\t\t\t\t\treturn [\r\n\t\t\t\t\t\t// left, front, right, back (rotation around Y-axis)\r\n\t\t\t\t\t\t`rotateY(-90deg) translateZ(${width / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(0deg) translateZ(${depth / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(90deg) translateZ(${width / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(180deg) translateZ(${depth / 2}px)`,\r\n\t\t\t\t\t]\r\n\t\t\t\tcase \"top\":\r\n\t\t\t\t\treturn [\r\n\t\t\t\t\t\t// top, front, bottom, back (rotation around X-axis)\r\n\t\t\t\t\t\t`rotateX(90deg) translateZ(${height / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(0deg) translateZ(${depth / 2}px)`,\r\n\t\t\t\t\t\t`rotateX(-90deg) translateZ(${height / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(180deg) translateZ(${depth / 2}px) rotateZ(180deg)`,\r\n\t\t\t\t\t]\r\n\t\t\t\tcase \"right\":\r\n\t\t\t\t\treturn [\r\n\t\t\t\t\t\t// right, front, left, back (rotation around Y-axis)\r\n\t\t\t\t\t\t`rotateY(90deg) translateZ(${width / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(0deg) translateZ(${depth / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(-90deg) translateZ(${width / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(180deg) translateZ(${depth / 2}px)`,\r\n\t\t\t\t\t]\r\n\t\t\t\tcase \"bottom\":\r\n\t\t\t\t\treturn [\r\n\t\t\t\t\t\t// bottom, front, top, back (rotation around X-axis)\r\n\t\t\t\t\t\t`rotateX(-90deg) translateZ(${height / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(0deg) translateZ(${depth / 2}px)`,\r\n\t\t\t\t\t\t`rotateX(90deg) translateZ(${height / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(180deg) translateZ(${depth / 2}px) rotateZ(180deg)`,\r\n\t\t\t\t\t]\r\n\t\t\t\tdefault:\r\n\t\t\t\t\treturn [\r\n\t\t\t\t\t\t// left, front, right, back (rotation around Y-axis)\r\n\t\t\t\t\t\t`rotateY(-90deg) translateZ(${width / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(0deg) translateZ(${depth / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(90deg) translateZ(${width / 2}px)`,\r\n\t\t\t\t\t\t`rotateY(180deg) translateZ(${depth / 2}px)`,\r\n\t\t\t\t\t]\r\n\t\t\t}\r\n\t\t})()\r\n\r\n\t\t// Auto play functionality\r\n\t\tuseEffect(() => {\r\n\t\t\tif (autoPlay && items.length > 0) {\r\n\t\t\t\tconst interval = setInterval(next, autoPlayInterval)\r\n\t\t\t\treturn () => clearInterval(interval)\r\n\t\t\t}\r\n\t\t}, [autoPlay, items.length, next, autoPlayInterval])\r\n\r\n\t\tconst handleKeyDown = useCallback(\r\n\t\t\t(e: React.KeyboardEvent) => {\r\n\t\t\t\tif (isRotating.current) return\r\n\r\n\t\t\t\tswitch (e.key) {\r\n\t\t\t\t\tcase \"ArrowLeft\":\r\n\t\t\t\t\t\te.preventDefault()\r\n\t\t\t\t\t\tif (direction === \"left\" || direction === \"right\") {\r\n\t\t\t\t\t\t\tprev()\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak\r\n\t\t\t\t\tcase \"ArrowRight\":\r\n\t\t\t\t\t\te.preventDefault()\r\n\t\t\t\t\t\tif (direction === \"left\" || direction === \"right\") {\r\n\t\t\t\t\t\t\tnext()\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak\r\n\t\t\t\t\tcase \"ArrowUp\":\r\n\t\t\t\t\t\te.preventDefault()\r\n\t\t\t\t\t\tif (direction === \"top\" || direction === \"bottom\") {\r\n\t\t\t\t\t\t\tprev()\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak\r\n\t\t\t\t\tcase \"ArrowDown\":\r\n\t\t\t\t\t\te.preventDefault()\r\n\t\t\t\t\t\tif (direction === \"top\" || direction === \"bottom\") {\r\n\t\t\t\t\t\t\tnext()\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\tbreak\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\t[direction, next, prev, items.length]\r\n\t\t)\r\n\r\n\t\treturn (\r\n\t\t\t<div\r\n\t\t\t\tclassName={cn(\"relative focus:outline-0\", enableDrag && \"cursor-move\", className)}\r\n\t\t\t\tstyle={{\r\n\t\t\t\t\twidth,\r\n\t\t\t\t\theight,\r\n\t\t\t\t\tperspective: `${perspective}px`,\r\n\t\t\t\t}}\r\n\t\t\t\tonKeyDown={handleKeyDown}\r\n\t\t\t\ttabIndex={0}\r\n\t\t\t\taria-label={`3D carousel with ${items.length} items`}\r\n\t\t\t\taria-describedby=\"carousel-instructions\"\r\n\t\t\t\taria-live=\"polite\"\r\n\t\t\t\taria-atomic=\"true\"\r\n\t\t\t\tonMouseDown={handleDragStart}\r\n\t\t\t\tonTouchStart={handleDragStart}\r\n\t\t\t\t{...props}\r\n\t\t\t>\r\n\t\t\t\t<div className=\"sr-only\" aria-live=\"assertive\">\r\n\t\t\t\t\tShowing item {currentItemIndex + 1} of {items.length}:{\" \"}\r\n\t\t\t\t\t{items[currentItemIndex]?.alt || `Item ${currentItemIndex + 1}`}\r\n\t\t\t\t</div>\r\n\r\n\t\t\t\t<motion.div\r\n\t\t\t\t\tclassName=\"relative w-full h-full transform-3d\"\r\n\t\t\t\t\tstyle={{\r\n\t\t\t\t\t\ttransform: transform,\r\n\t\t\t\t\t}}\r\n\t\t\t\t>\r\n\t\t\t\t\t{/* First face */}\r\n\t\t\t\t\t<CubeFace\r\n\t\t\t\t\t\ttransform={faceTransforms[0]}\r\n\t\t\t\t\t\tstyle={\r\n\t\t\t\t\t\t\tdebug\r\n\t\t\t\t\t\t\t\t? { width, height, backgroundColor: \"#ff9999\" }\r\n\t\t\t\t\t\t\t\t: { width, height }\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tdebug={debug}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\t<MediaRenderer item={items[prevIndex]} debug={debug} />\r\n\t\t\t\t\t</CubeFace>\r\n\r\n\t\t\t\t\t{/* Second face */}\r\n\t\t\t\t\t<CubeFace\r\n\t\t\t\t\t\ttransform={faceTransforms[1]}\r\n\t\t\t\t\t\tstyle={\r\n\t\t\t\t\t\t\tdebug\r\n\t\t\t\t\t\t\t\t? { width, height, backgroundColor: \"#99ff99\" }\r\n\t\t\t\t\t\t\t\t: { width, height }\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tdebug={debug}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\t<MediaRenderer item={items[currentIndex]} debug={debug} />\r\n\t\t\t\t\t</CubeFace>\r\n\r\n\t\t\t\t\t{/* Third face */}\r\n\t\t\t\t\t<CubeFace\r\n\t\t\t\t\t\ttransform={faceTransforms[2]}\r\n\t\t\t\t\t\tstyle={\r\n\t\t\t\t\t\t\tdebug\r\n\t\t\t\t\t\t\t\t? { width, height, backgroundColor: \"#9999ff\" }\r\n\t\t\t\t\t\t\t\t: { width, height }\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tdebug={debug}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\t<MediaRenderer item={items[nextIndex]} debug={debug} />\r\n\t\t\t\t\t</CubeFace>\r\n\r\n\t\t\t\t\t{/* Fourth face */}\r\n\t\t\t\t\t<CubeFace\r\n\t\t\t\t\t\ttransform={faceTransforms[3]}\r\n\t\t\t\t\t\tstyle={\r\n\t\t\t\t\t\t\tdebug\r\n\t\t\t\t\t\t\t\t? { width, height, backgroundColor: \"#ffff99\" }\r\n\t\t\t\t\t\t\t\t: { width, height }\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tdebug={debug}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\t<MediaRenderer item={items[afterNextIndex]} debug={debug} />\r\n\t\t\t\t\t</CubeFace>\r\n\t\t\t\t</motion.div>\r\n\t\t\t</div>\r\n\t\t)\r\n\t}\r\n)\r\n\r\nBoxCarousel.displayName = \"BoxCarousel\"\r\n\r\nexport default BoxCarousel\r\nexport type { CarouselItem, RotationDirection, SpringConfig }\r\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/utilities/cn.ts",
      "content": "import { ClassValue, clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n\treturn twMerge(clsx(inputs));\r\n}\r\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/skeleton.tsx",
      "content": "\"use client\";\r\n\r\nimport React from \"react\";\r\n\r\nimport { cn } from \"@/registry/utilities/cn\";\r\nimport { motion } from \"motion/react\";\r\n\r\nconst MOBILE_BREAKPOINT = 768;\r\n\r\nexport function useIsMobile() {\r\n\tconst [isMobile, setIsMobile] = React.useState<boolean | undefined>(\r\n\t\tundefined\r\n\t);\r\n\r\n\tReact.useEffect(() => {\r\n\t\tconst mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\r\n\t\tconst onChange = () => {\r\n\t\t\tsetIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\r\n\t\t};\r\n\t\tmql.addEventListener(\"change\", onChange);\r\n\t\tsetIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\r\n\t\treturn () => mql.removeEventListener(\"change\", onChange);\r\n\t}, []);\r\n\r\n\treturn !!isMobile;\r\n}\r\n\r\nexport interface SkeletonProps {\r\n\t/**\r\n\t * Width of the skeleton element. Can be a string (CSS value) or number (pixels)\r\n\t */\r\n\twidth?: string | number;\r\n\t/**\r\n\t * Height of the skeleton element. Can be a string (CSS value) or number (pixels)\r\n\t */\r\n\theight?: string | number;\r\n\t/**\r\n\t * Border radius of the skeleton element\r\n\t */\r\n\tradius?: \"none\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\";\r\n\t/**\r\n\t * Animation type for the skeleton loading effect\r\n\t */\r\n\tanimation?: \"pulse\" | \"wave\" | \"none\";\r\n\t/**\r\n\t * Additional class names for the skeleton element\r\n\t */\r\n\tclassName?: string;\r\n}\r\n\r\n/**\r\n * A versatile skeleton loading component for creating placeholder UI\r\n */\r\nexport default function Skeleton({\r\n\twidth = \"100%\",\r\n\theight = \"1rem\",\r\n\tradius = \"md\",\r\n\tanimation = \"pulse\",\r\n\tclassName,\r\n}: SkeletonProps) {\r\n\tconst radiusClasses = {\r\n\t\tnone: \"rounded-none\",\r\n\t\tsm: \"rounded-sm\",\r\n\t\tmd: \"rounded-md\",\r\n\t\tlg: \"rounded-lg\",\r\n\t\txl: \"rounded-xl\",\r\n\t\tfull: \"rounded-full\",\r\n\t};\r\n\r\n\treturn (\r\n\t\t<motion.div\r\n\t\t\tclassName={cn(\r\n\t\t\t\t\"bg-linear-to-r from-muted via-muted/70 to-muted\",\r\n\t\t\t\t\"dark:from-background dark:via-background dark:to-background\",\r\n\t\t\t\tradiusClasses[radius],\r\n\t\t\t\tanimation === \"pulse\" && \"animate-pulse\",\r\n\t\t\t\tanimation === \"wave\" && \"animate-shimmer\",\r\n\t\t\t\tclassName\r\n\t\t\t)}\r\n\t\t\tstyle={{\r\n\t\t\t\twidth: typeof width === \"number\" ? `${width}px` : width,\r\n\t\t\t\theight: typeof height === \"number\" ? `${height}px` : height,\r\n\t\t\t}}\r\n\t\t\tinitial={{ opacity: 0, scale: 0.95 }}\r\n\t\t\tanimate={{ opacity: 1, scale: 1 }}\r\n\t\t\ttransition={{ duration: 0.3, ease: \"easeOut\" }}\r\n\t\t/>\r\n\t);\r\n}\r\n\r\n/**\r\n * A beautiful profile card skeleton with animated loading states\r\n */\r\nexport function ProfileCardSkeleton() {\r\n\treturn (\r\n\t\t<motion.div\r\n\t\t\tclassName=\"w-full max-w-md mx-auto bg-card border border-border/50 rounded-2xl p-6 shadow-lg backdrop-blur-xs\"\r\n\t\t\tinitial={{ opacity: 0, y: 32, scale: 0.95 }}\r\n\t\t\tanimate={{ opacity: 1, y: 0, scale: 1 }}\r\n\t\t\ttransition={{ duration: 0.6, ease: [0.25, 0.46, 0.45, 0.94] }}\r\n\t\t>\r\n\t\t\t{/* Header with avatar and basic info */}\r\n\t\t\t<div className=\"flex items-center space-x-4 mb-6\">\r\n\t\t\t\t<motion.div\r\n\t\t\t\t\tinitial={{ opacity: 0, scale: 0 }}\r\n\t\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\r\n\t\t\t\t\ttransition={{\r\n\t\t\t\t\t\tdelay: 0.1,\r\n\t\t\t\t\t\tduration: 0.5,\r\n\t\t\t\t\t\ttype: \"spring\",\r\n\t\t\t\t\t\tstiffness: 200,\r\n\t\t\t\t\t}}\r\n\t\t\t\t>\r\n\t\t\t\t\t<Skeleton\r\n\t\t\t\t\t\twidth={80}\r\n\t\t\t\t\t\theight={80}\r\n\t\t\t\t\t\tradius=\"full\"\r\n\t\t\t\t\t\tclassName=\"shrink-0\"\r\n\t\t\t\t\t/>\r\n\t\t\t\t</motion.div>\r\n\r\n\t\t\t\t<div className=\"flex-1 space-y-3\">\r\n\t\t\t\t\t<motion.div\r\n\t\t\t\t\t\tinitial={{ opacity: 0, x: -20 }}\r\n\t\t\t\t\t\tanimate={{ opacity: 1, x: 0 }}\r\n\t\t\t\t\t\ttransition={{ delay: 0.2, duration: 0.4 }}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\t<Skeleton width=\"70%\" height=\"1.5rem\" radius=\"md\" />\r\n\t\t\t\t\t</motion.div>\r\n\t\t\t\t\t<motion.div\r\n\t\t\t\t\t\tinitial={{ opacity: 0, x: -20 }}\r\n\t\t\t\t\t\tanimate={{ opacity: 1, x: 0 }}\r\n\t\t\t\t\t\ttransition={{ delay: 0.3, duration: 0.4 }}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\t<Skeleton width=\"50%\" height=\"1rem\" radius=\"md\" />\r\n\t\t\t\t\t</motion.div>\r\n\t\t\t\t</div>\r\n\t\t\t</div>\r\n\r\n\t\t\t{/* Bio section */}\r\n\t\t\t<motion.div\r\n\t\t\t\tclassName=\"space-y-3 mb-6\"\r\n\t\t\t\tinitial={{ opacity: 0, y: 10 }}\r\n\t\t\t\tanimate={{ opacity: 1, y: 0 }}\r\n\t\t\t\ttransition={{ delay: 0.4, duration: 0.4 }}\r\n\t\t\t>\r\n\t\t\t\t<Skeleton width=\"100%\" height=\"1rem\" radius=\"md\" />\r\n\t\t\t\t<Skeleton width=\"85%\" height=\"1rem\" radius=\"md\" />\r\n\t\t\t\t<Skeleton width=\"60%\" height=\"1rem\" radius=\"md\" />\r\n\t\t\t</motion.div>\r\n\r\n\t\t\t{/* Stats section */}\r\n\t\t\t<motion.div\r\n\t\t\t\tclassName=\"grid grid-cols-3 gap-4 mb-6\"\r\n\t\t\t\tinitial={{ opacity: 0, y: 10 }}\r\n\t\t\t\tanimate={{ opacity: 1, y: 0 }}\r\n\t\t\t\ttransition={{ delay: 0.5, duration: 0.4 }}\r\n\t\t\t>\r\n\t\t\t\t{[...Array(3)].map((_, i) => (\r\n\t\t\t\t\t<motion.div\r\n\t\t\t\t\t\tkey={i}\r\n\t\t\t\t\t\tclassName=\"text-center space-y-2\"\r\n\t\t\t\t\t\tinitial={{ opacity: 0, scale: 0.8 }}\r\n\t\t\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\r\n\t\t\t\t\t\ttransition={{ delay: 0.6 + i * 0.1, duration: 0.3 }}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\t<Skeleton width=\"100%\" height=\"1.5rem\" radius=\"md\" />\r\n\t\t\t\t\t\t<Skeleton\r\n\t\t\t\t\t\t\twidth=\"80%\"\r\n\t\t\t\t\t\t\theight=\"0.875rem\"\r\n\t\t\t\t\t\t\tradius=\"md\"\r\n\t\t\t\t\t\t\tclassName=\"mx-auto\"\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t</motion.div>\r\n\t\t\t\t))}\r\n\t\t\t</motion.div>\r\n\r\n\t\t\t{/* Tags/Skills section */}\r\n\t\t\t<motion.div\r\n\t\t\t\tclassName=\"space-y-3 mb-6\"\r\n\t\t\t\tinitial={{ opacity: 0, y: 10 }}\r\n\t\t\t\tanimate={{ opacity: 1, y: 0 }}\r\n\t\t\t\ttransition={{ delay: 0.9, duration: 0.4 }}\r\n\t\t\t>\r\n\t\t\t\t<div className=\"flex flex-wrap gap-2\">\r\n\t\t\t\t\t{[40, 60, 35, 50, 45].map((width, i) => (\r\n\t\t\t\t\t\t<motion.div\r\n\t\t\t\t\t\t\tkey={i}\r\n\t\t\t\t\t\t\tinitial={{ opacity: 0, scale: 0 }}\r\n\t\t\t\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\r\n\t\t\t\t\t\t\ttransition={{ delay: 1.0 + i * 0.1, duration: 0.3 }}\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t<Skeleton width={width} height=\"1.5rem\" radius=\"full\" />\r\n\t\t\t\t\t\t</motion.div>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</div>\r\n\t\t\t</motion.div>\r\n\r\n\t\t\t{/* Action buttons */}\r\n\t\t\t<motion.div\r\n\t\t\t\tclassName=\"flex gap-3\"\r\n\t\t\t\tinitial={{ opacity: 0, y: 10 }}\r\n\t\t\t\tanimate={{ opacity: 1, y: 0 }}\r\n\t\t\t\ttransition={{ delay: 1.5, duration: 0.4 }}\r\n\t\t\t>\r\n\t\t\t\t<motion.div\r\n\t\t\t\t\tclassName=\"flex-1\"\r\n\t\t\t\t\tinitial={{ opacity: 0, scale: 0.9 }}\r\n\t\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\r\n\t\t\t\t\ttransition={{ delay: 1.6, duration: 0.3 }}\r\n\t\t\t\t>\r\n\t\t\t\t\t<Skeleton width=\"100%\" height=\"2.5rem\" radius=\"lg\" />\r\n\t\t\t\t</motion.div>\r\n\t\t\t\t<motion.div\r\n\t\t\t\t\tinitial={{ opacity: 0, scale: 0.9 }}\r\n\t\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\r\n\t\t\t\t\ttransition={{ delay: 1.7, duration: 0.3 }}\r\n\t\t\t\t>\r\n\t\t\t\t\t<Skeleton width=\"2.5rem\" height=\"2.5rem\" radius=\"lg\" />\r\n\t\t\t\t</motion.div>\r\n\t\t\t</motion.div>\r\n\t\t</motion.div>\r\n\t);\r\n}\r\n\r\nexport function SkeletonShowcase() {\r\n\tconst isMobile = useIsMobile();\r\n\r\n\treturn (\r\n\t\t<div className=\"flex items-center justify-center min-h-screen p-4 md:p-8\">\r\n\t\t\t<div className=\"w-full max-w-6xl space-y-8 md:space-y-12\">\r\n\t\t\t\t<div className=\"grid grid-cols-1 lg:grid-cols-2 gap-8 md:gap-12 items-start\">\r\n\t\t\t\t\t{/* Profile Card Skeleton Demo */}\r\n\t\t\t\t\t<div className=\"space-y-4 md:space-y-6\">\r\n\t\t\t\t\t\t<motion.div\r\n\t\t\t\t\t\t\tclassName=\"text-center\"\r\n\t\t\t\t\t\t\tinitial={{ opacity: 0, x: -32 }}\r\n\t\t\t\t\t\t\tanimate={{ opacity: 1, x: 0 }}\r\n\t\t\t\t\t\t\ttransition={{ delay: 0.2, duration: 0.6 }}\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t<p className=\"text-muted-foreground text-sm md:text-base\">\r\n\t\t\t\t\t\t\t\tA comprehensive loading state for user profile cards\r\n\t\t\t\t\t\t\t</p>\r\n\t\t\t\t\t\t</motion.div>\r\n\r\n\t\t\t\t\t\t<motion.div\r\n\t\t\t\t\t\t\tinitial={{ opacity: 0, scale: 0.9 }}\r\n\t\t\t\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\r\n\t\t\t\t\t\t\ttransition={{ delay: 0.4, duration: 0.6 }}\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t<ProfileCardSkeleton />\r\n\t\t\t\t\t\t</motion.div>\r\n\t\t\t\t\t</div>\r\n\r\n\t\t\t\t\t{/* Basic Skeleton Examples */}\r\n\t\t\t\t\t<div className=\"space-y-4 md:space-y-6\">\r\n\t\t\t\t\t\t<motion.div\r\n\t\t\t\t\t\t\tclassName=\"text-center\"\r\n\t\t\t\t\t\t\tinitial={{ opacity: 0, x: 32 }}\r\n\t\t\t\t\t\t\tanimate={{ opacity: 1, x: 0 }}\r\n\t\t\t\t\t\t\ttransition={{ delay: 0.2, duration: 0.6 }}\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t<p className=\"text-muted-foreground text-sm md:text-base\">\r\n\t\t\t\t\t\t\t\tFlexible building blocks for custom loading states\r\n\t\t\t\t\t\t\t</p>\r\n\t\t\t\t\t\t</motion.div>\r\n\r\n\t\t\t\t\t\t<motion.div\r\n\t\t\t\t\t\t\tclassName=\"bg-card border border-border/50 rounded-2xl p-4 md:p-6 space-y-4 md:space-y-6\"\r\n\t\t\t\t\t\t\tinitial={{ opacity: 0, scale: 0.9 }}\r\n\t\t\t\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\r\n\t\t\t\t\t\t\ttransition={{ delay: 0.6, duration: 0.6 }}\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t{/* Text lines */}\r\n\t\t\t\t\t\t\t<div className=\"space-y-3 md:space-y-4\">\r\n\t\t\t\t\t\t\t\t<h3\r\n\t\t\t\t\t\t\t\t\tclassName={`${isMobile ? \"text-base\" : \"text-lg\"} font-medium text-foreground`}\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\tText Content\r\n\t\t\t\t\t\t\t\t</h3>\r\n\t\t\t\t\t\t\t\t<div className=\"space-y-2 md:space-y-3\">\r\n\t\t\t\t\t\t\t\t\t<Skeleton\r\n\t\t\t\t\t\t\t\t\t\twidth=\"100%\"\r\n\t\t\t\t\t\t\t\t\t\theight={isMobile ? \"0.75rem\" : \"1rem\"}\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t<Skeleton\r\n\t\t\t\t\t\t\t\t\t\twidth=\"85%\"\r\n\t\t\t\t\t\t\t\t\t\theight={isMobile ? \"0.75rem\" : \"1rem\"}\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t<Skeleton\r\n\t\t\t\t\t\t\t\t\t\twidth=\"70%\"\r\n\t\t\t\t\t\t\t\t\t\theight={isMobile ? \"0.75rem\" : \"1rem\"}\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t\t</div>\r\n\r\n\t\t\t\t\t\t\t{/* Avatar examples */}\r\n\t\t\t\t\t\t\t<div className=\"space-y-3 md:space-y-4\">\r\n\t\t\t\t\t\t\t\t<h3\r\n\t\t\t\t\t\t\t\t\tclassName={`${isMobile ? \"text-base\" : \"text-lg\"} font-medium text-foreground`}\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\tAvatars\r\n\t\t\t\t\t\t\t\t</h3>\r\n\t\t\t\t\t\t\t\t<div className=\"flex items-center space-x-3 md:space-x-4\">\r\n\t\t\t\t\t\t\t\t\t<Skeleton\r\n\t\t\t\t\t\t\t\t\t\twidth={isMobile ? 32 : 40}\r\n\t\t\t\t\t\t\t\t\t\theight={isMobile ? 32 : 40}\r\n\t\t\t\t\t\t\t\t\t\tradius=\"full\"\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t<Skeleton\r\n\t\t\t\t\t\t\t\t\t\twidth={isMobile ? 40 : 50}\r\n\t\t\t\t\t\t\t\t\t\theight={isMobile ? 40 : 50}\r\n\t\t\t\t\t\t\t\t\t\tradius=\"full\"\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t<Skeleton\r\n\t\t\t\t\t\t\t\t\t\twidth={isMobile ? 48 : 60}\r\n\t\t\t\t\t\t\t\t\t\theight={isMobile ? 48 : 60}\r\n\t\t\t\t\t\t\t\t\t\tradius=\"full\"\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t\t</div>\r\n\r\n\t\t\t\t\t\t\t{/* Button examples */}\r\n\t\t\t\t\t\t\t<div className=\"space-y-3 md:space-y-4\">\r\n\t\t\t\t\t\t\t\t<h3\r\n\t\t\t\t\t\t\t\t\tclassName={`${isMobile ? \"text-base\" : \"text-lg\"} font-medium text-foreground`}\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\tButtons & Cards\r\n\t\t\t\t\t\t\t\t</h3>\r\n\t\t\t\t\t\t\t\t<div className=\"space-y-2 md:space-y-3\">\r\n\t\t\t\t\t\t\t\t\t<Skeleton\r\n\t\t\t\t\t\t\t\t\t\twidth={isMobile ? \"100px\" : \"120px\"}\r\n\t\t\t\t\t\t\t\t\t\theight={isMobile ? \"2rem\" : \"2.5rem\"}\r\n\t\t\t\t\t\t\t\t\t\tradius=\"lg\"\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t<Skeleton\r\n\t\t\t\t\t\t\t\t\t\twidth=\"100%\"\r\n\t\t\t\t\t\t\t\t\t\theight={isMobile ? \"3rem\" : \"4rem\"}\r\n\t\t\t\t\t\t\t\t\t\tradius=\"xl\"\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t</motion.div>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t</div>\r\n\r\n\t\t\t\t{/* Usage Example */}\r\n\t\t\t\t<motion.div\r\n\t\t\t\t\tclassName=\"bg-card border border-border/50 rounded-2xl p-4 md:p-6\"\r\n\t\t\t\t\tinitial={{ opacity: 0, y: 32 }}\r\n\t\t\t\t\tanimate={{ opacity: 1, y: 0 }}\r\n\t\t\t\t\ttransition={{ delay: 0.8, duration: 0.6 }}\r\n\t\t\t\t>\r\n\t\t\t\t\t<h3\r\n\t\t\t\t\t\tclassName={`${isMobile ? \"text-lg\" : \"text-xl\"} font-semibold mb-3 md:mb-4`}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\tUsage Examples\r\n\t\t\t\t\t</h3>\r\n\t\t\t\t\t<div className=\"grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-6\">\r\n\t\t\t\t\t\t<div className=\"space-y-2 md:space-y-3\">\r\n\t\t\t\t\t\t\t<h4\r\n\t\t\t\t\t\t\t\tclassName={`font-medium text-foreground ${isMobile ? \"text-sm\" : \"text-base\"}`}\r\n\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\tBasic Skeleton\r\n\t\t\t\t\t\t\t</h4>\r\n\t\t\t\t\t\t\t<div className=\"bg-muted/50 rounded-lg p-3 md:p-4\">\r\n\t\t\t\t\t\t\t\t<code\r\n\t\t\t\t\t\t\t\t\tclassName={`${isMobile ? \"text-xs\" : \"text-sm\"} text-foreground/80`}\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t{`<Skeleton width=\"100%\" height=\"1rem\" />`}\r\n\t\t\t\t\t\t\t\t</code>\r\n\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t<div className=\"space-y-2 md:space-y-3\">\r\n\t\t\t\t\t\t\t<h4\r\n\t\t\t\t\t\t\t\tclassName={`font-medium text-foreground ${isMobile ? \"text-sm\" : \"text-base\"}`}\r\n\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\tProfile Card\r\n\t\t\t\t\t\t\t</h4>\r\n\t\t\t\t\t\t\t<div className=\"bg-muted/50 rounded-lg p-3 md:p-4\">\r\n\t\t\t\t\t\t\t\t<code\r\n\t\t\t\t\t\t\t\t\tclassName={`${isMobile ? \"text-xs\" : \"text-sm\"} text-foreground/80`}\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t{`<ProfileCardSkeleton />`}\r\n\t\t\t\t\t\t\t\t</code>\r\n\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t</div>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t</motion.div>\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t);\r\n}\r\n\r\nexport function SkeletonTheme() {\r\n\treturn (\r\n\t\t<div className=\"space-y-4 md:space-y-6\">\r\n\t\t\t<motion.div\r\n\t\t\t\tclassName=\"text-center\"\r\n\t\t\t\tinitial={{ opacity: 0, x: -32 }}\r\n\t\t\t\tanimate={{ opacity: 1, x: 0 }}\r\n\t\t\t\ttransition={{ delay: 0.2, duration: 0.6 }}\r\n\t\t\t>\r\n\t\t\t\t<p className=\"text-muted-foreground text-sm md:text-base\">\r\n\t\t\t\t\tA comprehensive loading state for user profile cards\r\n\t\t\t\t</p>\r\n\t\t\t</motion.div>\r\n\r\n\t\t\t<motion.div\r\n\t\t\t\tinitial={{ opacity: 0, scale: 0.9 }}\r\n\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\r\n\t\t\t\ttransition={{ delay: 0.4, duration: 0.6 }}\r\n\t\t\t>\r\n\t\t\t\t<ProfileCardSkeleton />\r\n\t\t\t</motion.div>\r\n\t\t</div>\r\n\t);\r\n}\r\n",
      "type": "registry:ui"
    }
  ]
}