{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "keyboard",
  "title": "Keyboard UI",
  "description": "Sleek, minimalistic & interactive keyboard UI.",
  "files": [
    {
      "path": "packages/keyboard/keyboard.tsx",
      "content": "\"use client\";\r\n\r\nimport React, { useState, useEffect } from \"react\";\r\n\r\ninterface KeyboardUIProps {\r\n  keyAnimationToggle?: boolean;\r\n  animatedString?: string;\r\n}\r\n\r\nconst KeyboardUI = ({\r\n  keyAnimationToggle = false,\r\n  animatedString = \"SATORI UI\",\r\n}: KeyboardUIProps) => {\r\n  const [activeKey, setActiveKey] = useState<string | null>(null);\r\n\r\n  useEffect(() => {\r\n    if (!keyAnimationToggle || !animatedString) return;\r\n\r\n    let isMounted = true;\r\n    let currentIndex = 0;\r\n    let timeoutId: NodeJS.Timeout;\r\n\r\n    const typeNextChar = () => {\r\n      if (!isMounted) return;\r\n\r\n      if (currentIndex >= animatedString.length) {\r\n        currentIndex = 0;\r\n        timeoutId = setTimeout(typeNextChar, 2000); // 2 second pause before looping\r\n        return;\r\n      }\r\n\r\n      const char = animatedString[currentIndex].toUpperCase();\r\n      const mappedChar = char === \" \" ? \"SPACE\" : char;\r\n\r\n      setActiveKey(mappedChar);\r\n\r\n      setTimeout(() => {\r\n        if (isMounted) setActiveKey(null);\r\n      }, 100);\r\n\r\n      currentIndex++;\r\n      timeoutId = setTimeout(typeNextChar, 250); // Typing speed\r\n    };\r\n\r\n    timeoutId = setTimeout(typeNextChar, 1000); // Initial delay\r\n\r\n    return () => {\r\n      isMounted = false;\r\n      clearTimeout(timeoutId);\r\n    };\r\n  }, [keyAnimationToggle, animatedString]);\r\n\r\n  const getKeyClass = (keyTrigger: string, baseClass: string) => {\r\n    const isActive = activeKey === keyTrigger;\r\n    return `${baseClass} transition-all duration-100 ${\r\n      isActive \r\n        ? \"translate-y-[2px] scale-[0.98] brightness-90 shadow-none dark:brightness-125\" \r\n        : \"transform-none\"\r\n    }`;\r\n  };\r\n\r\n  return (\r\n    <div className=\"w-[800px] max-w-4xl mx-auto px-2 sm:px-4\">\r\n      <div className=\"w-full flex flex-col gap-1 sm:gap-2 md:gap-3 select-none\">\r\n        <div className=\"flex w-full gap-0.5 sm:gap-1 md:gap-2 h-8 sm:h-10 md:h-12\">\r\n          {[\r\n            \"`\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"0\", \"-\", \"=\",\r\n          ].map((k) => (\r\n            <div\r\n              key={k}\r\n              className={getKeyClass(k, \"flex-1 bg-white dark:bg-neutral-800 rounded sm:rounded-md md:rounded-lg shadow-sm dark:shadow-neutral-900/50 flex items-center justify-center text-neutral-900 dark:text-neutral-100 text-xs sm:text-sm md:text-xl font-normal hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors cursor-default min-w-0\")}\r\n            >\r\n              <span className=\"truncate\">{k}</span>\r\n            </div>\r\n          ))}\r\n          <div className={getKeyClass(\"DEL\", \"flex-[1.6] bg-neutral-200/80 dark:bg-neutral-700/80 rounded sm:rounded-md md:rounded-lg flex items-center justify-end pr-1 sm:pr-2 md:pr-4 text-neutral-900 dark:text-neutral-100 text-xs sm:text-sm md:text-lg font-normal hover:bg-neutral-300/80 dark:hover:bg-neutral-600/80 transition-colors cursor-default\")}>\r\n            <span className=\"truncate\">del</span>\r\n          </div>\r\n        </div>\r\n\r\n        <div className=\"flex w-full gap-0.5 sm:gap-1 md:gap-2 h-8 sm:h-10 md:h-12\">\r\n          <div className={getKeyClass(\"TAB\", \"flex-[1.6] bg-neutral-200/80 dark:bg-neutral-700/80 rounded sm:rounded-md md:rounded-lg flex items-center justify-start pl-1 sm:pl-2 md:pl-4 text-neutral-900 dark:text-neutral-100 text-xs sm:text-sm md:text-lg font-normal hover:bg-neutral-300/80 dark:hover:bg-neutral-600/80 transition-colors cursor-default\")}>\r\n            <span className=\"truncate\">tab</span>\r\n          </div>\r\n          {[\r\n            \"Q\", \"W\", \"E\", \"R\", \"T\", \"Y\", \"U\", \"I\", \"O\", \"P\", \"[\", \"]\", \"\\\\\",\r\n          ].map((k) => (\r\n            <div\r\n              key={k}\r\n              className={getKeyClass(k, \"flex-1 bg-white dark:bg-neutral-800 rounded sm:rounded-md md:rounded-lg shadow-sm dark:shadow-neutral-900/50 flex items-center justify-center text-neutral-900 dark:text-neutral-100 text-xs sm:text-sm md:text-xl font-normal hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors cursor-default min-w-0\")}\r\n            >\r\n              <span className=\"truncate\">{k}</span>\r\n            </div>\r\n          ))}\r\n        </div>\r\n\r\n        <div className=\"flex w-full gap-0.5 sm:gap-1 md:gap-2 h-8 sm:h-10 md:h-12\">\r\n          <div className={getKeyClass(\"CAPS\", \"flex-[1.9] bg-neutral-200/80 dark:bg-neutral-700/80 rounded sm:rounded-md md:rounded-lg flex items-center justify-start pl-1 sm:pl-2 md:pl-4 text-neutral-900 dark:text-neutral-100 text-xs sm:text-sm md:text-lg font-normal hover:bg-neutral-300/80 dark:hover:bg-neutral-600/80 transition-colors cursor-default\")}>\r\n            <span className=\"truncate\">caps</span>\r\n          </div>\r\n          {[\"A\", \"S\", \"D\", \"F\", \"G\", \"H\", \"J\", \"K\", \"L\", \";\", \"'\"].map((k) => (\r\n            <div\r\n              key={k}\r\n              className={getKeyClass(k, \"flex-1 bg-white dark:bg-neutral-800 rounded sm:rounded-md md:rounded-lg shadow-sm dark:shadow-neutral-900/50 flex items-center justify-center text-neutral-900 dark:text-neutral-100 text-xs sm:text-sm md:text-xl font-normal hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors cursor-default min-w-0\")}\r\n            >\r\n              <span className=\"truncate\">{k}</span>\r\n            </div>\r\n          ))}\r\n          <div className={getKeyClass(\"RETURN\", \"flex-[2.3] bg-[#348feb] dark:bg-[#1e5a8c] rounded sm:rounded-md md:rounded-lg flex items-end justify-end pr-1 sm:pr-2 md:pr-4 pb-1 sm:pb-2 md:pb-3 text-neutral-900 text-xs sm:text-sm md:text-lg font-normal relative hover:bg-[#2682de] dark:hover:bg-[#164466] transition-colors cursor-default\")}>\r\n            <div className=\"absolute top-1 right-1 w-1 h-1 sm:w-1.5 sm:h-1.5 bg-white rounded-full opacity-90\" />\r\n            <span className=\"truncate text-white dark:text-neutral-100\">\r\n              return\r\n            </span>\r\n          </div>\r\n        </div>\r\n\r\n        <div className=\"flex w-full gap-0.5 sm:gap-1 md:gap-2 h-8 sm:h-10 md:h-12\">\r\n          <div className={getKeyClass(\"SHIFT_L\", \"flex-[2.5] bg-neutral-200/80 dark:bg-neutral-700/80 rounded sm:rounded-md md:rounded-lg flex items-center justify-start pl-1 sm:pl-2 md:pl-4 text-neutral-900 dark:text-neutral-100 text-xs sm:text-sm md:text-lg font-normal hover:bg-neutral-300/80 dark:hover:bg-neutral-600/80 transition-colors cursor-default\")}>\r\n            <span className=\"truncate\">shift</span>\r\n          </div>\r\n          {[\"Z\", \"X\", \"C\", \"V\", \"B\", \"N\", \"M\", \",\", \".\", \"/\"].map((k) => (\r\n            <div\r\n              key={k}\r\n              className={getKeyClass(k, \"flex-1 bg-white dark:bg-neutral-800 rounded sm:rounded-md md:rounded-lg shadow-sm dark:shadow-neutral-900/50 flex items-center justify-center text-neutral-900 dark:text-neutral-100 text-xs sm:text-sm md:text-xl font-normal hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors cursor-default min-w-0\")}\r\n            >\r\n              <span className=\"truncate\">{k}</span>\r\n            </div>\r\n          ))}\r\n          <div className={getKeyClass(\"SHIFT_R\", \"flex-[2.5] bg-neutral-200/80 dark:bg-neutral-700/80 rounded sm:rounded-md md:rounded-lg flex items-center justify-end pr-1 sm:pr-2 md:pr-4 text-neutral-900 dark:text-neutral-100 text-xs sm:text-sm md:text-lg font-normal hover:bg-neutral-300/80 dark:hover:bg-neutral-600/80 transition-colors cursor-default\")}>\r\n            <span className=\"truncate\">shift</span>\r\n          </div>\r\n        </div>\r\n\r\n        <div className=\"flex w-full gap-0.5 sm:gap-1 md:gap-2 h-8 sm:h-10 md:h-12\">\r\n          {[\"ctrl\", \"opt\", \"hpOS\"].map((k) => (\r\n            <div\r\n              key={k}\r\n              className={getKeyClass(k.toUpperCase() + \"_L\", \"flex-[1.25] bg-neutral-200/80 dark:bg-neutral-700/80 rounded sm:rounded-md md:rounded-lg flex items-center justify-start pl-1 sm:pl-2 md:pl-4 pr-2 text-neutral-900 dark:text-neutral-100 text-xs sm:text-sm md:text-lg font-normal hover:bg-neutral-300/80 dark:hover:bg-neutral-600/80 transition-colors cursor-default\")}\r\n            >\r\n              <span className=\"truncate\">{k}</span>\r\n            </div>\r\n          ))}\r\n          <div className={getKeyClass(\"SPACE\", \"flex-[6.5] bg-white dark:bg-neutral-800 rounded sm:rounded-md md:rounded-lg shadow-sm dark:shadow-neutral-900/50 hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors cursor-default\")} />\r\n          {[\"hpOS\", \"opt\", \"ctrl\"].map((k) => (\r\n            <div\r\n              key={k}\r\n              className={getKeyClass(k.toUpperCase() + \"_R\", \"flex-[1.25] bg-neutral-200/80 dark:bg-neutral-700/80 rounded sm:rounded-md md:rounded-lg flex items-center justify-start pl-1 sm:pl-2 md:pl-4 pr-2 text-neutral-900 dark:text-neutral-100 text-xs sm:text-sm md:text-lg font-normal hover:bg-neutral-300/80 dark:hover:bg-neutral-600/80 transition-colors cursor-default\")}\r\n            >\r\n              <span className=\"truncate\">{k}</span>\r\n            </div>\r\n          ))}\r\n        </div>\r\n      </div>\r\n    </div>\r\n  );\r\n};\r\n\r\nexport default KeyboardUI;\r\n",
      "type": "registry:component",
      "target": "components/satori-ui/keyboard.tsx"
    }
  ],
  "type": "registry:component"
}