{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "phone-mockups-1",
  "title": "Phone Mockups 1",
  "description": "Solace UI phone mockups component variation 1.",
  "dependencies": [
    "motion",
    "lucide-react"
  ],
  "registryDependencies": [
    "button"
  ],
  "files": [
    {
      "path": "src/registry/components/phone-mockups/one/index.tsx",
      "content": "import React from \"react\";\r\nimport {\n    ImageItem,\n    PhoneCarousel,\n} from \"@/registry/components/phone-mockups/one/phone-carousel\";\n\r\nconst exampleImages: ImageItem[] = [\r\n    {\r\n        src: \"https://assets.solaceui.com/solaceui-Behance-screen.png\",\r\n        alt: \"Behance app on iPhone\",\r\n    },\r\n    {\r\n        src: \"https://assets.solaceui.com/solaceui-Notion-screen.png\",\r\n        alt: \"Notion app on iPhone\",\r\n    },\r\n    {\r\n        src: \"https://assets.solaceui.com/solaceui-One-screen.png\",\r\n        alt: \"One app on iPhone\",\r\n    },\r\n    {\r\n        src: \"https://assets.solaceui.com/solaceui-Reddit-nj7hwh.png\",\r\n        alt: \"Reddit app on iPhone\",\r\n    },\r\n];\r\n\r\nexport default function PhoneMockupBasic() {\r\n    return <PhoneCarousel images={exampleImages} />;\r\n}\r\n",
      "type": "registry:component",
      "target": "components/phone-mockups-1.tsx"
    },
    {
      "path": "src/registry/components/phone-mockups/one/phone-carousel.tsx",
      "content": "\"use client\";\r\nimport type React from \"react\";\r\nimport { useEffect, useState, useRef } from \"react\";\r\nimport Image from \"next/image\";\r\nimport { ChevronLeft, ChevronRight, Pause, Play } from \"lucide-react\";\r\nimport { Button } from \"@/components/ui/button\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { useIsMobile } from \"@/registry/components/phone-mockups/one/use-mobile\";\n\r\ninterface Iphone15ProProps extends React.SVGProps<SVGSVGElement> {\r\n    width?: string | number;\r\n    height?: string | number;\r\n    src?: string;\r\n    alt?: string;\r\n}\r\n\r\nconst Iphone15Pro: React.FC<Iphone15ProProps> = ({\r\n    width = \"100%\",\r\n    height = \"auto\",\r\n    src,\r\n    alt = \"iPhone screen content\",\r\n    className,\r\n    ...props\r\n}) => {\r\n    return (\r\n        <div className={cn(\"relative\", className)}>\r\n            <svg\r\n                width={width}\r\n                height={height}\r\n                viewBox=\"0 0 433 882\"\r\n                preserveAspectRatio=\"xMidYMid meet\"\r\n                fill=\"none\"\r\n                xmlns=\"http://www.w3.org/2000/svg\"\r\n                className=\"transition-all duration-500 ease-in-out\"\r\n                {...props}\r\n            >\r\n                {/* Outer frame */}\r\n                <path\r\n                    d=\"M2 73C2 32.6832 34.6832 0 75 0H357C397.317 0 430 32.6832 430 73V809C430 849.317 397.317 882 357 882H75C34.6832 882 2 849.317 2 809V73Z\"\r\n                    className=\"dark:fill-[#DADADA] fill-[#404040]\"\r\n                />\r\n                {/* side nubs */}\r\n                <path\r\n                    d=\"M0 171C0 170.448 0.447715 170 1 170H3V204H1C0.447715 204 0 203.552 0 203V171Z\"\r\n                    className=\"dark:fill-[#DADADA] fill-[#404040]\"\r\n                />\r\n                <path\r\n                    d=\"M1 234C1 233.448 1.44772 233 2 233H3.5V300H2C1.44772 300 1 299.552 1 299V234Z\"\r\n                    className=\"dark:fill-[#DADADA] fill-[#404040]\"\r\n                />\r\n                <path\r\n                    d=\"M1 319C1 318.448 1.44772 318 2 318H3.5V385H2C1.44772 385 1 384.552 1 384V319Z\"\r\n                    className=\"dark:fill-[#DADADA] fill-[#404040]\"\r\n                />\r\n                <path\r\n                    d=\"M430 279H432C432.552 279 433 279.448 433 280V384C433 384.552 432.552 385 432 385H430V279Z\"\r\n                    className=\"dark:fill-[#DADADA] fill-[#404040]\"\r\n                />\r\n                {/* inner body */}\r\n                <path\r\n                    d=\"M6 74C6 35.3401 37.3401 4 76 4H356C394.66 4 426 35.3401 426 74V808C426 846.66 394.66 878 356 878H76C37.3401 878 6 846.66 6 808V74Z\"\r\n                    className=\"fill-[#262626] dark:fill-gradient-to-b dark:from-white dark:to-[#F0F0F0]\"\r\n                />\r\n                <path\r\n                    opacity=\"0.5\"\r\n                    d=\"M174 5H258V5.5C258 6.60457 257.105 7.5 256 7.5H176C174.895 7.5 174 6.60457 174 5.5V5Z\"\r\n                    className=\"dark:fill-[#DADADA] fill-[#404040]\"\r\n                />\r\n                {/* screen area */}\r\n                <path\r\n                    d=\"M21.25 75C21.25 44.2101 46.2101 19.25 77 19.25H355C385.79 19.25 410.75 44.2101 410.75 75V807C410.75 837.79 385.79 862.75 355 862.75H77C46.2101 862.75 21.25 837.79 21.25 807V75Z\"\r\n                    className=\"dark:fill-[#F5F5F5] fill-[#404040] dark:stroke-[#E0E0E0] stroke-[#404040] stroke-[0.5]\"\r\n                    filter=\"drop-shadow(0px 2px 4px rgba(0, 0, 0, 0.1))\"\r\n                />\r\n                {src && (\r\n                    <foreignObject\r\n                        x=\"21.25\"\r\n                        y=\"19.25\"\r\n                        width=\"389.5\"\r\n                        height=\"843.5\"\r\n                        clipPath=\"url(#roundedCorners)\"\r\n                    >\r\n                        <div\r\n                            style={{ width: \"100%\", height: \"100%\", position: \"relative\" }}\r\n                        >\r\n                            <Image\r\n                                src={src || \"/placeholder.svg\"}\r\n                                alt={alt}\r\n                                fill\r\n                                style={{ objectFit: \"cover\" }}\r\n                                sizes=\"(max-width: 768px) 80vw, (max-width: 1200px) 50vw, 33vw\"\r\n                                priority\r\n                            />\r\n                        </div>\r\n                    </foreignObject>\r\n                )}\r\n                {/* notch area */}\r\n                <path\r\n                    d=\"M154 48.5C154 38.2827 162.283 30 172.5 30H259.5C269.717 30 278 38.2827 278 48.5C278 58.7173 269.717 67 259.5 67H172.5C162.283 67 154 58.7173 154 48.5Z\"\r\n                    className=\"fill-[#262626] dark:fill-[#F0F0F0] dark:drop-shadow-sm\"\r\n                />\r\n                <path\r\n                    d=\"M249 48.5C249 42.701 253.701 38 259.5 38C265.299 38 270 42.701 270 48.5C270 54.299 265.299 59 259.5 59C253.701 59 249 54.299 249 48.5Z\"\r\n                    className=\"fill-[#262626] dark:fill-[#F0F0F0]\"\r\n                />\r\n                <path\r\n                    d=\"M254 48.5C254 45.4624 256.462 43 259.5 43C262.538 43 265 45.4624 265 48.5C265 51.5376 262.538 54 259.5 54C256.462 54 254 51.5376 254 48.5Z\"\r\n                    className=\"fill-[#262626] dark:fill-[#E0E0E0]\"\r\n                />\r\n                {/* highlight */}\r\n                <path\r\n                    d=\"M76 4C37.3401 4 6 35.3401 6 74V808C6 846.66 37.3401 878 76 878H356C394.66 878 426 846.66 426 808V74C426 35.3401 394.66 4 356 4H76Z\"\r\n                    className=\"fill-transparent dark:stroke-white/20 stroke-[0.5] stroke-transparent\"\r\n                />\r\n                <defs>\r\n                    <clipPath id=\"roundedCorners\">\r\n                        <rect\r\n                            x=\"21.25\"\r\n                            y=\"19.25\"\r\n                            width=\"389.5\"\r\n                            height=\"843.5\"\r\n                            rx=\"55.75\"\r\n                            ry=\"55.75\"\r\n                        />\r\n                    </clipPath>\r\n                </defs>\r\n            </svg>\r\n        </div>\r\n    );\r\n};\r\n\r\nexport interface ImageItem {\r\n    src: string;\r\n    alt: string;\r\n}\r\n\r\ninterface PhoneCarouselProps {\r\n    images: ImageItem[];\r\n    className?: string;\r\n    featureMode?: boolean;\r\n    featuresData?: { images: ImageItem[] }[];\r\n    activeFeatureIndex?: number;\r\n}\r\n\r\nexport const PhoneCarousel: React.FC<PhoneCarouselProps> = ({\r\n    images,\r\n    className,\r\n    featureMode,\r\n    featuresData,\r\n    activeFeatureIndex = 0,\r\n}) => {\r\n    const [isClient, setIsClient] = useState<boolean>(false);\r\n    const [currentIndex, setCurrentIndex] = useState<number>(0);\r\n    const [isPaused, setIsPaused] = useState<boolean>(false);\r\n    const [isHovering, setIsHovering] = useState<boolean>(false);\r\n    const carouselRef = useRef<HTMLDivElement>(null);\r\n    const isMobile = useIsMobile();\r\n\r\n    useEffect(() => {\r\n        setIsClient(true);\r\n    }, []);\r\n\r\n    useEffect(() => {\r\n        if (featureMode) return;\r\n\r\n        let interval: NodeJS.Timeout;\r\n        if (!isPaused && !isHovering) {\r\n            interval = setInterval(() => {\r\n                setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length);\r\n            }, 3000);\r\n        }\r\n        return () => clearInterval(interval);\r\n    }, [isPaused, isHovering, images.length, featureMode]);\r\n\r\n    if (!isClient) {\r\n        return (\r\n            <div className=\"w-full h-[400px] flex items-center justify-center\">\r\n                <div className=\"animate-pulse w-64 h-96 rounded-3xl\"></div>\r\n            </div>\r\n        );\r\n    }\r\n\r\n    // FEATURE MODE\r\n    if (featureMode && featuresData) {\r\n        const total = featuresData.length;\r\n        const active = activeFeatureIndex;\r\n        const prev = (active - 1 + total) % total;\r\n        const next = (active + 1) % total;\r\n\r\n        // Each feature has a single image\r\n        const prevImage = featuresData[prev].images[0];\r\n        const activeImage = featuresData[active].images[0];\r\n        const nextImage = featuresData[next].images[0];\r\n\r\n        return (\r\n            <section\r\n                className={cn(\r\n                    \"relative w-full py-6 md:py-10 overflow-visible\",\r\n                    className\r\n                )}\r\n                aria-label=\"iPhone product showcase in feature mode\"\r\n            >\r\n                <div className=\"relative h-[600px] sm:h-[650px] lg:h-[700px] w-full\">\r\n                    {/* Center the phone stack */}\r\n                    <div className=\"absolute top-0 left-1/2 transform -translate-x-1/2\">\r\n                        {/* 1) Back phone (prev) */}\r\n                        <div\r\n                            className=\"absolute opacity-60\"\r\n                            style={{\r\n                                transform: \"translateY(-20px) scale(0.92)\",\r\n                                zIndex: 10,\r\n                            }}\r\n                        >\r\n                            <Iphone15Pro\r\n                                width={isMobile ? 280 : 350}\r\n                                height=\"auto\"\r\n                                src={prevImage.src}\r\n                                alt={prevImage.alt}\r\n                            />\r\n                        </div>\r\n\r\n                        {/* 2) Middle phone (next) */}\r\n                        <div\r\n                            className=\"absolute opacity-80\"\r\n                            style={{\r\n                                transform: \"translateY(25px) scale(0.96)\",\r\n                                zIndex: 20,\r\n                            }}\r\n                        >\r\n                            <Iphone15Pro\r\n                                width={isMobile ? 280 : 350}\r\n                                height=\"auto\"\r\n                                src={nextImage.src}\r\n                                alt={nextImage.alt}\r\n                            />\r\n                        </div>\r\n\r\n                        {/* 3) Front phone (active) */}\r\n                        <div\r\n                            className=\"relative\"\r\n                            style={{\r\n                                transform: \"translateY(70px) scale(1)\",\r\n                                zIndex: 30,\r\n                            }}\r\n                        >\r\n                            <Iphone15Pro\r\n                                width={isMobile ? 280 : 350}\r\n                                height=\"auto\"\r\n                                src={activeImage.src}\r\n                                alt={activeImage.alt}\r\n                            />\r\n                        </div>\r\n                    </div>\r\n                </div>\r\n            </section>\r\n        );\r\n    }\r\n\r\n    // NORMAL MODE\r\n    const handlePrevious = () => {\r\n        setCurrentIndex((prevIndex) =>\r\n            prevIndex === 0 ? images.length - 1 : prevIndex - 1\r\n        );\r\n    };\r\n\r\n    const handleNext = () => {\r\n        setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length);\r\n    };\r\n\r\n    const togglePause = () => {\r\n        setIsPaused((prev) => !prev);\r\n    };\r\n\r\n    return (\r\n        <section\r\n            className=\"relative w-full py-6 md:py-10 overflow-hidden\"\r\n            aria-label=\"iPhone product showcase\"\r\n        >\r\n            <div className=\"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8\">\r\n                <div className=\"relative\">\r\n                    {/* Main carousel container */}\r\n                    <div\r\n                        ref={carouselRef}\r\n                        className=\"flex justify-center items-start h-[410px] md:h-[510px] lg:h-[520px]\"\r\n                        onMouseEnter={() => setIsHovering(true)}\r\n                        onMouseLeave={() => setIsHovering(false)}\r\n                    >\r\n                        <div className=\"relative flex justify-center w-full\">\r\n                            {images.map((image, index) => {\r\n                                const isActive = index === currentIndex;\r\n                                const isPrevious =\r\n                                    index === currentIndex - 1 ||\r\n                                    (currentIndex === 0 && index === images.length - 1);\r\n                                const isNext =\r\n                                    index === currentIndex + 1 ||\r\n                                    (currentIndex === images.length - 1 && index === 0);\r\n\r\n                                return (\r\n                                    <div\r\n                                        key={index}\r\n                                        className={cn(\r\n                                            \"absolute transition-all duration-700 ease-in-out transform\",\r\n                                            isActive ? \"z-20 scale-100\" : \"opacity-0 scale-90\",\r\n                                            isPrevious ? \"-translate-x-[10%] opacity-30 z-10\" : \"\",\r\n                                            isNext ? \"translate-x-[10%] opacity-30 z-10\" : \"\",\r\n                                            !isActive && !isPrevious && !isNext ? \"opacity-0\" : \"\"\r\n                                        )}\r\n                                        style={{\r\n                                            top: \"0\",\r\n                                            transform: `translateY(0px) ${isPrevious\r\n                                                    ? \"translateX(-60%)\"\r\n                                                    : isNext\r\n                                                        ? \"translateX(60%)\"\r\n                                                        : \"translateX(0)\"\r\n                                                } ${isActive ? \"scale(1)\" : \"scale(0.9)\"}`,\r\n                                        }}\r\n                                        aria-hidden={!isActive}\r\n                                    >\r\n                                        <div className=\"group\">\r\n                                            <Iphone15Pro\r\n                                                width={isMobile ? 280 : 350}\r\n                                                height=\"auto\"\r\n                                                src={image.src}\r\n                                                alt={image.alt}\r\n                                                className=\"transition-all duration-100 hover:scale-105 hover:-rotate-6\"\r\n                                            />\r\n                                        </div>\r\n                                    </div>\r\n                                );\r\n                            })}\r\n                        </div>\r\n                    </div>\r\n\r\n                    {/* Controls */}\r\n                    <div className=\"absolute bottom-8 left-0 right-0 flex justify-center items-center gap-4 z-30\">\r\n                        <Button\r\n                            variant=\"outline\"\r\n                            size=\"icon\"\r\n                            onClick={handlePrevious}\r\n                            className=\"rounded-full bg-black/60 backdrop-blur-sm border-white/20 hover:bg-black/80 shadow-md\"\r\n                            aria-label=\"Previous image\"\r\n                        >\r\n                            <ChevronLeft className=\"h-5 w-5 text-white\" />\r\n                        </Button>\r\n                        <Button\r\n                            variant=\"outline\"\r\n                            size=\"icon\"\r\n                            onClick={togglePause}\r\n                            className=\"rounded-full bg-black/60 backdrop-blur-sm border-white/20 hover:bg-black/80 shadow-md\"\r\n                            aria-label={isPaused ? \"Play slideshow\" : \"Pause slideshow\"}\r\n                        >\r\n                            {isPaused ? (\r\n                                <Play className=\"h-5 w-5 text-white\" />\r\n                            ) : (\r\n                                <Pause className=\"h-5 w-5 text-white\" />\r\n                            )}\r\n                        </Button>\r\n                        <Button\r\n                            variant=\"outline\"\r\n                            size=\"icon\"\r\n                            onClick={handleNext}\r\n                            className=\"rounded-full bg-black/60 backdrop-blur-sm border-white/20 hover:bg-black/80 shadow-md\"\r\n                            aria-label=\"Next image\"\r\n                        >\r\n                            <ChevronRight className=\"h-5 w-5 text-white\" />\r\n                        </Button>\r\n                    </div>\r\n                </div>\r\n            </div>\r\n        </section>\r\n    );\r\n};\r\n",
      "type": "registry:component",
      "target": "components/phone-carousel.tsx"
    },
    {
      "path": "src/registry/components/phone-mockups/one/use-mobile.tsx",
      "content": "import * as React from \"react\";\r\n\r\nconst MOBILE_BREAKPOINT = 768;\r\n\r\nexport function useIsMobile() {\r\n    const [isMobile, setIsMobile] = React.useState<boolean | undefined>(\r\n        undefined\r\n    );\r\n\r\n    React.useEffect(() => {\r\n        const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);\r\n        const onChange = () => {\r\n            setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\r\n        };\r\n        mql.addEventListener(\"change\", onChange);\r\n        setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);\r\n        return () => mql.removeEventListener(\"change\", onChange);\r\n    }, []);\r\n\r\n    return !!isMobile;\r\n}\r\n",
      "type": "registry:hook",
      "target": "hooks/use-mobile.tsx"
    }
  ],
  "type": "registry:component"
}