{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "feature-01",
  "title": "Feature 01",
  "description": "List of items: select one to reveal its description and media.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "button"
  ],
  "files": [
    {
      "path": "registry/blocks/feature/feature-01/feature-01.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { useState } from 'react'\n\nimport { motion, useReducedMotion, type Variants } from 'motion/react'\n\nimport { Button } from '@/components/ui/button'\nimport { cn } from '@/lib/utils'\n\nexport interface Feature01Item {\n  id: string\n  title: string\n  description: string\n  media: {\n    src: string\n    alt: string\n  }\n}\n\nexport interface Feature01Props {\n  items: Feature01Item[]\n  variant?: 'standard' | 'compact' | 'prominent'\n  animation?: 'none' | 'subtle'\n}\n\nconst variantStyles = {\n  standard: {\n    container: 'py-12 sm:py-16',\n    grid: 'grid-cols-1 gap-10 md:grid-cols-2 md:items-center md:gap-14',\n    nav: 'gap-1',\n    button: 'py-2.5',\n    title: 'text-base',\n    titleSelected: 'font-medium',\n    desc: 'text-sm',\n    media: 'min-h-[320px] md:min-h-[420px]',\n    mediaRadius: 'rounded-lg',\n  },\n  compact: {\n    container: 'py-10 sm:py-12',\n    grid: 'grid-cols-1 gap-6 md:grid-cols-2 md:items-center md:gap-10',\n    nav: 'gap-0.5',\n    button: 'py-2',\n    title: 'text-sm md:text-base',\n    titleSelected: 'font-medium',\n    desc: 'text-xs',\n    media: 'min-h-[260px] md:min-h-[340px]',\n    mediaRadius: 'rounded-md',\n  },\n  prominent: {\n    container: 'py-14 sm:py-20',\n    grid: 'grid-cols-1 gap-12 md:grid-cols-2 md:items-center md:gap-16',\n    nav: 'gap-1.5',\n    button: 'py-3',\n    title: 'text-base md:text-lg',\n    titleSelected: 'font-semibold',\n    desc: 'text-sm md:text-base',\n    media: 'min-h-[380px] md:min-h-[480px]',\n    mediaRadius: 'rounded-xl',\n  },\n} as const\n\nconst container: Variants = {\n  hidden: {},\n  visible: { transition: { staggerChildren: 0.1, delayChildren: 0.05 } },\n}\n\nconst item: Variants = {\n  hidden: { opacity: 0, y: 12, filter: 'blur(6px)' },\n  visible: {\n    opacity: 1,\n    y: 0,\n    filter: 'blur(0px)',\n    transition: { duration: 0.5, ease: [0.22, 1, 0.36, 1] },\n  },\n}\n\nconst navList: Variants = {\n  hidden: {},\n  visible: { transition: { staggerChildren: 0.06, delayChildren: 0.04 } },\n}\n\nconst navItem: Variants = {\n  hidden: { opacity: 0, y: 12, filter: 'blur(8px)' },\n  visible: {\n    opacity: 1,\n    y: 0,\n    filter: 'blur(0px)',\n    transition: { duration: 0.55, ease: [0.22, 1, 0.36, 1] },\n  },\n}\n\nconst mediaEnter: Variants = {\n  hidden: { opacity: 0, scale: 0.96, filter: 'blur(8px)' },\n  visible: {\n    opacity: 1,\n    scale: 1,\n    filter: 'blur(0px)',\n    transition: { duration: 0.75, ease: [0.22, 1, 0.36, 1], delay: 0.08 },\n  },\n}\n\nconst viewport = {\n  once: true,\n  margin: '-80px' as const,\n}\n\nfunction Reveal({\n  active,\n  variants,\n  className,\n  children,\n}: Readonly<{\n  active: boolean\n  variants?: Variants\n  className?: string\n  children: React.ReactNode\n}>) {\n  if (!active) return <div className={className}>{children}</div>\n\n  return (\n    <motion.div variants={variants ?? item} className={className}>\n      {children}\n    </motion.div>\n  )\n}\n\nexport function Feature01({\n  items,\n  variant = 'standard',\n  animation = 'none',\n}: Readonly<Feature01Props>) {\n  const [selectedIndex, setSelectedIndex] = useState(0)\n  const reduce = useReducedMotion()\n  const animate = animation === 'subtle' && !reduce\n  const vs = variantStyles[variant]\n\n  if (!items.length) return null\n\n  const renderNavButton = (item: Feature01Item, index: number) => {\n    const isSelected = index === selectedIndex\n\n    return (\n      <Button\n        variant=\"ghost\"\n        type=\"button\"\n        onClick={() => setSelectedIndex(index)}\n        aria-current={isSelected ? 'true' : undefined}\n        className={cn(\n          'h-auto w-full justify-start rounded-sm text-left font-normal whitespace-normal',\n          vs.button,\n          'hover:bg-muted/50 hover:opacity-100',\n          isSelected && 'text-foreground bg-muted/50',\n          !isSelected && 'text-muted-foreground hover:text-foreground',\n        )}\n      >\n        <span className=\"flex flex-col gap-1\">\n          <span className={cn(vs.title, isSelected && vs.titleSelected)}>\n            {item.title}\n          </span>\n          <span\n            className={cn(\n              'grid transition-[grid-template-rows] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]',\n              isSelected ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n            )}\n          >\n            <span className=\"overflow-hidden\">\n              <span\n                className={cn(\n                  'text-muted-foreground block pb-0.5 transition-opacity duration-300 ease-[cubic-bezier(0.22,1,0.36,1)]',\n                  vs.desc,\n                  isSelected ? 'opacity-100' : 'opacity-0',\n                )}\n              >\n                {item.description}\n              </span>\n            </span>\n          </span>\n        </span>\n      </Button>\n    )\n  }\n\n  const mediaCrossfade = (\n    <div\n      className={cn(\n        'relative w-full overflow-hidden outline outline-black/10 dark:outline-white/10',\n        vs.media,\n        vs.mediaRadius,\n      )}\n    >\n      {items.map((item, index) => (\n        <div\n          key={item.id}\n          className={cn(\n            'absolute inset-0 transition-opacity duration-500 ease-[cubic-bezier(0.22,1,0.36,1)]',\n            index === selectedIndex ? 'opacity-100' : 'opacity-0',\n          )}\n        >\n          <img\n            src={item.media.src}\n            alt={item.media.alt || item.title}\n            loading={index === 0 ? 'eager' : 'lazy'}\n            decoding=\"async\"\n            fetchPriority={index === 0 ? 'high' : 'low'}\n            className=\"absolute inset-0 size-full object-cover\"\n          />\n        </div>\n      ))}\n    </div>\n  )\n\n  const gridElement = (\n    <div className={cn('grid grid-cols-1 md:grid-cols-2', vs.grid)}>\n      <nav\n        className={cn('flex flex-col justify-center', vs.nav)}\n        aria-label=\"List of items\"\n      >\n        {items.map((item, index) => (\n          <div key={item.id}>{renderNavButton(item, index)}</div>\n        ))}\n      </nav>\n      {mediaCrossfade}\n    </div>\n  )\n\n  const animatedGridElement = (\n    <div className={cn('grid grid-cols-1 md:grid-cols-2', vs.grid)}>\n      <Reveal active={animate} className=\"w-full self-center\">\n        <motion.nav\n          className={cn('flex flex-col justify-center', vs.nav)}\n          variants={navList}\n          aria-label=\"List of items\"\n        >\n          {items.map((item, index) => (\n            <motion.div key={item.id} variants={navItem}>\n              {renderNavButton(item, index)}\n            </motion.div>\n          ))}\n        </motion.nav>\n      </Reveal>\n      <Reveal\n        active={animate}\n        variants={mediaEnter}\n        className=\"relative min-w-0\"\n      >\n        {mediaCrossfade}\n      </Reveal>\n    </div>\n  )\n\n  if (animate) {\n    return (\n      <section className=\"w-full\">\n        <div\n          className={cn('mx-auto w-full max-w-6xl px-6', vs.container)}\n        >\n          <motion.div\n            variants={container}\n            initial=\"hidden\"\n            whileInView=\"visible\"\n            viewport={viewport}\n          >\n            {animatedGridElement}\n          </motion.div>\n        </div>\n      </section>\n    )\n  }\n\n  return (\n    <section className=\"w-full\">\n      <div className={cn('mx-auto w-full max-w-6xl px-6', vs.container)}>\n        {gridElement}\n      </div>\n    </section>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/flx/blocks/feature/feature-01/feature-01.tsx"
    },
    {
      "path": "registry/blocks/feature/feature-01/feature-01-example.tsx",
      "content": "import { Feature01, type Feature01Props } from './feature-01'\n\nexport const values = {\n  variant: 'standard',\n  animation: 'subtle',\n  items: [\n    {\n      id: '1',\n      title: 'Design',\n      description:\n        'Clean, accessible components that make your product feel modern and easy to use.',\n      media: {\n        src: 'https://images.unsplash.com/photo-1695152560286-b09a744834e1?q=80&w=1133&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',\n        alt: 'alt image',\n      },\n    },\n    {\n      id: '2',\n      title: 'Components',\n      description:\n        'Pre-built blocks you can drop into any layout. Customize once, reuse everywhere.',\n      media: {\n        src: 'https://images.unsplash.com/photo-1683143724745-d66cf5ea5ce7?q=80&w=1202&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',\n        alt: 'alt image',\n      },\n    },\n    {\n      id: '3',\n      title: 'Developer Experience',\n      description:\n        'Built with TypeScript, clear APIs, and documentation that gets you shipping faster.',\n      media: {\n        src: 'https://images.unsplash.com/photo-1577083862054-7324cd025fa6?q=80&w=1241&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',\n        alt: 'alt image',\n      },\n    },\n    {\n      id: '4',\n      title: 'Customization',\n      description:\n        'Themes, variants, and overrides. Make it look and behave exactly how you need.',\n      media: {\n        src: 'https://images.unsplash.com/photo-1683143726118-9abaed4e10f9?q=80&w=1062&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',\n        alt: 'alt image',\n      },\n    },\n    {\n      id: '5',\n      title: 'Performance',\n      description:\n        'Optimized for speed and accessibility. Less bundle size, smoother interactions.',\n      media: {\n        src: 'https://images.unsplash.com/photo-1734552452335-e8b67797bad0?q=80&w=1212&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',\n        alt: 'alt image',\n      },\n    },\n  ],\n} satisfies Feature01Props\n\nexport function Feature01Example() {\n  return (\n    <Feature01\n      items={values.items}\n      variant={values.variant}\n      animation={values.animation}\n    />\n  )\n}\n",
      "type": "registry:component",
      "target": "components/flx/blocks/feature/feature-01/feature-01-example.tsx"
    }
  ],
  "meta": {
    "iframeHeight": 700
  },
  "type": "registry:block"
}