{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "frequency-selector",
  "type": "registry:component",
  "title": "Frequency Selector",
  "description": "Select recurring time intervals using animated tabs and contextual sub options.",
  "dependencies": [
    "lucide-react",
    "motion"
  ],
  "files": [
    {
      "path": "components/watermelon/frequency-selector.tsx",
      "type": "registry:component",
      "content": "'use client';\n\nimport React, { useState } from 'react';\nimport { motion, AnimatePresence, LayoutGroup } from 'motion/react';\nimport { Check, ChevronRight } from 'lucide-react';\n\n/* ---------- Types ---------- */\nexport type FrequencyType = 'Daily' | 'Weekly' | 'Monthly' | 'Yearly';\n\nexport interface FrequencyData {\n  type: FrequencyType;\n  subValue?: string;\n}\n\ninterface FrequencySelectorProps {\n  value: FrequencyData;\n  onChange: (data: FrequencyData) => void;\n  className?: string;\n}\n\n/* ---------- Motion Config ---------- */\nconst smoothSpring = {\n  type: 'spring',\n  bounce: 0.3,\n  duration: 0.7,\n} as const;\n\n/* ---------- Data ---------- */\nconst FREQUENCIES: FrequencyType[] = ['Daily', 'Weekly', 'Monthly', 'Yearly'];\n\nconst SUB_OPTIONS: Record<FrequencyType, string[]> = {\n  Daily: [],\n  Weekly: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],\n  Monthly: Array.from({ length: 31 }, (_, i) => (i + 1).toString()),\n  Yearly: [\n    'Jan',\n    'Feb',\n    'Mar',\n    'Apr',\n    'May',\n    'Jun',\n    'Jul',\n    'Aug',\n    'Sep',\n    'Oct',\n    'Nov',\n    'Dec',\n  ],\n};\n\nexport const FrequencySelector: React.FC<FrequencySelectorProps> = ({\n  value,\n  onChange,\n  className = '',\n}) => {\n  const [isOpen, setIsOpen] = useState(false);\n  const [tempType, setTempType] = useState<FrequencyType>(value.type);\n  const [tempSubValue, setTempSubValue] = useState<string | undefined>(\n    value.subValue,\n  );\n\n  const handleOpen = () => {\n    setTempType(value.type);\n    setTempSubValue(value.subValue || SUB_OPTIONS[value.type][0]);\n    setIsOpen(true);\n  };\n\n  const handleConfirm = () => {\n    onChange({\n      type: tempType,\n      subValue: tempType === 'Daily' ? undefined : tempSubValue,\n    });\n    setIsOpen(false);\n  };\n\n  return (\n    <LayoutGroup id=\"frequency-root\">\n      <div\n        className={`flex w-full items-center justify-center p-4 antialiased select-none ${className}`}\n      >\n        <AnimatePresence mode=\"wait\">\n          {!isOpen ? (\n            /* ---------- CLOSED STATE ---------- */\n            <motion.div\n              layoutId=\"container\"\n              initial={{ filter: 'blur(4px)', opacity: 0 }}\n              animate={{ filter: 'blur(0px)', opacity: 1 }}\n              exit={{ filter: 'blur(4px)', opacity: 0 }}\n              onClick={handleOpen}\n              transition={smoothSpring}\n              className=\"flex min-h-14 w-full max-w-md cursor-pointer items-center justify-between rounded-full bg-neutral-100 p-1 pl-4 sm:pl-6  gap-4 dark:bg-neutral-900\"\n            >\n              <motion.span\n                layout\n                className=\"text-base font-bold text-neutral-500 sm:text-lg dark:text-neutral-400\"\n              >\n                Frequency\n              </motion.span>\n\n              <motion.div\n                layoutId=\"trigger-pill\"\n                transition={smoothSpring}\n                className=\"flex min-h-12 flex-1 items-center justify-between gap-2 rounded-full border border-black/5 bg-white px-3 py-1.5 shadow-sm sm:flex-initial sm:gap-3 sm:px-4 dark:border-white/5 dark:bg-neutral-800\"\n              >\n                <span className=\"text-base font-bold sm:text-lg\">\n                  {value.type}\n                  {value.subValue ? `, ${value.subValue}` : ''}\n                </span>\n\n                <ChevronRight size={18} className=\"shrink-0 text-neutral-400\" />\n              </motion.div>\n            </motion.div>\n          ) : (\n            /* ---------- OPEN STATE ---------- */\n            <motion.div\n              layoutId=\"container\"\n              initial={{ filter: 'blur(4px)', opacity: 0 }}\n              animate={{ filter: 'blur(0px)', opacity: 1 }}\n              exit={{ filter: 'blur(4px)', opacity: 0 }}\n              transition={smoothSpring}\n              className=\"flex w-full max-w-lg flex-col gap-3 rounded-[32px] border border-black/5 bg-neutral-100 p-2 shadow-xl dark:border-white/5 dark:bg-neutral-900\"\n            >\n              {/* Top Row */}\n              <div className=\"flex items-center gap-2\">\n                <motion.div\n                  layoutId=\"trigger-pill\"\n                  transition={smoothSpring}\n                  className=\"custom-scrollbar relative flex h-11 flex-1 items-center gap-2 overflow-x-auto rounded-full bg-white p-1 shadow-inner sm:h-13 sm:gap-2 dark:bg-neutral-800\"\n                >\n                  {FREQUENCIES.map((type) => (\n                    <button\n                      key={type}\n                      onClick={() => {\n                        setTempType(type);\n                        setTempSubValue(SUB_OPTIONS[type][0]);\n                      }}\n                      className=\"relative flex h-full flex-none items-center justify-center px-4 text-xs font-bold sm:flex-1 sm:min-w-fit sm:px-6 sm:text-[15px]\"\n                    >\n                      {tempType === type && (\n                        <motion.div\n                          layoutId=\"active-tab\"\n                          transition={smoothSpring}\n                          className=\"absolute inset-0 z-0 rounded-full bg-neutral-200 dark:bg-neutral-700\"\n                        />\n                      )}\n\n                      <span className=\"relative z-10\">{type}</span>\n                    </button>\n                  ))}\n                </motion.div>\n\n                <motion.button\n                  whileTap={{ scale: 0.9 }}\n                  onClick={handleConfirm}\n                  className=\"flex h-10 w-10 items-center justify-center rounded-full bg-neutral-900 text-white sm:h-12 sm:w-12 dark:bg-white dark:text-neutral-900\"\n                >\n                  <Check size={18} />\n                </motion.button>\n              </div>\n\n              {/* Sub Options */}\n              <AnimatePresence mode=\"wait\">\n                {SUB_OPTIONS[tempType].length > 0 && (\n                  <motion.div\n                    layout\n                    transition={smoothSpring}\n                    className=\"overflow-hidden\"\n                  >\n                    {SUB_OPTIONS[tempType].length > 0 && (\n                      <motion.div\n                        key={tempType}\n                        layout\n                        transition={smoothSpring}\n                        className={`grid gap-2 rounded-2xl bg-white p-3 shadow-inner dark:bg-neutral-800 ${\n                          tempType === 'Monthly'\n                            ? 'grid-cols-7'\n                            : tempType === 'Yearly'\n                              ? 'grid-cols-4'\n                              : 'grid-cols-7'\n                        }`}\n                      >\n                        {SUB_OPTIONS[tempType].map((option) => (\n                          <button\n                            key={option}\n                            onClick={() => setTempSubValue(option)}\n                            className=\"relative flex h-8 items-center justify-center rounded-full text-[10px] font-bold sm:h-9 sm:text-sm\"\n                          >\n                            {tempSubValue === option && (\n                              <motion.div\n                                layoutId=\"active-sub\"\n                                transition={smoothSpring}\n                                className=\"absolute inset-0 z-0 rounded-full bg-neutral-200 dark:bg-neutral-700\"\n                              />\n                            )}\n\n                            <span className=\"relative z-10\">{option}</span>\n                          </button>\n                        ))}\n                      </motion.div>\n                    )}\n                  </motion.div>\n                )}\n              </AnimatePresence>\n            </motion.div>\n          )}\n        </AnimatePresence>\n      </div>\n    </LayoutGroup>\n  );\n};\n"
    }
  ]
}
