{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "filter-disclosure",
  "type": "registry:component",
  "title": "Filter Disclosure",
  "description": "A smooth expanding filter component with active state indicators.",
  "dependencies": [
    "motion",
    "react-icons"
  ],
  "files": [
    {
      "path": "components/watermelon/filter-disclosure.tsx",
      "type": "registry:component",
      "content": "'use client';\n\nimport { useState, type FC } from 'react';\nimport {\n  motion,\n  AnimatePresence,\n  MotionConfig,\n} from 'motion/react';\nimport { FaBell, FaTasks } from 'react-icons/fa';\nimport { IoCalendar } from 'react-icons/io5';\nimport { BsCheckLg, BsFillPeopleFill, BsPinFill } from 'react-icons/bs';\nimport { RiBubbleChartFill } from 'react-icons/ri';\nimport { PiFunnelSimpleBold } from 'react-icons/pi';\nimport type { IconType } from 'react-icons';\n\nexport interface FilterItem {\n  id: string;\n  label: string;\n  icon: IconType;\n}\n\ninterface FilterDisclosureProps {\n  items?: FilterItem[];\n  defaultActiveId?: string;\n  onChange?: (id: string) => void;\n}\n\nconst SPRING = {\n  type: 'spring',\n  stiffness: 240,\n  damping: 20,\n  mass: 1,\n} as const;\n\nconst DEFAULT_ITEMS: FilterItem[] = [\n  { id: 'tasks', label: 'Tasks', icon: FaTasks },\n  { id: 'events', label: 'Events', icon: IoCalendar },\n  { id: 'reminders', label: 'Reminders', icon: FaBell },\n  { id: 'appointments', label: 'Appointment', icon: BsPinFill },\n  { id: 'meetings', label: 'Mettings', icon: BsFillPeopleFill },\n  { id: 'celebrations', label: 'Celebrations', icon: RiBubbleChartFill },\n];\n\nexport const FilterDisclosure: FC<FilterDisclosureProps> = ({\n  items = DEFAULT_ITEMS,\n  defaultActiveId = 'reminders',\n  onChange,\n}) => {\n  const [open, setOpen] = useState(false);\n  const [active, setActive] = useState(defaultActiveId);\n\n  const activeItem = items.find((i) => i.id === active);\n  const ActiveIcon = activeItem ? activeItem.icon : FaTasks;\n\n  const handleSelect = (id: string) => {\n    setActive(id);\n    onChange?.(id);\n    setTimeout(() => setOpen(false), 220);\n  };\n\n  return (\n    <div className=\"flex h-[70px] w-[300px] items-center justify-center\">\n      <MotionConfig\n        transition={{\n          type: 'spring',\n          bounce: 0.25,\n          duration: 0.7,\n        }}\n      >\n        <AnimatePresence mode=\"popLayout\" initial={false}>\n          {open ? (\n            <motion.div\n              key=\"open\"\n              layoutId=\"filter-disclosure\"\n              initial={{ opacity: 0 }}\n              animate={{ opacity: 1 }}\n              exit={{\n                opacity: 0,\n                transition: { duration: 0 },\n              }}\n              style={{ transformOrigin: '50% 100%', borderRadius: 32 }}\n              className=\"absolute z-20 flex w-[300px] flex-col gap-[4px] overflow-hidden rounded-2xl border-[1.6px] border-[#E5E5E9] bg-[#FEFEFE] p-[8px] shadow-[0_12px_40px_rgba(0,0,0,0.08)] will-change-transform dark:border-neutral-800 dark:bg-neutral-900 dark:shadow-[0_20px_50px_rgba(0,0,0,0.5)]\"\n            >\n              {items.map((item, index) => {\n                const Icon = item.icon;\n                const selected = active === item.id;\n\n                return (\n                  <motion.button\n                    key={item.id}\n                    initial={{ opacity: 0, scale: 1.1, y: 40 }}\n                    animate={{ opacity: 1, scale: 1, y: 0 }}\n                    onClick={() => handleSelect(item.id)}\n                    whileTap={{ scale: 0.98 }}\n                    transition={{ ...SPRING, delay: (3 + index) * 0.05 }}\n                    className=\"flex w-full cursor-pointer items-center justify-between rounded-[16px] px-[12px] py-[10px] transition-colors hover:bg-[#F6F5FA] dark:hover:bg-neutral-800/60\"\n                  >\n                    <div className=\"flex items-center gap-[28px]\">\n                      <Icon className=\"h-[24px] w-[24px] text-[#AFAEB9] dark:text-neutral-500\" />\n                      <span className=\"text-[18px] font-bold tracking-tight text-[#535257] dark:text-neutral-200\">\n                        {item.label}\n                      </span>\n                    </div>\n\n                    <motion.div\n                      animate={{\n                        backgroundColor: selected ? '#31C051' : 'rgba(0,0,0,0)',\n                      }}\n                      className={`flex h-[26px] w-[26px] shrink-0 items-center justify-center rounded-full border-[3px] ${selected ? 'border-[#31C051]' : 'border-[#ADADB2] dark:border-neutral-700'} `}\n                    >\n                      <motion.div\n                        animate={{\n                          scale: selected ? 1 : 0,\n                          opacity: selected ? 1 : 0,\n                        }}\n                        transition={{\n                          type: 'spring',\n                          stiffness: 520,\n                          damping: 30,\n                        }}\n                      >\n                        <BsCheckLg className=\"h-[16px] w-[16px] text-white\" />\n                      </motion.div>\n                    </motion.div>\n                  </motion.button>\n                );\n              })}\n            </motion.div>\n          ) : (\n            <div key=\"close\" className=\"flex items-center\">\n              <motion.button\n                layoutId=\"filter-disclosure\"\n                initial={{ opacity: 0 }}\n                animate={{ opacity: 1 }}\n                exit={{\n                  opacity: 0,\n                  transition: { duration: 0 },\n                }}\n                onClick={() => setOpen(true)}\n                whileHover={{ scale: 1.05 }}\n                whileTap={{ scale: 0.95 }}\n                style={{\n                  borderRadius: 32,\n                }}\n                className=\"z-30 flex h-[60px] w-[60px] cursor-pointer items-center justify-center rounded-full border-[1.6px] border-[#E5E5E9] bg-[#FEFEFE] shadow-xs will-change-transform dark:border-neutral-800 dark:bg-neutral-900\"\n              >\n                <PiFunnelSimpleBold className=\"h-[30px] w-[30px] text-[#272729] dark:text-neutral-100\" />\n              </motion.button>\n\n              <motion.div\n                initial={{ x: -30 }}\n                animate={{ x: 0 }}\n                transition={{\n                  type: 'spring',\n                  bounce: 0,\n                  duration: 1.2,\n                }}\n                className=\"z-10 -ml-[12px] flex h-[60px] w-[60px] items-center justify-center rounded-full border-[1.6px] border-[#E5E5E9] bg-[#FEFEFE] opacity-80 shadow-xs dark:border-neutral-800 dark:bg-neutral-900\"\n              >\n                <AnimatePresence mode=\"popLayout\" initial={false}>\n                  <motion.div\n                    key={active}\n                    initial={{ opacity: 0, scale: 0.6 }}\n                    animate={{ opacity: 1, scale: 1 }}\n                    exit={{ opacity: 0, scale: 0.6 }}\n                  >\n                    <ActiveIcon className=\"h-[24px] w-[24px] text-[#AFAEB9] dark:text-neutral-500\" />\n                  </motion.div>\n                </AnimatePresence>\n              </motion.div>\n            </div>\n          )}\n        </AnimatePresence>\n      </MotionConfig>\n    </div>\n  );\n};\n"
    }
  ]
}
