{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "inline-table-control",
  "type": "registry:component",
  "title": "Inline Table Control",
  "description": "Inline controls for editing table rows without breaking user focus.",
  "dependencies": [
    "lucide-react",
    "motion",
    "react-icons"
  ],
  "files": [
    {
      "path": "components/watermelon/inline-table-control.tsx",
      "type": "registry:component",
      "content": "'use client';\n\nimport React, { useState } from 'react';\nimport { motion, AnimatePresence, LayoutGroup } from 'motion/react';\nimport { Pencil, X, Check } from 'lucide-react';\nimport { GoStack } from 'react-icons/go';\nimport { BsArrowUpRightSquare } from 'react-icons/bs';\nimport { FaRegCreditCard } from 'react-icons/fa6';\n\nexport interface TableItem {\n  id: string;\n  expense: string;\n  method: string;\n  amount: string;\n}\n\ninterface InlineTableControlProps {\n  data: TableItem[];\n  onUpdate?: (item: TableItem) => void;\n  className?: string;\n}\n\nconst getIcon = (field: string) => {\n  const iconClass = 'text-neutral-400 dark:text-neutral-500';\n  if (field === 'expense')\n    return <FaRegCreditCard size={18} className={iconClass} />;\n  if (field === 'method') return <GoStack size={18} className={iconClass} />;\n  if (field === 'amount')\n    return <BsArrowUpRightSquare size={18} className={iconClass} />;\n  return null;\n};\n\nexport const InlineTableControl: React.FC<InlineTableControlProps> = ({\n  data,\n  onUpdate,\n  className = '',\n}) => {\n  const [items, setItems] = useState<TableItem[]>(data);\n  const [previousData, setPreviousData] = useState(data);\n  const [editingId, setEditingId] = useState<string | null>(null);\n  const [editValues, setEditValues] = useState<TableItem | null>(null);\n\n  if (previousData !== data) {\n    setPreviousData(data);\n    setItems(data);\n  }\n\n  const handleDone = () => {\n    if (editValues) {\n      const updatedItems = items.map((item) =>\n        item.id === editValues.id ? editValues : item,\n      );\n      setItems(updatedItems);\n      onUpdate?.(editValues);\n      setEditingId(null);\n      setEditValues(null);\n    }\n  };\n\n  const layoutTransition = {\n    type: 'spring' as const,\n    bounce: 0,\n    duration: 0.7,\n  };\n\n  return (\n    <div\n      className={`flex w-full flex-col items-center justify-center p-4 antialiased select-none sm:p-10 ${className}`}\n    >\n      <div className=\"w-full max-w-lg\">\n        <motion.div\n          layout\n          transition={layoutTransition}\n          className={`hidden grid-cols-[1.2fr_1fr_0.8fr_40px] px-6 py-4 text-sm font-semibold tracking-wider capitalize transition-all duration-300 sm:grid ${editingId ? 'opacity-20 blur-[1px]' : 'opacity-100'} text-neutral-400 dark:text-neutral-500`}\n        >\n          <motion.div layout className=\"flex items-center gap-2\">\n            <FaRegCreditCard size={18} /> Expense\n          </motion.div>\n          <motion.div layout className=\"flex items-center gap-2\">\n            <GoStack size={18} /> Method\n          </motion.div>\n          <motion.div layout className=\"flex items-center gap-2\">\n            <BsArrowUpRightSquare size={18} /> Amount\n          </motion.div>\n        </motion.div>\n\n        <LayoutGroup>\n          <div className=\"flex flex-col gap-2 sm:gap-0\">\n            {items.map((item) => (\n              <div key={item.id} className=\"relative\">\n                {!editingId && (\n                  <motion.div\n                    layoutId={`divider-${item.id}`}\n                    className=\"mx-6 hidden h-px bg-neutral-100 sm:block dark:bg-neutral-800\"\n                  />\n                )}\n\n                <AnimatePresence mode=\"popLayout\">\n                  {editingId === item.id ? (\n                    <motion.div\n                      layoutId={`container-${item.id}`}\n                      transition={layoutTransition}\n                      className=\"relative z-20 my-2 rounded-2xl border-[1.4px] border-r-0 border-l-0 border-neutral-200 bg-white p-4 shadow-xl sm:my-4 sm:rounded-none sm:p-8 sm:py-4 sm:shadow-none dark:border-neutral-800 dark:bg-neutral-900\"\n                    >\n                      <motion.div className=\"space-y-4 sm:space-y-5\">\n                        {(['expense', 'method', 'amount'] as const).map(\n                          (field) => (\n                            <div\n                              key={field}\n                              className=\"flex flex-col gap-1 sm:grid sm:grid-cols-[120px_1fr] sm:items-center sm:gap-0\"\n                            >\n                              <motion.label\n                                initial={{ opacity: 0 }}\n                                animate={{ opacity: 1 }}\n                                transition={{ duration: 0.3, delay: 0.1 }}\n                                className=\"flex items-center gap-2 text-[11px] font-bold tracking-wider text-neutral-400 uppercase sm:text-sm sm:capitalize dark:text-neutral-500\"\n                              >\n                                {getIcon(field)} {field}\n                              </motion.label>\n                              <motion.div\n                                layout=\"position\"\n                                transition={layoutTransition}\n                                className=\"flex w-full items-center rounded-xl border-[1.6px] border-neutral-200 bg-neutral-50 px-4 py-2.5 focus-within:border-blue-500 sm:py-2 dark:border-neutral-700 dark:bg-neutral-800 dark:focus-within:border-neutral-400\"\n                              >\n                                <motion.input\n                                  layoutId={`${field}-${item.id}`}\n                                  layout=\"position\"\n                                  title=\"edit text\"\n                                  type=\"text\"\n                                  value={editValues ? editValues[field] : ''}\n                                  transition={layoutTransition}\n                                  onChange={(e) =>\n                                    setEditValues((prev) =>\n                                      prev\n                                        ? { ...prev, [field]: e.target.value }\n                                        : null,\n                                    )\n                                  }\n                                  className=\"relative z-999 w-full bg-transparent text-base font-bold text-neutral-900 outline-none sm:text-sm dark:text-white\"\n                                />\n                              </motion.div>\n                            </div>\n                          ),\n                        )}\n                      </motion.div>\n\n                      <div className=\"mt-6 flex flex-row justify-end gap-2 sm:mt-4\">\n                        <button\n                          onClick={() => {\n                            setEditingId(null);\n                            setEditValues(null);\n                          }}\n                          className=\"flex flex-1 items-center justify-center gap-2 rounded-xl bg-neutral-100 px-5 py-3 text-sm font-bold text-neutral-600 sm:flex-none sm:py-2 dark:bg-neutral-800 dark:text-neutral-400\"\n                        >\n                          <X size={18} /> <span>Cancel</span>\n                        </button>\n                        <button\n                          onClick={handleDone}\n                          className=\"flex flex-1 items-center justify-center gap-2 rounded-xl bg-neutral-900 px-5 py-3 text-sm font-bold text-white sm:flex-none sm:py-2 dark:bg-white dark:text-black\"\n                        >\n                          <Check size={18} /> <span>Done</span>\n                        </button>\n                      </div>\n                    </motion.div>\n                  ) : (\n                    <motion.div\n                      layout=\"position\"\n                      layoutId={`container-${item.id}`}\n                      transition={layoutTransition}\n                      animate={{\n                        opacity: editingId ? 0.35 : 1,\n                        filter: editingId ? 'blur(1px)' : 'blur(0px)',\n                      }}\n                      className={`group grid cursor-default grid-cols-[1fr_auto_40px] items-center rounded-2xl px-4 py-4 transition-all duration-300 sm:grid-cols-[1.2fr_1fr_0.8fr_40px] sm:rounded-none sm:px-6 sm:py-5 ${\n                        editingId\n                          ? ''\n                          : 'border border-neutral-100 bg-neutral-50/50 opacity-100 hover:bg-neutral-50 sm:border-none sm:bg-transparent dark:border-white/[0.03] dark:bg-zinc-900/40 dark:hover:bg-zinc-800/60'\n                      }`}\n                    >\n                      <motion.div className=\"flex flex-col\">\n                        <motion.div\n                          layoutId={`expense-${item.id}`}\n                          layout=\"position\"\n                          className=\"flex text-sm font-bold text-neutral-900 sm:text-base\"\n                        >\n                          <motion.span\n                            layout=\"position\"\n                            transition={layoutTransition}\n                            className=\"dark:text-zinc-100\"\n                          >\n                            {item.expense}\n                          </motion.span>\n                        </motion.div>\n                        <motion.div\n                          layoutId={`method-mobile-${item.id}`}\n                          layout=\"position\"\n                          className=\"flex text-xs font-medium text-neutral-500 sm:hidden\"\n                        >\n                          <motion.span\n                            layout=\"position\"\n                            transition={layoutTransition}\n                            className=\"dark:text-zinc-500\"\n                          >\n                            {item.method}\n                          </motion.span>\n                        </motion.div>\n                      </motion.div>\n\n                      <motion.div\n                        layoutId={`method-${item.id}`}\n                        layout=\"position\"\n                        className=\"hidden text-sm font-semibold text-neutral-500 sm:flex\"\n                      >\n                        <motion.span\n                          layout=\"position\"\n                          transition={layoutTransition}\n                          className=\"dark:text-zinc-500\"\n                        >\n                          {item.method}\n                        </motion.span>\n                      </motion.div>\n\n                      <motion.div\n                        layoutId={`amount-${item.id}`}\n                        layout=\"position\"\n                        className=\"flex justify-end text-sm font-bold text-neutral-700 sm:justify-start sm:text-base\"\n                      >\n                        <motion.span\n                          layout=\"position\"\n                          transition={layoutTransition}\n                          className=\"flex items-center dark:text-zinc-300\"\n                        >\n                          <span className=\"mr-0.5 text-neutral-400 dark:text-zinc-600\">\n                            $\n                          </span>\n                          {item.amount}\n                        </motion.span>\n                      </motion.div>\n\n                      <button\n                        title=\"edit\"\n                        onClick={() => {\n                          setEditValues({ ...item });\n                          setEditingId(item.id);\n                        }}\n                        className=\"flex justify-end text-neutral-400 transition-transform hover:text-black active:scale-125 dark:hover:text-white\"\n                      >\n                        <Pencil size={18} strokeWidth={2.5} />\n                      </button>\n                    </motion.div>\n                  )}\n                </AnimatePresence>\n              </div>\n            ))}\n          </div>\n        </LayoutGroup>\n      </div>\n    </div>\n  );\n};\n"
    }
  ]
}
