{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "time-undo-action",
  "type": "registry:component",
  "title": "Timed Undo Action",
  "description": "An animated timed undo button that provides a visual countdown before an action is finalized.",
  "dependencies": [
    "lucide-react",
    "motion",
    "react-use-measure"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "components/watermelon/time-undo-action.tsx",
      "type": "registry:component",
      "content": "'use client';\n\nimport { cn } from '@/lib/utils';\nimport { Undo2 } from 'lucide-react';\nimport { useEffect, useState, type FC, type ReactNode } from 'react';\nimport { AnimatePresence, motion, MotionConfig } from 'motion/react';\nimport useMeasure from 'react-use-measure';\n\nexport interface TimedUndoActionProps {\n  initialSeconds?: number;\n  deleteLabel?: string;\n  undoLabel?: string;\n  icon?: ReactNode;\n}\n\nexport const TimedUndoAction: FC<TimedUndoActionProps> = ({\n  initialSeconds = 10,\n  deleteLabel = 'Delete Account',\n  undoLabel = 'Cancel Delete',\n  icon,\n}) => {\n  const [isDeleting, setIsDeleting] = useState(false);\n  const [countDown, setCountDown] = useState(initialSeconds);\n  const [ref, bounds] = useMeasure({ offsetSize: true });\n\n  const handleDelete = () => {\n    setIsDeleting((prev) => {\n      const next = !prev;\n\n      if (next) {\n        setCountDown(initialSeconds);\n      }\n\n      return next;\n    });\n  };\n\n  useEffect(() => {\n    if (!isDeleting) return;\n\n    const interval = setInterval(() => {\n      setCountDown((prev) => {\n        if (prev < 1) {\n          setIsDeleting(false);\n          return initialSeconds;\n        }\n        return prev - 1;\n      });\n    }, 1000);\n\n    return () => {\n      clearInterval(interval);\n    };\n  }, [isDeleting, initialSeconds]);\n\n  return (\n    <div className=\"flex w-full items-center justify-center font-sans\">\n      <div className=\"flex flex-col items-center justify-center will-change-transform\">\n        <MotionConfig\n          transition={{\n            type: 'spring',\n            stiffness: 250,\n            damping: 22,\n          }}\n        >\n          <motion.div\n            className={cn(\n              'relative flex cursor-pointer items-center justify-start overflow-hidden rounded-full bg-red-500 transition-colors duration-300 dark:bg-red-500',\n              isDeleting && 'bg-red-500/10 dark:bg-red-500/20',\n            )}\n            animate={{\n              width: bounds.width > 0 ? bounds.width : 'auto',\n            }}\n            onClick={handleDelete}\n          >\n            <div\n              className={cn(\n                'flex items-center justify-center gap-2 px-6 py-3',\n                isDeleting && 'px-3',\n              )}\n              ref={ref}\n            >\n              <AnimatePresence mode=\"popLayout\">\n                {isDeleting && (\n                  <motion.div\n                    className=\"rounded-full bg-red-500 p-2\"\n                    initial={{\n                      opacity: 0,\n                      filter: 'blur(2px)',\n                    }}\n                    animate={{\n                      opacity: 1,\n                      filter: 'blur(0px)',\n                    }}\n                    exit={{\n                      opacity: 0,\n                      filter: 'blur(2px)',\n                    }}\n                  >\n                    {icon ?? <Undo2 className=\"size-5 text-white\" />}\n                  </motion.div>\n                )}\n              </AnimatePresence>\n\n              <div className=\"flex items-center justify-center gap-2\">\n                <AnimatedText\n                  text={isDeleting ? undoLabel : deleteLabel}\n                  className={cn(\n                    'z-10 text-lg',\n                    isDeleting ? 'text-red-400' : 'text-neutral-50',\n                  )}\n                />\n              </div>\n\n              <AnimatePresence mode=\"popLayout\">\n                {isDeleting && (\n                  <motion.div\n                    className=\"flex items-center justify-center rounded-full bg-red-500 px-3 py-1 text-neutral-50 tabular-nums\"\n                    initial={{\n                      opacity: 0,\n                      filter: 'blur(2px)',\n                    }}\n                    animate={{\n                      opacity: 1,\n                      filter: 'blur(0px)',\n                    }}\n                    exit={{\n                      opacity: 0,\n                      filter: 'blur(2px)',\n                    }}\n                  >\n                    <AnimatePresence mode=\"popLayout\">\n                      <motion.span\n                        key={countDown}\n                        className=\"text-lg\"\n                        initial={{\n                          opacity: 0,\n                          y: -20,\n                          filter: 'blur(2px)',\n                          scale: 0.5,\n                        }}\n                        animate={{\n                          opacity: 1,\n                          y: 0,\n                          filter: 'blur(0px)',\n                          scale: 1,\n                        }}\n                        exit={{\n                          opacity: 0,\n                          y: 20,\n                          filter: 'blur(2px)',\n                          scale: 0.5,\n                        }}\n                        transition={{\n                          type: 'spring',\n                          stiffness: 240,\n                          damping: 20,\n                          mass: 1,\n                        }}\n                      >\n                        {countDown}\n                      </motion.span>\n                    </AnimatePresence>\n                  </motion.div>\n                )}\n              </AnimatePresence>\n            </div>\n          </motion.div>\n        </MotionConfig>\n      </div>\n    </div>\n  );\n};\n\nfunction AnimatedText({\n  text,\n  className,\n  delayStep = 0.014,\n}: {\n  text: string;\n  className?: string;\n  delayStep?: number;\n}) {\n  const chars = text.split('');\n\n  return (\n    <span className={className} style={{ display: 'inline-flex' }}>\n      <AnimatePresence mode=\"popLayout\" initial={false}>\n        <motion.span\n          key={text}\n          style={{ display: 'inline-flex ', willChange: 'transform' }}\n        >\n          {chars.map((char, i) => (\n            <motion.span\n              key={i}\n              initial={{\n                y: 10,\n                opacity: 0,\n                scale: 0.5,\n                filter: 'blur(2px)',\n              }}\n              animate={{\n                y: 0,\n                opacity: 1,\n                scale: 1,\n                filter: 'blur(0px)',\n              }}\n              exit={{\n                y: -10,\n                opacity: 0,\n                scale: 0.5,\n                filter: 'blur(2px)',\n              }}\n              transition={{\n                type: 'spring',\n                stiffness: 240,\n                damping: 16,\n                mass: 1.2,\n                delay: i * delayStep,\n              }}\n              style={{\n                display: 'inline-block',\n                whiteSpace: char === ' ' ? 'pre' : undefined,\n              }}\n            >\n              {char}\n            </motion.span>\n          ))}\n        </motion.span>\n      </AnimatePresence>\n    </span>\n  );\n}\n\nexport default TimedUndoAction;\n"
    }
  ]
}
