{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "info-card",
  "type": "registry:block",
  "title": "Info card",
  "description": "Info card",
  "files": [
    {
      "path": "components/usages/infocardusage.tsx",
      "content": "import { useState } from \"react\";\n\nimport {\n\tInfoCard,\n\tInfoCardAction,\n\tInfoCardContent,\n\tInfoCardDescription,\n\tInfoCardDismiss,\n\tInfoCardFooter,\n\tInfoCardMedia,\n\tInfoCardTitle,\n} from \"@/registry/open-source/info-card\";\nimport { Calendar, Home, Inbox, Search, Settings } from \"lucide-react\";\n\nexport interface Step {\n\ttitle: string;\n\tdescription: string;\n\timage: any[];\n\texpandHeight?: number;\n}\n\nexport default function MultiStepContent() {\n\tconst [currentStep, setCurrentStep] = useState(0);\n\n\tconst steps: Step[] = [\n\t\t{\n\t\t\ttitle: \"Welcome to Our Platform!\",\n\t\t\tdescription: \"Let's take a quick tour of our new features!\",\n\t\t\timage: [\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/second.webp\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/third.webp\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/first.webp\",\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\ttitle: \"Powerful Dashboard!\",\n\t\t\tdescription: \"Everything you need, right at your fingertips!\",\n\t\t\timage: [\n\t\t\t\t{\n\t\t\t\t\ttype: \"video\",\n\t\t\t\t\tsrc:\n\t\t\t\t\t\t\"https://video.twimg.com/ext_tw_video/\" +\n\t\t\t\t\t\t\"1811493439357476864/pu/vid/avc1/1280x720/r_A2n1_eDbYiTMkU.mp4?tag=12\",\n\t\t\t\t\tautoPlay: true,\n\t\t\t\t\tloop: true,\n\t\t\t\t\tclassName: \"shadow-none\",\n\t\t\t\t},\n\t\t\t],\n\t\t\texpandHeight: 120,\n\t\t},\n\t\t{\n\t\t\ttitle: \"Useful Tips!\",\n\t\t\tdescription: \"You can also use the sidebar to go to different pages!\",\n\t\t\timage: [\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/third.webp\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/second.webp\",\n\t\t\t\t},\n\t\t\t],\n\t\t\texpandHeight: 140,\n\t\t},\n\t\t{\n\t\t\ttitle: \"Ready to Start?\",\n\t\t\tdescription: \"You're all set to explore the platform!\",\n\t\t\timage: [\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/first.webp\",\n\t\t\t\t\tclassName: \"shadow-none\",\n\t\t\t\t},\n\t\t\t],\n\t\t\texpandHeight: 140,\n\t\t},\n\t];\n\n\tconst handleNext = () => {\n\t\tsetCurrentStep((prev) => prev + 1);\n\t};\n\n\treturn (\n\t\t<InfoCard>\n\t\t\t<InfoCardContent>\n\t\t\t\t<InfoCardTitle>{steps[currentStep].title}</InfoCardTitle>\n\t\t\t\t<InfoCardDescription>\n\t\t\t\t\t{steps[currentStep].description}\n\t\t\t\t</InfoCardDescription>\n\t\t\t\t{steps[currentStep].image && (\n\t\t\t\t\t<InfoCardMedia\n\t\t\t\t\t\tmedia={steps[currentStep].image}\n\t\t\t\t\t\texpandHeight={steps[currentStep].expandHeight || undefined}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t<InfoCardFooter>\n\t\t\t\t\t{currentStep === steps.length - 1 ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div />\n\t\t\t\t\t\t\t<InfoCardDismiss className=\"flex flex-row items-center gap-1 hover:underline hover:cursor-pointer\">\n\t\t\t\t\t\t\t\tGot it!\n\t\t\t\t\t\t\t</InfoCardDismiss>\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<InfoCardDismiss>Dismiss</InfoCardDismiss>\n\t\t\t\t\t\t\t<InfoCardAction\n\t\t\t\t\t\t\t\tonClick={handleNext}\n\t\t\t\t\t\t\t\tclassName=\"flex flex-row items-center gap-1 hover:underline hover:cursor-pointer\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tNext\n\t\t\t\t\t\t\t</InfoCardAction>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</InfoCardFooter>\n\t\t\t</InfoCardContent>\n\t\t</InfoCard>\n\t);\n}\n",
      "type": "registry:block",
      "target": "~/example.tsx"
    },
    {
      "path": "components/usages/infocardusage.tsx",
      "content": "import { useState } from \"react\";\n\nimport {\n\tInfoCard,\n\tInfoCardAction,\n\tInfoCardContent,\n\tInfoCardDescription,\n\tInfoCardDismiss,\n\tInfoCardFooter,\n\tInfoCardMedia,\n\tInfoCardTitle,\n} from \"@/registry/open-source/info-card\";\nimport { Calendar, Home, Inbox, Search, Settings } from \"lucide-react\";\n\nexport interface Step {\n\ttitle: string;\n\tdescription: string;\n\timage: any[];\n\texpandHeight?: number;\n}\n\nexport default function MultiStepContent() {\n\tconst [currentStep, setCurrentStep] = useState(0);\n\n\tconst steps: Step[] = [\n\t\t{\n\t\t\ttitle: \"Welcome to Our Platform!\",\n\t\t\tdescription: \"Let's take a quick tour of our new features!\",\n\t\t\timage: [\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/second.webp\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/third.webp\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/first.webp\",\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\ttitle: \"Powerful Dashboard!\",\n\t\t\tdescription: \"Everything you need, right at your fingertips!\",\n\t\t\timage: [\n\t\t\t\t{\n\t\t\t\t\ttype: \"video\",\n\t\t\t\t\tsrc:\n\t\t\t\t\t\t\"https://video.twimg.com/ext_tw_video/\" +\n\t\t\t\t\t\t\"1811493439357476864/pu/vid/avc1/1280x720/r_A2n1_eDbYiTMkU.mp4?tag=12\",\n\t\t\t\t\tautoPlay: true,\n\t\t\t\t\tloop: true,\n\t\t\t\t\tclassName: \"shadow-none\",\n\t\t\t\t},\n\t\t\t],\n\t\t\texpandHeight: 120,\n\t\t},\n\t\t{\n\t\t\ttitle: \"Useful Tips!\",\n\t\t\tdescription: \"You can also use the sidebar to go to different pages!\",\n\t\t\timage: [\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/third.webp\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/second.webp\",\n\t\t\t\t},\n\t\t\t],\n\t\t\texpandHeight: 140,\n\t\t},\n\t\t{\n\t\t\ttitle: \"Ready to Start?\",\n\t\t\tdescription: \"You're all set to explore the platform!\",\n\t\t\timage: [\n\t\t\t\t{\n\t\t\t\t\tsrc: \"https://cd-misc.s3.us-east-2.amazonaws.com/sidebar/first.webp\",\n\t\t\t\t\tclassName: \"shadow-none\",\n\t\t\t\t},\n\t\t\t],\n\t\t\texpandHeight: 140,\n\t\t},\n\t];\n\n\tconst handleNext = () => {\n\t\tsetCurrentStep((prev) => prev + 1);\n\t};\n\n\treturn (\n\t\t<InfoCard>\n\t\t\t<InfoCardContent>\n\t\t\t\t<InfoCardTitle>{steps[currentStep].title}</InfoCardTitle>\n\t\t\t\t<InfoCardDescription>\n\t\t\t\t\t{steps[currentStep].description}\n\t\t\t\t</InfoCardDescription>\n\t\t\t\t{steps[currentStep].image && (\n\t\t\t\t\t<InfoCardMedia\n\t\t\t\t\t\tmedia={steps[currentStep].image}\n\t\t\t\t\t\texpandHeight={steps[currentStep].expandHeight || undefined}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t<InfoCardFooter>\n\t\t\t\t\t{currentStep === steps.length - 1 ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div />\n\t\t\t\t\t\t\t<InfoCardDismiss className=\"flex flex-row items-center gap-1 hover:underline hover:cursor-pointer\">\n\t\t\t\t\t\t\t\tGot it!\n\t\t\t\t\t\t\t</InfoCardDismiss>\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<InfoCardDismiss>Dismiss</InfoCardDismiss>\n\t\t\t\t\t\t\t<InfoCardAction\n\t\t\t\t\t\t\t\tonClick={handleNext}\n\t\t\t\t\t\t\t\tclassName=\"flex flex-row items-center gap-1 hover:underline hover:cursor-pointer\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tNext\n\t\t\t\t\t\t\t</InfoCardAction>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</InfoCardFooter>\n\t\t\t</InfoCardContent>\n\t\t</InfoCard>\n\t);\n}\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/open-source/info-card.tsx",
      "content": "\"use client\";\r\n\r\nimport React, {\r\n\tcreateContext,\r\n\tuseCallback,\r\n\tuseContext,\r\n\tuseEffect,\r\n\tuseMemo,\r\n\tuseRef,\r\n\tuseState,\r\n} from \"react\";\r\n\r\nimport { cn } from \"@/registry/utilities/cn\";\r\nimport { AnimatePresence, motion } from \"motion/react\";\r\n\r\n// Credit:\r\n// https://karrix.dev/components/info-card#\r\n\r\ninterface InfoCardTitleProps extends React.HTMLAttributes<HTMLDivElement> {\r\n\tchildren: React.ReactNode;\r\n}\r\n\r\ninterface InfoCardDescriptionProps\r\n\textends React.HTMLAttributes<HTMLDivElement> {\r\n\tchildren: React.ReactNode;\r\n}\r\n\r\nconst InfoCardTitle = React.memo(\r\n\t({ children, className, ...props }: InfoCardTitleProps) => {\r\n\t\treturn (\r\n\t\t\t<div className={cn(\"font-medium mb-1\", className)} {...props}>\r\n\t\t\t\t{children}\r\n\t\t\t</div>\r\n\t\t);\r\n\t}\r\n);\r\nInfoCardTitle.displayName = \"InfoCardTitle\";\r\n\r\nconst InfoCardDescription = React.memo(\r\n\t({ children, className, ...props }: InfoCardDescriptionProps) => {\r\n\t\treturn (\r\n\t\t\t<div\r\n\t\t\t\tclassName={cn(\"text-muted-foreground leading-4\", className)}\r\n\t\t\t\t{...props}\r\n\t\t\t>\r\n\t\t\t\t{children}\r\n\t\t\t</div>\r\n\t\t);\r\n\t}\r\n);\r\nInfoCardDescription.displayName = \"InfoCardDescription\";\r\n\r\ninterface CommonCardProps extends React.HTMLAttributes<HTMLDivElement> {\r\n\tchildren: React.ReactNode;\r\n}\r\n\r\ninterface InfoCardProps extends React.HTMLAttributes<HTMLDivElement> {\r\n\tchildren: React.ReactNode;\r\n\tstorageKey?: string;\r\n\tdismissType?: \"once\" | \"forever\";\r\n}\r\n\r\ntype InfoCardContentProps = CommonCardProps;\r\ntype InfoCardFooterProps = CommonCardProps;\r\ntype InfoCardDismissProps = React.HTMLAttributes<HTMLDivElement> & {\r\n\tchildren: React.ReactNode;\r\n\tonDismiss?: () => void;\r\n};\r\ntype InfoCardActionProps = CommonCardProps;\r\n\r\nconst InfoCardContent = React.memo(\r\n\t({ children, className, ...props }: InfoCardContentProps) => {\r\n\t\treturn (\r\n\t\t\t<div\r\n\t\t\t\tclassName={cn(\"flex flex-col gap-1 text-xs\", className)}\r\n\t\t\t\t{...props}\r\n\t\t\t>\r\n\t\t\t\t{children}\r\n\t\t\t</div>\r\n\t\t);\r\n\t}\r\n);\r\nInfoCardContent.displayName = \"InfoCardContent\";\r\n\r\ninterface MediaItem {\r\n\ttype?: \"image\" | \"video\";\r\n\tsrc: string;\r\n\talt?: string;\r\n\tclassName?: string;\r\n\t[key: string]: any;\r\n}\r\n\r\ninterface InfoCardMediaProps extends React.HTMLAttributes<HTMLDivElement> {\r\n\tmedia: MediaItem[];\r\n\tloading?: \"eager\" | \"lazy\";\r\n\tshrinkHeight?: number;\r\n\texpandHeight?: number;\r\n}\r\n\r\nconst InfoCardImageContext = createContext<{\r\n\thandleMediaLoad: (mediaSrc: string) => void;\r\n\tsetAllImagesLoaded: (loaded: boolean) => void;\r\n}>({\r\n\thandleMediaLoad: () => {},\r\n\tsetAllImagesLoaded: () => {},\r\n});\r\n\r\nconst InfoCardContext = createContext<{\r\n\tisHovered: boolean;\r\n\tonDismiss: () => void;\r\n}>({\r\n\tisHovered: false,\r\n\tonDismiss: () => {},\r\n});\r\n\r\nfunction InfoCard({\r\n\tchildren,\r\n\tclassName,\r\n\tstorageKey,\r\n\tdismissType = \"once\",\r\n}: InfoCardProps) {\r\n\tif (dismissType === \"forever\" && !storageKey) {\r\n\t\tthrow new Error(\r\n\t\t\t'A storageKey must be provided when using dismissType=\"forever\"'\r\n\t\t);\r\n\t}\r\n\r\n\tconst [isHovered, setIsHovered] = useState(false);\r\n\tconst [allImagesLoaded, setAllImagesLoaded] = useState(true);\r\n\tconst [isDismissed, setIsDismissed] = useState(() => {\r\n\t\tif (typeof window === \"undefined\" || dismissType === \"once\") return false;\r\n\t\tif (dismissType !== \"forever\") return false;\r\n\t\ttry {\r\n\t\t\tconst ls = window.localStorage;\r\n\t\t\tif (\r\n\t\t\t\t!ls ||\r\n\t\t\t\ttypeof ls.getItem !== \"function\" ||\r\n\t\t\t\ttypeof ls.setItem !== \"function\"\r\n\t\t\t) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\treturn ls.getItem(storageKey!) === \"dismissed\";\r\n\t\t} catch {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t});\r\n\r\n\tconst handleDismiss = useCallback(() => {\r\n\t\tsetIsDismissed(true);\r\n\t\tif (dismissType !== \"forever\") return;\r\n\t\ttry {\r\n\t\t\tconst ls = window.localStorage;\r\n\t\t\tif (ls && typeof ls.setItem === \"function\") {\r\n\t\t\t\tls.setItem(storageKey!, \"dismissed\");\r\n\t\t\t}\r\n\t\t} catch {\r\n\t\t\t/* ignore */\r\n\t\t}\r\n\t}, [storageKey, dismissType]);\r\n\r\n\tconst imageContextValue = useMemo(\r\n\t\t() => ({\r\n\t\t\thandleMediaLoad: () => {},\r\n\t\t\tsetAllImagesLoaded,\r\n\t\t}),\r\n\t\t[setAllImagesLoaded]\r\n\t);\r\n\r\n\tconst cardContextValue = useMemo(\r\n\t\t() => ({\r\n\t\t\tisHovered,\r\n\t\t\tonDismiss: handleDismiss,\r\n\t\t}),\r\n\t\t[isHovered, handleDismiss]\r\n\t);\r\n\r\n\treturn (\r\n\t\t<InfoCardContext.Provider value={cardContextValue}>\r\n\t\t\t<InfoCardImageContext.Provider value={imageContextValue}>\r\n\t\t\t\t<AnimatePresence>\r\n\t\t\t\t\t{!isDismissed && (\r\n\t\t\t\t\t\t<motion.div\r\n\t\t\t\t\t\t\tinitial={{ opacity: 0, y: 10 }}\r\n\t\t\t\t\t\t\tanimate={{\r\n\t\t\t\t\t\t\t\topacity: allImagesLoaded ? 1 : 0,\r\n\t\t\t\t\t\t\t\ty: allImagesLoaded ? 0 : 10,\r\n\t\t\t\t\t\t\t}}\r\n\t\t\t\t\t\t\texit={{\r\n\t\t\t\t\t\t\t\topacity: 0,\r\n\t\t\t\t\t\t\t\ty: 10,\r\n\t\t\t\t\t\t\t\ttransition: { duration: 0.2 },\r\n\t\t\t\t\t\t\t}}\r\n\t\t\t\t\t\t\ttransition={{ duration: 0.3, delay: 0 }}\r\n\t\t\t\t\t\t\tclassName={cn(\r\n\t\t\t\t\t\t\t\t\"group rounded-lg border p-3\",\r\n\t\t\t\t\t\t\t\t\"bg-background\",\r\n\t\t\t\t\t\t\t\t\"dark:bg-linear-to-br dark:from-background dark:to-background\",\r\n\t\t\t\t\t\t\t\t\"dark:border-zinc-700\",\r\n\t\t\t\t\t\t\t\tclassName\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\tonMouseEnter={() => setIsHovered(true)}\r\n\t\t\t\t\t\t\tonMouseLeave={() => setIsHovered(false)}\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t{children}\r\n\t\t\t\t\t\t</motion.div>\r\n\t\t\t\t\t)}\r\n\t\t\t\t</AnimatePresence>\r\n\t\t\t</InfoCardImageContext.Provider>\r\n\t\t</InfoCardContext.Provider>\r\n\t);\r\n}\r\n\r\nconst InfoCardFooter = ({ children, className }: InfoCardFooterProps) => {\r\n\tconst { isHovered } = useContext(InfoCardContext);\r\n\r\n\treturn (\r\n\t\t<motion.div\r\n\t\t\tclassName={cn(\r\n\t\t\t\t\"flex justify-between text-xs text-muted-foreground\",\r\n\t\t\t\tclassName\r\n\t\t\t)}\r\n\t\t\tinitial={{ opacity: 0, height: \"0px\" }}\r\n\t\t\tanimate={{\r\n\t\t\t\topacity: isHovered ? 1 : 0,\r\n\t\t\t\theight: isHovered ? \"auto\" : \"0px\",\r\n\t\t\t}}\r\n\t\t\ttransition={{\r\n\t\t\t\ttype: \"spring\",\r\n\t\t\t\tstiffness: 300,\r\n\t\t\t\tdamping: 30,\r\n\t\t\t\tduration: 0.3,\r\n\t\t\t}}\r\n\t\t>\r\n\t\t\t{children}\r\n\t\t</motion.div>\r\n\t);\r\n};\r\n\r\nconst InfoCardDismiss = React.memo(\r\n\t({ children, className, onDismiss, ...props }: InfoCardDismissProps) => {\r\n\t\tconst { onDismiss: contextDismiss } = useContext(InfoCardContext);\r\n\r\n\t\tconst handleClick = (e: React.MouseEvent) => {\r\n\t\t\te.preventDefault();\r\n\t\t\tonDismiss?.();\r\n\t\t\tcontextDismiss();\r\n\t\t};\r\n\r\n\t\treturn (\r\n\t\t\t<div\r\n\t\t\t\tclassName={cn(\"cursor-pointer\", className)}\r\n\t\t\t\tonClick={handleClick}\r\n\t\t\t\t{...props}\r\n\t\t\t>\r\n\t\t\t\t{children}\r\n\t\t\t</div>\r\n\t\t);\r\n\t}\r\n);\r\nInfoCardDismiss.displayName = \"InfoCardDismiss\";\r\n\r\nconst InfoCardAction = React.memo(\r\n\t({ children, className, ...props }: InfoCardActionProps) => {\r\n\t\treturn (\r\n\t\t\t<div className={cn(\"\", className)} {...props}>\r\n\t\t\t\t{children}\r\n\t\t\t</div>\r\n\t\t);\r\n\t}\r\n);\r\nInfoCardAction.displayName = \"InfoCardAction\";\r\n\r\nconst InfoCardMedia = ({\r\n\tmedia = [],\r\n\tclassName,\r\n\tloading = undefined,\r\n\tshrinkHeight = 75,\r\n\texpandHeight = 150,\r\n}: InfoCardMediaProps) => {\r\n\tconst { isHovered } = useContext(InfoCardContext);\r\n\tconst { setAllImagesLoaded } = useContext(InfoCardImageContext);\r\n\tconst [isOverflowVisible, setIsOverflowVisible] = useState(false);\r\n\tconst loadedMedia = useRef(new Set());\r\n\r\n\tconst handleMediaLoad = (mediaSrc: string) => {\r\n\t\tloadedMedia.current.add(mediaSrc);\r\n\t\tif (loadedMedia.current.size === Math.min(3, media.slice(0, 3).length)) {\r\n\t\t\tsetAllImagesLoaded(true);\r\n\t\t}\r\n\t};\r\n\r\n\tconst processedMedia = useMemo(\r\n\t\t() =>\r\n\t\t\tmedia.map((item) => ({\r\n\t\t\t\t...item,\r\n\t\t\t\ttype: item.type || \"image\",\r\n\t\t\t})),\r\n\t\t[media]\r\n\t);\r\n\r\n\tconst displayMedia = useMemo(\r\n\t\t() => processedMedia.slice(0, 3),\r\n\t\t[processedMedia]\r\n\t);\r\n\r\n\tuseEffect(() => {\r\n\t\tif (media.length > 0) {\r\n\t\t\tsetAllImagesLoaded(false);\r\n\t\t\tloadedMedia.current.clear();\r\n\t\t} else {\r\n\t\t\tsetAllImagesLoaded(true); // No media to load\r\n\t\t}\r\n\t}, [media.length]);\r\n\r\n\tuseEffect(() => {\r\n\t\tlet timeoutId: NodeJS.Timeout;\r\n\t\tif (isHovered) {\r\n\t\t\ttimeoutId = setTimeout(() => {\r\n\t\t\t\tsetIsOverflowVisible(true);\r\n\t\t\t}, 100);\r\n\t\t} else {\r\n\t\t\tsetIsOverflowVisible(false);\r\n\t\t}\r\n\t\treturn () => clearTimeout(timeoutId);\r\n\t}, [isHovered]);\r\n\r\n\tconst mediaCount = displayMedia.length;\r\n\r\n\tconst getRotation = (index: number) => {\r\n\t\tif (!isHovered || mediaCount === 1) return 0;\r\n\t\treturn (index - (mediaCount === 2 ? 0.5 : 1)) * 5;\r\n\t};\r\n\r\n\tconst getTranslateX = (index: number) => {\r\n\t\tif (!isHovered || mediaCount === 1) return 0;\r\n\t\treturn (index - (mediaCount === 2 ? 0.5 : 1)) * 20;\r\n\t};\r\n\r\n\tconst getTranslateY = (index: number) => {\r\n\t\tif (!isHovered) return 0;\r\n\t\tif (mediaCount === 1) return -5;\r\n\t\treturn index === 0 ? -10 : index === 1 ? -5 : 0;\r\n\t};\r\n\r\n\tconst getScale = (index: number) => {\r\n\t\tif (!isHovered) return 1;\r\n\t\treturn mediaCount === 1 ? 1 : 0.95 + index * 0.02;\r\n\t};\r\n\r\n\treturn (\r\n\t\t<InfoCardImageContext.Provider\r\n\t\t\tvalue={{\r\n\t\t\t\thandleMediaLoad,\r\n\t\t\t\tsetAllImagesLoaded,\r\n\t\t\t}}\r\n\t\t>\r\n\t\t\t<motion.div\r\n\t\t\t\tclassName={cn(\"relative mt-2 rounded-md\", className)}\r\n\t\t\t\tanimate={{\r\n\t\t\t\t\theight:\r\n\t\t\t\t\t\tmedia.length > 0\r\n\t\t\t\t\t\t\t? isHovered\r\n\t\t\t\t\t\t\t\t? expandHeight\r\n\t\t\t\t\t\t\t\t: shrinkHeight\r\n\t\t\t\t\t\t\t: \"auto\",\r\n\t\t\t\t}}\r\n\t\t\t\tstyle={{\r\n\t\t\t\t\toverflow: isOverflowVisible ? \"visible\" : \"hidden\",\r\n\t\t\t\t}}\r\n\t\t\t\ttransition={{\r\n\t\t\t\t\ttype: \"spring\",\r\n\t\t\t\t\tstiffness: 300,\r\n\t\t\t\t\tdamping: 30,\r\n\t\t\t\t\tduration: 0.3,\r\n\t\t\t\t}}\r\n\t\t\t>\r\n\t\t\t\t<div\r\n\t\t\t\t\tclassName={cn(\r\n\t\t\t\t\t\t\"relative\",\r\n\t\t\t\t\t\tmedia.length > 0 ? { height: shrinkHeight } : \"h-auto\"\r\n\t\t\t\t\t)}\r\n\t\t\t\t>\r\n\t\t\t\t\t{displayMedia.map((item, index) => {\r\n\t\t\t\t\t\tconst {\r\n\t\t\t\t\t\t\ttype,\r\n\t\t\t\t\t\t\tsrc,\r\n\t\t\t\t\t\t\talt,\r\n\t\t\t\t\t\t\tclassName: itemClassName,\r\n\t\t\t\t\t\t\t...mediaProps\r\n\t\t\t\t\t\t} = item;\r\n\r\n\t\t\t\t\t\treturn (\r\n\t\t\t\t\t\t\t<motion.div\r\n\t\t\t\t\t\t\t\tkey={src}\r\n\t\t\t\t\t\t\t\tclassName=\"absolute w-full\"\r\n\t\t\t\t\t\t\t\tanimate={{\r\n\t\t\t\t\t\t\t\t\trotateZ: getRotation(index),\r\n\t\t\t\t\t\t\t\t\tx: getTranslateX(index),\r\n\t\t\t\t\t\t\t\t\ty: getTranslateY(index),\r\n\t\t\t\t\t\t\t\t\tscale: getScale(index),\r\n\t\t\t\t\t\t\t\t}}\r\n\t\t\t\t\t\t\t\ttransition={{\r\n\t\t\t\t\t\t\t\t\ttype: \"spring\",\r\n\t\t\t\t\t\t\t\t\tstiffness: 300,\r\n\t\t\t\t\t\t\t\t\tdamping: 30,\r\n\t\t\t\t\t\t\t\t}}\r\n\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t{type === \"video\" ? (\r\n\t\t\t\t\t\t\t\t\t<video\r\n\t\t\t\t\t\t\t\t\t\tsrc={src}\r\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\r\n\t\t\t\t\t\t\t\t\t\t\t\"w-full rounded-md border border-gray-200 dark:border-zinc-700/10 object-cover shadow-lg\",\r\n\t\t\t\t\t\t\t\t\t\t\titemClassName\r\n\t\t\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t\t\t\tonLoadedData={() => handleMediaLoad(src)}\r\n\t\t\t\t\t\t\t\t\t\tpreload=\"metadata\"\r\n\t\t\t\t\t\t\t\t\t\tmuted\r\n\t\t\t\t\t\t\t\t\t\tplaysInline\r\n\t\t\t\t\t\t\t\t\t\t{...mediaProps}\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t) : (\r\n\t\t\t\t\t\t\t\t\t<img\r\n\t\t\t\t\t\t\t\t\t\tsrc={src}\r\n\t\t\t\t\t\t\t\t\t\talt={alt}\r\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\r\n\t\t\t\t\t\t\t\t\t\t\t\"w-full rounded-md border border-gray-200 dark:border-zinc-700/10 object-cover shadow-lg\",\r\n\t\t\t\t\t\t\t\t\t\t\titemClassName\r\n\t\t\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t\t\t\tonLoad={() => handleMediaLoad(src)}\r\n\t\t\t\t\t\t\t\t\t\tloading={loading}\r\n\t\t\t\t\t\t\t\t\t\t{...mediaProps}\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t</motion.div>\r\n\t\t\t\t\t\t);\r\n\t\t\t\t\t})}\r\n\t\t\t\t</div>\r\n\r\n\t\t\t\t<motion.div\r\n\t\t\t\t\tclassName=\"absolute right-0 bottom-0 left-0 h-10 bg-linear-to-b from-transparent to-background dark:to-background\"\r\n\t\t\t\t\tanimate={{ opacity: isHovered ? 0 : 1 }}\r\n\t\t\t\t\ttransition={{\r\n\t\t\t\t\t\ttype: \"spring\",\r\n\t\t\t\t\t\tstiffness: 300,\r\n\t\t\t\t\t\tdamping: 30,\r\n\t\t\t\t\t\tduration: 0.3,\r\n\t\t\t\t\t}}\r\n\t\t\t\t/>\r\n\t\t\t</motion.div>\r\n\t\t</InfoCardImageContext.Provider>\r\n\t);\r\n};\r\n\r\nexport {\r\n\tInfoCard,\r\n\tInfoCardTitle,\r\n\tInfoCardDescription,\r\n\tInfoCardContent,\r\n\tInfoCardMedia,\r\n\tInfoCardFooter,\r\n\tInfoCardDismiss,\r\n\tInfoCardAction,\r\n};\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"
    }
  ]
}