{
  "$schema": "https://ui.shadcn.com/schema/registry.json",
  "name": "blocks",
  "homepage": "https://blocks.so",
  "items": [
    {
      "name": "ai-01",
      "type": "registry:block",
      "title": "AI Chat with Voice Input",
      "description": "A ai chat with voice input block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "dropdown-menu",
        "textarea"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/ai/ai-01.tsx",
          "type": "registry:component",
          "target": "components/ai-01.tsx",
          "content": "'use client';\n\nimport {\n  IconMicrophone,\n  IconPaperclip,\n  IconPlus,\n  IconSearch,\n  IconSend,\n  IconSparkles,\n  IconWaveSine,\n} from '@tabler/icons-react';\nimport type React from 'react';\nimport { useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Textarea } from '@/components/ui/textarea';\nimport { cn } from '@/lib/utils';\n\nexport default function Ai01() {\n  const [message, setMessage] = useState('');\n  const [isExpanded, setIsExpanded] = useState(false);\n  const textareaRef = useRef<HTMLTextAreaElement>(null);\n  const fileInputRef = useRef<HTMLInputElement>(null);\n\n  const handleSubmit = (e: React.FormEvent) => {\n    e.preventDefault();\n\n    if (message.trim()) {\n      setMessage('');\n      setIsExpanded(false);\n\n      if (textareaRef.current) {\n        textareaRef.current.style.height = 'auto';\n      }\n    }\n  };\n\n  const handleTextareaChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n    setMessage(e.target.value);\n\n    if (textareaRef.current) {\n      textareaRef.current.style.height = 'auto';\n      textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;\n    }\n\n    setIsExpanded(e.target.value.length > 100 || e.target.value.includes('\\n'));\n  };\n\n  const handleKeyDown = (e: React.KeyboardEvent) => {\n    if (e.key === 'Enter' && !e.shiftKey) {\n      e.preventDefault();\n      handleSubmit(e as any);\n    }\n  };\n\n  return (\n    <div className=\"w-full\">\n      <h1 className=\"mx-auto mb-8 max-w-2xl whitespace-pre-wrap text-balance text-pretty px-1 text-center font-semibold text-2xl text-foreground leading-9\">\n        How can I help you today?\n      </h1>\n\n      <form className=\"group/composer w-full\" onSubmit={handleSubmit}>\n        <input\n          className=\"sr-only\"\n          multiple\n          onChange={(e) => {}}\n          ref={fileInputRef}\n          type=\"file\"\n        />\n\n        <div\n          className={cn(\n            'mx-auto w-full max-w-2xl cursor-text overflow-clip border border-border bg-transparent bg-clip-padding p-2.5 shadow-lg transition-[border-radius] duration-200 ease-out dark:bg-muted/50',\n            isExpanded\n              ? \"grid rounded-3xl [grid-template-areas:'header'_'primary'_'footer'] [grid-template-columns:1fr] [grid-template-rows:auto_1fr_auto]\"\n              : \"grid rounded-3xl [grid-template-areas:'header_header_header'_'leading_primary_trailing'_'._footer_.'] [grid-template-columns:auto_1fr_auto] [grid-template-rows:auto_1fr_auto]\"\n          )}\n        >\n          <div\n            className={cn(\n              'flex min-h-14 items-center overflow-x-hidden px-1.5',\n              {\n                'mb-0 px-2 py-1': isExpanded,\n                '-my-2.5': !isExpanded,\n              }\n            )}\n            style={{ gridArea: 'primary' }}\n          >\n            <div className=\"max-h-52 flex-1 overflow-auto\">\n              <Textarea\n                className=\"scrollbar-thin min-h-0 resize-none rounded-none border-0 p-0 text-base placeholder:text-muted-foreground focus-visible:ring-0 focus-visible:ring-offset-0 dark:bg-transparent\"\n                onChange={handleTextareaChange}\n                onKeyDown={handleKeyDown}\n                placeholder=\"Ask anything\"\n                ref={textareaRef}\n                rows={1}\n                value={message}\n              />\n            </div>\n          </div>\n\n          <div\n            className={cn('flex', { hidden: isExpanded })}\n            style={{ gridArea: 'leading' }}\n          >\n            <DropdownMenu>\n              <DropdownMenuTrigger\n                render={\n                  <Button\n                    aria-label=\"Add attachments\"\n                    className=\"rounded-full outline-none ring-0 hover:bg-accent\"\n                    size=\"icon\"\n                    type=\"button\"\n                    variant=\"ghost\"\n                  />\n                }\n              >\n                <IconPlus className=\"size-6 text-muted-foreground\" />\n              </DropdownMenuTrigger>\n\n              <DropdownMenuContent\n                align=\"start\"\n                className=\"max-w-xs rounded-2xl p-1.5\"\n              >\n                <DropdownMenuGroup className=\"space-y-1\">\n                  <DropdownMenuItem\n                    className=\"rounded-md\"\n                    onClick={() => fileInputRef.current?.click()}\n                  >\n                    <IconPaperclip className=\"opacity-60\" size={20} />\n                    Add photos & files\n                  </DropdownMenuItem>\n                  <DropdownMenuItem className=\"rounded-md\" onClick={() => {}}>\n                    <div className=\"flex items-center gap-2\">\n                      <IconSparkles className=\"opacity-60\" size={20} />\n                      Agent mode\n                    </div>\n                  </DropdownMenuItem>\n                  <DropdownMenuItem className=\"rounded-md\" onClick={() => {}}>\n                    <IconSearch className=\"opacity-60\" size={20} />\n                    Deep Research\n                  </DropdownMenuItem>\n                </DropdownMenuGroup>\n              </DropdownMenuContent>\n            </DropdownMenu>\n          </div>\n\n          <div\n            className=\"flex items-center gap-2\"\n            style={{ gridArea: isExpanded ? 'footer' : 'trailing' }}\n          >\n            <div className=\"ms-auto flex items-center gap-1.5\">\n              <Button\n                aria-label=\"Record audio message\"\n                className=\"rounded-full hover:bg-accent\"\n                size=\"icon\"\n                type=\"button\"\n                variant=\"ghost\"\n              >\n                <IconMicrophone className=\"size-5 text-muted-foreground\" />\n              </Button>\n\n              <Button\n                aria-label=\"Audio visualization\"\n                className=\"relative h-9 w-9 rounded-full hover:bg-accent\"\n                size=\"icon\"\n                type=\"button\"\n                variant=\"ghost\"\n              >\n                <IconWaveSine className=\"size-5 text-muted-foreground\" />\n              </Button>\n\n              {message.trim() && (\n                <Button\n                  aria-label=\"Send message\"\n                  className=\"rounded-full\"\n                  size=\"icon\"\n                  type=\"submit\"\n                >\n                  <IconSend className=\"size-5\" />\n                </Button>\n              )}\n            </div>\n          </div>\n        </div>\n      </form>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "ai"
      ]
    },
    {
      "name": "ai-02",
      "type": "registry:block",
      "title": "AI Chat with Model Selection",
      "description": "A ai chat with model selection block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "select",
        "textarea"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/ai/ai-02.tsx",
          "type": "registry:component",
          "target": "components/ai-02.tsx",
          "content": "'use client';\n\nimport {\n  IconAlertTriangle,\n  IconArrowUp,\n  IconCloud,\n  IconFileSpark,\n  IconGauge,\n  IconPhotoScan,\n} from '@tabler/icons-react';\nimport { useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport { Textarea } from '@/components/ui/textarea';\nimport { cn } from '@/lib/utils';\n\nconst PROMPTS = [\n  {\n    icon: IconFileSpark,\n    text: 'Write documentation',\n    prompt:\n      'Write comprehensive documentation for this codebase, including setup instructions, API references, and usage examples.',\n  },\n  {\n    icon: IconGauge,\n    text: 'Optimize performance',\n    prompt:\n      'Analyze the codebase for performance bottlenecks and suggest optimizations to improve loading times and runtime efficiency.',\n  },\n  {\n    icon: IconAlertTriangle,\n    text: 'Find and fix 3 bugs',\n    prompt:\n      'Scan through the codebase to identify and fix 3 critical bugs, providing detailed explanations for each fix.',\n  },\n];\n\nconst MODELS = [\n  {\n    value: 'gpt-5',\n    name: 'GPT-5',\n    description: 'Most advanced model',\n    max: true,\n  },\n  {\n    value: 'gpt-4o',\n    name: 'GPT-4o',\n    description: 'Fast and capable',\n  },\n  {\n    value: 'gpt-4',\n    name: 'GPT-4',\n    description: 'Reliable and accurate',\n  },\n  {\n    value: 'claude-3.5',\n    name: 'Claude 3.5 Sonnet',\n    description: 'Great for coding tasks',\n  },\n];\n\nexport default function Ai02() {\n  const [inputValue, setInputValue] = useState('');\n  const [selectedModel, setSelectedModel] = useState(MODELS[0]);\n  const inputRef = useRef<HTMLTextAreaElement>(null);\n\n  const handlePromptClick = (prompt: string) => {\n    if (inputRef.current) {\n      inputRef.current.value = prompt;\n      setInputValue(prompt);\n      inputRef.current.focus();\n    }\n  };\n\n  const handleModelChange = (value: string) => {\n    const model = MODELS.find((m) => m.value === value);\n    if (model) {\n      setSelectedModel(model);\n    }\n  };\n\n  const renderMaxBadge = () => (\n    <div className=\"flex h-[14px] items-center gap-1.5 rounded border border-border px-1 py-0\">\n      <span\n        className=\"font-bold text-[9px] uppercase\"\n        style={{\n          background:\n            'linear-gradient(to right, rgb(129, 161, 193), rgb(125, 124, 155))',\n          WebkitBackgroundClip: 'text',\n          WebkitTextFillColor: 'transparent',\n        }}\n      >\n        MAX\n      </span>\n    </div>\n  );\n\n  return (\n    <div className=\"flex w-[calc(42rem-5rem)] flex-col gap-4\">\n      <div className=\"flex min-h-[120px] cursor-text flex-col rounded-2xl border border-border bg-card shadow-lg\">\n        <div className=\"relative max-h-[258px] flex-1 overflow-y-auto\">\n          <Textarea\n            className=\"min-h-[48.4px] w-full resize-none whitespace-pre-wrap break-words border-0 bg-transparent! p-3 text-[16px] text-foreground shadow-none outline-none transition-[padding] duration-200 ease-in-out focus-visible:ring-0 focus-visible:ring-offset-0\"\n            onChange={(e) => setInputValue(e.target.value)}\n            placeholder=\"Ask anything\"\n            ref={inputRef}\n            value={inputValue}\n          />\n        </div>\n\n        <div className=\"flex min-h-[40px] items-center gap-2 p-2 pb-1\">\n          <div className=\"flex aspect-1 items-center gap-1 rounded-full bg-muted p-1.5 text-xs\">\n            <IconCloud className=\"h-4 w-4 text-muted-foreground\" />\n          </div>\n\n          <div className=\"relative flex items-center\">\n            <Select\n              onValueChange={(value) => {\n                if (value) {\n                  handleModelChange(value);\n                }\n              }}\n              value={selectedModel.value}\n            >\n              <SelectTrigger className=\"w-fit border-none bg-transparent! p-0 text-muted-foreground text-sm shadow-none hover:text-foreground focus:ring-0\">\n                <SelectValue>\n                  {selectedModel.max ? (\n                    <div className=\"flex items-center gap-1\">\n                      <span>{selectedModel.name}</span>\n                      {renderMaxBadge()}\n                    </div>\n                  ) : (\n                    <span>{selectedModel.name}</span>\n                  )}\n                </SelectValue>\n              </SelectTrigger>\n              <SelectContent>\n                {MODELS.map((model) => (\n                  <SelectItem key={model.value} value={model.value}>\n                    {model.max ? (\n                      <div className=\"flex items-center gap-1\">\n                        <span>{model.name}</span>\n                        {renderMaxBadge()}\n                      </div>\n                    ) : (\n                      <span>{model.name}</span>\n                    )}\n                    <span className=\"block text-muted-foreground text-xs\">\n                      {model.description}\n                    </span>\n                  </SelectItem>\n                ))}\n              </SelectContent>\n            </Select>\n          </div>\n\n          <div className=\"ml-auto flex items-center gap-3\">\n            <Button\n              aria-label=\"Attach images\"\n              className=\"text-muted-foreground transition-colors duration-100 ease-out hover:text-foreground\"\n              size=\"icon-sm\"\n              title=\"Attach images\"\n              variant=\"ghost\"\n            >\n              <IconPhotoScan className=\"h-5 w-5\" />\n            </Button>\n\n            <Button\n              aria-label=\"Send message\"\n              className={cn(\n                'cursor-pointer rounded-full bg-primary transition-colors duration-100 ease-out',\n                inputValue && 'bg-primary hover:bg-primary/90!'\n              )}\n              disabled={!inputValue}\n              size=\"icon-sm\"\n              variant=\"ghost\"\n            >\n              <IconArrowUp className=\"h-4 w-4 text-primary-foreground\" />\n            </Button>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"flex flex-wrap justify-center gap-2\">\n        {PROMPTS.map((button) => {\n          const IconComponent = button.icon;\n          return (\n            <Button\n              className=\"group flex h-auto items-center gap-2 rounded-full border bg-transparent px-3 py-2 text-foreground text-sm transition-colors duration-200 ease-out hover:bg-muted/30 dark:bg-muted\"\n              key={button.text}\n              onClick={() => handlePromptClick(button.prompt)}\n              variant=\"ghost\"\n            >\n              <IconComponent className=\"h-4 w-4 text-muted-foreground transition-colors group-hover:text-foreground\" />\n              <span>{button.text}</span>\n            </Button>\n          );\n        })}\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "ai"
      ]
    },
    {
      "name": "ai-03",
      "type": "registry:block",
      "title": "AI Chat Compact Interface",
      "description": "A ai chat compact interface block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "dropdown-menu",
        "textarea"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/ai/ai-03.tsx",
          "type": "registry:component",
          "target": "components/ai-03.tsx",
          "content": "'use client';\n\nimport {\n  IconBolt,\n  IconChevronDown,\n  IconCircle,\n  IconCircleDashed,\n  IconCloud,\n  IconCode,\n  IconDeviceLaptop,\n  IconHistory,\n  IconPaperclip,\n  IconPlus,\n  IconProgress,\n  IconRobot,\n  IconSend,\n  IconUser,\n  IconWand,\n  IconWorld,\n} from '@tabler/icons-react';\nimport { useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Textarea } from '@/components/ui/textarea';\nimport { cn } from '@/lib/utils';\n\nexport default function Ai03() {\n  const [input, setInput] = useState('');\n  const [selectedModel, setSelectedModel] = useState('Local');\n  const [selectedAgent, setSelectedAgent] = useState('Agent');\n  const [selectedPerformance, setSelectedPerformance] = useState('High');\n  const [autoMode, setAutoMode] = useState(false);\n  const fileInputRef = useRef<HTMLInputElement>(null);\n\n  const handleSubmit = (e: React.FormEvent) => {\n    e.preventDefault();\n    if (input.trim()) {\n    }\n  };\n\n  return (\n    <div className=\"w-xl\">\n      <div className=\"overflow-hidden rounded-2xl border border-border bg-background\">\n        <input\n          className=\"sr-only\"\n          multiple\n          onChange={(e) => {}}\n          ref={fileInputRef}\n          type=\"file\"\n        />\n\n        <div className=\"grow px-3 pt-3 pb-2\">\n          <form onSubmit={handleSubmit}>\n            <Textarea\n              className=\"max-h-[25vh] min-h-10 w-full resize-none border-0 border-none bg-transparent! p-0 text-foreground text-sm placeholder-muted-foreground shadow-none outline-none focus-visible:ring-0 focus-visible:ring-offset-0\"\n              onChange={(e) => setInput(e.target.value)}\n              onInput={(e) => {\n                const target = e.target as HTMLTextAreaElement;\n                target.style.height = 'auto';\n                target.style.height = target.scrollHeight + 'px';\n              }}\n              placeholder=\"Ask anything\"\n              rows={1}\n              value={input}\n            />\n          </form>\n        </div>\n\n        <div className=\"mb-2 flex items-center justify-between px-2\">\n          <div className=\"flex items-center gap-1\">\n            <DropdownMenu>\n              <DropdownMenuTrigger\n                render={\n                  <Button\n                    className=\"h-7 w-7 rounded-full border border-border p-0 hover:bg-accent\"\n                    size=\"sm\"\n                    variant=\"ghost\"\n                  />\n                }\n              >\n                <IconPlus className=\"size-3\" />\n              </DropdownMenuTrigger>\n\n              <DropdownMenuContent\n                align=\"start\"\n                className=\"max-w-xs rounded-2xl p-1.5\"\n              >\n                <DropdownMenuGroup className=\"space-y-1\">\n                  <DropdownMenuItem\n                    className=\"rounded-[calc(1rem-6px)] text-xs\"\n                    onClick={() => fileInputRef.current?.click()}\n                  >\n                    <IconPaperclip className=\"opacity-60\" size={16} />\n                    Attach Files\n                  </DropdownMenuItem>\n                  <DropdownMenuItem\n                    className=\"rounded-[calc(1rem-6px)] text-xs\"\n                    onClick={() => {}}\n                  >\n                    <IconCode className=\"opacity-60\" size={16} />\n                    Code Interpreter\n                  </DropdownMenuItem>\n                  <DropdownMenuItem\n                    className=\"rounded-[calc(1rem-6px)] text-xs\"\n                    onClick={() => {}}\n                  >\n                    <IconWorld className=\"opacity-60\" size={16} />\n                    Web Search\n                  </DropdownMenuItem>\n                  <DropdownMenuItem\n                    className=\"rounded-[calc(1rem-6px)] text-xs\"\n                    onClick={() => {}}\n                  >\n                    <IconHistory className=\"opacity-60\" size={16} />\n                    Chat History\n                  </DropdownMenuItem>\n                </DropdownMenuGroup>\n              </DropdownMenuContent>\n            </DropdownMenu>\n\n            <Button\n              className={cn(\n                'h-7 rounded-full border border-border px-2 hover:bg-accent ',\n                {\n                  'border-primary/30 bg-primary/10 text-primary': autoMode,\n                  'text-muted-foreground': !autoMode,\n                }\n              )}\n              onClick={() => setAutoMode(!autoMode)}\n              size=\"sm\"\n              variant=\"ghost\"\n            >\n              <IconWand className=\"size-3\" />\n              <span className=\"text-xs\">Auto</span>\n            </Button>\n          </div>\n\n          <div>\n            <Button\n              className=\"size-7 rounded-full bg-primary p-0 disabled:cursor-not-allowed disabled:opacity-50\"\n              disabled={!input.trim()}\n              onClick={handleSubmit}\n              type=\"submit\"\n            >\n              <IconSend className=\"size-3 fill-primary\" />\n            </Button>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"flex items-center gap-0 pt-2\">\n        <DropdownMenu>\n          <DropdownMenuTrigger\n            render={\n              <Button\n                className=\"h-6 rounded-full border border-transparent px-2 text-muted-foreground text-xs hover:bg-accent\"\n                size=\"sm\"\n                variant=\"ghost\"\n              />\n            }\n          >\n            <IconDeviceLaptop className=\"size-3\" />\n            <span>{selectedModel}</span>\n            <IconChevronDown className=\"size-3\" />\n          </DropdownMenuTrigger>\n          <DropdownMenuContent\n            align=\"start\"\n            className=\"max-w-xs rounded-2xl border-border bg-popover p-1.5\"\n          >\n            <DropdownMenuGroup className=\"space-y-1\">\n              <DropdownMenuItem\n                className=\"rounded-[calc(1rem-6px)] text-xs\"\n                onClick={() => setSelectedModel('Local')}\n              >\n                <IconDeviceLaptop className=\"opacity-60\" size={16} />\n                Local\n              </DropdownMenuItem>\n              <DropdownMenuItem\n                className=\"rounded-[calc(1rem-6px)] text-xs\"\n                onClick={() => setSelectedModel('Cloud')}\n              >\n                <IconCloud className=\"opacity-60\" size={16} />\n                Cloud\n              </DropdownMenuItem>\n            </DropdownMenuGroup>\n          </DropdownMenuContent>\n        </DropdownMenu>\n\n        <DropdownMenu>\n          <DropdownMenuTrigger\n            render={\n              <Button\n                className=\"h-6 rounded-full border border-transparent px-2 text-muted-foreground text-xs hover:bg-accent\"\n                size=\"sm\"\n                variant=\"ghost\"\n              />\n            }\n          >\n            <IconUser className=\"size-3\" />\n            <span>{selectedAgent}</span>\n            <IconChevronDown className=\"size-3\" />\n          </DropdownMenuTrigger>\n          <DropdownMenuContent\n            align=\"start\"\n            className=\"max-w-xs rounded-2xl border-border bg-popover p-1.5\"\n          >\n            <DropdownMenuGroup className=\"space-y-1\">\n              <DropdownMenuItem\n                className=\"rounded-[calc(1rem-6px)] text-xs\"\n                onClick={() => setSelectedAgent('Agent')}\n              >\n                <IconUser className=\"opacity-60\" size={16} />\n                Agent\n              </DropdownMenuItem>\n              <DropdownMenuItem\n                className=\"rounded-[calc(1rem-6px)] text-xs\"\n                onClick={() => setSelectedAgent('Assistant')}\n              >\n                <IconRobot className=\"opacity-60\" size={16} />\n                Assistant\n              </DropdownMenuItem>\n            </DropdownMenuGroup>\n          </DropdownMenuContent>\n        </DropdownMenu>\n\n        <DropdownMenu>\n          <DropdownMenuTrigger\n            render={\n              <Button\n                className=\"h-6 rounded-full border border-transparent px-2 text-muted-foreground text-xs hover:bg-accent\"\n                size=\"sm\"\n                variant=\"ghost\"\n              />\n            }\n          >\n            <IconBolt className=\"size-3\" />\n            <span>{selectedPerformance}</span>\n            <IconChevronDown className=\"size-3\" />\n          </DropdownMenuTrigger>\n          <DropdownMenuContent\n            align=\"start\"\n            className=\"max-w-xs rounded-2xl border-border bg-popover p-1.5\"\n          >\n            <DropdownMenuGroup className=\"space-y-1\">\n              <DropdownMenuItem\n                className=\"rounded-[calc(1rem-6px)] text-xs\"\n                onClick={() => setSelectedPerformance('High')}\n              >\n                <IconCircle className=\"opacity-60\" size={16} />\n                High\n              </DropdownMenuItem>\n              <DropdownMenuItem\n                className=\"rounded-[calc(1rem-6px)] text-xs\"\n                onClick={() => setSelectedPerformance('Medium')}\n              >\n                <IconProgress className=\"opacity-60\" size={16} />\n                Medium\n              </DropdownMenuItem>\n              <DropdownMenuItem\n                className=\"rounded-[calc(1rem-6px)] text-xs\"\n                onClick={() => setSelectedPerformance('Low')}\n              >\n                <IconCircleDashed className=\"opacity-60\" size={16} />\n                Low\n              </DropdownMenuItem>\n            </DropdownMenuGroup>\n          </DropdownMenuContent>\n        </DropdownMenu>\n\n        <div className=\"flex-1\" />\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "ai"
      ]
    },
    {
      "name": "ai-04",
      "type": "registry:block",
      "title": "AI Chat with File Attachments",
      "description": "A ai chat with file attachments block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "badge",
        "button",
        "dropdown-menu",
        "label",
        "switch",
        "textarea"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/ai/ai-04.tsx",
          "type": "registry:component",
          "target": "components/ai-04.tsx",
          "content": "'use client';\n\nimport {\n  IconAdjustmentsHorizontal,\n  IconArrowUp,\n  IconBrandFigma,\n  IconCamera,\n  IconCirclePlus,\n  IconClipboard,\n  IconFileUpload,\n  IconHistory,\n  IconLayoutDashboard,\n  IconLink,\n  IconPaperclip,\n  IconPlayerPlay,\n  IconPlus,\n  IconSparkles,\n  IconTemplate,\n  IconX,\n} from '@tabler/icons-react';\nimport Image from 'next/image';\nimport { useRef, useState } from 'react';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Label } from '@/components/ui/label';\nimport { Switch } from '@/components/ui/switch';\nimport { Textarea } from '@/components/ui/textarea';\nimport { cn } from '@/lib/utils';\n\ninterface AttachedFile {\n  id: string;\n  name: string;\n  file: File;\n  preview?: string;\n}\n\nconst ACTIONS = [\n  { id: 'clone-screenshot', icon: IconCamera, label: 'Clone a Screenshot' },\n  { id: 'import-figma', icon: IconBrandFigma, label: 'Import from Figma' },\n  { id: 'upload-project', icon: IconFileUpload, label: 'Upload a Project' },\n  { id: 'landing-page', icon: IconLayoutDashboard, label: 'Landing Page' },\n];\n\nexport default function Ai04({\n  onSubmit,\n}: {\n  onSubmit?: (prompt: string) => void;\n}) {\n  const [prompt, setPrompt] = useState('');\n  const [isDragOver, setIsDragOver] = useState(false);\n  const [attachedFiles, setAttachedFiles] = useState<AttachedFile[]>([]);\n  const fileInputRef = useRef<HTMLInputElement>(null);\n\n  const [settings, setSettings] = useState({\n    autoComplete: true,\n    streaming: false,\n    showHistory: false,\n  });\n\n  const generateFileId = () => Math.random().toString(36).substring(7);\n  const processFiles = (files: File[]) => {\n    for (const file of files) {\n      const fileId = generateFileId();\n      const attachedFile: AttachedFile = {\n        id: fileId,\n        name: file.name,\n        file,\n      };\n\n      if (file.type.startsWith('image/')) {\n        const reader = new FileReader();\n        reader.onload = () => {\n          setAttachedFiles((prev) =>\n            prev.map((f) =>\n              f.id === fileId ? { ...f, preview: reader.result as string } : f\n            )\n          );\n        };\n        reader.readAsDataURL(file);\n      }\n\n      setAttachedFiles((prev) => [...prev, attachedFile]);\n    }\n  };\n  const submitPrompt = () => {\n    if (prompt.trim() && onSubmit) {\n      onSubmit(prompt.trim());\n      setPrompt('');\n    }\n  };\n  const updateSetting = (key: keyof typeof settings, value: boolean) => {\n    setSettings((prev) => ({ ...prev, [key]: value }));\n  };\n  const handleSubmit = (e: React.FormEvent) => {\n    e.preventDefault();\n    submitPrompt();\n  };\n  const handleDragOver = (e: React.DragEvent) => {\n    e.preventDefault();\n    setIsDragOver(true);\n  };\n  const handleDragLeave = (e: React.DragEvent) => {\n    e.preventDefault();\n    setIsDragOver(false);\n  };\n  const handleDrop = (e: React.DragEvent) => {\n    e.preventDefault();\n    setIsDragOver(false);\n\n    const files = Array.from(e.dataTransfer.files);\n    if (files.length > 0) {\n      processFiles(files);\n    }\n  };\n  const handleTextareaChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n    setPrompt(e.target.value);\n  };\n  const handleKeyDown = (e: React.KeyboardEvent) => {\n    if (e.key === 'Enter' && !e.shiftKey) {\n      e.preventDefault();\n      submitPrompt();\n    }\n  };\n\n  const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const files = Array.from(e.target.files || []);\n    processFiles(files);\n\n    if (fileInputRef.current) {\n      fileInputRef.current.value = '';\n    }\n  };\n\n  const handleRemoveFile = (fileId: string) => {\n    setAttachedFiles((prev) => prev.filter((file) => file.id !== fileId));\n  };\n\n  return (\n    <div className=\"mx-auto flex w-full flex-col gap-4\">\n      <h1 className=\"text-balance text-pretty text-center font-heading font-semibold text-[29px] text-foreground tracking-tighter sm:text-[32px] md:text-[46px]\">\n        Prompt. Refine. Ship.\n      </h1>\n      <h2 className=\"-my-5 text-balance pb-4 text-center text-muted-foreground text-xl\">\n        Build real, working software just by describing it\n      </h2>\n\n      <div className=\"relative z-10 mx-auto flex w-full max-w-2xl flex-col content-center\">\n        <form\n          className=\"overflow-visible rounded-xl border p-2 transition-colors duration-200 focus-within:border-ring\"\n          onDragLeave={handleDragLeave}\n          onDragOver={handleDragOver}\n          onDrop={handleDrop}\n          onSubmit={handleSubmit}\n        >\n          {attachedFiles.length > 0 && (\n            <div className=\"relative mb-2 flex w-fit items-center gap-2 overflow-hidden\">\n              {attachedFiles.map((file) => (\n                <Badge\n                  className=\"group relative h-6 max-w-30 cursor-pointer overflow-hidden px-0 text-[13px] transition-colors hover:bg-accent\"\n                  key={file.id}\n                  variant=\"outline\"\n                >\n                  <span className=\"flex h-full items-center gap-1.5 overflow-hidden pl-1 font-normal\">\n                    <div className=\"relative flex h-4 min-w-4 items-center justify-center\">\n                      {file.preview ? (\n                        <Image\n                          alt={file.name}\n                          className=\"absolute inset-0 h-4 w-4 rounded border object-cover\"\n                          height={16}\n                          src={file.preview}\n                          width={16}\n                        />\n                      ) : (\n                        <IconPaperclip className=\"opacity-60\" size={12} />\n                      )}\n                    </div>\n                    <span className=\"inline overflow-hidden truncate pr-1.5\">\n                      {file.name}\n                    </span>\n                  </span>\n                  <button\n                    className=\"absolute right-1 z-10 rounded-sm p-0.5 text-muted-foreground opacity-0 focus-visible:bg-accent focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-background group-hover:opacity-100\"\n                    onClick={() => handleRemoveFile(file.id)}\n                    type=\"button\"\n                  >\n                    <IconX size={12} />\n                  </button>\n                </Badge>\n              ))}\n            </div>\n          )}\n          <Textarea\n            className=\"max-h-50 min-h-12 resize-none rounded-none border-none bg-transparent! p-0 text-sm shadow-none focus-visible:border-transparent focus-visible:ring-0\"\n            onChange={handleTextareaChange}\n            onKeyDown={handleKeyDown}\n            placeholder=\"Ask anything\"\n            value={prompt}\n          />\n\n          <div className=\"flex items-center gap-1\">\n            <div className=\"flex items-end gap-0.5 sm:gap-1\">\n              <input\n                className=\"sr-only\"\n                multiple\n                onChange={handleFileSelect}\n                ref={fileInputRef}\n                type=\"file\"\n              />\n\n              <DropdownMenu>\n                <DropdownMenuTrigger\n                  render={\n                    <Button\n                      aria-label=\"Add attachments\"\n                      className=\"ml-[-2px] rounded-md\"\n                      size=\"icon-sm\"\n                      type=\"button\"\n                      variant=\"ghost\"\n                    />\n                  }\n                >\n                  <IconPlus size={16} />\n                </DropdownMenuTrigger>\n                <DropdownMenuContent\n                  align=\"start\"\n                  className=\"max-w-xs rounded-2xl p-1.5\"\n                >\n                  <DropdownMenuGroup className=\"space-y-1\">\n                    <DropdownMenuItem\n                      className=\"rounded-md text-xs\"\n                      onClick={() => fileInputRef.current?.click()}\n                    >\n                      <div className=\"flex items-center gap-2\">\n                        <IconPaperclip\n                          className=\"text-muted-foreground\"\n                          size={16}\n                        />\n                        <span>Attach Files</span>\n                      </div>\n                    </DropdownMenuItem>\n                    <DropdownMenuItem className=\"rounded-md text-xs\">\n                      <div className=\"flex items-center gap-2\">\n                        <IconLink className=\"text-muted-foreground\" size={16} />\n                        <span>Import from URL</span>\n                      </div>\n                    </DropdownMenuItem>\n                    <DropdownMenuItem className=\"rounded-md text-xs\">\n                      <div className=\"flex items-center gap-2\">\n                        <IconClipboard\n                          className=\"text-muted-foreground\"\n                          size={16}\n                        />\n                        <span>Paste from Clipboard</span>\n                      </div>\n                    </DropdownMenuItem>\n                    <DropdownMenuItem className=\"rounded-md text-xs\">\n                      <div className=\"flex items-center gap-2\">\n                        <IconTemplate\n                          className=\"text-muted-foreground\"\n                          size={16}\n                        />\n                        <span>Use Template</span>\n                      </div>\n                    </DropdownMenuItem>\n                  </DropdownMenuGroup>\n                </DropdownMenuContent>\n              </DropdownMenu>\n\n              <DropdownMenu>\n                <DropdownMenuTrigger\n                  render={\n                    <Button\n                      aria-label=\"Adjust settings\"\n                      className=\"rounded-md\"\n                      size=\"icon-sm\"\n                      type=\"button\"\n                      variant=\"ghost\"\n                    />\n                  }\n                >\n                  <IconAdjustmentsHorizontal size={16} />\n                </DropdownMenuTrigger>\n                <DropdownMenuContent\n                  align=\"start\"\n                  className=\"w-48 rounded-2xl p-3\"\n                >\n                  <DropdownMenuGroup className=\"space-y-3\">\n                    <div className=\"flex items-center justify-between\">\n                      <div className=\"flex items-center gap-2\">\n                        <IconSparkles\n                          className=\"text-muted-foreground\"\n                          size={16}\n                        />\n                        <Label className=\"text-xs\">Auto-complete</Label>\n                      </div>\n                      <Switch\n                        checked={settings.autoComplete}\n                        className=\"scale-75\"\n                        onCheckedChange={(value) =>\n                          updateSetting('autoComplete', value)\n                        }\n                      />\n                    </div>\n\n                    <div className=\"flex items-center justify-between\">\n                      <div className=\"flex items-center gap-2\">\n                        <IconPlayerPlay\n                          className=\"text-muted-foreground\"\n                          size={16}\n                        />\n                        <Label className=\"text-xs\">Streaming</Label>\n                      </div>\n                      <Switch\n                        checked={settings.streaming}\n                        className=\"scale-75\"\n                        onCheckedChange={(value) =>\n                          updateSetting('streaming', value)\n                        }\n                      />\n                    </div>\n\n                    <div className=\"flex items-center justify-between\">\n                      <div className=\"flex items-center gap-2\">\n                        <IconHistory\n                          className=\"text-muted-foreground\"\n                          size={16}\n                        />\n                        <Label className=\"text-xs\">Show History</Label>\n                      </div>\n                      <Switch\n                        checked={settings.showHistory}\n                        className=\"scale-75\"\n                        onCheckedChange={(value) =>\n                          updateSetting('showHistory', value)\n                        }\n                      />\n                    </div>\n                  </DropdownMenuGroup>\n                </DropdownMenuContent>\n              </DropdownMenu>\n            </div>\n\n            <div className=\"ml-auto flex items-center gap-0.5 sm:gap-1\">\n              <Button\n                aria-label=\"Send message\"\n                className=\"rounded-md\"\n                disabled={!prompt.trim()}\n                size=\"icon-sm\"\n                type=\"submit\"\n                variant=\"default\"\n              >\n                <IconArrowUp size={16} />\n              </Button>\n            </div>\n          </div>\n\n          <div\n            className={cn(\n              'pointer-events-none absolute inset-0 z-20 flex items-center justify-center rounded-[inherit] border border-border border-dashed bg-muted text-foreground text-sm transition-opacity duration-200',\n              isDragOver ? 'opacity-100' : 'opacity-0'\n            )}\n          >\n            <span className=\"flex w-full items-center justify-center gap-1 font-medium\">\n              <IconCirclePlus className=\"min-w-4\" size={16} />\n              Drop files here to add as attachments\n            </span>\n          </div>\n        </form>\n      </div>\n\n      <div className=\"mx-auto flex min-h-0 max-w-250 shrink-0 flex-wrap items-center justify-center gap-3\">\n        {ACTIONS.map((action) => (\n          <Button\n            className=\"gap-2 rounded-full\"\n            key={action.id}\n            size=\"sm\"\n            variant=\"outline\"\n          >\n            <action.icon size={16} />\n            {action.label}\n          </Button>\n        ))}\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "ai"
      ]
    },
    {
      "name": "ai-05",
      "type": "registry:block",
      "title": "AI Elements Chat",
      "description": "A ai elements chat block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "badge",
        "button"
      ],
      "dependencies": [
        "@tabler/icons-react",
        "ai"
      ],
      "files": [
        {
          "path": "content/components/ai/ai-05.tsx",
          "type": "registry:component",
          "target": "components/ai-05.tsx",
          "content": "'use client';\n\n// Install AI Elements components:\n// npx ai-elements@latest add conversation message prompt-input\n\nimport {\n  IconAdjustmentsHorizontal,\n  IconBolt,\n  IconMessageCircle,\n  IconPaperclip,\n  IconRefresh,\n  IconSparkles,\n} from '@tabler/icons-react';\nimport type { ChatStatus } from 'ai';\nimport { useEffect, useRef, useState } from 'react';\nimport {\n  Conversation,\n  ConversationContent,\n  ConversationScrollButton,\n} from '@/components/ai-elements/conversation';\nimport {\n  Message,\n  MessageContent,\n  MessageResponse,\n} from '@/components/ai-elements/message';\nimport {\n  PromptInput,\n  PromptInputButton,\n  PromptInputFooter,\n  PromptInputSubmit,\n  PromptInputTextarea,\n  PromptInputTools,\n} from '@/components/ai-elements/prompt-input';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/lib/utils';\n\ninterface DemoMessage {\n  id: string;\n  role: 'user' | 'assistant';\n  content: string;\n}\n\nconst INITIAL_MESSAGES: DemoMessage[] = [\n  {\n    id: 'intro',\n    role: 'assistant',\n    content:\n      '**Welcome back.** I can help you explore this chat block.\\n\\n- Draft UI copy\\n- Summarize docs\\n- Turn notes into tasks\\n\\nAsk me anything and I will respond with a demo reply.',\n  },\n  {\n    id: 'question',\n    role: 'user',\n    content: 'What makes this chat block reusable?',\n  },\n  {\n    id: 'answer',\n    role: 'assistant',\n    content:\n      'It is built with **AI Elements** for conversation layout and input, plus shadcn/ui for the chrome. That means you can drop it into other screens and wire it up to a real AI backend later.',\n  },\n];\n\nconst RESPONSES = [\n  'Here is a quick outline you can reuse:\\n\\n1. Swap the mock response with a real API call.\\n2. Stream tokens into `MessageResponse`.\\n3. Keep the layout exactly as-is for a consistent UI.',\n  'If you want multi-model support, add a small model selector next to the status badge and pass the selection to your backend.',\n  'You can also inject tools like file upload or voice input by adding buttons to the prompt footer.',\n];\n\nconst pickResponse = (index: number) => RESPONSES[index % RESPONSES.length];\n\nexport default function Ai05() {\n  const [messages, setMessages] = useState<DemoMessage[]>(INITIAL_MESSAGES);\n  const [inputValue, setInputValue] = useState('');\n  const [status, setStatus] = useState<ChatStatus>('ready');\n  const replyTimeoutRef = useRef<number | null>(null);\n\n  useEffect(() => {\n    return () => {\n      if (replyTimeoutRef.current) {\n        window.clearTimeout(replyTimeoutRef.current);\n      }\n    };\n  }, []);\n\n  const handleSend = (text: string) => {\n    const trimmed = text.trim();\n    if (!trimmed) {\n      return;\n    }\n\n    const newMessage: DemoMessage = {\n      id: `user-${Date.now()}`,\n      role: 'user',\n      content: trimmed,\n    };\n\n    setMessages((prev) => [...prev, newMessage]);\n    setInputValue('');\n    setStatus('submitted');\n\n    replyTimeoutRef.current = window.setTimeout(() => {\n      const response: DemoMessage = {\n        id: `assistant-${Date.now()}`,\n        role: 'assistant',\n        content: pickResponse(messages.length),\n      };\n\n      setMessages((prev) => [...prev, response]);\n      setStatus('ready');\n    }, 900);\n  };\n\n  return (\n    <div className=\"w-full px-4\">\n      <div className=\"mx-auto flex h-96 w-full max-w-2xl flex-col overflow-hidden rounded-2xl border border-border bg-card shadow-lg sm:w-3/5\">\n        <header className=\"flex items-center justify-between gap-4 border-border/80 border-b px-4 py-3\">\n          <div className=\"flex items-center gap-3\">\n            <div className=\"space-y-1\">\n              <div className=\"flex items-center gap-2 text-balance font-semibold text-sm\">\n                Documenso Chat\n              </div>\n              <div className=\"flex items-center gap-2 text-pretty text-muted-foreground text-xs\">\n                <span className=\"inline-flex items-center gap-1\">\n                  <span className=\"size-1.5 rounded-full bg-emerald-500\" />\n                  Live preview\n                </span>\n                <span className=\"hidden sm:inline\">- Powered by shadcn/ui</span>\n              </div>\n            </div>\n          </div>\n          <div className=\"flex items-center gap-1\">\n            <Button\n              aria-label=\"Refresh\"\n              className=\"size-8\"\n              size=\"icon\"\n              title=\"Refresh\"\n              variant=\"ghost\"\n            >\n              <IconRefresh className=\"size-4\" />\n            </Button>\n            <Button\n              aria-label=\"Settings\"\n              className=\"size-8\"\n              size=\"icon\"\n              title=\"Settings\"\n              variant=\"ghost\"\n            >\n              <IconAdjustmentsHorizontal className=\"size-4\" />\n            </Button>\n          </div>\n        </header>\n\n        <Conversation className=\"bg-muted/30\">\n          <ConversationContent className=\"gap-6 pl-1\">\n            {messages.map((message) => (\n              <Message from={message.role} key={message.id}>\n                <MessageContent\n                  className={cn(\n                    'leading-relaxed',\n                    message.role === 'assistant' && 'max-w-prose'\n                  )}\n                >\n                  {message.role === 'assistant' ? (\n                    <MessageResponse>{message.content}</MessageResponse>\n                  ) : (\n                    <p className=\"whitespace-pre-wrap text-pretty\">\n                      {message.content}\n                    </p>\n                  )}\n                </MessageContent>\n              </Message>\n            ))}\n          </ConversationContent>\n          <ConversationScrollButton />\n        </Conversation>\n\n        <div className=\"bg-background\">\n          <PromptInput\n            className=\"w-full [&>[data-slot=input-group]]:rounded-none [&>[data-slot=input-group]]:border-border/80 [&>[data-slot=input-group]]:border-x-0 [&>[data-slot=input-group]]:border-t [&>[data-slot=input-group]]:border-b-0 [&>[data-slot=input-group]]:shadow-none [&>[data-slot=input-group]]:focus-within:border-border/80 [&>[data-slot=input-group]]:focus-within:outline-none [&>[data-slot=input-group]]:focus-within:ring-0 [&>[data-slot=input-group]]:focus-within:ring-transparent [&>[data-slot=input-group]]:focus-within:ring-offset-0\"\n            onSubmit={(message) => handleSend(message.text)}\n          >\n            <PromptInputTextarea\n              onChange={(event) => setInputValue(event.currentTarget.value)}\n              placeholder=\"Ask about the block, UI patterns, or an AI workflow\"\n              value={inputValue}\n            />\n            <PromptInputFooter>\n              <PromptInputTools>\n                <PromptInputButton aria-label=\"Attach\">\n                  <IconPaperclip className=\"size-4\" />\n                </PromptInputButton>\n                <PromptInputButton aria-label=\"Quick prompt\">\n                  <IconBolt className=\"size-4\" />\n                </PromptInputButton>\n                <PromptInputButton aria-label=\"New chat\">\n                  <IconMessageCircle className=\"size-4\" />\n                </PromptInputButton>\n              </PromptInputTools>\n              <PromptInputSubmit\n                disabled={!inputValue.trim() || status !== 'ready'}\n                status={status}\n              />\n            </PromptInputFooter>\n          </PromptInput>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "ai"
      ]
    },
    {
      "name": "command-menu-01",
      "type": "registry:block",
      "title": "Command Menu with Groups",
      "description": "A command menu with groups block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "command",
        "kbd"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/command-menu/command-menu-01.tsx",
          "type": "registry:component",
          "target": "components/command-menu-01.tsx",
          "content": "'use client';\n\nimport {\n  IconBell,\n  IconBolt,\n  IconCalendar,\n  IconChartBar,\n  IconChartPie,\n  IconClock,\n  IconFileText,\n  IconHelp,\n  IconKeyboard,\n  IconLayoutDashboard,\n  IconLayoutKanban,\n  IconLogout,\n  IconMessage,\n  IconPalette,\n  IconSettings,\n  IconSquareCheck,\n  IconTarget,\n  IconTrendingUp,\n  IconUsers,\n} from '@tabler/icons-react';\nimport { useEffect, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  Command,\n  CommandDialog,\n  CommandEmpty,\n  CommandGroup,\n  CommandInput,\n  CommandItem,\n  CommandList,\n} from '@/components/ui/command';\nimport { Kbd } from '@/components/ui/kbd';\n\nconst workspaceItems = [\n  { icon: IconLayoutDashboard, label: 'Dashboard' },\n  { icon: IconLayoutKanban, label: 'Projects' },\n  { icon: IconSquareCheck, label: 'Tasks' },\n  { icon: IconCalendar, label: 'Calendar' },\n  { icon: IconUsers, label: 'Team members' },\n  { icon: IconMessage, label: 'Messages' },\n  { icon: IconFileText, label: 'Documents' },\n  { icon: IconBell, label: 'Notifications' },\n  { icon: IconClock, label: 'Time tracking' },\n  { icon: IconTarget, label: 'Goals' },\n];\n\nconst analyticsItems = [\n  { icon: IconChartBar, label: 'Overview' },\n  { icon: IconTrendingUp, label: 'Performance' },\n  { icon: IconChartPie, label: 'Reports' },\n  { icon: IconBolt, label: 'Insights' },\n];\n\nconst settingsItems = [\n  { icon: IconSettings, label: 'Preferences' },\n  { icon: IconPalette, label: 'Appearance' },\n  { icon: IconKeyboard, label: 'Keyboard shortcuts' },\n  { icon: IconHelp, label: 'Help & support' },\n  { icon: IconLogout, label: 'Sign out' },\n];\n\nexport function CommandMenu01() {\n  const [open, setOpen] = useState(true);\n\n  useEffect(() => {\n    const down = (e: KeyboardEvent) => {\n      if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {\n        e.preventDefault();\n        setOpen((prev) => !prev);\n      }\n    };\n\n    document.addEventListener('keydown', down);\n    return () => document.removeEventListener('keydown', down);\n  }, []);\n\n  return (\n    <>\n      <Button onClick={() => setOpen(true)} variant=\"outline\">\n        Open Command Menu\n      </Button>\n\n      <CommandDialog onOpenChange={setOpen} open={open} showCloseButton={false}>\n        <Command>\n          <CommandInput\n            className=\"h-12\"\n            placeholder=\"Type a command or search...\"\n          />\n          <CommandList className=\"h-[320px] max-h-[320px]\">\n            <CommandEmpty>No results found.</CommandEmpty>\n            <CommandGroup heading=\"Workspace\">\n              {workspaceItems.map((item) => (\n                <CommandItem key={item.label}>\n                  <item.icon className=\"mr-2 h-5 w-5\" />\n                  <span>{item.label}</span>\n                </CommandItem>\n              ))}\n            </CommandGroup>\n            <CommandGroup heading=\"Analytics\">\n              {analyticsItems.map((item) => (\n                <CommandItem key={item.label}>\n                  <item.icon className=\"mr-2 h-5 w-5\" />\n                  <span>{item.label}</span>\n                </CommandItem>\n              ))}\n            </CommandGroup>\n            <CommandGroup heading=\"Settings\">\n              {settingsItems.map((item) => (\n                <CommandItem key={item.label}>\n                  <item.icon className=\"mr-2 h-5 w-5\" />\n                  <span>{item.label}</span>\n                </CommandItem>\n              ))}\n            </CommandGroup>\n          </CommandList>\n          <div className=\"flex h-12 items-center justify-end border-t px-3\">\n            <button\n              className=\"flex items-center gap-1 text-muted-foreground text-sm hover:text-foreground\"\n              onClick={() => setOpen(false)}\n              type=\"button\"\n            >\n              <span>Close</span>\n              <Kbd className=\"ml-1\">Esc</Kbd>\n            </button>\n          </div>\n        </Command>\n      </CommandDialog>\n    </>\n  );\n}\n"
        }
      ],
      "categories": [
        "command-menu"
      ]
    },
    {
      "name": "command-menu-02",
      "type": "registry:block",
      "title": "Command Menu with Keyboard Shortcuts",
      "description": "A command menu with keyboard shortcuts block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "command",
        "dialog",
        "kbd"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/command-menu/command-menu-02.tsx",
          "type": "registry:component",
          "target": "components/command-menu-02.tsx",
          "content": "'use client';\n\nimport {\n  IconArrowRight,\n  IconAt,\n  IconCopy,\n  IconDeviceDesktop,\n  IconDownload,\n  IconFile,\n  IconFileSearch,\n  IconKeyboard,\n  IconLink,\n  IconLogout,\n  IconMessage,\n  IconPencil,\n  IconPlus,\n  IconSend,\n  IconSettings,\n  IconTemplate,\n  IconUser,\n  IconUsers,\n} from '@tabler/icons-react';\nimport { useEffect, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  Command,\n  CommandEmpty,\n  CommandGroup,\n  CommandInput,\n  CommandItem,\n  CommandList,\n} from '@/components/ui/command';\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog';\nimport { Kbd, KbdGroup } from '@/components/ui/kbd';\n\nexport function CommandMenu02() {\n  const [open, setOpen] = useState(true);\n  const [inputValue, setInputValue] = useState('');\n\n  useEffect(() => {\n    const down = (e: KeyboardEvent) => {\n      if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {\n        e.preventDefault();\n        setOpen((prev) => !prev);\n      }\n    };\n\n    document.addEventListener('keydown', down);\n    return () => document.removeEventListener('keydown', down);\n  }, []);\n\n  return (\n    <>\n      <Button onClick={() => setOpen(true)} variant=\"outline\">\n        Open Command Menu\n      </Button>\n\n      <Dialog onOpenChange={setOpen} open={open}>\n        <DialogHeader className=\"sr-only\">\n          <DialogTitle>Command Menu</DialogTitle>\n          <DialogDescription>\n            Use the command menu to navigate through the app.\n          </DialogDescription>\n        </DialogHeader>\n        <DialogContent\n          className=\"gap-0 overflow-hidden rounded-xl border-border/50 p-0 shadow-lg sm:max-w-lg\"\n          showCloseButton={false}\n        >\n          <Command className=\"flex h-full w-full flex-col overflow-hidden bg-popover **:data-[slot=command-input-wrapper]:h-auto **:data-[slot=command-input-wrapper]:grow **:data-[slot=command-input-wrapper]:border-0 **:data-[slot=command-input-wrapper]:px-0\">\n            <div className=\"flex h-12 items-center gap-2 border-border/50 border-b px-4\">\n              <CommandInput\n                className=\"h-10 text-[15px]\"\n                onValueChange={setInputValue}\n                placeholder=\"What do you need?\"\n                value={inputValue}\n              />\n              <button\n                className=\"flex shrink-0 items-center\"\n                onClick={() => setOpen(false)}\n                type=\"button\"\n              >\n                <Kbd>Esc</Kbd>\n              </button>\n            </div>\n\n            <CommandList className=\"max-h-[400px] py-2\">\n              <CommandEmpty>No results found.</CommandEmpty>\n\n              <CommandGroup>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconSettings aria-hidden />\n                  Account Settings...\n                  <KbdGroup className=\"ml-auto\">\n                    <Kbd>⌘</Kbd>\n                    <Kbd>,</Kbd>\n                  </KbdGroup>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconUser aria-hidden />\n                  Switch Workspace...\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconLogout aria-hidden />\n                  Log Out\n                  <KbdGroup className=\"ml-auto\">\n                    <Kbd>⌘</Kbd>\n                    <Kbd>Q</Kbd>\n                  </KbdGroup>\n                </CommandItem>\n              </CommandGroup>\n\n              <CommandGroup heading=\"Documents\">\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconFile aria-hidden />\n                  Search Documents...\n                  <KbdGroup className=\"ml-auto\">\n                    <Kbd>⌘</Kbd>\n                    <Kbd>F</Kbd>\n                  </KbdGroup>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconPlus aria-hidden />\n                  Create New Document...\n                  <KbdGroup className=\"ml-auto\">\n                    <Kbd>⌘</Kbd>\n                    <Kbd>N</Kbd>\n                  </KbdGroup>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconFile aria-hidden />\n                  Upload Document...\n                  <KbdGroup className=\"ml-auto\">\n                    <Kbd>⌘</Kbd>\n                    <Kbd>U</Kbd>\n                  </KbdGroup>\n                </CommandItem>\n              </CommandGroup>\n\n              <CommandGroup heading=\"Signing\">\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconSend aria-hidden />\n                  Request Signature...\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconPencil aria-hidden />\n                  Sign a Document...\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconUsers aria-hidden />\n                  Bulk Send for Signature...\n                </CommandItem>\n              </CommandGroup>\n\n              <CommandGroup heading=\"Templates\">\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconTemplate aria-hidden />\n                  Search Templates...\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconPlus aria-hidden />\n                  Create New Template...\n                </CommandItem>\n              </CommandGroup>\n\n              <CommandGroup heading=\"General\">\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconDeviceDesktop aria-hidden />\n                  Change Theme...\n                  <KbdGroup className=\"ml-auto\">\n                    <Kbd>⌘</Kbd>\n                    <Kbd>T</Kbd>\n                  </KbdGroup>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconCopy aria-hidden />\n                  Copy Current URL\n                  <KbdGroup className=\"ml-auto\">\n                    <Kbd>⌘</Kbd>\n                    <Kbd>⇧</Kbd>\n                    <Kbd>C</Kbd>\n                  </KbdGroup>\n                </CommandItem>\n              </CommandGroup>\n\n              <CommandGroup heading=\"Navigation\">\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconArrowRight aria-hidden />\n                  <span>\n                    Go to&nbsp;<strong className=\"font-semibold\">Inbox</strong>\n                  </span>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconArrowRight aria-hidden />\n                  <span>\n                    Go to&nbsp;\n                    <strong className=\"font-semibold\">Action Required</strong>\n                  </span>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconArrowRight aria-hidden />\n                  <span>\n                    Go to&nbsp;\n                    <strong className=\"font-semibold\">\n                      Waiting for Others\n                    </strong>\n                  </span>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconArrowRight aria-hidden />\n                  <span>\n                    Go to&nbsp;\n                    <strong className=\"font-semibold\">Completed</strong>\n                  </span>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconArrowRight aria-hidden />\n                  <span>\n                    Go to&nbsp;<strong className=\"font-semibold\">Drafts</strong>\n                  </span>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconArrowRight aria-hidden />\n                  <span>\n                    Go to&nbsp;\n                    <strong className=\"font-semibold\">Templates</strong>\n                  </span>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconArrowRight aria-hidden />\n                  <span>\n                    Go to&nbsp;\n                    <strong className=\"font-semibold\">Archive</strong>\n                  </span>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconArrowRight aria-hidden />\n                  <span>\n                    Go to&nbsp;<strong className=\"font-semibold\">Trash</strong>\n                  </span>\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconArrowRight aria-hidden />\n                  <span>\n                    Go to&nbsp;\n                    <strong className=\"font-semibold\">Settings</strong>\n                  </span>\n                </CommandItem>\n              </CommandGroup>\n\n              <CommandGroup heading=\"Quick Actions\">\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconLink aria-hidden />\n                  Copy Signing Link\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconDownload aria-hidden />\n                  Download Document\n                </CommandItem>\n              </CommandGroup>\n\n              <CommandGroup heading=\"Help\">\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconFileSearch aria-hidden />\n                  Search Help Center...\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconMessage aria-hidden />\n                  Send Feedback...\n                </CommandItem>\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconAt aria-hidden />\n                  Contact Support\n                </CommandItem>\n              </CommandGroup>\n\n              <CommandGroup heading=\"Keyboard Shortcuts\">\n                <CommandItem\n                  className=\"mx-2 rounded-lg py-2.5\"\n                  onSelect={() => setOpen(false)}\n                >\n                  <IconKeyboard aria-hidden />\n                  View Keyboard Shortcuts\n                  <KbdGroup className=\"ml-auto\">\n                    <Kbd>⌘</Kbd>\n                    <Kbd>/</Kbd>\n                  </KbdGroup>\n                </CommandItem>\n              </CommandGroup>\n            </CommandList>\n          </Command>\n        </DialogContent>\n      </Dialog>\n    </>\n  );\n}\n"
        }
      ],
      "categories": [
        "command-menu"
      ]
    },
    {
      "name": "command-menu-03",
      "type": "registry:block",
      "title": "Command Menu with Documentation Search",
      "description": "A command menu with documentation search block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "command",
        "dialog",
        "kbd"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/command-menu/command-menu-03.tsx",
          "type": "registry:component",
          "target": "components/command-menu-03.tsx",
          "content": "'use client';\n\nimport { IconArrowRight, IconCornerDownLeft } from '@tabler/icons-react';\nimport { useRouter } from 'next/navigation';\nimport { useCallback, useEffect, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  Command,\n  CommandEmpty,\n  CommandGroup,\n  CommandInput,\n  CommandItem,\n  CommandList,\n} from '@/components/ui/command';\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog';\nimport { Kbd } from '@/components/ui/kbd';\n\nconst navItems = [\n  { href: '/', label: 'Home', keywords: ['home', 'main', 'index'] },\n  {\n    href: '/dashboard',\n    label: 'Dashboard',\n    keywords: ['dashboard', 'overview'],\n  },\n  {\n    href: '/settings',\n    label: 'Settings',\n    keywords: ['settings', 'preferences'],\n  },\n];\n\nconst pageGroups = [\n  {\n    name: 'Getting Started',\n    pages: [\n      {\n        name: 'Introduction',\n        href: '/docs/introduction',\n        keywords: ['intro', 'start'],\n      },\n      {\n        name: 'Installation',\n        href: '/docs/installation',\n        keywords: ['install', 'setup'],\n      },\n      {\n        name: 'Quick Start',\n        href: '/docs/quick-start',\n        keywords: ['quick', 'begin'],\n      },\n    ],\n  },\n  {\n    name: 'Utilities',\n    pages: [\n      {\n        name: 'Typography',\n        href: '/docs/utilities/typography',\n        keywords: ['text', 'font'],\n      },\n      {\n        name: 'Colors',\n        href: '/docs/utilities/colors',\n        keywords: ['color', 'theme'],\n      },\n      {\n        name: 'Spacing',\n        href: '/docs/utilities/spacing',\n        keywords: ['margin', 'padding'],\n      },\n    ],\n  },\n];\n\nconst colorGroups = [\n  {\n    name: 'Neutral',\n    colors: [\n      {\n        name: 'Neutral 50',\n        className: 'neutral-50',\n        value: 'oklch(0.985 0 0)',\n      },\n      {\n        name: 'Neutral 100',\n        className: 'neutral-100',\n        value: 'oklch(0.97 0 0)',\n      },\n      {\n        name: 'Neutral 200',\n        className: 'neutral-200',\n        value: 'oklch(0.922 0 0)',\n      },\n      {\n        name: 'Neutral 500',\n        className: 'neutral-500',\n        value: 'oklch(0.556 0 0)',\n      },\n      {\n        name: 'Neutral 900',\n        className: 'neutral-900',\n        value: 'oklch(0.205 0 0)',\n      },\n    ],\n  },\n  {\n    name: 'Blue',\n    colors: [\n      {\n        name: 'Blue 50',\n        className: 'blue-50',\n        value: 'oklch(0.97 0.014 254.604)',\n      },\n      {\n        name: 'Blue 500',\n        className: 'blue-500',\n        value: 'oklch(0.623 0.214 259.815)',\n      },\n      {\n        name: 'Blue 600',\n        className: 'blue-600',\n        value: 'oklch(0.546 0.245 262.881)',\n      },\n    ],\n  },\n];\n\nexport function CommandMenu03() {\n  const router = useRouter();\n  const [open, setOpen] = useState(true);\n\n  const copyToClipboard = useCallback((text: string) => {\n    navigator.clipboard.writeText(text);\n  }, []);\n\n  const runCommand = useCallback((command: () => unknown) => {\n    setOpen(false);\n    command();\n  }, []);\n\n  useEffect(() => {\n    const down = (e: KeyboardEvent) => {\n      if ((e.key === 'k' && (e.metaKey || e.ctrlKey)) || e.key === '/') {\n        if (\n          (e.target instanceof HTMLElement && e.target.isContentEditable) ||\n          e.target instanceof HTMLInputElement ||\n          e.target instanceof HTMLTextAreaElement ||\n          e.target instanceof HTMLSelectElement\n        ) {\n          return;\n        }\n        e.preventDefault();\n        setOpen((prev) => !prev);\n      }\n    };\n\n    document.addEventListener('keydown', down);\n    return () => document.removeEventListener('keydown', down);\n  }, []);\n\n  return (\n    <>\n      <Button onClick={() => setOpen(true)} variant=\"outline\">\n        Open Command Menu\n      </Button>\n\n      <Dialog onOpenChange={setOpen} open={open}>\n        <DialogContent className=\"rounded-xl border-none bg-clip-padding p-2 pb-11 shadow-2xl ring-4 ring-neutral-200/80 dark:bg-neutral-900 dark:ring-neutral-800\">\n          <DialogHeader className=\"sr-only\">\n            <DialogTitle>Search documentation...</DialogTitle>\n            <DialogDescription>\n              Search for a command to run...\n            </DialogDescription>\n          </DialogHeader>\n\n          <Command className=\"rounded-none bg-transparent **:data-[slot=command-input-wrapper]:mb-0 **:data-[slot=command-input-wrapper]:h-9! **:data-[slot=command-input]:h-9! **:data-[slot=command-input-wrapper]:rounded-md **:data-[slot=command-input-wrapper]:border **:data-[slot=command-input-wrapper]:border-input **:data-[slot=command-input-wrapper]:bg-input/50 **:data-[slot=command-input]:py-0\">\n            <CommandInput placeholder=\"Search documentation...\" />\n            <CommandList className=\"no-scrollbar min-h-80 scroll-pt-2 scroll-pb-1.5\">\n              <CommandEmpty className=\"py-12 text-center text-muted-foreground text-sm\">\n                No results found.\n              </CommandEmpty>\n\n              {navItems.length > 0 && (\n                <CommandGroup\n                  className=\"p-0! **:[[cmdk-group-heading]]:scroll-mt-16 **:[[cmdk-group-heading]]:p-3! **:[[cmdk-group-heading]]:pb-1!\"\n                  heading=\"Pages\"\n                >\n                  {navItems.map((item) => (\n                    <CommandItem\n                      className=\"h-9 rounded-md border border-transparent px-3! font-medium hover:border-input hover:bg-input/50\"\n                      key={item.href}\n                      keywords={item.keywords}\n                      onSelect={() => {\n                        runCommand(() => router.push(item.href));\n                      }}\n                      value={`Navigation ${item.label}`}\n                    >\n                      <IconArrowRight aria-hidden=\"true\" className=\"size-4\" />\n                      {item.label}\n                    </CommandItem>\n                  ))}\n                </CommandGroup>\n              )}\n\n              {pageGroups.map((group) => (\n                <CommandGroup\n                  className=\"p-0! **:[[cmdk-group-heading]]:scroll-mt-16 **:[[cmdk-group-heading]]:p-3! **:[[cmdk-group-heading]]:pb-1!\"\n                  heading={group.name}\n                  key={group.name}\n                >\n                  {group.pages.map((page) => {\n                    const isComponent = page.href.includes('/components/');\n                    return (\n                      <CommandItem\n                        className=\"h-9 rounded-md border border-transparent px-3! font-medium hover:border-input hover:bg-input/50\"\n                        key={page.href}\n                        keywords={page.keywords}\n                        onSelect={() => {\n                          runCommand(() => router.push(page.href));\n                        }}\n                        value={`${group.name} ${page.name}`}\n                      >\n                        {isComponent ? (\n                          <div className=\"aspect-square size-4 rounded-full border border-muted-foreground border-dashed\" />\n                        ) : (\n                          <IconArrowRight\n                            aria-hidden=\"true\"\n                            className=\"size-4\"\n                          />\n                        )}\n                        {page.name}\n                      </CommandItem>\n                    );\n                  })}\n                </CommandGroup>\n              ))}\n\n              {colorGroups.map((colorGroup) => (\n                <CommandGroup\n                  className=\"p-0! **:[[cmdk-group-heading]]:p-3!\"\n                  heading={colorGroup.name}\n                  key={colorGroup.name}\n                >\n                  {colorGroup.colors.map((color) => (\n                    <CommandItem\n                      className=\"h-9 rounded-md border border-transparent px-3! font-medium hover:border-input hover:bg-input/50\"\n                      key={color.className}\n                      keywords={['color', color.name, color.className]}\n                      onSelect={() => {\n                        runCommand(() => copyToClipboard(color.value));\n                      }}\n                      value={color.className}\n                    >\n                      <div\n                        className=\"aspect-square size-4 rounded-sm border\"\n                        style={{ backgroundColor: color.value }}\n                      />\n                      {color.className}\n                      <span className=\"ml-auto font-mono font-normal text-muted-foreground text-xs tabular-nums\">\n                        {color.value}\n                      </span>\n                    </CommandItem>\n                  ))}\n                </CommandGroup>\n              ))}\n            </CommandList>\n          </Command>\n\n          <div className=\"absolute inset-x-0 bottom-0 z-20 flex h-10 items-center gap-2 rounded-b-xl border-t border-t-neutral-100 bg-neutral-50 px-4 font-medium text-muted-foreground text-xs dark:border-t-neutral-700 dark:bg-neutral-800\">\n            <Kbd>\n              <IconCornerDownLeft aria-hidden=\"true\" className=\"size-3\" />\n            </Kbd>\n            Select\n          </div>\n        </DialogContent>\n      </Dialog>\n    </>\n  );\n}\n"
        }
      ],
      "categories": [
        "command-menu"
      ]
    },
    {
      "name": "dialog-01",
      "type": "registry:block",
      "title": "Dialog Confirmation",
      "description": "A dialog confirmation block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "dialog"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/dialogs/dialog-01.tsx",
          "type": "registry:component",
          "target": "components/dialog-01.tsx",
          "content": "'use client';\n\nimport { Check } from 'lucide-react';\nimport { useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from '@/components/ui/dialog';\n\nexport default function Dialog01() {\n  const [open, setOpen] = useState(true);\n\n  return (\n    <Dialog onOpenChange={setOpen} open={open}>\n      <DialogTrigger render={<Button variant=\"outline\" />}>\n        Show Dialog\n      </DialogTrigger>\n\n      <DialogContent className=\"flex flex-col items-center sm:max-w-sm\">\n        <div className=\"flex justify-center\">\n          <div className=\"mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100\">\n            <Check className=\"h-6 w-6 text-green-600\" />\n          </div>\n        </div>\n\n        <DialogHeader className=\"gap-0 text-center\">\n          <DialogTitle className=\"text-balance text-center\">\n            Payment successful\n          </DialogTitle>\n          <DialogDescription className=\"mx-auto mt-2 text-pretty text-center sm:max-w-[90%]\">\n            Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur\n            amet labore.\n          </DialogDescription>\n        </DialogHeader>\n        <DialogFooter className=\"w-full sm:justify-center\">\n          <DialogClose render={<Button className=\"w-full\" />}>\n            Go back to dashboard\n          </DialogClose>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "dialog-02",
      "type": "registry:block",
      "title": "Dialog with Warning Icon",
      "description": "A dialog with warning icon block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "dialog"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/dialogs/dialog-02.tsx",
          "type": "registry:component",
          "target": "components/dialog-02.tsx",
          "content": "'use client';\n\nimport { Check } from 'lucide-react';\nimport { useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from '@/components/ui/dialog';\n\nexport default function Dialog04() {\n  const [open, setOpen] = useState(true);\n\n  return (\n    <Dialog onOpenChange={setOpen} open={open}>\n      <DialogTrigger render={<Button variant=\"outline\" />}>\n        Show Dialog\n      </DialogTrigger>\n\n      <DialogContent className=\"flex flex-col items-center sm:max-w-sm\">\n        <div className=\"flex justify-center\">\n          <div className=\"mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100\">\n            <Check className=\"h-6 w-6 text-green-600\" />\n          </div>\n        </div>\n\n        <DialogHeader className=\"gap-0 text-center\">\n          <DialogTitle className=\"text-balance text-center\">\n            Payment successful\n          </DialogTitle>\n          <DialogDescription className=\"mx-auto mt-2 text-pretty text-center sm:max-w-[90%]\">\n            Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur\n            amet labore.\n          </DialogDescription>\n        </DialogHeader>\n        <DialogFooter className=\"flex w-full flex-col gap-2 sm:flex-row sm:gap-3\">\n          <DialogClose\n            render={<Button className=\"w-full sm:w-1/2\" variant=\"default\" />}\n          >\n            Deactivate\n          </DialogClose>\n          <DialogClose\n            render={<Button className=\"w-full sm:w-1/2\" variant=\"outline\" />}\n          >\n            Cancel\n          </DialogClose>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "dialog-03",
      "type": "registry:block",
      "title": "Dialog with Input Field",
      "description": "A dialog with input field block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "dialog"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/dialogs/dialog-03.tsx",
          "type": "registry:component",
          "target": "components/dialog-03.tsx",
          "content": "'use client';\nimport { AlertTriangleIcon } from 'lucide-react';\nimport { useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from '@/components/ui/dialog';\n\nexport default function Dialog02() {\n  const [open, setOpen] = useState(true);\n\n  return (\n    <Dialog onOpenChange={setOpen} open={open}>\n      <DialogTrigger render={<Button variant=\"destructive\" />}>\n        Deactivate\n      </DialogTrigger>\n      <DialogContent className=\"sm:max-w-lg\">\n        <div className=\"flex items-start space-x-4\">\n          <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-red-100\">\n            <AlertTriangleIcon className=\"h-6 w-6 text-red-600\" />\n          </div>\n          <DialogHeader>\n            <DialogTitle>Deactivate account</DialogTitle>\n            <DialogDescription>\n              Are you sure you want to deactivate your account? All of your data\n              will be permanently removed. This action cannot be undone.\n            </DialogDescription>\n          </DialogHeader>\n        </div>\n        <DialogFooter>\n          <DialogClose render={<Button variant=\"outline\" />}>\n            Cancel\n          </DialogClose>\n          <Button onClick={() => setOpen(false)} variant=\"destructive\">\n            Deactivate\n          </Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "dialog-04",
      "type": "registry:block",
      "title": "Dialog with Two Buttons",
      "description": "A dialog with two buttons block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "dialog",
        "input",
        "label"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/dialogs/dialog-04.tsx",
          "type": "registry:component",
          "target": "components/dialog-04.tsx",
          "content": "'use client';\n\nimport { useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from '@/components/ui/dialog';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\n\nexport default function Dialog03() {\n  const [isOpen, setIsOpen] = useState(true);\n\n  return (\n    <Dialog onOpenChange={setIsOpen} open={isOpen}>\n      <div className=\"flex items-center justify-center py-36\">\n        <DialogTrigger render={<Button />}>Edit Profile</DialogTrigger>\n      </div>\n\n      <DialogContent className=\"sm:max-w-md\">\n        <DialogHeader>\n          <DialogTitle>Edit Profile</DialogTitle>\n          <DialogDescription>\n            Make changes to your profile here. Click save when you&apos;re done.\n          </DialogDescription>\n        </DialogHeader>\n        <div className=\"space-y-2\">\n          <Label className=\"font-medium text-sm\" htmlFor=\"username\">\n            Username\n          </Label>\n          <Input\n            id=\"username\"\n            name=\"username\"\n            placeholder=\"Your username\"\n            type=\"text\"\n          />\n        </div>\n        <DialogFooter>\n          <Button className=\"w-full\" type=\"submit\">\n            Save Changes\n          </Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "dialog-05",
      "type": "registry:block",
      "title": "Dialog with Password Confirmation",
      "description": "A dialog with password confirmation block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "alert-dialog",
        "button",
        "input",
        "label"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/dialogs/dialog-05.tsx",
          "type": "registry:component",
          "target": "components/dialog-05.tsx",
          "content": "'use client';\n\nimport { EyeIcon, EyeOffIcon } from 'lucide-react';\nimport { type FormEvent, useState } from 'react';\nimport {\n  AlertDialog,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogTitle,\n  AlertDialogTrigger,\n} from '@/components/ui/alert-dialog';\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\n\nexport default function Dialog05() {\n  const [isOpen, setIsOpen] = useState(true);\n  const [isVisible, setIsVisible] = useState<boolean>(false);\n\n  const toggleVisibility = () => setIsVisible((prevState) => !prevState);\n  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n    event.preventDefault();\n    setIsOpen(false);\n  };\n\n  return (\n    <AlertDialog onOpenChange={setIsOpen} open={isOpen}>\n      <AlertDialogTrigger render={<Button variant=\"destructive\" />}>\n        Delete Workspace\n      </AlertDialogTrigger>\n      <AlertDialogContent className=\"sm:max-w-md\">\n        <AlertDialogHeader>\n          <AlertDialogTitle className=\"text-balance\">\n            Delete workspace\n          </AlertDialogTitle>\n          <AlertDialogDescription className=\"text-pretty\">\n            All workspace data will be permanently deleted. There is no coming\n            back after you press delete.\n          </AlertDialogDescription>\n        </AlertDialogHeader>\n        <form onSubmit={handleSubmit}>\n          <div>\n            <Label className=\"font-medium text-sm\" htmlFor=\"delete-workspace\">\n              Confirm password\n            </Label>\n            <div className=\"relative mt-2\">\n              <Input\n                className=\"pe-9\"\n                id=\"delete-workspace\"\n                name=\"delete-workspace\"\n                placeholder=\"Password\"\n                required\n                type={isVisible ? 'text' : 'password'}\n              />\n              <button\n                aria-controls=\"delete-workspace\"\n                aria-label={isVisible ? 'Hide password' : 'Show password'}\n                aria-pressed={isVisible}\n                className=\"absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center rounded-e-md\"\n                onClick={toggleVisibility}\n                type=\"button\"\n              >\n                {isVisible ? (\n                  <EyeOffIcon aria-hidden=\"true\" size={16} />\n                ) : (\n                  <EyeIcon aria-hidden=\"true\" size={16} />\n                )}\n              </button>\n            </div>\n          </div>\n          <AlertDialogFooter className=\"mt-4\">\n            <AlertDialogCancel>Cancel</AlertDialogCancel>\n            <Button type=\"submit\" variant=\"destructive\">\n              Delete workspace permanently\n            </Button>\n          </AlertDialogFooter>\n        </form>\n      </AlertDialogContent>\n    </AlertDialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "dialog-06",
      "type": "registry:block",
      "title": "Dialog with Privacy Toggle",
      "description": "A dialog with privacy toggle block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "dialog",
        "input",
        "label",
        "switch"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/dialogs/dialog-06.tsx",
          "type": "registry:component",
          "target": "components/dialog-06.tsx",
          "content": "'use client';\n\nimport { useState } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from '@/components/ui/dialog';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { Switch } from '@/components/ui/switch';\n\nexport default function Dialog06() {\n  const [open, setOpen] = useState(true);\n\n  return (\n    <Dialog onOpenChange={setOpen} open={open}>\n      <DialogTrigger render={<Button onClick={() => setOpen(true)} />}>\n        Create Workspace\n      </DialogTrigger>\n      <DialogContent className=\"p-0 sm:max-w-lg\">\n        <DialogHeader className=\"px-6 pt-4\">\n          <DialogTitle className=\"text-balance font-semibold text-foreground text-lg\">\n            Create workspace\n          </DialogTitle>\n          <DialogDescription className=\"mt-2 text-pretty text-muted-foreground text-sm leading-6\">\n            Workspaces are shared environments where teams can connect to data\n            sources, run queries and create reports.\n          </DialogDescription>\n        </DialogHeader>\n\n        <form action=\"#\" method=\"POST\">\n          <div className=\"px-6 pb-4\">\n            <Label className=\"font-medium text-sm\" htmlFor=\"workspace-name\">\n              Workspace Name<span className=\"text-destructive\">*</span>\n            </Label>\n            <Input\n              className=\"mt-2\"\n              id=\"workspace-name\"\n              name=\"workspace-name\"\n              placeholder=\"My workspace\"\n              required\n              type=\"text\"\n            />\n            <Button className=\"mt-4 w-full\" type=\"submit\">\n              Create workspace\n            </Button>\n          </div>\n          <div className=\"rounded-b-md border-t bg-muted px-6 py-4\">\n            <div className=\"flex items-start space-x-3\">\n              <div className=\"mt-1 pt-0.5\">\n                <Switch\n                  id=\"enable-private-workspace\"\n                  name=\"enable-private-workspace\"\n                />\n              </div>\n              <div>\n                <Label\n                  className=\"font-medium text-sm\"\n                  htmlFor=\"enable-private-workspace\"\n                >\n                  Set workspace to private\n                </Label>\n                <p className=\"text-pretty text-muted-foreground text-sm\">\n                  Only those invited can access or view\n                </p>\n              </div>\n            </div>\n          </div>\n        </form>\n      </DialogContent>\n    </Dialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "dialog-07",
      "type": "registry:block",
      "title": "Dialog with Member List",
      "description": "A dialog with member list block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "alert-dialog",
        "button",
        "input",
        "label"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/dialogs/dialog-07.tsx",
          "type": "registry:component",
          "target": "components/dialog-07.tsx",
          "content": "'use client';\n\nimport { EyeIcon, EyeOffIcon } from 'lucide-react';\nimport { type FormEvent, useState } from 'react';\nimport {\n  AlertDialog,\n  AlertDialogCancel,\n  AlertDialogContent,\n  AlertDialogDescription,\n  AlertDialogFooter,\n  AlertDialogHeader,\n  AlertDialogTitle,\n  AlertDialogTrigger,\n} from '@/components/ui/alert-dialog';\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\n\nexport default function Dialog08() {\n  const [open, setOpen] = useState(true);\n  const [isVisible, setIsVisible] = useState<boolean>(false);\n\n  const toggleVisibility = () => setIsVisible((prevState) => !prevState);\n  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {\n    event.preventDefault();\n    setOpen(false);\n  };\n\n  return (\n    <AlertDialog onOpenChange={setOpen} open={open}>\n      <AlertDialogTrigger render={<Button variant=\"destructive\" />}>\n        Deactivate 2FA\n      </AlertDialogTrigger>\n      <AlertDialogContent className=\"sm:max-w-lg\">\n        <AlertDialogHeader>\n          <AlertDialogTitle className=\"text-balance\">\n            Deactivate two-step authentication\n          </AlertDialogTitle>\n          <AlertDialogDescription className=\"text-pretty\">\n            Enter your password to deactivate the two-step authentication login.\n            Make sure to have your smartphone ready.\n          </AlertDialogDescription>\n        </AlertDialogHeader>\n        <form className=\"space-y-4\" onSubmit={handleSubmit}>\n          <div>\n            <Label className=\"font-medium text-sm\" htmlFor=\"email\">\n              Email\n            </Label>\n            <Input\n              className=\"mt-2\"\n              disabled\n              id=\"email\"\n              name=\"email\"\n              placeholder=\"ephraim@blocks.so\"\n              type=\"email\"\n            />\n          </div>\n          <div>\n            <Label className=\"font-medium text-sm\" htmlFor=\"password\">\n              Confirm password\n            </Label>\n            <div className=\"relative mt-2\">\n              <Input\n                className=\"pe-9\"\n                id=\"password\"\n                name=\"password\"\n                placeholder=\"Password\"\n                required\n                type={isVisible ? 'text' : 'password'}\n              />\n              <button\n                aria-controls=\"password\"\n                aria-label={isVisible ? 'Hide password' : 'Show password'}\n                aria-pressed={isVisible}\n                className=\"absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center rounded-e-md\"\n                onClick={toggleVisibility}\n                type=\"button\"\n              >\n                {isVisible ? (\n                  <EyeOffIcon aria-hidden=\"true\" size={16} />\n                ) : (\n                  <EyeIcon aria-hidden=\"true\" size={16} />\n                )}\n              </button>\n            </div>\n          </div>\n\n          <AlertDialogFooter>\n            <AlertDialogCancel>Cancel</AlertDialogCancel>\n            <Button type=\"submit\" variant=\"destructive\">\n              Deactivate\n            </Button>\n          </AlertDialogFooter>\n        </form>\n      </AlertDialogContent>\n    </AlertDialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "dialog-08",
      "type": "registry:block",
      "title": "Dialog with Email and Password Fields",
      "description": "A dialog with email and password fields block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "avatar",
        "badge",
        "button",
        "dialog",
        "input"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/dialogs/dialog-08.tsx",
          "type": "registry:component",
          "target": "components/dialog-08.tsx",
          "content": "'use client';\n\nimport { UserPlus } from 'lucide-react';\nimport { useState } from 'react';\n\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from '@/components/ui/dialog';\nimport { Input } from '@/components/ui/input';\n\nconst members = [\n  {\n    name: 'Ephraim Duncan',\n    email: 'ephraim@documenso.com',\n    avatarUrl: 'https://blocks.so/avatar-01.png',\n    initials: 'ED',\n    status: 'member',\n  },\n  {\n    name: 'Lucas Smith',\n    email: 'lucas@documenso.com',\n    avatarUrl: 'https://blocks.so/avatar-03.png',\n    initials: 'LS',\n    status: 'member',\n  },\n  {\n    name: 'Timur Ercan',\n    email: 'timur@documenso.com',\n    avatarUrl: 'https://blocks.so/avatar-02.jpg',\n    initials: 'TE',\n    status: 'member',\n  },\n  {\n    name: 'Catalin Pit',\n    email: 'catalin@documenso.com',\n    avatarUrl: 'https://blocks.so/avatar-04.jpg',\n    initials: 'CP',\n    status: 'member',\n  },\n];\n\nexport default function Dialog07() {\n  const [open, setOpen] = useState(true);\n\n  return (\n    <Dialog onOpenChange={setOpen} open={open}>\n      <DialogTrigger render={<Button onClick={() => setOpen(true)} />}>\n        Invite members\n      </DialogTrigger>\n      <DialogContent className=\"sm:max-w-2xl\">\n        <DialogHeader>\n          <DialogTitle className=\"text-balance font-semibold text-foreground\">\n            Invite members\n          </DialogTitle>\n          <DialogDescription className=\"text-pretty text-muted-foreground text-sm leading-6\">\n            Add new team members to your workspace. Please consider your\n            organization&apos;s policies when adding external people.\n          </DialogDescription>\n        </DialogHeader>\n        <form>\n          <div className=\"flex w-full items-center space-x-2\">\n            <div className=\"relative flex-1\">\n              <UserPlus className=\"-translate-y-1/2 absolute top-1/2 left-3 h-4 w-4 text-muted-foreground\" />\n              <Input\n                className=\"h-10 pl-9\"\n                id=\"inviteEmail\"\n                placeholder=\"Add email...\"\n                type=\"email\"\n              />\n            </div>\n            <Button className=\"h-10\" type=\"submit\">\n              Invite\n            </Button>\n          </div>\n        </form>\n        <h4 className=\"mt-4 text-balance font-medium text-foreground text-sm\">\n          People with existing access\n        </h4>\n        <ul className=\"divide-y\">\n          {members.map((member) => (\n            <li\n              className=\"flex items-center justify-between py-2.5\"\n              key={member.name}\n            >\n              <div className=\"flex items-center space-x-3\">\n                <Avatar className=\"h-9 w-9\">\n                  <AvatarImage alt={member.name} src={member.avatarUrl} />\n                  <AvatarFallback>{member.initials}</AvatarFallback>\n                </Avatar>\n                <span className=\"font-medium text-foreground\">\n                  {member.name}\n                </span>\n              </div>\n              <Badge\n                className=\"bg-background font-medium text-xs\"\n                variant=\"outline\"\n              >\n                {member.status}\n              </Badge>\n            </li>\n          ))}\n        </ul>\n      </DialogContent>\n    </Dialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "dialog-09",
      "type": "registry:block",
      "title": "Dialog with Link Share and Toggles",
      "description": "A dialog with link share and toggles block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "dialog",
        "input",
        "label",
        "switch",
        "tooltip"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/dialogs/dialog-09.tsx",
          "type": "registry:component",
          "target": "components/dialog-09.tsx",
          "content": "'use client';\n\nimport { CheckIcon, CopyIcon, ExternalLink, Link, Share2 } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  Dialog,\n  DialogContent,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from '@/components/ui/dialog';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { Switch } from '@/components/ui/switch';\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipProvider,\n  TooltipTrigger,\n} from '@/components/ui/tooltip';\nimport { cn } from '@/lib/utils';\n\nexport default function Dialog09() {\n  const [open, setOpen] = useState<boolean>(true);\n  const [copied, setCopied] = useState<boolean>(false);\n  const inputRef = useRef<HTMLInputElement>(null);\n\n  const handleCopy = () => {\n    if (inputRef.current) {\n      navigator.clipboard.writeText(inputRef.current.value);\n      setCopied(true);\n      setTimeout(() => setCopied(false), 1500);\n    }\n  };\n\n  return (\n    <Dialog onOpenChange={setOpen} open={open}>\n      <DialogTrigger render={<Button />}>\n        <Share2 className=\"mr-2 h-4 w-4\" />\n        Share\n      </DialogTrigger>\n      <DialogContent className=\"sm:max-w-md\">\n        <DialogHeader>\n          <DialogTitle>Share & Collaborate</DialogTitle>\n          <p className=\"text-pretty text-muted-foreground text-sm\">\n            Share this project with your team to collaborate on it.\n          </p>\n        </DialogHeader>\n        <div className=\"space-y-4 py-4\">\n          <div className=\"flex items-center justify-between space-x-2\">\n            <div className=\"flex items-center space-x-2\">\n              <span>Enable comments and suggestions</span>\n            </div>\n            <Switch id=\"comments\" />\n          </div>\n\n          <div className=\"space-y-1.5\">\n            <Label className=\"sr-only\" htmlFor=\"share-link\">\n              Share Link\n            </Label>\n            <div className=\"relative\">\n              <Input\n                className=\"pe-9\"\n                id=\"share-link\"\n                readOnly\n                ref={inputRef}\n                value=\"https://writer.so/app/projects/123?share=true\"\n              />\n              <TooltipProvider delay={0}>\n                <Tooltip>\n                  <TooltipTrigger\n                    render={\n                      <button\n                        aria-label={copied ? 'Copied' : 'Copy to clipboard'}\n                        className=\"absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center rounded-e-md text-muted-foreground/80 outline-none transition-[color,box-shadow] hover:text-foreground focus:z-10 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed\"\n                        disabled={copied}\n                        onClick={handleCopy}\n                      />\n                    }\n                  >\n                    <div\n                      className={cn(\n                        'transition-[transform,opacity] duration-200 ease-out',\n                        copied ? 'scale-100 opacity-100' : 'scale-0 opacity-0'\n                      )}\n                    >\n                      <CheckIcon\n                        aria-hidden=\"true\"\n                        className=\"text-primary\"\n                        size={16}\n                      />\n                    </div>\n                    <div\n                      className={cn(\n                        'absolute transition-[transform,opacity] duration-200 ease-out',\n                        copied ? 'scale-0 opacity-0' : 'scale-100 opacity-100'\n                      )}\n                    >\n                      <CopyIcon aria-hidden=\"true\" size={16} />\n                    </div>\n                  </TooltipTrigger>\n                  <TooltipContent className=\"px-2 py-1 text-xs\">\n                    {copied ? 'Copied!' : 'Copy to clipboard'}\n                  </TooltipContent>\n                </Tooltip>\n              </TooltipProvider>\n            </div>\n          </div>\n\n          <div className=\"flex space-x-2\">\n            <Button className=\"flex-1 gap-2\" onClick={handleCopy}>\n              <Link className=\"h-4 w-4\" />\n              Copy Link\n            </Button>\n            <Button className=\"flex-1 gap-2\" variant=\"outline\">\n              <ExternalLink className=\"h-4 w-4\" />\n              Preview\n            </Button>\n          </div>\n        </div>\n      </DialogContent>\n    </Dialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "dialog-10",
      "type": "registry:block",
      "title": "Dialog with Calendar and Time Picker",
      "description": "A dialog with calendar and time picker block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "calendar",
        "dialog",
        "input",
        "label",
        "popover",
        "select",
        "textarea"
      ],
      "dependencies": [
        "date-fns",
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/dialogs/dialog-10.tsx",
          "type": "registry:component",
          "target": "components/dialog-10.tsx",
          "content": "'use client';\n\nimport { format } from 'date-fns';\nimport { CalendarIcon } from 'lucide-react';\nimport { useMemo, useState } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { Calendar } from '@/components/ui/calendar';\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from '@/components/ui/dialog';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport {\n  Popover,\n  PopoverContent,\n  PopoverTrigger,\n} from '@/components/ui/popover';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport { Textarea } from '@/components/ui/textarea';\nimport { cn } from '@/lib/utils';\n\nexport default function Dialog10() {\n  const [open, setOpen] = useState(true);\n  const [date, setDate] = useState<Date | undefined>(new Date());\n  const [startTime, setStartTime] = useState('09:00');\n\n  const timeOptions = useMemo(() => {\n    const options = [];\n    for (let hour = 0; hour <= 23; hour++) {\n      for (let minute = 0; minute < 60; minute += 30) {\n        const formattedHour = hour.toString().padStart(2, '0');\n        const formattedMinute = minute.toString().padStart(2, '0');\n        const value = `${formattedHour}:${formattedMinute}`;\n        const tempDate = new Date(2000, 0, 1, hour, minute);\n        const label = format(tempDate, 'h:mm a');\n        options.push({ value, label });\n      }\n    }\n\n    if (!options.find((opt) => opt.value === '23:59')) {\n      const endOfDay = new Date(2000, 0, 1, 23, 59);\n      options.push({ value: '23:59', label: format(endOfDay, 'h:mm a') });\n    }\n\n    return options;\n  }, []);\n\n  return (\n    <Dialog onOpenChange={setOpen} open={open}>\n      <DialogTrigger render={<Button />}>Show dialog</DialogTrigger>\n      <DialogContent className=\"gap-0 p-0 sm:max-w-lg\">\n        <DialogHeader className=\"border-b px-6 py-4 pt-5\">\n          <DialogTitle>Schedule a Meeting</DialogTitle>\n        </DialogHeader>\n\n        <form action=\"#\" method=\"POST\">\n          <div className=\"space-y-6 p-6\">\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"title\">Meeting Title</Label>\n              <Input\n                id=\"title\"\n                name=\"title\"\n                placeholder=\"e.g., Project Kickoff\"\n              />\n            </div>\n\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"attendees\">Attendees</Label>\n              <Input\n                id=\"attendees\"\n                name=\"attendees\"\n                placeholder=\"user1@example.com, user2@example.com\"\n              />\n              <p className=\"text-pretty text-muted-foreground text-xs\">\n                Enter email addresses separated by commas.\n              </p>\n            </div>\n\n            <div className=\"grid grid-cols-3 gap-4\">\n              <div className=\"col-span-2 space-y-2\">\n                <Label htmlFor=\"date\">Date</Label>\n                <Popover>\n                  <PopoverTrigger\n                    render={\n                      <Button\n                        className={cn(\n                          'w-full justify-start text-left font-normal',\n                          !date && 'text-muted-foreground'\n                        )}\n                        id=\"date\"\n                        variant={'outline'}\n                      />\n                    }\n                  >\n                    <CalendarIcon className=\"mr-1 h-4 w-4 shrink-0\" />{' '}\n                    {date ? format(date, 'PPP') : <span>Pick a date</span>}\n                  </PopoverTrigger>\n                  <PopoverContent align=\"start\" className=\"w-auto p-0\">\n                    <Calendar\n                      autoFocus\n                      mode=\"single\"\n                      onSelect={setDate}\n                      selected={date}\n                    />\n                  </PopoverContent>\n                </Popover>\n              </div>\n\n              <div className=\"space-y-2\">\n                <Label htmlFor=\"time\">Time</Label>\n                <Select\n                  items={timeOptions}\n                  onValueChange={(value) => {\n                    if (value) {\n                      setStartTime(value);\n                    }\n                  }}\n                  value={startTime}\n                >\n                  <SelectTrigger className=\"w-full\" id=\"time\">\n                    <SelectValue placeholder=\"Select time\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    {timeOptions.map((option) => (\n                      <SelectItem key={option.value} value={option.value}>\n                        {option.label}\n                      </SelectItem>\n                    ))}\n                  </SelectContent>\n                </Select>\n              </div>\n            </div>\n\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"location\">Location / Conference Link</Label>\n              <Input\n                id=\"location\"\n                name=\"location\"\n                placeholder=\"e.g., Conference Room B or https://meet.example.com/...\"\n              />\n            </div>\n\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"description\">Description</Label>\n              <Textarea\n                className=\"min-h-[100px]\"\n                id=\"description\"\n                name=\"description\"\n                placeholder=\"Optional: Add an agenda or notes...\"\n              />\n            </div>\n          </div>\n\n          <div className=\"flex items-center justify-end space-x-2 border-t p-4\">\n            <DialogClose render={<Button type=\"button\" variant=\"ghost\" />}>\n              Cancel\n            </DialogClose>\n            <Button size=\"sm\" type=\"submit\">\n              Schedule\n            </Button>\n          </div>\n        </form>\n      </DialogContent>\n    </Dialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "dialog-11",
      "type": "registry:block",
      "title": "Dialog Multi-Step Wizard",
      "description": "A dialog multi-step wizard block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "dialog",
        "label",
        "select",
        "separator"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/dialogs/dialog-11.tsx",
          "type": "registry:component",
          "target": "components/dialog-11.tsx",
          "content": "'use client';\n\nimport { AppWindowIcon as Apps } from 'lucide-react';\nimport { useState } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from '@/components/ui/dialog';\nimport { Label } from '@/components/ui/label';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport { Separator } from '@/components/ui/separator';\n\nexport default function Dialog11() {\n  const [open, setOpen] = useState(true);\n\n  return (\n    <Dialog onOpenChange={setOpen} open={open}>\n      <DialogTrigger render={<Button />}>Initialize New Project</DialogTrigger>\n      <DialogContent className=\"gap-0 overflow-visible p-0 sm:max-w-2xl\">\n        <DialogHeader className=\"mb-0 border-b px-6 py-4\">\n          <DialogTitle>Initialize New Project</DialogTitle>\n        </DialogHeader>\n\n        <form action=\"#\" method=\"POST\">\n          <div className=\"flex flex-col-reverse md:flex-row\">\n            <div className=\"flex flex-col justify-between md:w-80 md:border-r\">\n              <div className=\"flex-1 grow\">\n                <div className=\"border-t p-6 md:border-none\">\n                  <div className=\"flex items-center space-x-3\">\n                    <div className=\"inline-flex shrink-0 items-center justify-center rounded-sm bg-muted p-3\">\n                      <Apps\n                        aria-hidden={true}\n                        className=\"size-5 text-foreground\"\n                      />\n                    </div>\n                    <div className=\"space-y-0.5\">\n                      <h3 className=\"text-balance font-medium text-foreground text-sm\">\n                        Project Starter\n                      </h3>\n                      <p className=\"text-pretty text-muted-foreground text-sm\">\n                        Configure your new codebase\n                      </p>\n                    </div>\n                  </div>\n                  <Separator className=\"my-4\" />\n                  <h4 className=\"text-balance font-medium text-foreground text-sm\">\n                    Description\n                  </h4>\n                  <p className=\"mt-1 text-pretty text-muted-foreground text-sm leading-6\">\n                    Quickly set up the foundational tools for your project.\n                  </p>\n                  <h4 className=\"mt-6 text-balance font-medium text-foreground text-sm\">\n                    Info\n                  </h4>\n                  <p className=\"mt-1 text-pretty text-muted-foreground text-sm leading-6\">\n                    Select your preferred stack and configurations.\n                  </p>\n                </div>\n              </div>\n              <div className=\"flex items-center justify-between border-t p-4\">\n                <DialogClose render={<Button type=\"button\" variant=\"ghost\" />}>\n                  Cancel\n                </DialogClose>\n                <Button size=\"sm\" type=\"submit\">\n                  Initialize\n                </Button>\n              </div>\n            </div>\n\n            <div className=\"flex-1 space-y-6 p-6 md:px-6 md:pt-6 md:pb-8\">\n              <div className=\"space-y-2\">\n                <div className=\"flex items-center space-x-3\">\n                  <div className=\"inline-flex size-6 items-center justify-center rounded-sm bg-muted text-foreground text-sm\">\n                    1\n                  </div>\n                  <Label\n                    className=\"font-medium text-foreground text-sm\"\n                    htmlFor=\"framework\"\n                  >\n                    Select Framework\n                  </Label>\n                </div>\n                <Select\n                  defaultValue=\"react\"\n                  items={{\n                    react: 'Next.js',\n                    vue: 'React Router',\n                    angular: 'Tanstack Start',\n                    svelte: 'SvelteKit',\n                    vanilla: 'SolidStart',\n                  }}\n                >\n                  <SelectTrigger\n                    className=\"w-full\"\n                    id=\"framework\"\n                    name=\"framework\"\n                  >\n                    <SelectValue placeholder=\"Select framework\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectItem value=\"react\">Next.js</SelectItem>\n                    <SelectItem value=\"vue\">React Router</SelectItem>\n                    <SelectItem value=\"angular\">Tanstack Start</SelectItem>\n                    <SelectItem value=\"svelte\">SvelteKit</SelectItem>\n                    <SelectItem value=\"vanilla\">SolidStart</SelectItem>\n                  </SelectContent>\n                </Select>\n              </div>\n              <div className=\"space-y-2\">\n                <div className=\"flex items-center space-x-3\">\n                  <div className=\"inline-flex size-6 items-center justify-center rounded-sm bg-muted text-foreground text-sm\">\n                    2\n                  </div>\n                  <Label\n                    className=\"font-medium text-foreground text-sm\"\n                    htmlFor=\"package-manager\"\n                  >\n                    Choose Package Manager\n                  </Label>\n                </div>\n                <Select\n                  defaultValue=\"npm\"\n                  items={{ npm: 'npm', yarn: 'yarn', pnpm: 'pnpm', bun: 'bun' }}\n                >\n                  <SelectTrigger\n                    className=\"w-full\"\n                    id=\"package-manager\"\n                    name=\"package-manager\"\n                  >\n                    <SelectValue placeholder=\"Select manager\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectItem value=\"npm\">npm</SelectItem>\n                    <SelectItem value=\"yarn\">yarn</SelectItem>\n                    <SelectItem value=\"pnpm\">pnpm</SelectItem>\n                    <SelectItem value=\"bun\">bun</SelectItem>\n                  </SelectContent>\n                </Select>\n              </div>\n              <div>\n                <div className=\"flex items-center space-x-3\">\n                  <div className=\"inline-flex size-6 items-center justify-center rounded-sm bg-muted text-foreground text-sm\">\n                    3\n                  </div>\n                  <Label\n                    className=\"font-medium text-foreground text-sm\"\n                    htmlFor=\"linter\"\n                  >\n                    Configure Linter/Formatter\n                  </Label>\n                </div>\n                <p className=\"mt-1 text-pretty text-muted-foreground text-xs\">\n                  Ensure code quality and consistency.\n                </p>\n                <Select\n                  defaultValue=\"eslint-prettier\"\n                  items={{\n                    'eslint-prettier': 'ESLint + Prettier',\n                    eslint: 'ESLint Only',\n                    prettier: 'Prettier Only',\n                    biome: 'Biome',\n                    oxlint: 'Oxlint',\n                    none: 'None',\n                  }}\n                >\n                  <SelectTrigger\n                    className=\"mt-4 w-full\"\n                    id=\"linter\"\n                    name=\"linter\"\n                  >\n                    <SelectValue placeholder=\"Select tools\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectItem value=\"eslint-prettier\">\n                      ESLint + Prettier\n                    </SelectItem>\n                    <SelectItem value=\"eslint\">ESLint Only</SelectItem>\n                    <SelectItem value=\"prettier\">Prettier Only</SelectItem>\n                    <SelectItem value=\"biome\">Biome</SelectItem>\n                    <SelectItem value=\"oxlint\">Oxlint</SelectItem>\n                    <SelectItem value=\"none\">None</SelectItem>\n                  </SelectContent>\n                </Select>\n              </div>\n              <div>\n                <div className=\"flex items-center space-x-3\">\n                  <div className=\"inline-flex size-6 items-center justify-center rounded-sm bg-muted text-foreground text-sm\">\n                    4\n                  </div>\n                  <Label\n                    className=\"font-medium text-foreground text-sm\"\n                    htmlFor=\"testing-tool\"\n                  >\n                    Select Testing Tool\n                  </Label>\n                </div>\n                <p className=\"mt-1 text-pretty text-muted-foreground text-xs\">\n                  Choose a framework for unit/integration tests.\n                </p>\n                <Select\n                  defaultValue=\"jest\"\n                  items={{\n                    jest: 'Jest',\n                    vitest: 'Vitest',\n                    cypress: 'Cypress',\n                    none: 'None',\n                  }}\n                >\n                  <SelectTrigger\n                    className=\"mt-4 w-full\"\n                    id=\"testing-tool\"\n                    name=\"testing-tool\"\n                  >\n                    <SelectValue placeholder=\"Select tool\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectItem value=\"jest\">Jest</SelectItem>\n                    <SelectItem value=\"vitest\">Vitest</SelectItem>\n                    <SelectItem value=\"cypress\">Cypress</SelectItem>\n                    <SelectItem value=\"none\">None</SelectItem>\n                  </SelectContent>\n                </Select>\n              </div>\n            </div>\n          </div>\n        </form>\n      </DialogContent>\n    </Dialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "dialog-12",
      "type": "registry:block",
      "title": "Dialog with Avatar Upload",
      "description": "A dialog with avatar upload block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "avatar",
        "button",
        "dialog",
        "input",
        "label"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/dialogs/dialog-12.tsx",
          "type": "registry:component",
          "target": "components/dialog-12.tsx",
          "content": "'use client';\n\nimport { Plus, UserRoundIcon, X } from 'lucide-react';\nimport { useRef, useState } from 'react';\n\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';\nimport { Button } from '@/components/ui/button';\nimport {\n  Dialog,\n  DialogContent,\n  DialogHeader,\n  DialogTitle,\n  DialogTrigger,\n} from '@/components/ui/dialog';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\n\nexport default function Dialog12() {\n  const [open, setOpen] = useState(true);\n  const [authorName, setAuthorName] = useState('Ephraim Duncan');\n  const [title, setTitle] = useState('Design Engineer');\n  const [image, setImage] = useState<string | null>(null);\n  const fileInputRef = useRef<HTMLInputElement>(null);\n\n  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const file = e.target.files?.[0];\n    if (file) {\n      if (file.size > 1_048_576) {\n        alert('File size exceeds 1MB limit');\n        return;\n      }\n\n      const reader = new FileReader();\n      reader.onload = (event) => {\n        setImage(event.target?.result as string);\n      };\n      reader.readAsDataURL(file);\n    }\n  };\n\n  const triggerFileInput = () => {\n    fileInputRef.current?.click();\n  };\n\n  return (\n    <Dialog onOpenChange={setOpen} open={open}>\n      <DialogTrigger render={<Button />}>Open Dialog</DialogTrigger>\n      <DialogContent className=\"gap-0 rounded-3xl p-0 sm:max-w-lg\">\n        <DialogHeader className=\"border-b px-6 py-4\">\n          <DialogTitle className=\"text-balance font-medium\">\n            Add a writer\n          </DialogTitle>\n        </DialogHeader>\n\n        <div className=\"grid grid-cols-1 px-6 pt-4 pb-6 md:grid-cols-5\">\n          <div className=\"flex flex-col items-center justify-center md:col-span-2\">\n            <div className=\"relative mb-2\">\n              <Avatar className=\"h-24 w-24 border-2 border-muted\">\n                <AvatarImage alt=\"Profile\" src={image || undefined} />\n                <AvatarFallback>\n                  <UserRoundIcon\n                    aria-hidden=\"true\"\n                    className=\"text-muted-foreground\"\n                    size={52}\n                  />\n                </AvatarFallback>\n              </Avatar>\n              <Button\n                className=\"-top-0.5 -right-0.5 absolute rounded-full border-[3px] border-background bg-accent hover:bg-accent\"\n                onClick={() => {\n                  if (image) {\n                    setImage(null);\n                    if (fileInputRef.current) {\n                      fileInputRef.current.value = '';\n                    }\n                  } else {\n                    triggerFileInput();\n                  }\n                }}\n                size=\"icon-sm\"\n                variant=\"ghost\"\n              >\n                {image ? (\n                  <X className=\"h-4 w-4 text-muted-foreground\" />\n                ) : (\n                  <Plus className=\"h-3 w-3 text-muted-foreground\" />\n                )}\n                <span className=\"sr-only\">\n                  {image ? 'Remove image' : 'Upload image'}\n                </span>\n              </Button>\n            </div>\n\n            <p className=\"text-pretty text-center font-medium\">Upload Image</p>\n            <p className=\"text-pretty text-center text-muted-foreground text-sm\">\n              Max file size: 1MB\n            </p>\n            <input\n              accept=\"image/*\"\n              className=\"hidden\"\n              onChange={handleFileChange}\n              ref={fileInputRef}\n              type=\"file\"\n            />\n            <Button\n              className=\"mt-2\"\n              onClick={triggerFileInput}\n              size=\"sm\"\n              variant=\"outline\"\n            >\n              Add Image\n            </Button>\n          </div>\n\n          <div className=\"flex flex-col justify-between md:col-span-3\">\n            <div className=\"space-y-4\">\n              <div className=\"space-y-1\">\n                <Label className=\"flex items-center\" htmlFor=\"author-name\">\n                  Author name <span className=\"text-primary\">*</span>\n                </Label>\n                <Input\n                  id=\"author-name\"\n                  onChange={(e) => setAuthorName(e.target.value)}\n                  required\n                  value={authorName}\n                />\n              </div>\n\n              <div className=\"space-y-1\">\n                <div className=\"flex items-center\">\n                  <Label htmlFor=\"title\">Title</Label>\n                </div>\n                <Input\n                  id=\"title\"\n                  onChange={(e) => setTitle(e.target.value)}\n                  value={title}\n                />\n              </div>\n            </div>\n\n            <div className=\"flex justify-end gap-2\">\n              <Button onClick={() => setOpen(false)} variant=\"outline\">\n                Cancel\n              </Button>\n              <Button className=\"bg-foreground text-background hover:bg-foreground/90\">\n                Save Changes\n              </Button>\n            </div>\n          </div>\n        </div>\n      </DialogContent>\n    </Dialog>\n  );\n}\n"
        }
      ],
      "categories": [
        "dialogs"
      ]
    },
    {
      "name": "file-upload-01",
      "type": "registry:block",
      "title": "File Upload with Preview",
      "description": "A file upload with preview block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "input",
        "label",
        "select",
        "tooltip"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/file-upload/file-upload-01/file-list.tsx",
          "type": "registry:component",
          "target": "components/file-upload-01/file-list.tsx",
          "content": "import { cn } from '@/lib/utils';\nimport { UploadedFileItem } from '@/components/file-upload-01/file-item';\n\ninterface UploadedFileListProps {\n  uploadedFiles: File[];\n  fileProgresses: Record<string, number>;\n  removeFile: (filename: string) => void;\n}\n\nexport function FileList({\n  uploadedFiles,\n  fileProgresses,\n  removeFile,\n}: UploadedFileListProps) {\n  if (uploadedFiles.length === 0) {\n    return null;\n  }\n\n  return (\n    <div className={cn('mt-4 space-y-3 px-6 pb-5')}>\n      {uploadedFiles.map((file, index) => (\n        <UploadedFileItem\n          file={file}\n          key={file.name + index}\n          onRemove={removeFile}\n          progress={fileProgresses[file.name] || 0}\n        />\n      ))}\n    </div>\n  );\n}\n"
        },
        {
          "path": "content/components/file-upload/file-upload-01/file-item.tsx",
          "type": "registry:component",
          "target": "components/file-upload-01/file-item.tsx",
          "content": "import { Trash2 } from 'lucide-react';\nimport { useEffect } from 'react';\nimport { Button } from '@/components/ui/button';\n\ninterface UploadedFileItemProps {\n  file: File;\n  progress: number;\n  onRemove: (filename: string) => void;\n}\n\nexport function UploadedFileItem({\n  file,\n  progress,\n  onRemove,\n}: UploadedFileItemProps) {\n  const imageUrl = URL.createObjectURL(file);\n\n  useEffect(() => {\n    return () => URL.revokeObjectURL(imageUrl);\n  }, [imageUrl]);\n\n  return (\n    <div\n      className=\"flex flex-col rounded-lg border border-border p-2\"\n      key={file.name}\n    >\n      <div className=\"flex items-center gap-2\">\n        <div className=\"row-span-2 flex h-14 w-18 items-center justify-center self-start overflow-hidden rounded-sm bg-muted\">\n          <img\n            alt={file.name}\n            className=\"h-full w-full object-cover\"\n            src={imageUrl}\n          />\n        </div>\n\n        <div className=\"flex-1 pr-1\">\n          <div className=\"flex items-center justify-between\">\n            <div className=\"flex items-center gap-2\">\n              <span className=\"max-w-[250px] truncate text-foreground text-sm\">\n                {file.name}\n              </span>\n              <span className=\"whitespace-nowrap text-muted-foreground text-sm\">\n                {Math.round(file.size / 1024)} KB\n              </span>\n            </div>\n            <Button\n              className=\"bg-transparent! hover:text-red-500\"\n              onClick={() => onRemove(file.name)}\n              size=\"icon-sm\"\n              variant=\"ghost\"\n            >\n              <Trash2 className=\"h-4 w-4\" />\n            </Button>\n          </div>\n\n          <div className=\"flex items-center gap-2\">\n            <div className=\"h-2 flex-1 overflow-hidden rounded-full bg-muted\">\n              <div\n                className=\"h-full bg-primary\"\n                style={{\n                  width: `${progress || 0}%`,\n                }}\n              />\n            </div>\n            <span className=\"whitespace-nowrap text-muted-foreground text-xs\">\n              {Math.round(progress || 0)}%\n            </span>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        },
        {
          "path": "content/components/file-upload/file-upload-01/index.tsx",
          "type": "registry:component",
          "target": "components/file-upload-01/index.tsx",
          "content": "'use client';\n\nimport { HelpCircle } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent } from '@/components/ui/card';\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipProvider,\n  TooltipTrigger,\n} from '@/components/ui/tooltip';\nimport { FileDropzone } from '@/components/file-upload-01/dropzone';\nimport { FileList } from '@/components/file-upload-01/file-list';\nimport { Form } from '@/components/file-upload-01/form';\n\nexport default function FileUpload01() {\n  const fileInputRef = useRef<HTMLInputElement>(null);\n  const [uploadedFiles, setUploadedFiles] = useState<File[]>([]);\n  const [fileProgresses, setFileProgresses] = useState<Record<string, number>>(\n    {}\n  );\n\n  const handleFileSelect = (files: FileList | null) => {\n    if (!files) return;\n\n    const newFiles = Array.from(files);\n    setUploadedFiles((prev) => [...prev, ...newFiles]);\n\n    newFiles.forEach((file) => {\n      let progress = 0;\n      const interval = setInterval(() => {\n        progress += Math.random() * 10;\n        if (progress >= 100) {\n          progress = 100;\n          clearInterval(interval);\n        }\n        setFileProgresses((prev) => ({\n          ...prev,\n          [file.name]: Math.min(progress, 100),\n        }));\n      }, 300);\n    });\n  };\n\n  const handleBoxClick = () => {\n    fileInputRef.current?.click();\n  };\n\n  const handleDragOver = (e: React.DragEvent) => {\n    e.preventDefault();\n  };\n\n  const handleDrop = (e: React.DragEvent) => {\n    e.preventDefault();\n    handleFileSelect(e.dataTransfer.files);\n  };\n\n  const removeFile = (filename: string) => {\n    setUploadedFiles((prev) => prev.filter((file) => file.name !== filename));\n    setFileProgresses((prev) => {\n      const newProgresses = { ...prev };\n      delete newProgresses[filename];\n      return newProgresses;\n    });\n  };\n\n  return (\n    <div className=\"flex items-center justify-center p-10\">\n      <Card className=\"mx-auto w-full max-w-lg rounded-lg bg-background p-0 shadow-md\">\n        <CardContent className=\"p-0\">\n          <div className=\"p-6 pb-4\">\n            <div className=\"flex items-start justify-between\">\n              <div>\n                <h2 className=\"font-medium text-foreground text-lg\">\n                  Create a new project\n                </h2>\n                <p className=\"mt-1 text-muted-foreground text-sm\">\n                  Drag and drop files to create a new project.\n                </p>\n              </div>\n            </div>\n          </div>\n          <Form />\n          <FileDropzone\n            fileInputRef={fileInputRef}\n            handleBoxClick={handleBoxClick}\n            handleDragOver={handleDragOver}\n            handleDrop={handleDrop}\n            handleFileSelect={handleFileSelect}\n          />\n          <FileList\n            fileProgresses={fileProgresses}\n            removeFile={removeFile}\n            uploadedFiles={uploadedFiles}\n          />\n          <div className=\"flex items-center justify-between rounded-b-lg border-border border-t bg-muted px-6 py-3\">\n            <TooltipProvider delay={0}>\n              <Tooltip>\n                <TooltipTrigger\n                  render={\n                    <Button\n                      className=\"flex items-center text-muted-foreground hover:text-foreground\"\n                      size=\"sm\"\n                      variant=\"ghost\"\n                    />\n                  }\n                >\n                  <HelpCircle className=\"mr-1 h-4 w-4\" />\n                  Need help?\n                </TooltipTrigger>\n                <TooltipContent className=\"border bg-background py-3 text-foreground\">\n                  <div className=\"space-y-1\">\n                    <p className=\"font-medium text-[13px]\">Need assistance?</p>\n                    <p className=\"max-w-[200px] text-muted-foreground text-xs dark:text-muted-background\">\n                      Upload project images by dragging and dropping files or\n                      using the file browser. Supported formats: JPG, PNG, SVG.\n                      Maximum file size: 4MB.\n                    </p>\n                  </div>\n                </TooltipContent>\n              </Tooltip>\n            </TooltipProvider>\n\n            <div className=\"flex gap-2\">\n              <Button\n                className=\"h-9 px-4 font-medium text-sm\"\n                variant=\"outline\"\n              >\n                Cancel\n              </Button>\n              <Button className=\"h-9 px-4 font-medium text-sm\">Continue</Button>\n            </div>\n          </div>\n        </CardContent>\n      </Card>\n    </div>\n  );\n}\n"
        },
        {
          "path": "content/components/file-upload/file-upload-01/dropzone.tsx",
          "type": "registry:component",
          "target": "components/file-upload-01/dropzone.tsx",
          "content": "import { Upload } from 'lucide-react';\nimport type React from 'react';\nimport type { RefObject } from 'react';\n\ninterface FileDropzoneProps {\n  fileInputRef: RefObject<HTMLInputElement | null>;\n  handleBoxClick: () => void;\n  handleDragOver: (e: React.DragEvent) => void;\n  handleDrop: (e: React.DragEvent) => void;\n  handleFileSelect: (files: FileList | null) => void;\n}\n\nexport function FileDropzone({\n  fileInputRef,\n  handleBoxClick,\n  handleDragOver,\n  handleDrop,\n  handleFileSelect,\n}: FileDropzoneProps) {\n  return (\n    <div className=\"px-6\">\n      <div\n        className=\"flex cursor-pointer flex-col items-center justify-center rounded-md border-2 border-border border-dashed p-8 text-center\"\n        onClick={handleBoxClick}\n        onDragOver={handleDragOver}\n        onDrop={handleDrop}\n      >\n        <div className=\"mb-2 rounded-full bg-muted p-3\">\n          <Upload className=\"h-5 w-5 text-muted-foreground\" />\n        </div>\n        <p className=\"font-medium text-foreground text-sm\">\n          Upload a project image\n        </p>\n        <p className=\"mt-1 text-muted-foreground text-sm\">\n          or,{' '}\n          <label\n            className=\"cursor-pointer font-medium text-primary hover:text-primary/90\"\n            htmlFor=\"fileUpload\"\n            onClick={(e) => e.stopPropagation()} // Prevent triggering handleBoxClick\n          >\n            click to browse\n          </label>{' '}\n          (4MB max)\n        </p>\n        <input\n          accept=\"image/*\"\n          className=\"hidden\"\n          id=\"fileUpload\"\n          onChange={(e) => handleFileSelect(e.target.files)}\n          ref={fileInputRef}\n          type=\"file\"\n        />\n      </div>\n    </div>\n  );\n}\n"
        },
        {
          "path": "content/components/file-upload/file-upload-01/form.tsx",
          "type": "registry:component",
          "target": "components/file-upload-01/form.tsx",
          "content": "import { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport {\n  Select,\n  SelectContent,\n  SelectGroup,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\n\nexport function Form() {\n  return (\n    <div className=\"mt-2 px-6 pb-4\">\n      <div className=\"grid grid-cols-2 gap-4\">\n        <div>\n          <Label className=\"mb-2\" htmlFor=\"projectName\">\n            Project name\n          </Label>\n          <Input\n            defaultValue=\"Open Source Stripe\"\n            id=\"projectName\"\n            type=\"text\"\n          />\n        </div>\n\n        <div>\n          <Label className=\"mb-2\" htmlFor=\"projectLead\">\n            Project lead\n          </Label>\n          <Select\n            defaultValue=\"1\"\n            items={{\n              '1': 'Ephraim Duncan',\n              '2': 'Lucas Smith',\n              '3': 'Timur Ercan',\n            }}\n          >\n            <SelectTrigger className=\"ps-2\" id=\"projectLead\">\n              <SelectValue placeholder=\"Select framework\" />\n            </SelectTrigger>\n            <SelectContent>\n              <SelectGroup>\n                <SelectItem value=\"1\">\n                  <img\n                    alt=\"Ephraim Duncan\"\n                    className=\"size-5 rounded\"\n                    height={20}\n                    src=\"https://blocks.so/avatar-01.png\"\n                    width={20}\n                  />\n                  <span className=\"truncate\">Ephraim Duncan</span>\n                </SelectItem>\n                <SelectItem value=\"2\">\n                  <img\n                    alt=\"Lucas Smith\"\n                    className=\"size-5 rounded\"\n                    height={20}\n                    src=\"https://blocks.so/avatar-03.png\"\n                    width={20}\n                  />\n                  <span className=\"truncate\">Lucas Smith</span>\n                </SelectItem>\n                <SelectItem value=\"3\">\n                  <img\n                    alt=\"Timur Ercan\"\n                    className=\"size-5 rounded\"\n                    height={20}\n                    src=\"https://blocks.so/avatar-02.jpg\"\n                    width={20}\n                  />\n                  <span className=\"truncate\">Timur Ercan</span>\n                </SelectItem>\n              </SelectGroup>\n            </SelectContent>\n          </Select>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "file-upload"
      ]
    },
    {
      "name": "file-upload-01",
      "type": "registry:block",
      "title": "File Upload with Preview",
      "description": "A file upload with preview block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "input",
        "label",
        "select",
        "tooltip"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/file-upload/file-upload-01.tsx",
          "type": "registry:component",
          "target": "components/file-upload-01.tsx",
          "content": "'use client';\n\nimport { HelpCircle, Trash2, Upload } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport {\n  Select,\n  SelectContent,\n  SelectGroup,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipProvider,\n  TooltipTrigger,\n} from '@/components/ui/tooltip';\nimport { cn } from '@/lib/utils';\n\nexport default function FileUpload01() {\n  const fileInputRef = useRef<HTMLInputElement>(null);\n  const [uploadedFiles, setUploadedFiles] = useState<File[]>([]);\n  const [fileProgresses, setFileProgresses] = useState<Record<string, number>>(\n    {}\n  );\n\n  const handleFileSelect = (files: FileList | null) => {\n    if (!files) return;\n\n    const newFiles = Array.from(files);\n    setUploadedFiles((prev) => [...prev, ...newFiles]);\n\n    // Simulate upload progress for each file\n    newFiles.forEach((file) => {\n      let progress = 0;\n      const interval = setInterval(() => {\n        progress += Math.random() * 10;\n        if (progress >= 100) {\n          progress = 100;\n          clearInterval(interval);\n        }\n        setFileProgresses((prev) => ({\n          ...prev,\n          [file.name]: Math.min(progress, 100),\n        }));\n      }, 300);\n    });\n  };\n\n  const handleBoxClick = () => {\n    fileInputRef.current?.click();\n  };\n\n  const handleDragOver = (e: React.DragEvent) => {\n    e.preventDefault();\n  };\n\n  const handleDrop = (e: React.DragEvent) => {\n    e.preventDefault();\n    handleFileSelect(e.dataTransfer.files);\n  };\n\n  const removeFile = (filename: string) => {\n    setUploadedFiles((prev) => prev.filter((file) => file.name !== filename));\n    setFileProgresses((prev) => {\n      const newProgresses = { ...prev };\n      delete newProgresses[filename];\n      return newProgresses;\n    });\n  };\n\n  return (\n    <div className=\"flex items-center justify-center p-10\">\n      <Card className=\"mx-auto w-full max-w-lg rounded-lg bg-background p-0 shadow-md\">\n        <CardContent className=\"p-0\">\n          <div className=\"p-6 pb-4\">\n            <div className=\"flex items-start justify-between\">\n              <div>\n                <h2 className=\"text-balance font-medium text-foreground text-lg\">\n                  Create a new project\n                </h2>\n                <p className=\"mt-1 text-pretty text-muted-foreground text-sm\">\n                  Drag and drop files to create a new project.\n                </p>\n              </div>\n            </div>\n          </div>\n\n          <div className=\"mt-2 px-6 pb-4\">\n            <div className=\"grid grid-cols-2 gap-4\">\n              <div>\n                <Label className=\"mb-2\" htmlFor=\"projectName\">\n                  Project name\n                </Label>\n                <Input\n                  defaultValue=\"Open Source Stripe\"\n                  id=\"projectName\"\n                  type=\"text\"\n                />\n              </div>\n\n              <div>\n                <Label className=\"mb-2\" htmlFor=\"projectLead\">\n                  Project lead\n                </Label>\n                <Select\n                  defaultValue=\"1\"\n                  items={{\n                    '1': 'Ephraim Duncan',\n                    '2': 'Lucas Smith',\n                    '3': 'Timur Ercan',\n                  }}\n                >\n                  <SelectTrigger className=\"w-full ps-2\" id=\"projectLead\">\n                    <SelectValue placeholder=\"Select project lead\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectGroup>\n                      <SelectItem value=\"1\">\n                        <img\n                          alt=\"Ephraim Duncan\"\n                          className=\"size-5 rounded\"\n                          height={20}\n                          src=\"https://blocks.so/avatar-01.png\"\n                          width={20}\n                        />\n                        <span className=\"truncate\">Ephraim Duncan</span>\n                      </SelectItem>\n                      <SelectItem value=\"2\">\n                        <img\n                          alt=\"Lucas Smith\"\n                          className=\"size-5 rounded\"\n                          height={20}\n                          src=\"https://blocks.so/avatar-03.png\"\n                          width={20}\n                        />\n                        <span className=\"truncate\">Lucas Smith</span>\n                      </SelectItem>\n                      <SelectItem value=\"3\">\n                        <img\n                          alt=\"Timur Ercan\"\n                          className=\"size-5 rounded\"\n                          height={20}\n                          src=\"https://blocks.so/avatar-02.jpg\"\n                          width={20}\n                        />\n                        <span className=\"truncate\">Timur Ercan</span>\n                      </SelectItem>\n                    </SelectGroup>\n                  </SelectContent>\n                </Select>\n              </div>\n            </div>\n          </div>\n\n          <div className=\"px-6\">\n            <div\n              className=\"flex cursor-pointer flex-col items-center justify-center rounded-md border-2 border-border border-dashed p-8 text-center\"\n              onClick={handleBoxClick}\n              onDragOver={handleDragOver}\n              onDrop={handleDrop}\n            >\n              <div className=\"mb-2 rounded-full bg-muted p-3\">\n                <Upload className=\"h-5 w-5 text-muted-foreground\" />\n              </div>\n              <p className=\"text-pretty font-medium text-foreground text-sm\">\n                Upload a project image\n              </p>\n              <p className=\"mt-1 text-pretty text-muted-foreground text-sm\">\n                or,{' '}\n                <label\n                  className=\"cursor-pointer font-medium text-primary hover:text-primary/90\"\n                  htmlFor=\"fileUpload\"\n                  onClick={(e) => e.stopPropagation()}\n                >\n                  click to browse\n                </label>{' '}\n                (4MB max)\n              </p>\n              <input\n                accept=\"image/*\"\n                className=\"hidden\"\n                id=\"fileUpload\"\n                onChange={(e) => handleFileSelect(e.target.files)}\n                ref={fileInputRef}\n                type=\"file\"\n              />\n            </div>\n          </div>\n\n          <div\n            className={cn(\n              'space-y-3 px-6 pb-5',\n              uploadedFiles.length > 0 ? 'mt-4' : ''\n            )}\n          >\n            {uploadedFiles.map((file, index) => {\n              const imageUrl = URL.createObjectURL(file);\n\n              return (\n                <div\n                  className=\"flex flex-col rounded-lg border border-border p-2\"\n                  key={file.name + index}\n                  onLoad={() => {\n                    return () => URL.revokeObjectURL(imageUrl);\n                  }}\n                >\n                  <div className=\"flex items-center gap-2\">\n                    <div className=\"row-span-2 flex h-14 w-18 items-center justify-center self-start overflow-hidden rounded-sm bg-muted\">\n                      <img\n                        alt={file.name}\n                        className=\"h-full w-full object-cover\"\n                        src={imageUrl}\n                      />\n                    </div>\n\n                    <div className=\"flex-1 pr-1\">\n                      <div className=\"flex items-center justify-between\">\n                        <div className=\"flex items-center gap-2\">\n                          <span className=\"max-w-[250px] truncate text-foreground text-sm\">\n                            {file.name}\n                          </span>\n                          <span className=\"whitespace-nowrap text-muted-foreground text-sm\">\n                            {Math.round(file.size / 1024)} KB\n                          </span>\n                        </div>\n                        <Button\n                          className=\"bg-transparent! hover:text-red-500\"\n                          onClick={() => removeFile(file.name)}\n                          size=\"icon-sm\"\n                          variant=\"ghost\"\n                        >\n                          <Trash2 className=\"h-4 w-4\" />\n                        </Button>\n                      </div>\n\n                      <div className=\"flex items-center gap-2\">\n                        <div className=\"h-2 flex-1 overflow-hidden rounded-full bg-muted\">\n                          <div\n                            className=\"h-full bg-primary\"\n                            style={{\n                              width: `${fileProgresses[file.name] || 0}%`,\n                            }}\n                          />\n                        </div>\n                        <span className=\"whitespace-nowrap text-muted-foreground text-xs\">\n                          {Math.round(fileProgresses[file.name] || 0)}%\n                        </span>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n              );\n            })}\n          </div>\n\n          <div className=\"flex items-center justify-between rounded-b-lg border-border border-t bg-muted px-6 py-3\">\n            <TooltipProvider delay={0}>\n              <Tooltip>\n                <TooltipTrigger\n                  render={\n                    <Button\n                      className=\"flex items-center text-muted-foreground hover:text-foreground\"\n                      size=\"sm\"\n                      variant=\"ghost\"\n                    />\n                  }\n                >\n                  <HelpCircle className=\"mr-1 h-4 w-4\" />\n                  Need help?\n                </TooltipTrigger>\n                <TooltipContent className=\"border bg-background py-3 text-foreground\">\n                  <div className=\"space-y-1\">\n                    <p className=\"text-pretty font-medium text-[13px]\">\n                      Need assistance?\n                    </p>\n                    <p className=\"max-w-[200px] text-pretty text-muted-foreground text-xs dark:text-muted-background\">\n                      Upload project images by dragging and dropping files or\n                      using the file browser. Supported formats: JPG, PNG, SVG.\n                      Maximum file size: 4MB.\n                    </p>\n                  </div>\n                </TooltipContent>\n              </Tooltip>\n            </TooltipProvider>\n\n            <div className=\"flex gap-2\">\n              <Button\n                className=\"h-9 px-4 font-medium text-sm\"\n                variant=\"outline\"\n              >\n                Cancel\n              </Button>\n              <Button className=\"h-9 px-4 font-medium text-sm\">Continue</Button>\n            </div>\n          </div>\n        </CardContent>\n      </Card>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "file-upload"
      ]
    },
    {
      "name": "file-upload-02",
      "type": "registry:block",
      "title": "File Upload Simple",
      "description": "A file upload simple block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "input",
        "label"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/file-upload/file-upload-02.tsx",
          "type": "registry:component",
          "target": "components/file-upload-02.tsx",
          "content": "import { Button } from '@/components/ui/button';\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from '@/components/ui/card';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\n\nexport default function FileUpload02() {\n  return (\n    <div className=\"flex items-center justify-center p-10\">\n      <Card className=\"shadow-none\">\n        <CardHeader>\n          <CardTitle>Set up your first workspace</CardTitle>\n          <CardDescription>\n            Lorem ipsum dolor sit amet, consetetur sadipscing elitr.\n          </CardDescription>\n        </CardHeader>\n        <CardContent>\n          <form action=\"#\" method=\"POST\">\n            <div className=\"space-y-6\">\n              <div className=\"space-y-2\">\n                <Label htmlFor=\"workspace-name\">\n                  Workspace <span className=\"text-destructive\">*</span>\n                </Label>\n                <Input\n                  autoComplete=\"workspace-name\"\n                  id=\"workspace-name\"\n                  name=\"workspace-name\"\n                  placeholder=\"Workspace name\"\n                  required\n                  type=\"text\"\n                />\n              </div>\n              <div className=\"space-y-2\">\n                <Label htmlFor=\"file-1\">\n                  Upload file <span className=\"text-destructive\">*</span>\n                </Label>\n                <Input\n                  accept=\".csv, .xlsx, .xls\"\n                  id=\"file-1\"\n                  name=\"file-1\"\n                  type=\"file\"\n                />\n                <p className=\"text-pretty text-muted-foreground text-sm\">\n                  You are only allowed to upload CSV, XLSX or XLS files.\n                </p>\n              </div>\n            </div>\n            <div className=\"mt-8 flex justify-end space-x-3\">\n              <Button type=\"button\" variant=\"outline\">\n                Cancel\n              </Button>\n              <Button type=\"submit\">Submit</Button>\n            </div>\n          </form>\n        </CardContent>\n      </Card>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "file-upload"
      ]
    },
    {
      "name": "file-upload-03",
      "type": "registry:block",
      "title": "File Upload Multi-File Dropzone",
      "description": "A file upload multi-file dropzone block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "input",
        "label",
        "select",
        "separator"
      ],
      "dependencies": [
        "lucide-react",
        "react-dropzone"
      ],
      "files": [
        {
          "path": "content/components/file-upload/file-upload-03.tsx",
          "type": "registry:component",
          "target": "components/file-upload-03.tsx",
          "content": "'use client';\n\nimport { File, Trash } from 'lucide-react';\nimport React from 'react';\nimport { useDropzone } from 'react-dropzone';\n\nimport { Button } from '@/components/ui/button';\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from '@/components/ui/card';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport { Separator } from '@/components/ui/separator';\nimport { cn } from '@/lib/utils';\n\nexport default function FileUpload03() {\n  const [files, setFiles] = React.useState<File[]>([]);\n  const { getRootProps, getInputProps, isDragActive } = useDropzone({\n    onDrop: (acceptedFiles) => setFiles(acceptedFiles),\n  });\n\n  const filesList = files.map((file) => (\n    <li className=\"relative\" key={file.name}>\n      <Card className=\"relative p-4 shadow-none\">\n        <div className=\"-translate-y-1/2 absolute top-1/2 right-4\">\n          <Button\n            aria-label=\"Remove file\"\n            onClick={() =>\n              setFiles((prevFiles) =>\n                prevFiles.filter((prevFile) => prevFile.name !== file.name)\n              )\n            }\n            size=\"icon\"\n            type=\"button\"\n            variant=\"ghost\"\n          >\n            <Trash aria-hidden={true} className=\"h-5 w-5\" />\n          </Button>\n        </div>\n        <CardContent className=\"flex items-center space-x-3 p-0\">\n          <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-muted\">\n            <File aria-hidden={true} className=\"h-5 w-5 text-foreground\" />\n          </span>\n          <div>\n            <p className=\"text-pretty font-medium text-foreground\">\n              {file.name}\n            </p>\n            <p className=\"mt-0.5 text-pretty text-muted-foreground text-sm\">\n              {file.size} bytes\n            </p>\n          </div>\n        </CardContent>\n      </Card>\n    </li>\n  ));\n\n  return (\n    <div className=\"flex items-center justify-center p-10\">\n      <Card className=\"shadow-none sm:mx-auto sm:max-w-xl\">\n        <CardHeader>\n          <CardTitle>Set up your first cloud storage</CardTitle>\n          <CardDescription>\n            Lorem ipsum dolor sit amet, consetetur sadipscing elitr.\n          </CardDescription>\n        </CardHeader>\n        <CardContent>\n          <form action=\"#\" method=\"post\">\n            <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-6\">\n              <div className=\"col-span-full sm:col-span-3\">\n                <Label className=\"font-medium\" htmlFor=\"bucket-name\">\n                  Bucket name\n                </Label>\n                <Input\n                  className=\"mt-2\"\n                  id=\"bucket-name\"\n                  name=\"bucket-name\"\n                  placeholder=\"Bucket name\"\n                  type=\"text\"\n                />\n              </div>\n              <div className=\"col-span-full sm:col-span-3\">\n                <Label className=\"font-medium\" htmlFor=\"visibility\">\n                  Visibility\n                </Label>\n                <Select\n                  defaultValue=\"private\"\n                  disabled\n                  items={{ private: 'Private', public: 'Public' }}\n                >\n                  <SelectTrigger\n                    className=\"mt-2 w-full\"\n                    id=\"visibility\"\n                    name=\"visibility\"\n                  >\n                    <SelectValue placeholder=\"Select visibility\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectItem value=\"private\">Private</SelectItem>\n                    <SelectItem value=\"public\">Public</SelectItem>\n                  </SelectContent>\n                </Select>\n                <p className=\"mt-2 text-pretty text-muted-foreground text-sm\">\n                  Only admins can change visibility.\n                </p>\n              </div>\n              <div className=\"col-span-full\">\n                <Label className=\"font-medium\" htmlFor=\"file-upload-2\">\n                  File(s) upload\n                </Label>\n                <div\n                  {...getRootProps()}\n                  className={cn(\n                    isDragActive\n                      ? 'border-primary bg-primary/10 ring-2 ring-primary/20'\n                      : 'border-border',\n                    'mt-2 flex justify-center rounded-md border border-dashed px-6 py-20 transition-colors duration-200'\n                  )}\n                >\n                  <div>\n                    <File\n                      aria-hidden={true}\n                      className=\"mx-auto h-12 w-12 text-muted-foreground/80\"\n                    />\n                    <div className=\"mt-4 flex text-muted-foreground\">\n                      <p>Drag and drop or</p>\n                      <label\n                        className=\"relative cursor-pointer rounded-sm pl-1 font-medium text-primary hover:text-primary/80 hover:underline hover:underline-offset-4\"\n                        htmlFor=\"file\"\n                      >\n                        <span>choose file(s)</span>\n                        <input\n                          {...getInputProps()}\n                          className=\"sr-only\"\n                          id=\"file-upload-2\"\n                          name=\"file-upload-2\"\n                          type=\"file\"\n                        />\n                      </label>\n                      <p className=\"text-pretty pl-1\">to upload</p>\n                    </div>\n                  </div>\n                </div>\n                <p className=\"mt-2 text-pretty text-muted-foreground text-sm leading-5 sm:flex sm:items-center sm:justify-between\">\n                  <span>All file types are allowed to upload.</span>\n                  <span className=\"pl-1 sm:pl-0\">Max. size per file: 50MB</span>\n                </p>\n                {filesList.length > 0 && (\n                  <>\n                    <h4 className=\"mt-6 text-balance font-medium text-foreground\">\n                      File(s) to upload\n                    </h4>\n                    <ul className=\"mt-4 space-y-4\" role=\"list\">\n                      {filesList}\n                    </ul>\n                  </>\n                )}\n              </div>\n            </div>\n            <Separator className=\"my-6\" />\n            <div className=\"flex items-center justify-end space-x-3\">\n              <Button type=\"button\" variant=\"outline\">\n                Cancel\n              </Button>\n              <Button type=\"submit\">Upload</Button>\n            </div>\n          </form>\n        </CardContent>\n      </Card>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "file-upload"
      ]
    },
    {
      "name": "file-upload-04",
      "type": "registry:block",
      "title": "File Upload Drag & Drop",
      "description": "A file upload drag & drop block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "progress"
      ],
      "dependencies": [
        "lucide-react",
        "sonner"
      ],
      "files": [
        {
          "path": "content/components/file-upload/file-upload-04.tsx",
          "type": "registry:component",
          "target": "components/file-upload-04.tsx",
          "content": "'use client';\n\nimport { File, FileSpreadsheet, X } from 'lucide-react';\nimport { type ChangeEvent, type DragEvent, useRef, useState } from 'react';\nimport { toast } from 'sonner';\n\nimport { Button } from '@/components/ui/button';\nimport { Card } from '@/components/ui/card';\nimport { Progress } from '@/components/ui/progress';\n\nexport default function FileUpload04() {\n  const [uploadState, setUploadState] = useState<{\n    file: File | null;\n    progress: number;\n    uploading: boolean;\n  }>({\n    file: null,\n    progress: 0,\n    uploading: false,\n  });\n  const [showDummy, setShowDummy] = useState(true);\n  const fileInputRef = useRef<HTMLInputElement>(null);\n\n  const validFileTypes = [\n    'text/csv',\n    'application/vnd.ms-excel',\n    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n  ];\n\n  const handleFile = (file: File | undefined) => {\n    if (!file) return;\n\n    if (validFileTypes.includes(file.type)) {\n      setUploadState({ file, progress: 0, uploading: true });\n\n      const interval = setInterval(() => {\n        setUploadState((prev) => {\n          const newProgress = prev.progress + 5;\n          if (newProgress >= 100) {\n            clearInterval(interval);\n            return { ...prev, progress: 100, uploading: false };\n          }\n          return { ...prev, progress: newProgress };\n        });\n      }, 200);\n    } else {\n      toast.error('Please upload a CSV, XLSX, or XLS file.', {\n        position: 'bottom-right',\n        duration: 3000,\n      });\n    }\n  };\n\n  const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => {\n    handleFile(event.target.files?.[0]);\n  };\n\n  const handleDrop = (event: DragEvent<HTMLDivElement>) => {\n    event.preventDefault();\n    handleFile(event.dataTransfer.files?.[0]);\n  };\n\n  const resetFile = () => {\n    setUploadState({ file: null, progress: 0, uploading: false });\n    if (fileInputRef.current) {\n      fileInputRef.current.value = '';\n    }\n  };\n\n  const getFileIcon = () => {\n    if (!uploadState.file) return <File />;\n\n    const fileExt = uploadState.file.name.split('.').pop()?.toLowerCase() || '';\n    return ['csv', 'xlsx', 'xls'].includes(fileExt) ? (\n      <FileSpreadsheet className=\"h-5 w-5 text-foreground\" />\n    ) : (\n      <File className=\"h-5 w-5 text-foreground\" />\n    );\n  };\n\n  const formatFileSize = (bytes: number) => {\n    if (bytes === 0) return '0 Bytes';\n    const k = 1024;\n    const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n    const i = Math.floor(Math.log(bytes) / Math.log(k));\n    return Number.parseFloat((bytes / k ** i).toFixed(1)) + ' ' + sizes[i];\n  };\n\n  const { file, progress, uploading } = uploadState;\n\n  return (\n    <div className=\"flex w-full max-w-lg items-center justify-center p-10\">\n      <form className=\"w-full\" onSubmit={(e) => e.preventDefault()}>\n        <h3 className=\"text-balance font-semibold text-foreground text-lg\">\n          File Upload\n        </h3>\n\n        <div\n          className=\"mt-2 flex justify-center rounded-md border border-input border-dashed px-6 py-12\"\n          onDragOver={(e) => e.preventDefault()}\n          onDrop={handleDrop}\n        >\n          <div>\n            <File\n              aria-hidden={true}\n              className=\"mx-auto h-12 w-12 text-muted-foreground\"\n            />\n            <div className=\"flex text-muted-foreground text-sm leading-6\">\n              <p>Drag and drop or</p>\n              <label\n                className=\"relative cursor-pointer rounded-sm pl-1 font-medium text-primary hover:underline hover:underline-offset-4\"\n                htmlFor=\"file-upload-03\"\n              >\n                <span>choose file</span>\n                <input\n                  accept=\".csv, .xlsx, .xls\"\n                  className=\"sr-only\"\n                  id=\"file-upload-03\"\n                  name=\"file-upload-03\"\n                  onChange={handleFileChange}\n                  ref={fileInputRef}\n                  type=\"file\"\n                />\n              </label>\n              <p className=\"text-pretty pl-1\">to upload</p>\n            </div>\n          </div>\n        </div>\n\n        <p className=\"mt-2 text-pretty text-muted-foreground text-xs leading-5 sm:flex sm:items-center sm:justify-between\">\n          <span>Accepted file types: CSV, XLSX or XLS files.</span>\n          <span className=\"pl-1 sm:pl-0\">Max. size: 10MB</span>\n        </p>\n\n        {!file && showDummy && (\n          <Card className=\"relative mt-8 gap-4 bg-muted p-4 shadow-none\">\n            <Button\n              aria-label=\"Remove\"\n              className=\"absolute top-1 right-1 text-muted-foreground hover:text-foreground\"\n              onClick={() => setShowDummy(false)}\n              size=\"icon-sm\"\n              type=\"button\"\n              variant=\"ghost\"\n            >\n              <X aria-hidden={true} className=\"h-5 w-5 shrink-0\" />\n            </Button>\n\n            <div className=\"flex items-center space-x-2.5\">\n              <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-sm bg-background shadow-sm ring-1 ring-border ring-inset\">\n                <FileSpreadsheet\n                  aria-hidden={true}\n                  className=\"h-5 w-5 text-foreground\"\n                />\n              </span>\n              <div>\n                <p className=\"text-pretty font-medium text-foreground text-xs\">\n                  Revenue_Q1_2024.xlsx\n                </p>\n                <p className=\"mt-0.5 text-pretty text-muted-foreground text-xs\">\n                  3.1 MB\n                </p>\n              </div>\n            </div>\n\n            <div className=\"flex items-center space-x-3\">\n              <Progress className=\"h-1.5\" value={45} />\n              <span className=\"text-muted-foreground text-xs\">45%</span>\n            </div>\n          </Card>\n        )}\n\n        {file && (\n          <Card className=\"relative mt-8 gap-4 bg-muted p-4 shadow-none\">\n            <Button\n              aria-label=\"Remove\"\n              className=\"absolute top-1 right-1 text-muted-foreground hover:text-foreground\"\n              onClick={resetFile}\n              size=\"icon-sm\"\n              type=\"button\"\n              variant=\"ghost\"\n            >\n              <X aria-hidden={true} className=\"h-5 w-5 shrink-0\" />\n            </Button>\n\n            <div className=\"flex items-center space-x-2.5\">\n              <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-sm bg-background shadow-sm ring-1 ring-border ring-inset\">\n                {getFileIcon()}\n              </span>\n              <div>\n                <p className=\"text-pretty font-medium text-foreground text-xs\">\n                  {file?.name}\n                </p>\n                <p className=\"mt-0.5 text-pretty text-muted-foreground text-xs\">\n                  {file && formatFileSize(file.size)}\n                </p>\n              </div>\n            </div>\n\n            <div className=\"flex items-center space-x-3\">\n              <Progress className=\"h-1.5\" value={progress} />\n              <span className=\"text-muted-foreground text-xs\">{progress}%</span>\n            </div>\n          </Card>\n        )}\n\n        <div className=\"mt-8 flex items-center justify-end space-x-3\">\n          <Button\n            className=\"whitespace-nowrap\"\n            disabled={!file}\n            onClick={resetFile}\n            type=\"button\"\n            variant=\"outline\"\n          >\n            Cancel\n          </Button>\n          <Button\n            className=\"whitespace-nowrap\"\n            disabled={!file || uploading || progress < 100}\n            type=\"submit\"\n          >\n            Upload\n          </Button>\n        </div>\n      </form>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "file-upload"
      ]
    },
    {
      "name": "file-upload-05",
      "type": "registry:block",
      "title": "File Upload with Progress",
      "description": "A file upload with progress block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "label"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/file-upload/file-upload-05.tsx",
          "type": "registry:component",
          "target": "components/file-upload-05.tsx",
          "content": "import { FileSpreadsheet, Upload, X } from 'lucide-react';\nimport { Button } from '@/components/ui/button';\nimport { Label } from '@/components/ui/label';\n\nexport default function FileUpload05() {\n  return (\n    <div className=\"flex w-full max-w-lg items-center justify-center p-10 sm:mx-auto sm:max-w-lg\">\n      <form>\n        <h3 className=\"text-balance font-semibold text-foreground text-lg\">\n          File Upload\n        </h3>\n        <div className=\"mt-4 flex justify-center space-x-4 rounded-md border border-input border-dashed px-6 py-10\">\n          <div className=\"sm:flex sm:items-center sm:gap-x-3\">\n            <Upload\n              aria-hidden={true}\n              className=\"mx-auto h-8 w-8 text-muted-foreground sm:mx-0 sm:h-6 sm:w-6\"\n            />\n            <div className=\"mt-4 flex text-foreground text-sm leading-6 sm:mt-0\">\n              <p>Drag and drop or</p>\n              <Label\n                className=\"relative cursor-pointer rounded-sm pl-1 font-medium text-primary hover:underline hover:underline-offset-4\"\n                htmlFor=\"file-upload-4\"\n              >\n                <span>choose file</span>\n                <input\n                  className=\"sr-only\"\n                  id=\"file-upload-4\"\n                  name=\"file-upload-4\"\n                  type=\"file\"\n                />\n              </Label>\n              <p className=\"text-pretty pl-1\">to upload</p>\n            </div>\n          </div>\n        </div>\n        <p className=\"mt-2 flex items-center justify-between text-pretty text-muted-foreground text-xs leading-5\">\n          Recommended max. size: 10 MB, Accepted file types: XLSX, XLS, CSV.\n        </p>\n        <div className=\"relative mt-8 rounded-lg bg-muted p-3\">\n          <div className=\"absolute top-1 right-1\">\n            <Button\n              aria-label=\"Remove\"\n              className=\"rounded-sm p-2 text-muted-foreground hover:text-foreground\"\n              size=\"sm\"\n              type=\"button\"\n              variant=\"ghost\"\n            >\n              <X aria-hidden={true} className=\"size-4 shrink-0\" />\n            </Button>\n          </div>\n          <div className=\"flex items-center space-x-2.5\">\n            <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-sm bg-background shadow-sm ring-1 ring-input ring-inset\">\n              <FileSpreadsheet\n                aria-hidden={true}\n                className=\"size-5 text-foreground\"\n              />\n            </span>\n            <div className=\"w-full\">\n              <p className=\"text-pretty font-medium text-foreground text-xs\">\n                Revenue_Q1_2024.xlsx\n              </p>\n              <p className=\"mt-0.5 flex justify-between text-pretty text-muted-foreground text-xs\">\n                <span>3.1 MB</span>\n                <span>Completed</span>\n              </p>\n            </div>\n          </div>\n        </div>\n        <div className=\"mt-8 flex items-center justify-end space-x-3\">\n          <Button\n            className=\"whitespace-nowrap rounded-sm border border-input px-4 py-2 font-medium text-foreground text-sm shadow-sm hover:bg-accent hover:text-foreground\"\n            type=\"button\"\n            variant=\"outline\"\n          >\n            Cancel\n          </Button>\n          <Button\n            className=\"whitespace-nowrap rounded-sm bg-primary px-4 py-2 font-medium text-primary-foreground text-sm shadow-sm hover:bg-primary/90\"\n            type=\"submit\"\n            variant=\"default\"\n          >\n            Upload\n          </Button>\n        </div>\n      </form>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "file-upload"
      ]
    },
    {
      "name": "file-upload-06",
      "type": "registry:block",
      "title": "File Upload with Status Sections",
      "description": "A file upload with status sections block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "progress",
        "separator"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/file-upload/file-upload-06.tsx",
          "type": "registry:component",
          "target": "components/file-upload-06.tsx",
          "content": "'use client';\n\nimport { CheckCircle, FileText, Loader2, Upload, X } from 'lucide-react';\nimport type React from 'react';\nimport { useRef, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Card } from '@/components/ui/card';\nimport { Progress } from '@/components/ui/progress';\nimport { Separator } from '@/components/ui/separator';\n\ninterface UploadItem {\n  id: string;\n  name: string;\n  progress: number;\n  status: 'uploading' | 'completed';\n}\n\nexport default function FileUpload06() {\n  const [uploads, setUploads] = useState<UploadItem[]>([\n    {\n      id: 'a1',\n      name: 'design-mock-landing.png',\n      progress: 62,\n      status: 'uploading',\n    },\n    {\n      id: 'b2',\n      name: 'team-headshot-2025-01-09.jpg',\n      progress: 28,\n      status: 'uploading',\n    },\n    {\n      id: 'c3',\n      name: 'logo-v3-final.gif',\n      progress: 100,\n      status: 'completed',\n    },\n  ]);\n  const filePickerRef = useRef<HTMLInputElement>(null);\n\n  const openFilePicker = () => {\n    filePickerRef.current?.click();\n  };\n\n  const onFileInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n    const selectedFiles = event.target.files;\n    if (selectedFiles) {\n      console.log('Files selected:', selectedFiles);\n    }\n  };\n\n  const onDragOver = (event: React.DragEvent) => {\n    event.preventDefault();\n  };\n\n  const onDropFiles = (event: React.DragEvent) => {\n    event.preventDefault();\n    const droppedFiles = event.dataTransfer.files;\n    if (droppedFiles) {\n      console.log('Files dropped:', droppedFiles);\n    }\n  };\n\n  const removeUploadById = (id: string) => {\n    setUploads(uploads.filter((file) => file.id !== id));\n  };\n\n  const activeUploads = uploads.filter((file) => file.status === 'uploading');\n  const completedUploads = uploads.filter(\n    (file) => file.status === 'completed'\n  );\n\n  return (\n    <div className=\"mx-auto flex w-full max-w-sm flex-col gap-y-6\">\n      <Card\n        className=\"group flex max-h-[200px] w-full cursor-pointer flex-col items-center justify-center gap-4 border-dashed py-8 text-sm shadow-none transition-colors hover:bg-muted/50\"\n        onClick={openFilePicker}\n        onDragOver={onDragOver}\n        onDrop={onDropFiles}\n      >\n        <div className=\"grid space-y-3\">\n          <div className=\"flex items-center gap-x-2 text-muted-foreground\">\n            <Upload className=\"size-5\" />\n            <div>\n              Drop files here or{' '}\n              <Button\n                className=\"h-auto p-0 font-normal text-primary\"\n                onClick={openFilePicker}\n                variant=\"link\"\n              >\n                browse files\n              </Button>{' '}\n              to add\n            </div>\n          </div>\n        </div>\n        <input\n          accept=\"image/png,image/jpeg,image/gif\"\n          className=\"hidden\"\n          multiple\n          onChange={onFileInputChange}\n          ref={filePickerRef}\n          type=\"file\"\n        />\n        <span className=\"mt-2 block text-base/6 text-muted-foreground group-disabled:opacity-50 sm:text-xs\">\n          Supported: JPG, PNG, GIF (max 10 MB)\n        </span>\n      </Card>\n\n      <div className=\"flex flex-col gap-y-4\">\n        {activeUploads.length > 0 && (\n          <div>\n            <h2 className=\"mb-4 flex items-center text-balance font-mono font-normal text-foreground text-lg uppercase sm:text-xs\">\n              <Loader2 className=\"mr-1 size-4 animate-spin\" />\n              Uploading\n            </h2>\n            <div className=\"-mt-2 divide-y\">\n              {activeUploads.map((file) => (\n                <div className=\"group flex items-center py-4\" key={file.id}>\n                  <div className=\"mr-3 grid size-10 shrink-0 place-content-center rounded border bg-muted\">\n                    <FileText className=\"inline size-4 group-hover:hidden\" />\n                    <Button\n                      aria-label=\"Cancel\"\n                      className=\"hidden size-4 h-auto p-0 group-hover:inline\"\n                      onClick={() => removeUploadById(file.id)}\n                      size=\"icon\"\n                      variant=\"ghost\"\n                    >\n                      <X className=\"size-4\" />\n                    </Button>\n                  </div>\n                  <div className=\"mb-1 flex w-full flex-col\">\n                    <div className=\"flex justify-between gap-2\">\n                      <span className=\"select-none text-base/6 text-foreground group-disabled:opacity-50 sm:text-sm/6\">\n                        {file.name}\n                      </span>\n                      <span className=\"text-muted-foreground text-sm tabular-nums\">\n                        {file.progress}%\n                      </span>\n                    </div>\n                    <Progress\n                      className=\"mt-1 h-2 min-w-64\"\n                      value={file.progress}\n                    />\n                  </div>\n                </div>\n              ))}\n            </div>\n          </div>\n        )}\n\n        {activeUploads.length > 0 && completedUploads.length > 0 && (\n          <Separator className=\"my-0\" />\n        )}\n\n        {completedUploads.length > 0 && (\n          <div>\n            <h2 className=\"mb-4 flex items-center text-balance font-mono font-normal text-foreground text-lg uppercase sm:text-xs\">\n              <CheckCircle className=\"mr-1 size-4\" />\n              Finished\n            </h2>\n            <div className=\"-mt-2 divide-y\">\n              {completedUploads.map((file) => (\n                <div className=\"group flex items-center py-4\" key={file.id}>\n                  <div className=\"mr-3 grid size-10 shrink-0 place-content-center rounded border bg-muted\">\n                    <FileText className=\"inline size-4 group-hover:hidden\" />\n                    <Button\n                      aria-label=\"Remove\"\n                      className=\"hidden size-4 h-auto p-0 group-hover:inline\"\n                      onClick={() => removeUploadById(file.id)}\n                      size=\"icon\"\n                      variant=\"ghost\"\n                    >\n                      <X className=\"size-4\" />\n                    </Button>\n                  </div>\n                  <div className=\"mb-1 flex w-full flex-col\">\n                    <div className=\"flex justify-between gap-2\">\n                      <span className=\"select-none text-base/6 text-foreground group-disabled:opacity-50 sm:text-sm/6\">\n                        {file.name}\n                      </span>\n                      <span className=\"text-muted-foreground text-sm tabular-nums\">\n                        {file.progress}%\n                      </span>\n                    </div>\n                    <Progress\n                      className=\"mt-1 h-2 min-w-64\"\n                      value={file.progress}\n                    />\n                  </div>\n                </div>\n              ))}\n            </div>\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "file-upload"
      ]
    },
    {
      "name": "form-layout-01",
      "type": "registry:block",
      "title": "Form with Workspace Fields",
      "description": "A form with workspace fields block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "field",
        "input",
        "separator"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/form-layout/form-layout-01.tsx",
          "type": "registry:component",
          "target": "components/form-layout-01.tsx",
          "content": "import { Button } from '@/components/ui/button';\nimport { Field, FieldLabel } from '@/components/ui/field';\nimport { Input } from '@/components/ui/input';\nimport { Separator } from '@/components/ui/separator';\n\nexport default function FormLayout01() {\n  return (\n    <div className=\"flex items-center justify-center p-10\">\n      <div className=\"sm:mx-auto sm:max-w-2xl\">\n        <h3 className=\"text-balance font-semibold text-2xl text-foreground dark:text-foreground\">\n          Register to workspace\n        </h3>\n        <p className=\"mt-1 text-pretty text-muted-foreground text-sm dark:text-muted-foreground\">\n          Take a few moments to register for your company&apos;s workspace\n        </p>\n        <form action=\"#\" className=\"mt-8\" method=\"post\">\n          <div className=\"grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-6\">\n            <div className=\"col-span-full sm:col-span-3\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"first-name\">\n                  First name\n                  <span className=\"text-red-500\">*</span>\n                </FieldLabel>\n                <Input\n                  autoComplete=\"first-name\"\n                  id=\"first-name\"\n                  name=\"first-name\"\n                  placeholder=\"First name\"\n                  required\n                  type=\"text\"\n                />\n              </Field>\n            </div>\n            <div className=\"col-span-full sm:col-span-3\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"last-name\">\n                  Last name\n                  <span className=\"text-red-500\">*</span>\n                </FieldLabel>\n                <Input\n                  autoComplete=\"last-name\"\n                  id=\"last-name\"\n                  name=\"last-name\"\n                  placeholder=\"Last name\"\n                  required\n                  type=\"text\"\n                />\n              </Field>\n            </div>\n            <div className=\"col-span-full\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"email\">\n                  Email\n                  <span className=\"text-red-500\">*</span>\n                </FieldLabel>\n                <Input\n                  autoComplete=\"email\"\n                  id=\"email\"\n                  name=\"email\"\n                  placeholder=\"Email\"\n                  required\n                  type=\"email\"\n                />\n              </Field>\n            </div>\n            <div className=\"col-span-full\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"address\">Address</FieldLabel>\n                <Input\n                  autoComplete=\"street-address\"\n                  id=\"address\"\n                  name=\"address\"\n                  placeholder=\"Address\"\n                  type=\"text\"\n                />\n              </Field>\n            </div>\n            <div className=\"col-span-full sm:col-span-2\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"city\">City</FieldLabel>\n                <Input\n                  autoComplete=\"address-level2\"\n                  id=\"city\"\n                  name=\"city\"\n                  placeholder=\"City\"\n                  type=\"text\"\n                />\n              </Field>\n            </div>\n            <div className=\"col-span-full sm:col-span-2\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"state\">State</FieldLabel>\n                <Input\n                  autoComplete=\"address-level1\"\n                  id=\"state\"\n                  name=\"state\"\n                  placeholder=\"State\"\n                  type=\"text\"\n                />\n              </Field>\n            </div>\n            <div className=\"col-span-full sm:col-span-2\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"postal-code\">Postal code</FieldLabel>\n                <Input\n                  autoComplete=\"postal-code\"\n                  id=\"postal-code\"\n                  name=\"postal-code\"\n                  placeholder=\"Postal code\"\n                />\n              </Field>\n            </div>\n          </div>\n          <Separator className=\"my-6\" />\n          <div className=\"flex items-center justify-end space-x-4\">\n            <Button\n              className=\"whitespace-nowrap\"\n              type=\"button\"\n              variant=\"outline\"\n            >\n              Cancel\n            </Button>\n            <Button className=\"whitespace-nowrap\" type=\"submit\">\n              Submit\n            </Button>\n          </div>\n        </form>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "form-layout"
      ]
    },
    {
      "name": "form-layout-02",
      "type": "registry:block",
      "title": "Form with Side Labels",
      "description": "A form with side labels block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "field",
        "input",
        "radio-group",
        "select",
        "separator",
        "textarea"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/form-layout/form-layout-02.tsx",
          "type": "registry:component",
          "target": "components/form-layout-02.tsx",
          "content": "import { Button } from '@/components/ui/button';\nimport { Field, FieldDescription, FieldLabel } from '@/components/ui/field';\nimport { Input } from '@/components/ui/input';\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport { Separator } from '@/components/ui/separator';\nimport { Textarea } from '@/components/ui/textarea';\n\nexport default function FormLayout02() {\n  return (\n    <div className=\"flex items-center justify-center p-10\">\n      <form>\n        <div className=\"grid grid-cols-1 gap-10 md:grid-cols-3\">\n          <div>\n            <h2 className=\"text-balance font-semibold text-foreground dark:text-foreground\">\n              Personal information\n            </h2>\n            <p className=\"mt-1 text-pretty text-muted-foreground text-sm leading-6 dark:text-muted-foreground\">\n              Lorem ipsum dolor sit amet, consetetur sadipscing elitr.\n            </p>\n          </div>\n          <div className=\"sm:max-w-3xl md:col-span-2\">\n            <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-6\">\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"first-name\">First name</FieldLabel>\n                  <Input\n                    autoComplete=\"given-name\"\n                    id=\"first-name\"\n                    name=\"first-name\"\n                    placeholder=\"Emma\"\n                    type=\"text\"\n                  />\n                </Field>\n              </div>\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"last-name\">Last name</FieldLabel>\n                  <Input\n                    autoComplete=\"family-name\"\n                    id=\"last-name\"\n                    name=\"last-name\"\n                    placeholder=\"Crown\"\n                    type=\"text\"\n                  />\n                </Field>\n              </div>\n              <div className=\"col-span-full\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"email\">Email</FieldLabel>\n                  <Input\n                    autoComplete=\"email\"\n                    id=\"email\"\n                    name=\"email\"\n                    placeholder=\"emma@company.com\"\n                    type=\"email\"\n                  />\n                </Field>\n              </div>\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"birthyear\">Birth year</FieldLabel>\n                  <Input\n                    id=\"birthyear\"\n                    name=\"year\"\n                    placeholder=\"1990\"\n                    type=\"number\"\n                  />\n                </Field>\n              </div>\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"role\">Role</FieldLabel>\n                  <Input\n                    disabled\n                    id=\"role\"\n                    name=\"role\"\n                    placeholder=\"Senior Manager\"\n                    type=\"text\"\n                  />\n                  <FieldDescription>\n                    Roles can only be changed by system admin.\n                  </FieldDescription>\n                </Field>\n              </div>\n            </div>\n          </div>\n        </div>\n        <Separator className=\"my-8\" />\n        <div className=\"grid grid-cols-1 gap-10 md:grid-cols-3\">\n          <div>\n            <h2 className=\"text-balance font-semibold text-foreground dark:text-foreground\">\n              Workspace settings\n            </h2>\n            <p className=\"mt-1 text-pretty text-muted-foreground text-sm leading-6 dark:text-muted-foreground\">\n              Lorem ipsum dolor sit amet, consetetur sadipscing elitr.\n            </p>\n          </div>\n          <div className=\"sm:max-w-3xl md:col-span-2\">\n            <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-6\">\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"workspace-name\">\n                    Workspace name\n                  </FieldLabel>\n                  <Input\n                    id=\"workspace-name\"\n                    name=\"workspace-name\"\n                    placeholder=\"Test workspace\"\n                    type=\"text\"\n                  />\n                </Field>\n              </div>\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"visibility\">Visibility</FieldLabel>\n                  <Select\n                    defaultValue=\"private\"\n                    items={{ private: 'Private', public: 'Public' }}\n                    name=\"visibility\"\n                  >\n                    <SelectTrigger id=\"visibility\">\n                      <SelectValue placeholder=\"Select visibility\" />\n                    </SelectTrigger>\n                    <SelectContent>\n                      <SelectItem value=\"public\">Public</SelectItem>\n                      <SelectItem value=\"private\">Private</SelectItem>\n                    </SelectContent>\n                  </Select>\n                </Field>\n              </div>\n              <div className=\"col-span-full\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"workspace-description\">\n                    Workspace description\n                  </FieldLabel>\n                  <Textarea\n                    id=\"workspace-description\"\n                    name=\"workspace-description\"\n                    rows={4}\n                  />\n                  <FieldDescription>\n                    Note: description provided will not be displayed externally.\n                  </FieldDescription>\n                </Field>\n              </div>\n            </div>\n          </div>\n        </div>\n        <Separator className=\"my-8\" />\n        <div className=\"grid grid-cols-1 gap-10 md:grid-cols-3\">\n          <div>\n            <h2 className=\"text-balance font-semibold text-foreground dark:text-foreground\">\n              Notification settings\n            </h2>\n            <p className=\"mt-1 text-pretty text-muted-foreground text-sm leading-6 dark:text-muted-foreground\">\n              Lorem ipsum dolor sit amet, consetetur sadipscing elitr.\n            </p>\n          </div>\n          <div className=\"sm:max-w-3xl md:col-span-2\">\n            <fieldset>\n              <legend className=\"font-medium text-foreground text-sm dark:text-foreground\">\n                Newsletter\n              </legend>\n              <FieldDescription\n                className=\"mt-2 leading-6\"\n                id=\"newsletter-description\"\n              >\n                Change how often you want to receive updates from our\n                newsletter.\n              </FieldDescription>\n              <RadioGroup className=\"mt-6\" defaultValue=\"never\">\n                <div className=\"flex items-center gap-x-3\">\n                  <RadioGroupItem\n                    aria-describedby=\"newsletter-description\"\n                    id=\"every-week\"\n                    value=\"every-week\"\n                  />\n                  <FieldLabel className=\"font-normal\" htmlFor=\"every-week\">\n                    Every week\n                  </FieldLabel>\n                </div>\n                <div className=\"flex items-center gap-x-3\">\n                  <RadioGroupItem\n                    aria-describedby=\"newsletter-description\"\n                    id=\"every-month\"\n                    value=\"every-month\"\n                  />\n                  <FieldLabel className=\"font-normal\" htmlFor=\"every-month\">\n                    Every month\n                  </FieldLabel>\n                </div>\n                <div className=\"flex items-center gap-x-3\">\n                  <RadioGroupItem\n                    aria-describedby=\"newsletter-description\"\n                    id=\"never\"\n                    value=\"never\"\n                  />\n                  <FieldLabel className=\"font-normal\" htmlFor=\"never\">\n                    Never\n                  </FieldLabel>\n                </div>\n              </RadioGroup>\n            </fieldset>\n          </div>\n        </div>\n        <Separator className=\"my-8\" />\n        <div className=\"flex items-center justify-end space-x-4\">\n          <Button className=\"whitespace-nowrap\" type=\"button\" variant=\"outline\">\n            Go back\n          </Button>\n          <Button className=\"whitespace-nowrap\" type=\"submit\">\n            Save settings\n          </Button>\n        </div>\n      </form>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "form-layout"
      ]
    },
    {
      "name": "form-layout-03",
      "type": "registry:block",
      "title": "Form with Checkbox Settings",
      "description": "A form with checkbox settings block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "checkbox",
        "field",
        "input",
        "select",
        "separator",
        "textarea"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/form-layout/form-layout-03.tsx",
          "type": "registry:component",
          "target": "components/form-layout-03.tsx",
          "content": "import { Button } from '@/components/ui/button';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { Field, FieldDescription, FieldLabel } from '@/components/ui/field';\nimport { Input } from '@/components/ui/input';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport { Separator } from '@/components/ui/separator';\nimport { Textarea } from '@/components/ui/textarea';\n\nexport default function FormLayout03() {\n  return (\n    <div className=\"flex items-center justify-center p-10\">\n      <form>\n        <div className=\"grid grid-cols-1 gap-10 md:grid-cols-3\">\n          <div>\n            <h2 className=\"text-balance font-semibold text-foreground dark:text-foreground\">\n              Personal information\n            </h2>\n            <p className=\"mt-1 text-pretty text-muted-foreground text-sm leading-6 dark:text-muted-foreground\">\n              Lorem ipsum dolor sit amet, consetetur sadipscing elitr.\n            </p>\n          </div>\n          <div className=\"sm:max-w-3xl md:col-span-2\">\n            <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-6\">\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"first-name\">First name</FieldLabel>\n                  <Input\n                    autoComplete=\"given-name\"\n                    id=\"first-name\"\n                    name=\"first-name\"\n                    placeholder=\"Emma\"\n                    type=\"text\"\n                  />\n                </Field>\n              </div>\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"last-name\">Last name</FieldLabel>\n                  <Input\n                    autoComplete=\"family-name\"\n                    id=\"last-name\"\n                    name=\"last-name\"\n                    placeholder=\"Crown\"\n                    type=\"text\"\n                  />\n                </Field>\n              </div>\n              <div className=\"col-span-full\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"email\">Email</FieldLabel>\n                  <Input\n                    autoComplete=\"email\"\n                    id=\"email\"\n                    name=\"email\"\n                    placeholder=\"emma@company.com\"\n                    type=\"email\"\n                  />\n                </Field>\n              </div>\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"birthyear\">Birth year</FieldLabel>\n                  <Input\n                    id=\"birthyear\"\n                    name=\"year\"\n                    placeholder=\"1990\"\n                    type=\"number\"\n                  />\n                </Field>\n              </div>\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"role\">Role</FieldLabel>\n                  <Input\n                    disabled\n                    id=\"role\"\n                    name=\"role\"\n                    placeholder=\"Senior Manager\"\n                    type=\"text\"\n                  />\n                  <FieldDescription>\n                    Roles can only be changed by system admin.\n                  </FieldDescription>\n                </Field>\n              </div>\n            </div>\n          </div>\n        </div>\n        <Separator className=\"my-8\" />\n        <div className=\"grid grid-cols-1 gap-10 md:grid-cols-3\">\n          <div>\n            <h2 className=\"text-balance font-semibold text-foreground dark:text-foreground\">\n              Workspace settings\n            </h2>\n            <p className=\"mt-1 text-pretty text-muted-foreground text-sm leading-6 dark:text-muted-foreground\">\n              Lorem ipsum dolor sit amet, consetetur sadipscing elitr.\n            </p>\n          </div>\n          <div className=\"sm:max-w-3xl md:col-span-2\">\n            <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-6\">\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"workspace-name\">\n                    Workspace name\n                  </FieldLabel>\n                  <Input\n                    id=\"workspace-name\"\n                    name=\"workspace-name\"\n                    placeholder=\"Test workspace\"\n                    type=\"text\"\n                  />\n                </Field>\n              </div>\n              <div className=\"col-span-full sm:col-span-3\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"visibility\">Visibility</FieldLabel>\n                  <Select\n                    defaultValue=\"private\"\n                    items={{ private: 'Private', public: 'Public' }}\n                    name=\"visibility\"\n                  >\n                    <SelectTrigger id=\"visibility\">\n                      <SelectValue placeholder=\"Select visibility\" />\n                    </SelectTrigger>\n                    <SelectContent>\n                      <SelectItem value=\"public\">Public</SelectItem>\n                      <SelectItem value=\"private\">Private</SelectItem>\n                    </SelectContent>\n                  </Select>\n                </Field>\n              </div>\n              <div className=\"col-span-full\">\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"workspace-description\">\n                    Workspace description\n                  </FieldLabel>\n                  <Textarea\n                    id=\"workspace-description\"\n                    name=\"workspace-description\"\n                    rows={4}\n                  />\n                  <FieldDescription>\n                    Note: description provided will not be displayed externally.\n                  </FieldDescription>\n                </Field>\n              </div>\n            </div>\n          </div>\n        </div>\n        <Separator className=\"my-8\" />\n        <div className=\"grid grid-cols-1 gap-10 md:grid-cols-3\">\n          <div>\n            <h2 className=\"text-balance font-semibold text-foreground dark:text-foreground\">\n              Notification settings\n            </h2>\n            <p className=\"mt-1 text-pretty text-muted-foreground text-sm leading-6 dark:text-muted-foreground\">\n              Lorem ipsum dolor sit amet, consetetur sadipscing elitr.\n            </p>\n          </div>\n          <div className=\"sm:max-w-3xl md:col-span-2\">\n            <fieldset>\n              <legend className=\"font-medium text-foreground text-sm dark:text-foreground\">\n                Team\n              </legend>\n              <FieldDescription className=\"mt-1 leading-6\">\n                Configure the types of team alerts you want to receive.\n              </FieldDescription>\n              <div className=\"mt-2\">\n                <div className=\"flex items-center gap-x-3 py-1\">\n                  <Checkbox\n                    defaultChecked\n                    id=\"team-requests\"\n                    name=\"team-requests\"\n                  />\n                  <FieldLabel className=\"font-normal\" htmlFor=\"team-requests\">\n                    Team join requests\n                  </FieldLabel>\n                </div>\n                <div className=\"flex items-center gap-x-3 py-1\">\n                  <Checkbox\n                    id=\"team-activity-digest\"\n                    name=\"team-activity-digest\"\n                  />\n                  <FieldLabel\n                    className=\"font-normal\"\n                    htmlFor=\"team-activity-digest\"\n                  >\n                    Weekly team activity digest\n                  </FieldLabel>\n                </div>\n              </div>\n            </fieldset>\n            <fieldset className=\"mt-6\">\n              <legend className=\"font-medium text-foreground text-sm dark:text-foreground\">\n                Usage\n              </legend>\n              <FieldDescription className=\"mt-1 leading-6\">\n                Configure the types of usage alerts you want to receive.\n              </FieldDescription>\n              <div className=\"mt-2\">\n                <div className=\"flex items-center gap-x-3 py-1\">\n                  <Checkbox id=\"api-requests\" name=\"api-requests\" />\n                  <FieldLabel className=\"font-normal\" htmlFor=\"api-requests\">\n                    API requests\n                  </FieldLabel>\n                </div>\n                <div className=\"flex items-center gap-x-3 py-1\">\n                  <Checkbox\n                    id=\"workspace-execution\"\n                    name=\"workspace-execution\"\n                  />\n                  <FieldLabel\n                    className=\"font-normal\"\n                    htmlFor=\"workspace-execution\"\n                  >\n                    Workspace loading times\n                  </FieldLabel>\n                </div>\n                <div className=\"flex items-center gap-x-3 py-1\">\n                  <Checkbox\n                    defaultChecked\n                    id=\"query-caching\"\n                    name=\"query-caching\"\n                  />\n                  <FieldLabel className=\"font-normal\" htmlFor=\"query-caching\">\n                    Query caching\n                  </FieldLabel>\n                </div>\n                <div className=\"flex items-center gap-x-3 py-1\">\n                  <Checkbox defaultChecked id=\"storage\" name=\"storage\" />\n                  <FieldLabel className=\"font-normal\" htmlFor=\"storage\">\n                    Storage\n                  </FieldLabel>\n                </div>\n              </div>\n            </fieldset>\n          </div>\n        </div>\n        <Separator className=\"my-8\" />\n        <div className=\"flex items-center justify-end space-x-4\">\n          <Button className=\"whitespace-nowrap\" type=\"button\" variant=\"outline\">\n            Go back\n          </Button>\n          <Button className=\"whitespace-nowrap\" type=\"submit\">\n            Save settings\n          </Button>\n        </div>\n      </form>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "form-layout"
      ]
    },
    {
      "name": "form-layout-04",
      "type": "registry:block",
      "title": "Form with Package Selection",
      "description": "A form with package selection block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "field",
        "input",
        "radio-group",
        "select",
        "separator"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/form-layout/form-layout-04.tsx",
          "type": "registry:component",
          "target": "components/form-layout-04.tsx",
          "content": "'use client';\n\nimport { useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Field, FieldDescription, FieldLabel } from '@/components/ui/field';\nimport { Input } from '@/components/ui/input';\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport { Separator } from '@/components/ui/separator';\n\nconst workspaces = [\n  {\n    id: 1,\n    title: 'Starter',\n    description: 'Up to 10,000 requests per day.',\n    users: 'Free',\n  },\n  {\n    id: 2,\n    title: 'Premium',\n    description: '500,000 requests per day¹',\n    users: '$900/month²',\n  },\n  {\n    id: 3,\n    title: 'Enterprise',\n    description: 'Based on your specific needs',\n    users: 'Custom',\n  },\n];\n\nexport default function FormLayout04() {\n  const [selectedWorkspace, setSelectedWorkspace] = useState(workspaces[0]);\n\n  return (\n    <div className=\"flex items-center justify-center p-10\">\n      <div className=\"sm:mx-auto sm:max-w-2xl\">\n        <h3 className=\"text-balance font-semibold text-foreground text-lg\">\n          Apply for early access\n        </h3>\n        <p className=\"mt-1 text-pretty text-muted-foreground text-sm leading-6\">\n          Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam\n          nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.\n        </p>\n        <form action=\"#\" className=\"mt-8\" method=\"post\">\n          <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-6\">\n            <div className=\"col-span-full sm:col-span-3\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"first-name\">\n                  First name<span className=\"text-red-500\">*</span>\n                </FieldLabel>\n                <Input\n                  autoComplete=\"given-name\"\n                  id=\"first-name\"\n                  name=\"first-name\"\n                  placeholder=\"Emma\"\n                  required\n                  type=\"text\"\n                />\n              </Field>\n            </div>\n            <div className=\"col-span-full sm:col-span-3\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"last-name\">Last name</FieldLabel>\n                <Input\n                  autoComplete=\"family-name\"\n                  id=\"last-name\"\n                  name=\"last-name\"\n                  placeholder=\"Crown\"\n                  type=\"text\"\n                />\n              </Field>\n            </div>\n            <div className=\"col-span-full\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"email\">\n                  Work email<span className=\"text-red-500\">*</span>\n                </FieldLabel>\n                <Input\n                  autoComplete=\"email\"\n                  id=\"email\"\n                  name=\"email\"\n                  placeholder=\"emma@company.com\"\n                  required\n                  type=\"email\"\n                />\n              </Field>\n            </div>\n            <div className=\"col-span-full sm:col-span-3\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"company\">Company</FieldLabel>\n                <Input\n                  autoComplete=\"organization\"\n                  id=\"company\"\n                  name=\"company\"\n                  placeholder=\"Company, Inc.\"\n                  type=\"text\"\n                />\n              </Field>\n            </div>\n            <div className=\"col-span-full sm:col-span-3\">\n              <Field className=\"gap-2\">\n                <FieldLabel htmlFor=\"size\">Company size (employees)</FieldLabel>\n                <Select defaultValue=\"\">\n                  <SelectTrigger id=\"size\" name=\"size\">\n                    <SelectValue placeholder=\"Select company size\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    <SelectItem value=\"1-9\">1-9</SelectItem>\n                    <SelectItem value=\"10-50\">10-50</SelectItem>\n                    <SelectItem value=\"50-250\">50-250</SelectItem>\n                    <SelectItem value=\"250+\">250+</SelectItem>\n                  </SelectContent>\n                </Select>\n              </Field>\n            </div>\n            <Separator className=\"col-span-full my-4\" />\n            <div className=\"col-span-full\">\n              <FieldLabel className=\"mb-4 block font-semibold text-foreground\">\n                Select a workspace package\n              </FieldLabel>\n\n              <RadioGroup\n                className=\"grid grid-cols-1 gap-5 sm:grid-cols-3\"\n                defaultValue={selectedWorkspace.id.toString()}\n                onValueChange={(value) =>\n                  setSelectedWorkspace(\n                    workspaces.find(\n                      (workspace) => workspace.id.toString() === value\n                    ) || workspaces[0]\n                  )\n                }\n              >\n                {workspaces.map((item) => (\n                  <div\n                    className=\"relative flex flex-col gap-2 rounded-md border border-input p-4 shadow-xs outline-none has-data-checked:border-ring\"\n                    key={item.id.toString()}\n                  >\n                    <div className=\"flex justify-between\">\n                      <RadioGroupItem\n                        className=\"order-1 after:absolute after:inset-0\"\n                        id={item.id.toString()}\n                        value={item.id.toString()}\n                      />\n\n                      <FieldLabel\n                        className=\"block font-medium text-foreground text-sm\"\n                        htmlFor={item.id.toString()}\n                      >\n                        {item.title}\n                      </FieldLabel>\n                    </div>\n                    <div className=\"flex h-full flex-col justify-between\">\n                      <p className=\"mt-1 text-pretty text-muted-foreground text-sm\">\n                        {item.description}\n                      </p>\n                      <span className=\"mt-4 block font-medium text-foreground text-sm\">\n                        {item.users}\n                      </span>\n                    </div>\n                  </div>\n                ))}\n              </RadioGroup>\n\n              <FieldDescription className=\"mt-2!\">\n                <sup>1</sup> $0.5/10K requests after limit reach.\n              </FieldDescription>\n              <FieldDescription className=\"mt-1\">\n                <sup>2</sup> No credit card required for registration.\n              </FieldDescription>\n            </div>\n          </div>\n          <Separator className=\"my-6\" />\n          <div className=\"flex items-center justify-end space-x-4\">\n            <Button\n              className=\"whitespace-nowrap\"\n              type=\"button\"\n              variant=\"outline\"\n            >\n              Go back\n            </Button>\n            <Button className=\"whitespace-nowrap\" type=\"submit\">\n              Apply\n            </Button>\n          </div>\n        </form>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "form-layout"
      ]
    },
    {
      "name": "form-layout-05",
      "type": "registry:block",
      "title": "Form with Plan Selection",
      "description": "A form with plan selection block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "badge",
        "button",
        "card",
        "field",
        "input",
        "radio-group",
        "select",
        "separator"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/form-layout/form-layout-05.tsx",
          "type": "registry:component",
          "target": "components/form-layout-05.tsx",
          "content": "'use client';\n\nimport { Check, CircleCheck, ExternalLink } from 'lucide-react';\nimport { useState } from 'react';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { Field, FieldDescription, FieldLabel } from '@/components/ui/field';\nimport { Input } from '@/components/ui/input';\nimport { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport { Separator } from '@/components/ui/separator';\nimport { cn } from '@/lib/utils';\n\nconst highlights = [\n  {\n    id: 1,\n    feature: 'Used by top design teams worldwide',\n  },\n  {\n    id: 2,\n    feature: 'Seamless integration with design tools',\n  },\n  {\n    id: 3,\n    feature: 'Real-time collaboration features',\n  },\n];\n\nconst plans = [\n  {\n    name: 'Creator',\n    features: [\n      { feature: 'Up to 3 design projects' },\n      { feature: 'Basic collaboration tools' },\n      { feature: '5GB cloud storage' },\n      { feature: 'Community forum support' },\n    ],\n    price: '$15',\n    href: '#',\n    isRecommended: false,\n  },\n  {\n    name: 'Team',\n    features: [\n      { feature: 'Unlimited design projects' },\n      { feature: 'Advanced collaboration suite' },\n      { feature: '50GB cloud storage' },\n      { feature: 'Priority email support' },\n    ],\n    price: '$49',\n    href: '#',\n    isRecommended: true,\n  },\n  {\n    name: 'Agency',\n    features: [\n      { feature: 'Unlimited projects and team members' },\n      { feature: 'Client portal access' },\n      { feature: '250GB cloud storage' },\n      { feature: 'White-labeling options' },\n      { feature: 'Dedicated account manager' },\n    ],\n    price: '$99',\n    href: '#',\n    isRecommended: false,\n  },\n];\n\nexport default function FormLayout05() {\n  const [selected, setSelected] = useState(plans[0]);\n\n  return (\n    <div className=\"flex items-center justify-center p-10\">\n      <form className=\"sm:mx-auto sm:max-w-7xl\">\n        <h3 className=\"text-balance font-semibold text-foreground text-xl\">\n          Create new design workspace\n        </h3>\n        <div className=\"grid grid-cols-1 gap-10 lg:grid-cols-12 lg:gap-12\">\n          <div className=\"mt-6 lg:col-span-7\">\n            <div className=\"space-y-4 md:space-y-6\">\n              <div className=\"md:flex md:items-center md:space-x-4\">\n                <div className=\"md:w-1/4\">\n                  <Field className=\"gap-2\">\n                    <FieldLabel htmlFor=\"organization\">Organization</FieldLabel>\n                    <Select\n                      defaultValue=\"1\"\n                      items={{\n                        '1': 'Acme, Inc.',\n                        '2': 'Hero Labs',\n                        '3': 'Rose Holding',\n                      }}\n                    >\n                      <SelectTrigger\n                        className=\"w-full\"\n                        id=\"organization\"\n                        name=\"organization\"\n                      >\n                        <SelectValue placeholder=\"Select organization\" />\n                      </SelectTrigger>\n                      <SelectContent>\n                        <SelectItem value=\"1\">Acme, Inc.</SelectItem>\n                        <SelectItem value=\"2\">Hero Labs</SelectItem>\n                        <SelectItem value=\"3\">Rose Holding</SelectItem>\n                      </SelectContent>\n                    </Select>\n                  </Field>\n                </div>\n                <div className=\"mt-4 md:mt-0 md:w-3/4\">\n                  <Field className=\"gap-2\">\n                    <FieldLabel htmlFor=\"workspace\">Workspace name</FieldLabel>\n                    <Input id=\"workspace\" name=\"workspace\" />\n                  </Field>\n                </div>\n              </div>\n              <div>\n                <Field className=\"gap-2\">\n                  <FieldLabel htmlFor=\"region\">Region</FieldLabel>\n                  <Select\n                    defaultValue=\"iad1\"\n                    items={{\n                      fra1: 'eu-central-1 (Frankfurt, Germany)',\n                      iad1: 'us-east-1 (Washington, D.C., USA)',\n                      lhr1: 'eu-west-2 (London, United Kingdom)',\n                      sfo1: 'us-west-1 (San Francisco, USA)',\n                      sin1: 'ap-southeast-1 (Singapore)',\n                    }}\n                  >\n                    <SelectTrigger id=\"region\" name=\"region\">\n                      <SelectValue placeholder=\"Select region\" />\n                    </SelectTrigger>\n                    <SelectContent>\n                      <SelectItem value=\"fra1\">\n                        eu-central-1 (Frankfurt, Germany)\n                      </SelectItem>\n                      <SelectItem value=\"iad1\">\n                        us-east-1 (Washington, D.C., USA)\n                      </SelectItem>\n                      <SelectItem value=\"lhr1\">\n                        eu-west-2 (London, United Kingdom)\n                      </SelectItem>\n                      <SelectItem value=\"sfo1\">\n                        us-west-1 (San Francisco, USA)\n                      </SelectItem>\n                      <SelectItem value=\"sin1\">\n                        ap-southeast-1 (Singapore)\n                      </SelectItem>\n                    </SelectContent>\n                  </Select>\n                  <FieldDescription>\n                    For best performance, choose a region closest to your\n                    operations\n                  </FieldDescription>\n                </Field>\n              </div>\n            </div>\n            <h4 className=\"mt-14 text-balance font-medium\">\n              Plan type<span className=\"text-red-500\">*</span>\n            </h4>\n            <RadioGroup\n              className=\"mt-4 space-y-4\"\n              onValueChange={(value) =>\n                setSelected(\n                  plans.find((plan) => plan.name === value) || plans[0]\n                )\n              }\n              value={selected.name}\n            >\n              {plans.map((plan) => (\n                <label\n                  className={cn(\n                    'relative block cursor-pointer rounded-md border bg-background transition',\n                    selected.name === plan.name\n                      ? 'border-primary/20 ring-2 ring-primary/20'\n                      : 'border-border'\n                  )}\n                  htmlFor={plan.name}\n                  key={plan.name}\n                >\n                  <div className=\"flex items-start space-x-4 px-6 py-4\">\n                    <div className=\"mt-1 flex h-4 w-4 shrink-0 items-center justify-center\">\n                      <RadioGroupItem id={plan.name} value={plan.name} />\n                    </div>\n                    <div className=\"w-full\">\n                      <p className=\"text-pretty leading-6\">\n                        <span className=\"font-semibold text-foreground\">\n                          {plan.name}\n                        </span>\n                        {plan.isRecommended && (\n                          <Badge className=\"ml-2\" variant=\"secondary\">\n                            recommended\n                          </Badge>\n                        )}\n                      </p>\n                      <ul className=\"mt-2 space-y-1\">\n                        {plan.features.map((feature, index) => (\n                          <li\n                            className=\"flex items-center gap-2 text-sm\"\n                            key={index}\n                          >\n                            <Check\n                              aria-hidden={true}\n                              className=\"h-4 w-4 text-muted-foreground\"\n                            />\n                            {feature.feature}\n                          </li>\n                        ))}\n                      </ul>\n                    </div>\n                  </div>\n                  <div className=\"flex items-center justify-between rounded-b-md border-border border-t bg-muted px-6 py-3\">\n                    <a\n                      className=\"inline-flex items-center gap-1 text-primary text-sm hover:underline hover:underline-offset-4\"\n                      href={plan.href}\n                    >\n                      Learn more\n                      <ExternalLink aria-hidden={true} className=\"h-4 w-4\" />\n                    </a>\n                    <div>\n                      <span className=\"font-semibold text-foreground text-lg\">\n                        {plan.price}\n                      </span>\n                      <span className=\"text-muted-foreground text-sm\">/mo</span>\n                    </div>\n                  </div>\n                </label>\n              ))}\n            </RadioGroup>\n          </div>\n          <div className=\"lg:col-span-5\">\n            <Card className=\"bg-muted shadow-none\">\n              <CardContent>\n                <h4 className=\"text-balance font-semibold text-foreground text-sm\">\n                  Choose the right plan for your design team\n                </h4>\n                <p className=\"mt-2 text-pretty text-muted-foreground text-sm leading-6\">\n                  Our flexible plans are designed to scale with your team&apos;s\n                  needs. All plans include core design collaboration features\n                  with varying levels of storage and support.\n                </p>\n                <ul className=\"mt-4 space-y-1\">\n                  {highlights.map((item) => (\n                    <li\n                      className=\"flex items-center space-x-2 py-1.5 text-foreground\"\n                      key={item.id}\n                    >\n                      <CircleCheck className=\"h-5 w-5 text-primary\" />\n                      <span className=\"truncate text-sm\">{item.feature}</span>\n                    </li>\n                  ))}\n                </ul>\n                <a\n                  className=\"mt-4 inline-flex items-center gap-1 text-primary text-sm\"\n                  href=\"#\"\n                >\n                  Learn more\n                  <ExternalLink aria-hidden={true} className=\"h-4 w-4\" />\n                </a>\n              </CardContent>\n            </Card>\n          </div>\n        </div>\n        <Separator className=\"my-10\" />\n        <div className=\"flex items-center justify-end space-x-4\">\n          <Button type=\"button\" variant=\"ghost\">\n            Cancel\n          </Button>\n          <Button type=\"submit\">Update</Button>\n        </div>\n      </form>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "form-layout"
      ]
    },
    {
      "name": "grid-list-01",
      "type": "registry:block",
      "title": "Grid List with Dropdown",
      "description": "A grid list with dropdown block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "dropdown-menu"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/grid-list/grid-list-01.tsx",
          "type": "registry:component",
          "target": "components/grid-list-01.tsx",
          "content": "import { MoreVertical } from 'lucide-react';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent } from '@/components/ui/card';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\n\nconst bookCollections = [\n  { name: 'Science Fiction', initials: 'SF', href: '#', books: 37 },\n  { name: 'Mystery Thrillers', initials: 'MT', href: '#', books: 29 },\n  { name: 'Historical Fiction', initials: 'HF', href: '#', books: 23 },\n];\n\nexport default function GridList01() {\n  return (\n    <div className=\"flex items-center justify-center p-8\">\n      <div>\n        <h2 className=\"text-balance font-medium text-muted-foreground text-sm\">\n          Favorite Book Collections\n        </h2>\n        <ul\n          className=\"mt-3 grid grid-cols-1 gap-5 sm:gap-6 lg:grid-cols-3\"\n          role=\"list\"\n        >\n          {bookCollections.map((collection) => (\n            <li className=\"col-span-1\" key={collection.name}>\n              <Card className=\"flex w-full flex-row gap-0 overflow-hidden rounded-md py-0 shadow-2xs\">\n                <div className=\"flex w-16 shrink-0 items-center justify-center bg-primary font-medium text-primary-foreground text-sm\">\n                  {collection.initials}\n                </div>\n                <CardContent className=\"flex flex-1 items-center justify-between truncate bg-card p-0\">\n                  <div className=\"flex-1 truncate px-4 py-2 text-sm\">\n                    <a\n                      className=\"font-medium text-foreground hover:text-muted-foreground\"\n                      href={collection.href}\n                    >\n                      {collection.name}\n                    </a>\n                    <p className=\"text-pretty text-muted-foreground\">\n                      {collection.books} Books\n                    </p>\n                  </div>\n                  <div className=\"shrink-0 pr-2\">\n                    <DropdownMenu>\n                      <DropdownMenuTrigger\n                        render={\n                          <Button\n                            className=\"h-8 w-8 rounded-full\"\n                            size=\"icon\"\n                            type=\"button\"\n                            variant=\"ghost\"\n                          />\n                        }\n                      >\n                        <span className=\"sr-only\">Open options</span>\n                        <MoreVertical className=\"h-5 w-5\" />\n                      </DropdownMenuTrigger>\n                      <DropdownMenuContent align=\"end\">\n                        <DropdownMenuItem>View collection</DropdownMenuItem>\n                        <DropdownMenuItem>Edit collection</DropdownMenuItem>\n                        <DropdownMenuSeparator />\n                        <DropdownMenuItem>Share collection</DropdownMenuItem>\n                        <DropdownMenuItem className=\"text-destructive hover:bg-destructive/10 hover:text-destructive focus:bg-destructive/10 focus:text-destructive\">\n                          Delete collection\n                        </DropdownMenuItem>\n                      </DropdownMenuContent>\n                    </DropdownMenu>\n                  </div>\n                </CardContent>\n              </Card>\n            </li>\n          ))}\n        </ul>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "grid-list"
      ]
    },
    {
      "name": "grid-list-02",
      "type": "registry:block",
      "title": "Grid List with Links",
      "description": "A grid list with links block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "avatar",
        "card"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/grid-list/grid-list-02.tsx",
          "type": "registry:component",
          "target": "components/grid-list-02.tsx",
          "content": "import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';\nimport { Card, CardContent } from '@/components/ui/card';\n\nconst people = [\n  {\n    name: 'Timur Ercan',\n    email: 'timur@documenso.com',\n    role: 'Co-Founder / CEO',\n    imageUrl: 'https://blocks.so/avatar-02.png',\n  },\n  {\n    name: 'Lucas Smith',\n    email: 'lucas@documenso.com',\n    role: 'Co-Founder / CTO',\n    imageUrl: 'https://blocks.so/avatar-03.png',\n  },\n  {\n    name: 'Ephraim Duncan',\n    email: 'ephraim@documenso.com',\n    role: 'Software Engineer',\n    imageUrl: 'https://blocks.so/avatar-01.png',\n  },\n  {\n    name: 'Catalin Pit',\n    email: 'catalin@documenso.com',\n    role: 'Software Engineer',\n    imageUrl: 'https://blocks.so/avatar-04.png',\n  },\n];\n\nexport default function GridList02() {\n  return (\n    <div className=\"flex items-center justify-center p-8\">\n      <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n        {people.map((person) => (\n          <Card\n            className=\"relative border py-0 shadow-2xs transition-[border-color,box-shadow] duration-100 ease-out focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 hover:border-muted-foreground hover:shadow-sm\"\n            key={person.email}\n          >\n            <CardContent className=\"flex items-center space-x-4 p-4\">\n              <Avatar className=\"h-10 w-10\">\n                <AvatarImage alt={person.name} src={person.imageUrl} />\n                <AvatarFallback>{person.name.charAt(0)}</AvatarFallback>\n              </Avatar>\n              <div className=\"min-w-0 flex-1\">\n                <a className=\"focus:outline-none\" href=\"#\">\n                  <span aria-hidden=\"true\" className=\"absolute inset-0\" />\n                  <p className=\"text-pretty font-medium text-foreground text-sm\">\n                    {person.name}\n                  </p>\n                  <p className=\"truncate text-pretty text-muted-foreground text-sm\">\n                    {person.role}\n                  </p>\n                </a>\n              </div>\n            </CardContent>\n          </Card>\n        ))}\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "grid-list"
      ]
    },
    {
      "name": "grid-list-03",
      "type": "registry:block",
      "title": "Grid List with Icons",
      "description": "A grid list with icons block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "card"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/grid-list/grid-list-03.tsx",
          "type": "registry:component",
          "target": "components/grid-list-03.tsx",
          "content": "import {\n  ArrowRight,\n  ArrowUpRight,\n  CheckCircle,\n  ContactRound,\n  Hand,\n  Server,\n  UserCircle,\n} from 'lucide-react';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\nconst actions = [\n  {\n    title: 'Getting Started',\n    description:\n      'Everything you need to know to get started and get to work in ChatCloud.',\n    href: '#',\n    icon: ArrowRight,\n    iconForeground: 'text-green-700',\n    iconBackground: 'bg-green-50 dark:bg-green-950/30',\n    ringColorClass: 'ring-green-700/30',\n  },\n  {\n    title: 'Admin Settings',\n    description:\n      'Learn how to manage your current workspace or your enterprise space.',\n    href: '#',\n    icon: UserCircle,\n    iconForeground: 'text-red-700',\n    iconBackground: 'bg-red-50 dark:bg-red-950/30',\n    ringColorClass: 'ring-red-700/30',\n  },\n  {\n    title: 'Server Setup',\n    description:\n      'Connect, simplify, and automate. Discover the power of apps and tools.',\n    href: '#',\n    icon: Server,\n    iconForeground: 'text-blue-700',\n    iconBackground: 'bg-blue-50 dark:bg-blue-950/30',\n    ringColorClass: 'ring-blue-700/30',\n  },\n  {\n    title: 'Login and Verification',\n    description:\n      'Read on to learn how to sign in with your email address, or your Apple or Google.',\n    href: '#',\n    icon: CheckCircle,\n    iconForeground: 'text-sky-700',\n    iconBackground: 'bg-sky-50 dark:bg-sky-950/30',\n    ringColorClass: 'ring-sky-700/30',\n  },\n  {\n    title: 'Account Setup',\n    description:\n      'Adjust your profile and preferences to make ChatCloud work just for you.',\n    href: '#',\n    icon: ContactRound,\n    iconForeground: 'text-pink-700',\n    iconBackground: 'bg-pink-50 dark:bg-pink-950/30',\n    ringColorClass: 'ring-pink-700/30',\n  },\n  {\n    title: 'Trust & Safety',\n    description:\n      'Trust on our current database and learn how we distribute your data.',\n    href: '#',\n    icon: Hand,\n    iconForeground: 'text-orange-700',\n    iconBackground: 'bg-orange-50 dark:bg-orange-950/30',\n    ringColorClass: 'ring-orange-700/30',\n  },\n];\n\nexport default function GridList03() {\n  return (\n    <div className=\"flex items-center justify-center p-8\">\n      <div className=\"grid grid-cols-1 space-y-0.5 overflow-hidden rounded-2xl bg-muted p-0.5 shadow-sm sm:grid-cols-2 sm:gap-0.5 sm:space-y-0 lg:grid-cols-3\">\n        {actions.map((action) => (\n          <Card\n            className={cn(\n              'group relative rounded-xl border-0 bg-card p-0 shadow-none focus-within:ring-2 focus-within:ring-ring focus-within:ring-inset'\n            )}\n            key={action.title}\n          >\n            <CardContent className=\"p-6\">\n              <div>\n                <span\n                  className={cn(\n                    action.iconBackground,\n                    action.iconForeground,\n                    'inline-flex rounded-lg p-3 ring-2 ring-inset',\n                    action.ringColorClass\n                  )}\n                >\n                  <action.icon aria-hidden=\"true\" className=\"h-6 w-6\" />\n                </span>\n              </div>\n              <div className=\"mt-4\">\n                <h3 className=\"text-balance font-semibold text-base text-foreground\">\n                  <a className=\"focus:outline-none\" href={action.href}>\n                    <span aria-hidden=\"true\" className=\"absolute inset-0\" />\n                    {action.title}\n                  </a>\n                </h3>\n                <p className=\"mt-2 text-pretty text-muted-foreground text-sm\">\n                  {action.description}\n                </p>\n              </div>\n              <span\n                aria-hidden=\"true\"\n                className=\"pointer-events-none absolute top-6 right-6 text-muted-foreground/50 group-hover:text-muted-foreground/60\"\n              >\n                <ArrowUpRight className=\"h-6 w-6\" />\n              </span>\n            </CardContent>\n          </Card>\n        ))}\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "grid-list"
      ]
    },
    {
      "name": "login-01",
      "type": "registry:block",
      "title": "Login with Email and Google",
      "description": "A login with email and google block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "input",
        "label",
        "separator"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/login/login-01.tsx",
          "type": "registry:component",
          "target": "components/login-01.tsx",
          "content": "import type { JSX, SVGProps } from 'react';\nimport { Button, buttonVariants } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { Separator } from '@/components/ui/separator';\nimport { cn } from '@/lib/utils';\n\nconst GoogleIcon = (\n  props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>\n) => (\n  <svg fill=\"currentColor\" viewBox=\"0 0 24 24\" {...props}>\n    <path d=\"M3.06364 7.50914C4.70909 4.24092 8.09084 2 12 2C14.6954 2 16.959 2.99095 18.6909 4.60455L15.8227 7.47274C14.7864 6.48185 13.4681 5.97727 12 5.97727C9.39542 5.97727 7.19084 7.73637 6.40455 10.1C6.2045 10.7 6.09086 11.3409 6.09086 12C6.09086 12.6591 6.2045 13.3 6.40455 13.9C7.19084 16.2636 9.39542 18.0227 12 18.0227C13.3454 18.0227 14.4909 17.6682 15.3864 17.0682C16.4454 16.3591 17.15 15.3 17.3818 14.05H12V10.1818H21.4181C21.5364 10.8363 21.6 11.5182 21.6 12.2273C21.6 15.2727 20.5091 17.8363 18.6181 19.5773C16.9636 21.1046 14.7 22 12 22C8.09084 22 4.70909 19.7591 3.06364 16.4909C2.38638 15.1409 2 13.6136 2 12C2 10.3864 2.38638 8.85911 3.06364 7.50914Z\" />\n  </svg>\n);\n\nexport default function Login01() {\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center\">\n      <div className=\"flex flex-1 flex-col justify-center px-4 py-10 lg:px-6\">\n        <div className=\"sm:mx-auto sm:w-full sm:max-w-sm\">\n          <h2 className=\"text-balance text-center font-semibold text-foreground text-xl\">\n            Log in or create account\n          </h2>\n          <form action=\"#\" className=\"mt-6\" method=\"post\">\n            <Label className=\"font-medium text-foreground\" htmlFor=\"email\">\n              Email\n            </Label>\n            <Input\n              autoComplete=\"email\"\n              className=\"mt-2\"\n              id=\"email\"\n              name=\"email\"\n              placeholder=\"john@company.com\"\n              type=\"email\"\n            />\n            <Button className=\"mt-4 w-full\" type=\"submit\">\n              Sign in\n            </Button>\n          </form>\n\n          <div className=\"relative my-6\">\n            <div className=\"absolute inset-0 flex items-center\">\n              <Separator className=\"w-full\" />\n            </div>\n            <div className=\"relative flex justify-center text-xs uppercase\">\n              <span className=\"bg-background px-2 text-muted-foreground\">\n                or with\n              </span>\n            </div>\n          </div>\n\n          <a\n            className={cn(\n              buttonVariants({ variant: 'outline' }),\n              'inline-flex w-full items-center justify-center space-x-2'\n            )}\n            href=\"#\"\n          >\n            <GoogleIcon aria-hidden={true} className=\"size-5\" />\n            <span className=\"font-medium text-sm\">Sign in with Google</span>\n          </a>\n\n          <p className=\"mt-4 text-pretty text-muted-foreground text-xs\">\n            By signing in, you agree to our{' '}\n            <a className=\"underline underline-offset-4\" href=\"#\">\n              terms of service\n            </a>{' '}\n            and{' '}\n            <a className=\"underline underline-offset-4\" href=\"#\">\n              privacy policy\n            </a>\n            .\n          </p>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "login"
      ]
    },
    {
      "name": "login-02",
      "type": "registry:block",
      "title": "Login with Email, Password and Google",
      "description": "A login with email, password and google block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "input",
        "label",
        "separator"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/login/login-02.tsx",
          "type": "registry:component",
          "target": "components/login-02.tsx",
          "content": "import type { JSX, SVGProps } from 'react';\nimport { Button, buttonVariants } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { Separator } from '@/components/ui/separator';\nimport { cn } from '@/lib/utils';\n\nconst GoogleIcon = (\n  props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>\n) => (\n  <svg fill=\"currentColor\" viewBox=\"0 0 24 24\" {...props}>\n    <path d=\"M3.06364 7.50914C4.70909 4.24092 8.09084 2 12 2C14.6954 2 16.959 2.99095 18.6909 4.60455L15.8227 7.47274C14.7864 6.48185 13.4681 5.97727 12 5.97727C9.39542 5.97727 7.19084 7.73637 6.40455 10.1C6.2045 10.7 6.09086 11.3409 6.09086 12C6.09086 12.6591 6.2045 13.3 6.40455 13.9C7.19084 16.2636 9.39542 18.0227 12 18.0227C13.3454 18.0227 14.4909 17.6682 15.3864 17.0682C16.4454 16.3591 17.15 15.3 17.3818 14.05H12V10.1818H21.4181C21.5364 10.8363 21.6 11.5182 21.6 12.2273C21.6 15.2727 20.5091 17.8363 18.6181 19.5773C16.9636 21.1046 14.7 22 12 22C8.09084 22 4.70909 19.7591 3.06364 16.4909C2.38638 15.1409 2 13.6136 2 12C2 10.3864 2.38638 8.85911 3.06364 7.50914Z\" />\n  </svg>\n);\n\nexport default function Login02() {\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center\">\n      <div className=\"flex flex-1 flex-col justify-center px-4 py-10 lg:px-6\">\n        <div className=\"sm:mx-auto sm:w-full sm:max-w-sm\">\n          <h2 className=\"text-balance text-center font-semibold text-foreground text-xl\">\n            Log in or create account\n          </h2>\n          <form action=\"#\" className=\"mt-6 space-y-4\" method=\"post\">\n            <div>\n              <Label\n                className=\"font-medium text-foreground text-sm dark:text-foreground\"\n                htmlFor=\"email-login-02\"\n              >\n                Email\n              </Label>\n              <Input\n                autoComplete=\"email\"\n                className=\"mt-2\"\n                id=\"email-login-02\"\n                name=\"email-login-02\"\n                placeholder=\"ephraim@blocks.so\"\n                type=\"email\"\n              />\n            </div>\n            <div>\n              <Label\n                className=\"font-medium text-foreground text-sm dark:text-foreground\"\n                htmlFor=\"password-login-02\"\n              >\n                Password\n              </Label>\n              <Input\n                autoComplete=\"password\"\n                className=\"mt-2\"\n                id=\"password-login-02\"\n                name=\"password-login-02\"\n                placeholder=\"**************\"\n                type=\"password\"\n              />\n            </div>\n            <Button className=\"mt-4 w-full py-2 font-medium\" type=\"submit\">\n              Sign in\n            </Button>\n          </form>\n\n          <div className=\"relative my-6\">\n            <div className=\"absolute inset-0 flex items-center\">\n              <Separator className=\"w-full\" />\n            </div>\n            <div className=\"relative flex justify-center text-xs uppercase\">\n              <span className=\"bg-background px-2 text-muted-foreground\">\n                or with\n              </span>\n            </div>\n          </div>\n\n          <a\n            className={cn(\n              buttonVariants({ variant: 'outline' }),\n              'flex w-full items-center justify-center space-x-2 py-2'\n            )}\n            href=\"#\"\n          >\n            <GoogleIcon aria-hidden={true} className=\"size-5\" />\n            <span className=\"font-medium text-sm\">Sign in with Google</span>\n          </a>\n\n          <p className=\"mt-4 text-pretty text-muted-foreground text-xs dark:text-muted-foreground\">\n            By signing in, you agree to our{' '}\n            <a className=\"underline underline-offset-4\" href=\"#\">\n              terms of service\n            </a>{' '}\n            and{' '}\n            <a className=\"underline underline-offset-4\" href=\"#\">\n              privacy policy\n            </a>\n            .\n          </p>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "login"
      ]
    },
    {
      "name": "login-03",
      "type": "registry:block",
      "title": "Login with Email and Password",
      "description": "A login with email and password block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "input",
        "label"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/login/login-03.tsx",
          "type": "registry:component",
          "target": "components/login-03.tsx",
          "content": "'use client';\n\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\n\nexport default function Login03() {\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center\">\n      <div className=\"flex flex-1 flex-col justify-center px-4 py-10 lg:px-6\">\n        <div className=\"sm:mx-auto sm:w-full sm:max-w-sm\">\n          <h3 className=\"text-balance text-center font-semibold text-foreground text-lg dark:text-foreground\">\n            Welcome Back\n          </h3>\n          <p className=\"text-pretty text-center text-muted-foreground text-sm dark:text-muted-foreground\">\n            Enter your credentials to access your account.\n          </p>\n          <form action=\"#\" className=\"mt-6 space-y-4\" method=\"post\">\n            <div>\n              <Label\n                className=\"font-medium text-foreground text-sm dark:text-foreground\"\n                htmlFor=\"email-login-03\"\n              >\n                Email\n              </Label>\n              <Input\n                autoComplete=\"email\"\n                className=\"mt-2\"\n                id=\"email-login-03\"\n                name=\"email-login-03\"\n                placeholder=\"ephraim@blocks.so\"\n                type=\"email\"\n              />\n            </div>\n            <div>\n              <Label\n                className=\"font-medium text-foreground text-sm dark:text-foreground\"\n                htmlFor=\"password-login-03\"\n              >\n                Password\n              </Label>\n              <Input\n                autoComplete=\"password\"\n                className=\"mt-2\"\n                id=\"password-login-03\"\n                name=\"password-login-03\"\n                placeholder=\"**************\"\n                type=\"password\"\n              />\n            </div>\n            <Button className=\"mt-4 w-full py-2 font-medium\" type=\"submit\">\n              Sign in\n            </Button>\n          </form>\n          <p className=\"mt-6 text-pretty text-muted-foreground text-sm dark:text-muted-foreground\">\n            Forgot your password?{' '}\n            <a\n              className=\"font-medium text-primary hover:text-primary/90 dark:text-primary dark:hover:text-primary/90\"\n              href=\"#\"\n            >\n              Reset password\n            </a>\n          </p>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "login"
      ]
    },
    {
      "name": "login-04",
      "type": "registry:block",
      "title": "Login with Social Buttons",
      "description": "A login with social buttons block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "input",
        "label",
        "separator"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/login/login-04.tsx",
          "type": "registry:component",
          "target": "components/login-04.tsx",
          "content": "import type { JSX, SVGProps } from 'react';\nimport { Button, buttonVariants } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { Separator } from '@/components/ui/separator';\nimport { cn } from '@/lib/utils';\n\nconst GitHubIcon = (\n  props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>\n) => (\n  <svg fill=\"currentColor\" viewBox=\"0 0 24 24\" {...props}>\n    <path d=\"M12.001 2C6.47598 2 2.00098 6.475 2.00098 12C2.00098 16.425 4.86348 20.1625 8.83848 21.4875C9.33848 21.575 9.52598 21.275 9.52598 21.0125C9.52598 20.775 9.51348 19.9875 9.51348 19.15C7.00098 19.6125 6.35098 18.5375 6.15098 17.975C6.03848 17.6875 5.55098 16.8 5.12598 16.5625C4.77598 16.375 4.27598 15.9125 5.11348 15.9C5.90098 15.8875 6.46348 16.625 6.65098 16.925C7.55098 18.4375 8.98848 18.0125 9.56348 17.75C9.65098 17.1 9.91348 16.6625 10.201 16.4125C7.97598 16.1625 5.65098 15.3 5.65098 11.475C5.65098 10.3875 6.03848 9.4875 6.67598 8.7875C6.57598 8.5375 6.22598 7.5125 6.77598 6.1375C6.77598 6.1375 7.61348 5.875 9.52598 7.1625C10.326 6.9375 11.176 6.825 12.026 6.825C12.876 6.825 13.726 6.9375 14.526 7.1625C16.4385 5.8625 17.276 6.1375 17.276 6.1375C17.826 7.5125 17.476 8.5375 17.376 8.7875C18.0135 9.4875 18.401 10.375 18.401 11.475C18.401 15.3125 16.0635 16.1625 13.8385 16.4125C14.201 16.725 14.5135 17.325 14.5135 18.2625C14.5135 19.6 14.501 20.675 14.501 21.0125C14.501 21.275 14.6885 21.5875 15.1885 21.4875C19.259 20.1133 21.9999 16.2963 22.001 12C22.001 6.475 17.526 2 12.001 2Z\" />\n  </svg>\n);\n\nconst GoogleIcon = (\n  props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>\n) => (\n  <svg fill=\"currentColor\" viewBox=\"0 0 24 24\" {...props}>\n    <path d=\"M3.06364 7.50914C4.70909 4.24092 8.09084 2 12 2C14.6954 2 16.959 2.99095 18.6909 4.60455L15.8227 7.47274C14.7864 6.48185 13.4681 5.97727 12 5.97727C9.39542 5.97727 7.19084 7.73637 6.40455 10.1C6.2045 10.7 6.09086 11.3409 6.09086 12C6.09086 12.6591 6.2045 13.3 6.40455 13.9C7.19084 16.2636 9.39542 18.0227 12 18.0227C13.3454 18.0227 14.4909 17.6682 15.3864 17.0682C16.4454 16.3591 17.15 15.3 17.3818 14.05H12V10.1818H21.4181C21.5364 10.8363 21.6 11.5182 21.6 12.2273C21.6 15.2727 20.5091 17.8363 18.6181 19.5773C16.9636 21.1046 14.7 22 12 22C8.09084 22 4.70909 19.7591 3.06364 16.4909C2.38638 15.1409 2 13.6136 2 12C2 10.3864 2.38638 8.85911 3.06364 7.50914Z\" />\n  </svg>\n);\n\nconst Logo = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (\n  <svg\n    fill=\"currentColor\"\n    height=\"48\"\n    viewBox=\"0 0 40 48\"\n    width=\"40\"\n    {...props}\n  >\n    <clipPath id=\"a\">\n      <path d=\"m0 0h40v48h-40z\" />\n    </clipPath>\n    <g clipPath=\"url(#a)\">\n      <path d=\"m25.0887 5.05386-3.933-1.05386-3.3145 12.3696-2.9923-11.16736-3.9331 1.05386 3.233 12.0655-8.05262-8.0526-2.87919 2.8792 8.83271 8.8328-10.99975-2.9474-1.05385625 3.933 12.01860625 3.2204c-.1376-.5935-.2104-1.2119-.2104-1.8473 0-4.4976 3.646-8.1436 8.1437-8.1436 4.4976 0 8.1436 3.646 8.1436 8.1436 0 .6313-.0719 1.2459-.2078 1.8359l10.9227 2.9267 1.0538-3.933-12.0664-3.2332 11.0005-2.9476-1.0539-3.933-12.0659 3.233 8.0526-8.0526-2.8792-2.87916-8.7102 8.71026z\" />\n      <path d=\"m27.8723 26.2214c-.3372 1.4256-1.0491 2.7063-2.0259 3.7324l7.913 7.9131 2.8792-2.8792z\" />\n      <path d=\"m25.7665 30.0366c-.9886 1.0097-2.2379 1.7632-3.6389 2.1515l2.8794 10.746 3.933-1.0539z\" />\n      <path d=\"m21.9807 32.2274c-.65.1671-1.3313.2559-2.0334.2559-.7522 0-1.4806-.102-2.1721-.2929l-2.882 10.7558 3.933 1.0538z\" />\n      <path d=\"m17.6361 32.1507c-1.3796-.4076-2.6067-1.1707-3.5751-2.1833l-7.9325 7.9325 2.87919 2.8792z\" />\n      <path d=\"m13.9956 29.8973c-.9518-1.019-1.6451-2.2826-1.9751-3.6862l-10.95836 2.9363 1.05385 3.933z\" />\n    </g>\n  </svg>\n);\n\nexport default function Login04() {\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center\">\n      <div className=\"flex flex-1 flex-col justify-center px-4 py-10 lg:px-6\">\n        <div className=\"sm:mx-auto sm:w-full sm:max-w-md\">\n          <div className=\"flex items-center space-x-1.5\">\n            <Logo\n              aria-hidden={true}\n              className=\"h-7 w-7 text-foreground dark:text-foreground\"\n            />\n            <p className=\"text-pretty font-medium text-foreground text-lg dark:text-foreground\">\n              Acme\n            </p>\n          </div>\n          <h3 className=\"mt-6 text-balance font-semibold text-foreground text-lg dark:text-foreground\">\n            Sign in to your account\n          </h3>\n          <p className=\"mt-2 text-pretty text-muted-foreground text-sm dark:text-muted-foreground\">\n            Don&apos;t have an account?{' '}\n            <a\n              className=\"font-medium text-primary hover:text-primary/90 dark:text-primary hover:dark:text-primary/90\"\n              href=\"#\"\n            >\n              Sign up\n            </a>\n          </p>\n          <div className=\"mt-8 flex flex-col items-center space-y-2 sm:flex-row sm:space-x-4 sm:space-y-0\">\n            <a\n              className={cn(\n                buttonVariants({ variant: 'outline' }),\n                'flex-1 items-center justify-center space-x-2 py-2'\n              )}\n              href=\"#\"\n            >\n              <GitHubIcon aria-hidden={true} className=\"size-5\" />\n              <span className=\"font-medium text-sm\">Login with GitHub</span>\n            </a>\n            <a\n              className={cn(\n                buttonVariants({ variant: 'outline' }),\n                'mt-2 flex-1 items-center justify-center space-x-2 py-2 sm:mt-0'\n              )}\n              href=\"#\"\n            >\n              <GoogleIcon aria-hidden={true} className=\"size-4\" />\n              <span className=\"font-medium text-sm\">Login with Google</span>\n            </a>\n          </div>\n\n          <div className=\"relative my-6\">\n            <div className=\"absolute inset-0 flex items-center\">\n              <Separator className=\"w-full\" />\n            </div>\n            <div className=\"relative flex justify-center text-xs uppercase\">\n              <span className=\"bg-background px-2 text-muted-foreground\">\n                or\n              </span>\n            </div>\n          </div>\n\n          <form action=\"#\" className=\"mt-6 space-y-4\" method=\"post\">\n            <div>\n              <Label\n                className=\"font-medium text-foreground text-sm dark:text-foreground\"\n                htmlFor=\"email-login-04\"\n              >\n                Email\n              </Label>\n              <Input\n                autoComplete=\"email\"\n                className=\"mt-2\"\n                id=\"email-login-04\"\n                name=\"email-login-04\"\n                placeholder=\"ephraim@blocks.so\"\n                type=\"email\"\n              />\n            </div>\n            <div>\n              <Label\n                className=\"font-medium text-foreground text-sm dark:text-foreground\"\n                htmlFor=\"password-login-04\"\n              >\n                Password\n              </Label>\n              <Input\n                autoComplete=\"password\"\n                className=\"mt-2\"\n                id=\"password-login-04\"\n                name=\"password-login-04\"\n                placeholder=\"********\"\n                type=\"password\"\n              />\n            </div>\n            <Button className=\"mt-4 w-full py-2 font-medium\" type=\"submit\">\n              Sign in\n            </Button>\n          </form>\n          <p className=\"mt-6 text-pretty text-muted-foreground text-sm dark:text-muted-foreground\">\n            Forgot your password?{' '}\n            <a\n              className=\"font-medium text-primary hover:text-primary/90 dark:text-primary hover:dark:text-primary/90\"\n              href=\"#\"\n            >\n              Reset password\n            </a>\n          </p>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "login"
      ]
    },
    {
      "name": "login-05",
      "type": "registry:block",
      "title": "Login Card Signup Form",
      "description": "A login card signup form block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "checkbox",
        "input",
        "label"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/login/login-05.tsx",
          "type": "registry:component",
          "target": "components/login-05.tsx",
          "content": "import type { JSX, SVGProps } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\n\nconst Logo = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (\n  <svg\n    fill=\"currentColor\"\n    height=\"48\"\n    viewBox=\"0 0 40 48\"\n    width=\"40\"\n    {...props}\n  >\n    <clipPath id=\"a\">\n      <path d=\"m0 0h40v48h-40z\" />\n    </clipPath>\n    <g clipPath=\"url(#a)\">\n      <path d=\"m25.0887 5.05386-3.933-1.05386-3.3145 12.3696-2.9923-11.16736-3.9331 1.05386 3.233 12.0655-8.05262-8.0526-2.87919 2.8792 8.83271 8.8328-10.99975-2.9474-1.05385625 3.933 12.01860625 3.2204c-.1376-.5935-.2104-1.2119-.2104-1.8473 0-4.4976 3.646-8.1436 8.1437-8.1436 4.4976 0 8.1436 3.646 8.1436 8.1436 0 .6313-.0719 1.2459-.2078 1.8359l10.9227 2.9267 1.0538-3.933-12.0664-3.2332 11.0005-2.9476-1.0539-3.933-12.0659 3.233 8.0526-8.0526-2.8792-2.87916-8.7102 8.71026z\" />\n      <path d=\"m27.8723 26.2214c-.3372 1.4256-1.0491 2.7063-2.0259 3.7324l7.913 7.9131 2.8792-2.8792z\" />\n      <path d=\"m25.7665 30.0366c-.9886 1.0097-2.2379 1.7632-3.6389 2.1515l2.8794 10.746 3.933-1.0539z\" />\n      <path d=\"m21.9807 32.2274c-.65.1671-1.3313.2559-2.0334.2559-.7522 0-1.4806-.102-2.1721-.2929l-2.882 10.7558 3.933 1.0538z\" />\n      <path d=\"m17.6361 32.1507c-1.3796-.4076-2.6067-1.1707-3.5751-2.1833l-7.9325 7.9325 2.87919 2.8792z\" />\n      <path d=\"m13.9956 29.8973c-.9518-1.019-1.6451-2.2826-1.9751-3.6862l-10.95836 2.9363 1.05385 3.933z\" />\n    </g>\n  </svg>\n);\n\nexport default function Login05() {\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center\">\n      <div className=\"flex flex-1 flex-col justify-center px-4 py-10 lg:px-6\">\n        <div className=\"sm:mx-auto sm:w-full sm:max-w-md\">\n          <Logo\n            aria-hidden={true}\n            className=\"mx-auto h-10 w-10 text-foreground dark:text-foreground\"\n          />\n          <h3 className=\"mt-2 text-balance text-center font-bold text-foreground text-lg dark:text-foreground\">\n            Create new account for workspace\n          </h3>\n        </div>\n\n        <Card className=\"mt-4 shadow-2xs sm:mx-auto sm:w-full sm:max-w-md\">\n          <CardContent>\n            <form action=\"#\" className=\"space-y-4\" method=\"post\">\n              <div>\n                <Label\n                  className=\"font-medium text-foreground text-sm dark:text-foreground\"\n                  htmlFor=\"name-login-05\"\n                >\n                  Name\n                </Label>\n                <Input\n                  autoComplete=\"name-login-05\"\n                  className=\"mt-2\"\n                  id=\"name-login-05\"\n                  name=\"name-login-05\"\n                  placeholder=\"Name\"\n                  type=\"text\"\n                />\n              </div>\n\n              <div>\n                <Label\n                  className=\"font-medium text-foreground text-sm dark:text-foreground\"\n                  htmlFor=\"email-login-05\"\n                >\n                  Email\n                </Label>\n                <Input\n                  autoComplete=\"email-login-05\"\n                  className=\"mt-2\"\n                  id=\"email-login-05\"\n                  name=\"email-login-05\"\n                  placeholder=\"ephraim@blocks.so\"\n                  type=\"email\"\n                />\n              </div>\n\n              <div>\n                <Label\n                  className=\"font-medium text-foreground text-sm dark:text-foreground\"\n                  htmlFor=\"password-login-05\"\n                >\n                  Password\n                </Label>\n                <Input\n                  autoComplete=\"password-login-05\"\n                  className=\"mt-2\"\n                  id=\"password-login-05   \"\n                  name=\"password-login-05\"\n                  placeholder=\"Password\"\n                  type=\"password\"\n                />\n              </div>\n\n              <div>\n                <Label\n                  className=\"font-medium text-foreground text-sm dark:text-foreground\"\n                  htmlFor=\"confirm-password-login-05\"\n                >\n                  Confirm password\n                </Label>\n                <Input\n                  autoComplete=\"confirm-password-login-05\"\n                  className=\"mt-2\"\n                  id=\"confirm-password-login-05\"\n                  name=\"confirm-password-login-05\"\n                  placeholder=\"Password\"\n                  type=\"password\"\n                />\n              </div>\n\n              <div className=\"mt-2 flex items-start\">\n                <div className=\"flex h-6 items-center\">\n                  <Checkbox\n                    className=\"size-4\"\n                    id=\"newsletter-login-05\"\n                    name=\"newsletter-login-05\"\n                  />\n                </div>\n                <Label\n                  className=\"ml-3 text-muted-foreground text-sm leading-6 dark:text-muted-foreground\"\n                  htmlFor=\"newsletter-login-05\"\n                >\n                  Sign up to our newsletter\n                </Label>\n              </div>\n\n              <Button className=\"mt-4 w-full py-2 font-medium\" type=\"submit\">\n                Create account\n              </Button>\n\n              <p className=\"text-pretty text-center text-muted-foreground text-xs dark:text-muted-foreground\">\n                By signing in, you agree to our{' '}\n                <a\n                  className=\"text-primary capitalize hover:text-primary/90 dark:text-primary hover:dark:text-primary/90\"\n                  href=\"#\"\n                >\n                  Terms of use\n                </a>{' '}\n                and{' '}\n                <a\n                  className=\"text-primary capitalize hover:text-primary/90 dark:text-primary hover:dark:text-primary/90\"\n                  href=\"#\"\n                >\n                  Privacy policy\n                </a>\n              </p>\n            </form>\n          </CardContent>\n        </Card>\n\n        <p className=\"mt-6 text-pretty text-center text-muted-foreground text-sm dark:text-muted-foreground\">\n          Already have an account?{' '}\n          <a\n            className=\"font-medium text-primary hover:text-primary/90 dark:text-primary hover:dark:text-primary/90\"\n            href=\"#\"\n          >\n            Sign in\n          </a>\n        </p>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "login"
      ]
    },
    {
      "name": "login-06",
      "type": "registry:block",
      "title": "Login with Magic Link and SSO",
      "description": "A login with magic link and sso block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "input",
        "separator"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/login/login-06.tsx",
          "type": "registry:component",
          "target": "components/login-06.tsx",
          "content": "import type { JSX, SVGProps } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { Input } from '@/components/ui/input';\nimport { Separator } from '@/components/ui/separator';\n\nconst Logo = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (\n  <svg\n    fill=\"currentColor\"\n    height=\"48\"\n    viewBox=\"0 0 40 48\"\n    width=\"40\"\n    {...props}\n  >\n    <clipPath id=\"a\">\n      <path d=\"m0 0h40v48h-40z\" />\n    </clipPath>\n    <g clipPath=\"url(#a)\">\n      <path d=\"m25.0887 5.05386-3.933-1.05386-3.3145 12.3696-2.9923-11.16736-3.9331 1.05386 3.233 12.0655-8.05262-8.0526-2.87919 2.8792 8.83271 8.8328-10.99975-2.9474-1.05385625 3.933 12.01860625 3.2204c-.1376-.5935-.2104-1.2119-.2104-1.8473 0-4.4976 3.646-8.1436 8.1437-8.1436 4.4976 0 8.1436 3.646 8.1436 8.1436 0 .6313-.0719 1.2459-.2078 1.8359l10.9227 2.9267 1.0538-3.933-12.0664-3.2332 11.0005-2.9476-1.0539-3.933-12.0659 3.233 8.0526-8.0526-2.8792-2.87916-8.7102 8.71026z\" />\n      <path d=\"m27.8723 26.2214c-.3372 1.4256-1.0491 2.7063-2.0259 3.7324l7.913 7.9131 2.8792-2.8792z\" />\n      <path d=\"m25.7665 30.0366c-.9886 1.0097-2.2379 1.7632-3.6389 2.1515l2.8794 10.746 3.933-1.0539z\" />\n      <path d=\"m21.9807 32.2274c-.65.1671-1.3313.2559-2.0334.2559-.7522 0-1.4806-.102-2.1721-.2929l-2.882 10.7558 3.933 1.0538z\" />\n      <path d=\"m17.6361 32.1507c-1.3796-.4076-2.6067-1.1707-3.5751-2.1833l-7.9325 7.9325 2.87919 2.8792z\" />\n      <path d=\"m13.9956 29.8973c-.9518-1.019-1.6451-2.2826-1.9751-3.6862l-10.95836 2.9363 1.05385 3.933z\" />\n    </g>\n  </svg>\n);\n\nexport default function Login06() {\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center\">\n      <Card className=\"w-full max-w-sm rounded-4xl px-6 py-10 pt-14 shadow-2xs\">\n        <CardContent className=\"\">\n          <div className=\"flex flex-col items-center space-y-8\">\n            <Logo />\n\n            <div className=\"space-y-2 text-center\">\n              <h1 className=\"text-balance font-semibold text-3xl text-foreground\">\n                Welcome back!\n              </h1>\n              <p className=\"text-pretty text-muted-foreground text-sm\">\n                First time here?{' '}\n                <a className=\"text-foreground hover:underline\" href=\"#\">\n                  Sign up for free\n                </a>\n              </p>\n            </div>\n\n            <div className=\"w-full space-y-4\">\n              <Input\n                className=\"w-full rounded-xl\"\n                placeholder=\"Your email\"\n                type=\"email\"\n              />\n              <div className=\"flex flex-col gap-2\">\n                <Button className=\"w-full rounded-xl\" size=\"lg\">\n                  Send me the magic link\n                </Button>\n                <Button\n                  className=\"w-full text-muted-foreground text-sm\"\n                  variant=\"link\"\n                >\n                  Sign in using password\n                </Button>\n              </div>\n\n              <div className=\"flex items-center gap-4 py-2\">\n                <Separator className=\"flex-1\" />\n                <span className=\"text-muted-foreground text-sm\">OR</span>\n                <Separator className=\"flex-1\" />\n              </div>\n\n              <Button className=\"w-full rounded-xl\" size=\"lg\" variant=\"outline\">\n                Single sign-on (SSO)\n              </Button>\n            </div>\n\n            <p className=\"w-11/12 text-pretty text-center text-muted-foreground text-xs\">\n              You acknowledge that you read, and agree, to our{' '}\n              <a className=\"underline hover:text-foreground\" href=\"#\">\n                Terms of Service\n              </a>{' '}\n              and our{' '}\n              <a className=\"underline hover:text-foreground\" href=\"#\">\n                Privacy Policy\n              </a>\n              .\n            </p>\n          </div>\n        </CardContent>\n      </Card>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "login"
      ]
    },
    {
      "name": "login-07",
      "type": "registry:block",
      "title": "Login Full Page with Icons",
      "description": "A login full page with icons block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "checkbox",
        "input",
        "label",
        "separator"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/login/login-07.tsx",
          "type": "registry:component",
          "target": "components/login-07.tsx",
          "content": "'use client';\n\nimport { ArrowRight, Eye, EyeOff, Lock, Mail } from 'lucide-react';\nimport { type JSX, type SVGProps, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport { Separator } from '@/components/ui/separator';\n\nconst GoogleIcon = (\n  props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>\n) => (\n  <svg fill=\"currentColor\" viewBox=\"0 0 24 24\" {...props}>\n    <path d=\"M3.06364 7.50914C4.70909 4.24092 8.09084 2 12 2C14.6954 2 16.959 2.99095 18.6909 4.60455L15.8227 7.47274C14.7864 6.48185 13.4681 5.97727 12 5.97727C9.39542 5.97727 7.19084 7.73637 6.40455 10.1C6.2045 10.7 6.09086 11.3409 6.09086 12C6.09086 12.6591 6.2045 13.3 6.40455 13.9C7.19084 16.2636 9.39542 18.0227 12 18.0227C13.3454 18.0227 14.4909 17.6682 15.3864 17.0682C16.4454 16.3591 17.15 15.3 17.3818 14.05H12V10.1818H21.4181C21.5364 10.8363 21.6 11.5182 21.6 12.2273C21.6 15.2727 20.5091 17.8363 18.6181 19.5773C16.9636 21.1046 14.7 22 12 22C8.09084 22 4.70909 19.7591 3.06364 16.4909C2.38638 15.1409 2 13.6136 2 12C2 10.3864 2.38638 8.85911 3.06364 7.50914Z\" />\n  </svg>\n);\n\nconst Logo = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (\n  <svg\n    fill=\"currentColor\"\n    height=\"48\"\n    viewBox=\"0 0 40 48\"\n    width=\"40\"\n    {...props}\n  >\n    <clipPath id=\"a\">\n      <path d=\"m0 0h40v48h-40z\" />\n    </clipPath>\n    <g clipPath=\"url(#a)\">\n      <path d=\"m25.0887 5.05386-3.933-1.05386-3.3145 12.3696-2.9923-11.16736-3.9331 1.05386 3.233 12.0655-8.05262-8.0526-2.87919 2.8792 8.83271 8.8328-10.99975-2.9474-1.05385625 3.933 12.01860625 3.2204c-.1376-.5935-.2104-1.2119-.2104-1.8473 0-4.4976 3.646-8.1436 8.1437-8.1436 4.4976 0 8.1436 3.646 8.1436 8.1436 0 .6313-.0719 1.2459-.2078 1.8359l10.9227 2.9267 1.0538-3.933-12.0664-3.2332 11.0005-2.9476-1.0539-3.933-12.0659 3.233 8.0526-8.0526-2.8792-2.87916-8.7102 8.71026z\" />\n      <path d=\"m27.8723 26.2214c-.3372 1.4256-1.0491 2.7063-2.0259 3.7324l7.913 7.9131 2.8792-2.8792z\" />\n      <path d=\"m25.7665 30.0366c-.9886 1.0097-2.2379 1.7632-3.6389 2.1515l2.8794 10.746 3.933-1.0539z\" />\n      <path d=\"m21.9807 32.2274c-.65.1671-1.3313.2559-2.0334.2559-.7522 0-1.4806-.102-2.1721-.2929l-2.882 10.7558 3.933 1.0538z\" />\n      <path d=\"m17.6361 32.1507c-1.3796-.4076-2.6067-1.1707-3.5751-2.1833l-7.9325 7.9325 2.87919 2.8792z\" />\n      <path d=\"m13.9956 29.8973c-.9518-1.019-1.6451-2.2826-1.9751-3.6862l-10.95836 2.9363 1.05385 3.933z\" />\n    </g>\n  </svg>\n);\n\nexport default function Login07() {\n  const [isVisible, setIsVisible] = useState<boolean>(false);\n\n  const toggleVisibility = () => setIsVisible((prevState) => !prevState);\n\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center\">\n      <div className=\"mx-auto w-full max-w-xs space-y-6\">\n        <div className=\"space-y-2 text-center\">\n          <Logo className=\"mx-auto h-16 w-16\" />\n          <h1 className=\"text-balance font-semibold text-3xl\">Welcome back</h1>\n          <p className=\"text-pretty text-muted-foreground\">\n            Sign in to access to your dashboard, settings and projects.\n          </p>\n        </div>\n\n        <div className=\"space-y-5\">\n          <Button className=\"w-full justify-center gap-2\" variant=\"outline\">\n            <GoogleIcon className=\"h-4 w-4\" />\n            Sign in with Google\n          </Button>\n\n          <div className=\"flex items-center gap-2\">\n            <Separator className=\"flex-1\" />\n            <span className=\"text-muted-foreground text-sm\">\n              or sign in with email\n            </span>\n            <Separator className=\"flex-1\" />\n          </div>\n\n          <div className=\"space-y-6\">\n            <div>\n              <Label htmlFor=\"email\">Email</Label>\n              <div className=\"relative mt-2.5\">\n                <Input\n                  className=\"peer ps-9\"\n                  id=\"email\"\n                  placeholder=\"ephraim@blocks.so\"\n                  type=\"email\"\n                />\n                <div className=\"pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 text-muted-foreground/80 peer-disabled:opacity-50\">\n                  <Mail aria-hidden=\"true\" size={16} />\n                </div>\n              </div>\n            </div>\n\n            <div>\n              <div className=\"flex items-center justify-between\">\n                <Label htmlFor=\"password\">Password</Label>\n                <a className=\"text-primary text-sm hover:underline\" href=\"#\">\n                  Forgot Password?\n                </a>\n              </div>\n              <div className=\"relative mt-2.5\">\n                <Input\n                  className=\"ps-9 pe-9\"\n                  id=\"password\"\n                  placeholder=\"Enter your password\"\n                  type={isVisible ? 'text' : 'password'}\n                />\n                <div className=\"pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 text-muted-foreground/80 peer-disabled:opacity-50\">\n                  <Lock aria-hidden=\"true\" size={16} />\n                </div>\n                <button\n                  aria-controls=\"password\"\n                  aria-label={isVisible ? 'Hide password' : 'Show password'}\n                  aria-pressed={isVisible}\n                  className=\"absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center rounded-e-md text-muted-foreground/80 outline-none transition-[color,box-shadow] hover:text-foreground focus:z-10 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\"\n                  onClick={toggleVisibility}\n                  type=\"button\"\n                >\n                  {isVisible ? (\n                    <EyeOff aria-hidden=\"true\" size={16} />\n                  ) : (\n                    <Eye aria-hidden=\"true\" size={16} />\n                  )}\n                </button>\n              </div>\n            </div>\n\n            <div className=\"flex items-center gap-2 pt-1\">\n              <Checkbox id=\"remember-me\" />\n              <Label htmlFor=\"remember-me\">Remember for 30 days</Label>\n            </div>\n          </div>\n\n          <Button className=\"w-full\">\n            Sign in\n            <ArrowRight className=\"h-4 w-4\" />\n          </Button>\n\n          <div className=\"text-center text-sm\">\n            No account?{' '}\n            <a className=\"font-medium text-primary hover:underline\" href=\"#\">\n              Create an account\n            </a>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "login"
      ]
    },
    {
      "name": "login-08",
      "type": "registry:block",
      "title": "Login with SSO",
      "description": "A login with sso block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "checkbox",
        "input",
        "label"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/login/login-08.tsx",
          "type": "registry:component",
          "target": "components/login-08.tsx",
          "content": "'use client';\n\nimport { EyeIcon, EyeOffIcon, Key } from 'lucide-react';\nimport Link from 'next/link';\nimport { type JSX, type SVGProps, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  Card,\n  CardContent,\n  CardFooter,\n  CardHeader,\n} from '@/components/ui/card';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\n\nconst Logo = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (\n  <svg\n    fill=\"currentColor\"\n    height=\"48\"\n    viewBox=\"0 0 40 48\"\n    width=\"40\"\n    {...props}\n  >\n    <clipPath id=\"a\">\n      <path d=\"m0 0h40v48h-40z\" />\n    </clipPath>\n    <g clipPath=\"url(#a)\">\n      <path d=\"m25.0887 5.05386-3.933-1.05386-3.3145 12.3696-2.9923-11.16736-3.9331 1.05386 3.233 12.0655-8.05262-8.0526-2.87919 2.8792 8.83271 8.8328-10.99975-2.9474-1.05385625 3.933 12.01860625 3.2204c-.1376-.5935-.2104-1.2119-.2104-1.8473 0-4.4976 3.646-8.1436 8.1437-8.1436 4.4976 0 8.1436 3.646 8.1436 8.1436 0 .6313-.0719 1.2459-.2078 1.8359l10.9227 2.9267 1.0538-3.933-12.0664-3.2332 11.0005-2.9476-1.0539-3.933-12.0659 3.233 8.0526-8.0526-2.8792-2.87916-8.7102 8.71026z\" />\n      <path d=\"m27.8723 26.2214c-.3372 1.4256-1.0491 2.7063-2.0259 3.7324l7.913 7.9131 2.8792-2.8792z\" />\n      <path d=\"m25.7665 30.0366c-.9886 1.0097-2.2379 1.7632-3.6389 2.1515l2.8794 10.746 3.933-1.0539z\" />\n      <path d=\"m21.9807 32.2274c-.65.1671-1.3313.2559-2.0334.2559-.7522 0-1.4806-.102-2.1721-.2929l-2.882 10.7558 3.933 1.0538z\" />\n      <path d=\"m17.6361 32.1507c-1.3796-.4076-2.6067-1.1707-3.5751-2.1833l-7.9325 7.9325 2.87919 2.8792z\" />\n      <path d=\"m13.9956 29.8973c-.9518-1.019-1.6451-2.2826-1.9751-3.6862l-10.95836 2.9363 1.05385 3.933z\" />\n    </g>\n  </svg>\n);\n\nexport default function SignIn() {\n  const [isPasswordVisible, setIsPasswordVisible] = useState<boolean>(false);\n\n  const togglePasswordVisibility = () => setIsPasswordVisible((prev) => !prev);\n\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center\">\n      <Card className=\"mx-4 w-full max-w-md pb-0 shadow-2xs\">\n        <CardHeader className=\"mt-4 mb-2 space-y-1 text-center\">\n          <div className=\"flex justify-center\">\n            <Logo />\n          </div>\n          <div>\n            <h2 className=\"text-balance font-semibold text-2xl\">\n              Sign in to Acme\n            </h2>\n            <p className=\"text-pretty text-muted-foreground text-sm\">\n              Welcome back! Please enter your details.\n            </p>\n          </div>\n        </CardHeader>\n        <CardContent className=\"space-y-6\">\n          <div className=\"space-y-2\">\n            <Label htmlFor=\"email\">Email address</Label>\n            <Input id=\"email\" placeholder=\"ephraim@blocks.so\" type=\"email\" />\n          </div>\n          <div className=\"space-y-0\">\n            <div className=\"mb-2 flex items-center justify-between\">\n              <Label htmlFor=\"password\">Password</Label>\n              <Link className=\"text-primary text-sm hover:underline\" href=\"#\">\n                Reset password\n              </Link>\n            </div>\n            <div className=\"relative\">\n              <Input\n                className=\"pe-9\"\n                id=\"password\"\n                placeholder=\"Enter your password\"\n                type={isPasswordVisible ? 'text' : 'password'}\n              />\n              <button\n                aria-controls=\"password\"\n                aria-label={\n                  isPasswordVisible ? 'Hide password' : 'Show password'\n                }\n                aria-pressed={isPasswordVisible}\n                className=\"absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center rounded-e-md text-muted-foreground/80 outline-none transition-[color,box-shadow] hover:text-foreground focus:z-10 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\"\n                onClick={togglePasswordVisibility}\n                type=\"button\"\n              >\n                {isPasswordVisible ? (\n                  <EyeOffIcon aria-hidden=\"true\" size={16} />\n                ) : (\n                  <EyeIcon aria-hidden=\"true\" size={16} />\n                )}\n              </button>\n            </div>\n          </div>\n          <div className=\"flex items-center space-x-2\">\n            <Checkbox defaultChecked id=\"remember\" />\n            <Label className=\"font-normal text-sm\" htmlFor=\"remember\">\n              Remember me\n            </Label>\n          </div>\n\n          <div className=\"space-y-2\">\n            <Button className=\"w-full\" type=\"submit\">\n              Sign In\n            </Button>\n            <Button className=\"w-full\" type=\"button\" variant=\"outline\">\n              <Key className=\"mr-2 h-4 w-4\" />\n              Single sign-on (SSO)\n            </Button>\n          </div>\n        </CardContent>\n        <CardFooter className=\"flex justify-center border-t py-4!\">\n          <p className=\"text-pretty text-center text-muted-foreground text-sm\">\n            New to Acme?{' '}\n            <Link className=\"text-primary hover:underline\" href=\"#\">\n              Sign up\n            </Link>\n          </p>\n        </CardFooter>\n      </Card>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "login"
      ]
    },
    {
      "name": "login-09",
      "type": "registry:block",
      "title": "Login Signup with Role Selection",
      "description": "A login signup with role selection block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "checkbox",
        "input",
        "label",
        "select"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/login/login-09.tsx",
          "type": "registry:component",
          "target": "components/login-09.tsx",
          "content": "'use client';\n\nimport { BarChart, Code, Eye, EyeOff, User } from 'lucide-react';\nimport Link from 'next/link';\nimport { type JSX, type SVGProps, useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport {\n  Card,\n  CardContent,\n  CardFooter,\n  CardHeader,\n} from '@/components/ui/card';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\n\nconst Logo = (props: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (\n  <svg\n    fill=\"currentColor\"\n    height=\"48\"\n    viewBox=\"0 0 40 48\"\n    width=\"40\"\n    {...props}\n  >\n    <clipPath id=\"a\">\n      <path d=\"m0 0h40v48h-40z\" />\n    </clipPath>\n    <g clipPath=\"url(#a)\">\n      <path d=\"m25.0887 5.05386-3.933-1.05386-3.3145 12.3696-2.9923-11.16736-3.9331 1.05386 3.233 12.0655-8.05262-8.0526-2.87919 2.8792 8.83271 8.8328-10.99975-2.9474-1.05385625 3.933 12.01860625 3.2204c-.1376-.5935-.2104-1.2119-.2104-1.8473 0-4.4976 3.646-8.1436 8.1437-8.1436 4.4976 0 8.1436 3.646 8.1436 8.1436 0 .6313-.0719 1.2459-.2078 1.8359l10.9227 2.9267 1.0538-3.933-12.0664-3.2332 11.0005-2.9476-1.0539-3.933-12.0659 3.233 8.0526-8.0526-2.8792-2.87916-8.7102 8.71026z\" />\n      <path d=\"m27.8723 26.2214c-.3372 1.4256-1.0491 2.7063-2.0259 3.7324l7.913 7.9131 2.8792-2.8792z\" />\n      <path d=\"m25.7665 30.0366c-.9886 1.0097-2.2379 1.7632-3.6389 2.1515l2.8794 10.746 3.933-1.0539z\" />\n      <path d=\"m21.9807 32.2274c-.65.1671-1.3313.2559-2.0334.2559-.7522 0-1.4806-.102-2.1721-.2929l-2.882 10.7558 3.933 1.0538z\" />\n      <path d=\"m17.6361 32.1507c-1.3796-.4076-2.6067-1.1707-3.5751-2.1833l-7.9325 7.9325 2.87919 2.8792z\" />\n      <path d=\"m13.9956 29.8973c-.9518-1.019-1.6451-2.2826-1.9751-3.6862l-10.95836 2.9363 1.05385 3.933z\" />\n    </g>\n  </svg>\n);\n\nexport default function SignupForm() {\n  const [showPassword, setShowPassword] = useState(false);\n\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center\">\n      <div className=\"w-full max-w-md\">\n        <Card className=\"border-none pb-0 shadow-lg\">\n          <CardHeader className=\"flex flex-col items-center space-y-1.5 pt-6 pb-4\">\n            <Logo className=\"h-12 w-12\" />\n            <div className=\"flex flex-col items-center space-y-0.5\">\n              <h2 className=\"text-balance font-semibold text-2xl text-foreground\">\n                Create an account\n              </h2>\n              <p className=\"text-pretty text-muted-foreground\">\n                Welcome! Create an account to get started.\n              </p>\n            </div>\n          </CardHeader>\n          <CardContent className=\"space-y-6 px-8\">\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"role\">Role</Label>\n              <Select\n                defaultValue=\"designer\"\n                items={{\n                  designer: 'Product Designer',\n                  developer: 'Developer',\n                  manager: 'Product Manager',\n                }}\n              >\n                <SelectTrigger\n                  className=\"[&>span]:flex [&>span]:items-center [&>span]:gap-2 [&>span_svg]:shrink-0\"\n                  id=\"role\"\n                >\n                  <SelectValue placeholder=\"Select role\" />\n                </SelectTrigger>\n                <SelectContent className=\"[&_*[role=option]>span>svg]:shrink-0 [&_*[role=option]>span]:start-auto [&_*[role=option]>span]:end-2 [&_*[role=option]>span]:flex [&_*[role=option]>span]:items-center [&_*[role=option]>span]:gap-2 [&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8\">\n                  <SelectItem value=\"designer\">\n                    <User aria-hidden=\"true\" size={16} />\n                    <span className=\"truncate\">Product Designer</span>\n                  </SelectItem>\n                  <SelectItem value=\"developer\">\n                    <Code aria-hidden=\"true\" size={16} />\n                    <span className=\"truncate\">Developer</span>\n                  </SelectItem>\n                  <SelectItem value=\"manager\">\n                    <BarChart aria-hidden=\"true\" size={16} />\n                    <span className=\"truncate\">Product Manager</span>\n                  </SelectItem>\n                </SelectContent>\n              </Select>\n            </div>\n\n            <div className=\"grid grid-cols-2 gap-4\">\n              <div className=\"space-y-2\">\n                <Label htmlFor=\"firstName\">First name</Label>\n                <Input id=\"firstName\" />\n              </div>\n              <div className=\"space-y-2\">\n                <Label htmlFor=\"lastName\">Last name</Label>\n                <Input id=\"lastName\" />\n              </div>\n            </div>\n\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"username\">Username</Label>\n              <Input id=\"username\" />\n            </div>\n\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"email\">Email address</Label>\n              <Input id=\"email\" type=\"email\" />\n            </div>\n\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"password\">Password</Label>\n              <div className=\"relative\">\n                <Input\n                  className=\"pr-10\"\n                  id=\"password\"\n                  type={showPassword ? 'text' : 'password'}\n                />\n                <Button\n                  className=\"absolute top-0 right-0 h-full px-3 text-muted-foreground hover:bg-transparent\"\n                  onClick={() => setShowPassword(!showPassword)}\n                  size=\"icon\"\n                  type=\"button\"\n                  variant=\"ghost\"\n                >\n                  {showPassword ? (\n                    <EyeOff className=\"h-4 w-4\" />\n                  ) : (\n                    <Eye className=\"h-4 w-4\" />\n                  )}\n                </Button>\n              </div>\n            </div>\n\n            <div className=\"flex items-center space-x-2\">\n              <Checkbox id=\"terms\" />\n              <label className=\"text-muted-foreground text-sm\" htmlFor=\"terms\">\n                I agree to the{' '}\n                <Link className=\"text-primary hover:underline\" href=\"#\">\n                  Terms\n                </Link>{' '}\n                and{' '}\n                <Link className=\"text-primary hover:underline\" href=\"#\">\n                  Conditions\n                </Link>\n              </label>\n            </div>\n\n            <Button className=\"w-full bg-primary text-primary-foreground\">\n              Create free account\n            </Button>\n          </CardContent>\n          <CardFooter className=\"flex justify-center border-t py-4!\">\n            <p className=\"text-pretty text-center text-muted-foreground text-sm\">\n              Already have an account?{' '}\n              <Link className=\"text-primary hover:underline\" href=\"#\">\n                Sign in\n              </Link>\n            </p>\n          </CardFooter>\n        </Card>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "login"
      ]
    },
    {
      "name": "onboarding-01",
      "type": "registry:block",
      "title": "Onboarding",
      "description": "A onboarding block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "collapsible",
        "dropdown-menu"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/onboarding/onboarding-01.tsx",
          "type": "registry:component",
          "target": "components/onboarding-01.tsx",
          "content": "'use client';\n\nimport {\n  IconArchive,\n  IconChevronRight,\n  IconCircleCheckFilled,\n  IconCircleDashed,\n  IconDots,\n  IconMail,\n} from '@tabler/icons-react';\nimport { useState } from 'react';\nimport { Button, buttonVariants } from '@/components/ui/button';\nimport { Collapsible, CollapsibleContent } from '@/components/ui/collapsible';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { cn } from '@/lib/utils';\n\nconst steps = [\n  {\n    id: 'profile',\n    title: 'Complete your profile',\n    description:\n      'Add your name, photo, and role so your team knows who you are.',\n    completed: true,\n    actionLabel: 'Edit profile',\n    actionHref: '#',\n  },\n  {\n    id: 'workspace',\n    title: 'Set up your workspace',\n    description:\n      'Customize your workspace with a name, icon, and default settings.',\n    completed: false,\n    actionLabel: 'Configure workspace',\n    actionHref: '#',\n  },\n  {\n    id: 'invite',\n    title: 'Invite your team',\n    description:\n      'Bring your teammates on board so you can collaborate in real time.',\n    completed: false,\n    actionLabel: 'Send invites',\n    actionHref: '#',\n  },\n  {\n    id: 'integrations',\n    title: 'Connect integrations',\n    description:\n      'Link your favorite tools like Slack, GitHub, and Linear to streamline workflows.',\n    completed: false,\n    actionLabel: 'Browse integrations',\n    actionHref: '#',\n  },\n  {\n    id: 'workflow',\n    title: 'Create your first workflow',\n    description:\n      'Automate a repetitive task with a simple drag-and-drop workflow builder.',\n    completed: false,\n    actionLabel: 'Build workflow',\n    actionHref: '#',\n  },\n  {\n    id: 'notifications',\n    title: 'Set up notifications',\n    description:\n      'Choose how and when you want to be notified about updates and mentions.',\n    completed: false,\n    actionLabel: 'Manage notifications',\n    actionHref: '#',\n  },\n];\n\ninterface OnboardingStep {\n  id: string;\n  title: string;\n  description: string;\n  completed: boolean;\n  actionLabel: string;\n  actionHref: string;\n}\n\nfunction CircularProgress({\n  completed,\n  total,\n}: {\n  completed: number;\n  total: number;\n}) {\n  const progress = total > 0 ? ((total - completed) / total) * 100 : 0;\n  const strokeDashoffset = 100 - progress;\n\n  return (\n    <svg className=\"-rotate-90\" height=\"14\" viewBox=\"0 0 14 14\" width=\"14\">\n      <circle\n        className=\"stroke-muted\"\n        cx=\"7\"\n        cy=\"7\"\n        fill=\"none\"\n        pathLength=\"100\"\n        r=\"6\"\n        strokeWidth=\"2\"\n      />\n      <circle\n        className=\"stroke-primary\"\n        cx=\"7\"\n        cy=\"7\"\n        fill=\"none\"\n        pathLength=\"100\"\n        r=\"6\"\n        strokeDasharray=\"100\"\n        strokeLinecap=\"round\"\n        strokeWidth=\"2\"\n        style={{ strokeDashoffset }}\n      />\n    </svg>\n  );\n}\n\nfunction StepIndicator({ completed }: { completed: boolean }) {\n  if (completed) {\n    return (\n      <IconCircleCheckFilled\n        aria-hidden=\"true\"\n        className=\"mt-1 size-4.5 shrink-0 text-primary\"\n      />\n    );\n  }\n  return (\n    <IconCircleDashed\n      aria-hidden=\"true\"\n      className=\"mt-1 size-5 shrink-0 stroke-muted-foreground/40\"\n      strokeWidth={2}\n    />\n  );\n}\n\nexport function Onboarding01() {\n  const [currentSteps, setCurrentSteps] = useState<OnboardingStep[]>(steps);\n  const [openStepId, setOpenStepId] = useState<string | null>(() => {\n    const firstIncomplete = steps.find((s) => !s.completed);\n    return firstIncomplete?.id ?? steps[0]?.id ?? null;\n  });\n  const [dismissed, setDismissed] = useState(false);\n\n  const completedCount = currentSteps.filter((s) => s.completed).length;\n  const remainingCount = currentSteps.length - completedCount;\n\n  const handleStepClick = (stepId: string) => {\n    setOpenStepId(openStepId === stepId ? null : stepId);\n  };\n\n  const handleStepAction = (step: OnboardingStep) => {\n    const updated = currentSteps.map((s) =>\n      s.id === step.id ? { ...s, completed: true } : s\n    );\n    setCurrentSteps(updated);\n    const nextIncomplete = updated.find((s) => !s.completed);\n    setOpenStepId(nextIncomplete?.id ?? null);\n  };\n\n  if (dismissed) {\n    return (\n      <div className=\"flex min-h-dvh items-center justify-center bg-background p-4\">\n        <div className=\"text-center\">\n          <p className=\"text-pretty text-muted-foreground\">\n            Checklist dismissed\n          </p>\n          <button\n            className=\"mt-2 text-primary text-sm underline\"\n            onClick={() => setDismissed(false)}\n          >\n            Show again\n          </button>\n        </div>\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center bg-background p-4\">\n      <div className=\"w-full max-w-lg\">\n        <div className=\"w-md rounded-lg border bg-card p-4 text-card-foreground shadow-xs\">\n          <div className=\"mr-2 mb-4 flex flex-col justify-between sm:flex-row sm:items-center\">\n            <h3 className=\"ml-2 text-balance font-semibold text-foreground\">\n              Get started with Acme\n            </h3>\n            <div className=\"mt-2 flex items-center justify-end sm:mt-0\">\n              <CircularProgress\n                completed={remainingCount}\n                total={currentSteps.length}\n              />\n              <div className=\"mr-3 ml-1.5 text-muted-foreground text-sm\">\n                <span className=\"font-medium text-foreground\">\n                  {completedCount}\n                </span>\n                {' / '}\n                <span className=\"font-medium text-foreground\">\n                  {currentSteps.length}\n                </span>{' '}\n                completed\n              </div>\n              <DropdownMenu>\n                <DropdownMenuTrigger\n                  render={\n                    <Button className=\"h-6 w-6\" size=\"icon\" variant=\"ghost\" />\n                  }\n                >\n                  <IconDots aria-hidden=\"true\" className=\"h-4 w-4 shrink-0\" />\n                  <span className=\"sr-only\">Options</span>\n                </DropdownMenuTrigger>\n                <DropdownMenuContent align=\"end\" className=\"w-40\">\n                  <DropdownMenuItem onClick={() => setDismissed(true)}>\n                    <IconArchive\n                      aria-hidden=\"true\"\n                      className=\"mr-2 h-4 w-4 shrink-0\"\n                    />\n                    Dismiss\n                  </DropdownMenuItem>\n                  <DropdownMenuItem\n                    onClick={() =>\n                      window.open('mailto:support@acme.com?subject=Feedback')\n                    }\n                  >\n                    <IconMail\n                      aria-hidden=\"true\"\n                      className=\"mr-2 h-4 w-4 shrink-0\"\n                    />\n                    Give feedback\n                  </DropdownMenuItem>\n                </DropdownMenuContent>\n              </DropdownMenu>\n            </div>\n          </div>\n\n          <div className=\"space-y-0\">\n            {currentSteps.map((step, index) => {\n              const isOpen = openStepId === step.id;\n              const isFirst = index === 0;\n              const prevStep = currentSteps[index - 1];\n              const isPrevOpen = prevStep && openStepId === prevStep.id;\n\n              const showBorderTop = !(isFirst || isOpen || isPrevOpen);\n\n              return (\n                <div\n                  className={cn(\n                    'group',\n                    isOpen && 'rounded-lg',\n                    showBorderTop && 'border-border border-t'\n                  )}\n                  key={step.id}\n                >\n                  <div\n                    className={cn(\n                      'block w-full cursor-pointer text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n                      isOpen && 'rounded-lg'\n                    )}\n                    onClick={() => handleStepClick(step.id)}\n                    onKeyDown={(e) => {\n                      if (e.key === 'Enter' || e.key === ' ') {\n                        e.preventDefault();\n                        handleStepClick(step.id);\n                      }\n                    }}\n                    role=\"button\"\n                    tabIndex={0}\n                  >\n                    <div\n                      className={cn(\n                        'relative overflow-hidden rounded-lg transition-colors',\n                        isOpen && 'border border-border bg-muted'\n                      )}\n                    >\n                      <div className=\"relative flex items-center justify-between gap-3 py-3 pr-2 pl-4\">\n                        <div className=\"flex w-full gap-3\">\n                          <div className=\"shrink-0\">\n                            <StepIndicator completed={step.completed} />\n                          </div>\n                          <div className=\"mt-0.5 grow\">\n                            <h4\n                              className={cn(\n                                'font-semibold',\n                                step.completed\n                                  ? 'text-primary'\n                                  : 'text-foreground'\n                              )}\n                            >\n                              {step.title}\n                            </h4>\n                            <Collapsible open={isOpen}>\n                              <CollapsibleContent>\n                                <p className=\"mt-2 text-pretty text-muted-foreground text-sm sm:max-w-64 md:max-w-xs\">\n                                  {step.description}\n                                </p>\n                                <a\n                                  className={cn(\n                                    buttonVariants({ size: 'sm' }),\n                                    'mt-3'\n                                  )}\n                                  href={step.actionHref}\n                                  onClick={(e) => {\n                                    e.stopPropagation();\n                                    handleStepAction(step);\n                                  }}\n                                >\n                                  {step.actionLabel}\n                                </a>\n                              </CollapsibleContent>\n                            </Collapsible>\n                          </div>\n                        </div>\n                        {!isOpen && (\n                          <IconChevronRight\n                            aria-hidden=\"true\"\n                            className=\"h-4 w-4 shrink-0 text-muted-foreground\"\n                          />\n                        )}\n                      </div>\n                    </div>\n                  </div>\n                </div>\n              );\n            })}\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "onboarding"
      ]
    },
    {
      "name": "onboarding-02",
      "type": "registry:block",
      "title": "Onboarding Workspace Setup",
      "description": "A onboarding workspace setup block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/onboarding/onboarding-02.tsx",
          "type": "registry:component",
          "target": "components/onboarding-02.tsx",
          "content": "'use client';\n\nimport type { Icon } from '@tabler/icons-react';\nimport {\n  IconCircleCheckFilled,\n  IconFolder,\n  IconPlug,\n  IconRocket,\n  IconUsers,\n} from '@tabler/icons-react';\nimport { useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/lib/utils';\n\ninterface StepData {\n  title: string;\n  description: string;\n  icon: Icon;\n  actionLabel: string;\n}\n\nconst steps: StepData[] = [\n  {\n    title: 'Create your workspace',\n    description:\n      'Name your workspace and pick a URL. This is where your team will collaborate on everything.',\n    icon: IconRocket,\n    actionLabel: 'Get started',\n  },\n  {\n    title: 'Invite your team',\n    description:\n      'Add teammates by email so everyone can collaborate in real time across projects.',\n    icon: IconUsers,\n    actionLabel: 'Send invites',\n  },\n  {\n    title: 'Set up your first project',\n    description:\n      'Create a project to organize tasks, docs, and milestones all in one place.',\n    icon: IconFolder,\n    actionLabel: 'Create project',\n  },\n  {\n    title: 'Connect your tools',\n    description:\n      'Link Slack, GitHub, or Figma to keep your workflow in sync automatically.',\n    icon: IconPlug,\n    actionLabel: 'Browse integrations',\n  },\n];\n\nfunction getIconColor(isCompleted: boolean, isActive: boolean) {\n  if (isCompleted) {\n    return 'text-muted-foreground/30';\n  }\n  if (isActive) {\n    return 'text-primary';\n  }\n  return 'text-muted-foreground/40';\n}\n\nfunction getTitleClass(isCompleted: boolean, isActive: boolean) {\n  if (isCompleted) {\n    return 'text-muted-foreground/50 line-through';\n  }\n  if (isActive) {\n    return 'text-foreground';\n  }\n  return 'text-muted-foreground';\n}\n\nfunction StepIndicator({\n  index,\n  isCompleted,\n  isActive,\n}: {\n  index: number;\n  isCompleted: boolean;\n  isActive: boolean;\n}) {\n  if (isCompleted) {\n    return (\n      <div className=\"flex size-7 items-center justify-center\">\n        <IconCircleCheckFilled\n          aria-hidden=\"true\"\n          className=\"size-7 text-emerald-500\"\n        />\n      </div>\n    );\n  }\n  return (\n    <div\n      className={cn(\n        'flex size-7 items-center justify-center rounded-full font-semibold text-xs',\n        isActive\n          ? 'bg-primary text-primary-foreground'\n          : 'bg-muted text-muted-foreground'\n      )}\n    >\n      {index + 1}\n    </div>\n  );\n}\n\nfunction StepCard({\n  step,\n  index,\n  isCompleted,\n  isActive,\n  onComplete,\n}: {\n  step: StepData;\n  index: number;\n  isCompleted: boolean;\n  isActive: boolean;\n  onComplete: () => void;\n}) {\n  const StepIcon = step.icon;\n\n  return (\n    <div\n      className={cn(\n        'rounded-lg border p-4 transition-colors',\n        isActive && 'border-primary/30 bg-muted/50',\n        !isActive && 'border-border bg-background'\n      )}\n    >\n      <div className=\"flex gap-3\">\n        <div className=\"mt-0.5 shrink-0\">\n          <StepIndicator\n            index={index}\n            isActive={isActive}\n            isCompleted={isCompleted}\n          />\n        </div>\n        <div className=\"min-w-0 flex-1\">\n          <div className=\"flex items-start gap-3\">\n            <div className=\"min-w-0 flex-1\">\n              <p\n                className={cn(\n                  'font-medium leading-6',\n                  getTitleClass(isCompleted, isActive)\n                )}\n              >\n                {step.title}\n              </p>\n              <p\n                className={cn(\n                  'mt-0.5 text-sm leading-5',\n                  isActive\n                    ? 'text-muted-foreground'\n                    : 'text-muted-foreground/60'\n                )}\n              >\n                {step.description}\n              </p>\n              {isActive && (\n                <Button className=\"mt-3\" onClick={onComplete} size=\"sm\">\n                  <StepIcon\n                    aria-hidden=\"true\"\n                    className=\"-ml-0.5 size-4 shrink-0\"\n                  />\n                  {step.actionLabel}\n                </Button>\n              )}\n            </div>\n            <StepIcon\n              aria-hidden=\"true\"\n              className={cn(\n                'mt-0.5 size-5 shrink-0',\n                getIconColor(isCompleted, isActive)\n              )}\n            />\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n\nexport function Onboarding02() {\n  const [completedSteps, setCompletedSteps] = useState<Set<number>>(\n    () => new Set([0])\n  );\n\n  const currentStep = steps.findIndex((_, i) => !completedSteps.has(i));\n  const completedCount = completedSteps.size;\n  const allDone = completedCount === steps.length;\n\n  const handleComplete = (index: number) => {\n    setCompletedSteps((prev) => {\n      const next = new Set(prev);\n      next.add(index);\n      return next;\n    });\n  };\n\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center bg-background p-4\">\n      <div className=\"w-full max-w-xl\">\n        <div className=\"mb-6\">\n          <h3 className=\"font-semibold text-foreground text-lg\">\n            Set up your workspace\n          </h3>\n          <p className=\"mt-1 text-muted-foreground text-sm\">\n            Complete these steps to get your team up and running\n          </p>\n          <div className=\"mt-4\">\n            <div className=\"flex items-center justify-between text-sm\">\n              <span className=\"text-muted-foreground\">\n                {allDone ? (\n                  <span className=\"font-medium text-emerald-600\">\n                    All done 🎉\n                  </span>\n                ) : (\n                  <>\n                    <span className=\"font-medium text-foreground\">\n                      {completedCount}\n                    </span>{' '}\n                    of {steps.length} completed\n                  </>\n                )}\n              </span>\n            </div>\n            <div className=\"mt-2 h-1.5 w-full overflow-hidden rounded-full bg-muted\">\n              <div\n                className=\"h-full rounded-full bg-emerald-500 transition-all duration-500\"\n                style={{\n                  width: `${(completedCount / steps.length) * 100}%`,\n                }}\n              />\n            </div>\n          </div>\n        </div>\n\n        <div className=\"space-y-3\">\n          {steps.map((step, index) => (\n            <StepCard\n              index={index}\n              isActive={index === currentStep}\n              isCompleted={completedSteps.has(index)}\n              key={step.title}\n              onComplete={() => handleComplete(index)}\n              step={step}\n            />\n          ))}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "onboarding"
      ]
    },
    {
      "name": "onboarding-03",
      "type": "registry:block",
      "title": "Onboarding Steps with Progress",
      "description": "A onboarding steps with progress block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "progress"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/onboarding/onboarding-03.tsx",
          "type": "registry:component",
          "target": "components/onboarding-03.tsx",
          "content": "'use client';\n\nimport { IconCircleCheckFilled } from '@tabler/icons-react';\nimport { useState } from 'react';\nimport { Progress } from '@/components/ui/progress';\nimport { cn } from '@/lib/utils';\n\nconst steps = [\n  {\n    id: '1.',\n    title: 'Create your store',\n    description:\n      \"Choose a name, pick a subdomain, and configure your store's basic settings.\",\n  },\n  {\n    id: '2.',\n    title: 'Add your products',\n    description:\n      'Upload your catalog with photos, pricing, and inventory details.',\n  },\n  {\n    id: '3.',\n    title: 'Set up payments',\n    description:\n      'Connect Stripe or PayPal to start accepting orders from customers.',\n  },\n  {\n    id: '4.',\n    title: 'Launch your store',\n    description: 'Review everything and publish your storefront to the world.',\n  },\n];\n\nexport function Onboarding03() {\n  const [activeStep, setActiveStep] = useState(0);\n\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center bg-background p-4\">\n      <div className=\"sm:mx-auto sm:max-w-lg\">\n        <h3 className=\"font-semibold text-foreground text-lg\">Store setup</h3>\n        <p className=\"mt-1 text-muted-foreground text-sm leading-6\">\n          Complete each step to launch your online store.\n        </p>\n        <div className=\"mt-4 flex items-center justify-end space-x-4\">\n          <span className=\"text-muted-foreground text-sm\">\n            Step {activeStep + 1}/{steps.length}\n          </span>\n          <Progress\n            className=\"w-32\"\n            value={(activeStep / steps.length) * 100}\n          />\n        </div>\n        <ul className=\"mt-4 space-y-4\">\n          {steps.map((step, index) => (\n            <li key={step.id}>\n              <button\n                className={cn(\n                  'relative w-full cursor-pointer rounded-lg border bg-card p-4 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n                  index === activeStep\n                    ? 'border-foreground/20'\n                    : 'border-border'\n                )}\n                onClick={() => setActiveStep(index)}\n                type=\"button\"\n              >\n                <div className=\"flex items-start space-x-3\">\n                  {index < activeStep ? (\n                    <IconCircleCheckFilled\n                      aria-hidden={true}\n                      className=\"size-6 shrink-0 text-foreground\"\n                    />\n                  ) : (\n                    <span\n                      aria-hidden={true}\n                      className=\"flex size-6 items-center justify-center font-medium text-muted-foreground\"\n                    >\n                      {step.id}\n                    </span>\n                  )}\n                  <div>\n                    <h3\n                      className={cn(\n                        'font-medium',\n                        index < activeStep\n                          ? 'text-muted-foreground line-through'\n                          : 'text-foreground'\n                      )}\n                    >\n                      {step.title}\n                    </h3>\n                    <p className=\"mt-1 text-muted-foreground text-sm leading-6\">\n                      {step.description}\n                    </p>\n                  </div>\n                </div>\n              </button>\n            </li>\n          ))}\n        </ul>\n        <div className=\"mt-6 rounded-lg bg-muted p-4\">\n          <h4 className=\"font-medium text-foreground text-sm\">Need help?</h4>\n          <p className=\"mt-1 text-muted-foreground text-sm\">\n            Connect with a member of our team at{' '}\n            <a\n              className=\"font-medium text-primary\"\n              href=\"mailto:help@example.com\"\n            >\n              help@example.com\n            </a>\n            .\n          </p>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "onboarding"
      ]
    },
    {
      "name": "onboarding-04",
      "type": "registry:block",
      "title": "Onboarding Accordion",
      "description": "A onboarding accordion block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "accordion",
        "button"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/onboarding/onboarding-04.tsx",
          "type": "registry:component",
          "target": "components/onboarding-04.tsx",
          "content": "'use client';\n\nimport {\n  IconAdjustments,\n  IconCalculator,\n  IconChartBar,\n  IconCircleCheckFilled,\n  IconDatabase,\n} from '@tabler/icons-react';\nimport { useState } from 'react';\nimport {\n  Accordion,\n  AccordionContent,\n  AccordionItem,\n  AccordionTrigger,\n} from '@/components/ui/accordion';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/lib/utils';\n\nconst steps = [\n  {\n    title: 'Configure your environment',\n    subtitle: 'Environment ready',\n    icon: IconAdjustments,\n    description:\n      'Set up your development environment with API keys and preferences.',\n    buttonText: 'Edit settings',\n  },\n  {\n    title: 'Connect your database',\n    subtitle: 'Add connection',\n    icon: IconDatabase,\n    description:\n      'Link your PostgreSQL, MySQL, or MongoDB instance to get started.',\n    buttonText: 'Add database',\n  },\n  {\n    title: 'Define your schema',\n    subtitle: 'Create schema',\n    icon: IconCalculator,\n    description: 'Model your data with types, relations, and validation rules.',\n    buttonText: 'Open editor',\n  },\n  {\n    title: 'Build your first API',\n    subtitle: 'Generate endpoints',\n    icon: IconChartBar,\n    description:\n      'Auto-generate REST or GraphQL endpoints from your schema in seconds.',\n    buttonText: 'Generate API',\n  },\n];\n\nexport function Onboarding04() {\n  const [activeStep, setActiveStep] = useState(1);\n\n  const [openItem, setOpenItem] = useState(\n    activeStep < steps.length ? steps[activeStep].title : ''\n  );\n\n  const handleComplete = () => {\n    const next = activeStep + 1;\n    setActiveStep(next);\n    setOpenItem(next < steps.length ? steps[next].title : '');\n  };\n\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center bg-background p-4\">\n      <div className=\"mx-auto w-full min-w-0 max-w-sm sm:min-w-sm\">\n        <h3 className=\"font-semibold text-foreground text-lg\">Quick start</h3>\n        <p className=\"mt-1 text-muted-foreground text-sm\">\n          Set up your backend in four simple steps\n        </p>\n        <Accordion\n          className=\"mt-6 space-y-2\"\n          onValueChange={(value) => setOpenItem(value[0] ?? '')}\n          value={openItem ? [openItem] : []}\n        >\n          {steps.map((step, index) => {\n            let status: 'complete' | 'current' | 'upcoming' = 'upcoming';\n            if (index < activeStep) {\n              status = 'complete';\n            } else if (index === activeStep) {\n              status = 'current';\n            }\n\n            return (\n              <AccordionItem\n                className=\"!border-b rounded-lg border shadow-xs\"\n                key={step.title}\n                value={step.title}\n              >\n                <AccordionTrigger className=\"px-4 hover:no-underline\">\n                  <div className=\"flex items-center space-x-2\">\n                    {status === 'complete' ? (\n                      <span\n                        aria-hidden\n                        className=\"flex size-5 items-center justify-center\"\n                      >\n                        <IconCircleCheckFilled\n                          aria-hidden\n                          className=\"size-6 shrink-0 text-foreground\"\n                        />\n                      </span>\n                    ) : (\n                      <span\n                        aria-hidden\n                        className=\"size-5 shrink-0 rounded-full border border-border\"\n                      />\n                    )}\n                    <p\n                      className={cn(\n                        'font-medium text-sm',\n                        status === 'upcoming'\n                          ? 'text-muted-foreground/60'\n                          : 'text-foreground'\n                      )}\n                    >\n                      {step.title}\n                    </p>\n                  </div>\n                </AccordionTrigger>\n                <AccordionContent className=\"px-4\">\n                  <div className=\"flex items-center justify-center rounded-md bg-muted px-4 py-5 ring-1 ring-ring ring-inset\">\n                    <div className=\"max-w-xs text-center\">\n                      <step.icon\n                        aria-hidden\n                        className=\"mx-auto size-7 shrink-0 text-muted-foreground\"\n                      />\n                      <p className=\"mt-4 font-semibold text-muted-foreground text-sm\">\n                        {step.subtitle}\n                      </p>\n                      <p className=\"mt-1 text-muted-foreground text-sm\">\n                        {step.description}\n                      </p>\n                      {status === 'complete' ? (\n                        <Button className=\"mt-6\" size=\"sm\" variant=\"outline\">\n                          {step.buttonText}\n                        </Button>\n                      ) : (\n                        <Button\n                          className=\"mt-6\"\n                          disabled={status === 'upcoming'}\n                          onClick={() => {\n                            if (status === 'current') {\n                              handleComplete();\n                            }\n                          }}\n                          size=\"sm\"\n                        >\n                          {step.buttonText}\n                        </Button>\n                      )}\n                    </div>\n                  </div>\n                </AccordionContent>\n              </AccordionItem>\n            );\n          })}\n        </Accordion>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "onboarding"
      ]
    },
    {
      "name": "onboarding-05",
      "type": "registry:block",
      "title": "Onboarding Activity Feed",
      "description": "A onboarding activity feed block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/onboarding/onboarding-05.tsx",
          "type": "registry:component",
          "target": "components/onboarding-05.tsx",
          "content": "import { cn } from '@/lib/utils';\n\nconst steps = [\n  {\n    id: 1,\n    type: 'created',\n    description: 'Created project \"Brand Refresh\"',\n    user: { name: 'Sarah K.', initial: 'S', bgColor: 'bg-violet-500' },\n    activityTime: '3d ago',\n  },\n  {\n    id: 2,\n    type: 'created',\n    description: 'Uploaded 12 design assets',\n    user: { name: 'Marcus L.', initial: 'M', bgColor: 'bg-orange-500' },\n    activityTime: '2d ago',\n  },\n  {\n    id: 3,\n    type: 'created',\n    description: 'Shared prototype with stakeholders',\n    user: { name: 'Sarah K.', initial: 'S', bgColor: 'bg-emerald-500' },\n    activityTime: '2h ago',\n  },\n  {\n    id: 4,\n    type: 'created',\n    description: 'Left feedback on homepage layout',\n    user: { name: 'Jamie R.', initial: 'J', bgColor: 'bg-fuchsia-500' },\n    activityTime: '5min ago',\n  },\n  {\n    id: 5,\n    type: 'in progress',\n    description: 'Scheduled design review meeting',\n    user: { name: 'Team Ops', initial: 'T', bgColor: 'bg-blue-500' },\n    activityTime: 'today 2:30pm',\n  },\n];\n\nexport function Onboarding05() {\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center bg-background p-4\">\n      <div className=\"sm:max-w-lg md:mx-auto\">\n        <h3 className=\"font-medium text-foreground\">Project activity</h3>\n        <p className=\"mt-1 text-muted-foreground text-sm leading-6\">\n          Recent updates from your team\n        </p>\n        <ul className=\"mt-6 space-y-6 pb-2\">\n          {steps.map((step, stepIdx) => (\n            <li className=\"relative flex gap-x-3\" key={step.id}>\n              <div\n                className={cn(\n                  'absolute top-0 left-0 flex w-6 justify-center',\n                  stepIdx === steps.length - 1 ? 'h-6' : '-bottom-6'\n                )}\n              >\n                <span aria-hidden className=\"w-px bg-border\" />\n              </div>\n              <div className=\"flex items-start space-x-2\">\n                <div className=\"flex items-center space-x-2\">\n                  <div className=\"relative flex size-6 flex-none items-center justify-center bg-background\">\n                    {step.type === 'created' ? (\n                      <div className=\"size-3 rounded-full border border-gray-300 bg-muted/50 ring-4 ring-background\" />\n                    ) : (\n                      <div className=\"size-3 rounded-full border border-gray-300 bg-background ring-4 ring-background\" />\n                    )}\n                  </div>\n                  <span\n                    aria-hidden\n                    className={cn(\n                      step.user.bgColor,\n                      'inline-flex size-6 flex-none items-center justify-center rounded-full text-primary-foreground text-xs'\n                    )}\n                  >\n                    {step.user.initial}\n                  </span>\n                </div>\n                <p className=\"mt-0.5 font-medium text-foreground text-sm\">\n                  {step.user.name}\n                  <span className=\"font-normal text-muted-foreground\">\n                    {' '}\n                    {step.description}\n                  </span>\n                  <span className=\"font-normal text-muted-foreground/60\">\n                    {' '}\n                    &#8729; {step.activityTime}\n                  </span>\n                </p>\n              </div>\n            </li>\n          ))}\n        </ul>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "onboarding"
      ]
    },
    {
      "name": "onboarding-06",
      "type": "registry:block",
      "title": "Onboarding Timeline",
      "description": "A onboarding timeline block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/onboarding/onboarding-06.tsx",
          "type": "registry:component",
          "target": "components/onboarding-06.tsx",
          "content": "import { IconCheck } from '@tabler/icons-react';\nimport { cn } from '@/lib/utils';\n\nconst steps = [\n  {\n    id: 1,\n    type: 'done',\n    title: 'Repository connected',\n    description: 'Linked GitHub repository to deployment pipeline',\n    activityTime: '3d ago',\n  },\n  {\n    id: 2,\n    type: 'done',\n    title: 'Build configuration set',\n    description: 'Configured build commands and environment variables',\n    activityTime: '2d ago',\n  },\n  {\n    id: 3,\n    type: 'done',\n    title: 'Domain configured',\n    description: 'Custom domain verified and SSL certificate issued',\n    activityTime: '31min ago',\n  },\n  {\n    id: 4,\n    type: 'in progress',\n    title: 'Running health checks',\n    description: 'Verifying all endpoints respond correctly',\n    activityTime: 'Running now...',\n  },\n  {\n    id: 5,\n    type: 'open',\n    title: 'Go live',\n    description: 'Switch traffic to the new deployment',\n    activityTime: 'Upcoming',\n  },\n];\n\nexport function Onboarding06() {\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center bg-background p-4\">\n      <div className=\"sm:mx-auto sm:max-w-lg\">\n        <h3 className=\"font-medium text-foreground\">Deployment progress</h3>\n        <ul className=\"mt-6 space-y-6\">\n          {steps.map((step, stepIdx) => (\n            <li className=\"relative flex gap-x-3\" key={step.id}>\n              <div\n                className={cn(\n                  'absolute top-0 left-0 flex w-6 justify-center',\n                  stepIdx === steps.length - 1 ? 'h-6' : '-bottom-6'\n                )}\n              >\n                <span aria-hidden className=\"w-px bg-border\" />\n              </div>\n              <div className=\"flex items-start space-x-2.5\">\n                <div className=\"relative flex size-6 flex-none items-center justify-center bg-background\">\n                  {step.type === 'done' ? (\n                    <IconCheck aria-hidden className=\"size-5 text-primary\" />\n                  ) : step.type === 'in progress' ? (\n                    <div\n                      aria-hidden\n                      className=\"size-2.5 rounded-full bg-primary ring-4 ring-background\"\n                    />\n                  ) : (\n                    <div\n                      aria-hidden\n                      className=\"size-3 rounded-full border border-border bg-background ring-4 ring-background\"\n                    />\n                  )}\n                </div>\n                <div>\n                  <p className=\"mt-0.5 font-medium text-foreground text-sm\">\n                    {step.title}{' '}\n                    <span className=\"font-normal text-muted-foreground/60\">\n                      &#8729; {step.activityTime}\n                    </span>\n                  </p>\n                  <p className=\"mt-0.5 text-muted-foreground text-sm leading-6\">\n                    {step.description}\n                  </p>\n                </div>\n              </div>\n            </li>\n          ))}\n        </ul>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "onboarding"
      ]
    },
    {
      "name": "onboarding-07",
      "type": "registry:block",
      "title": "Onboarding Deploy Pipeline",
      "description": "A onboarding deploy pipeline block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "accordion",
        "button",
        "progress"
      ],
      "dependencies": [
        "@tabler/icons-react"
      ],
      "files": [
        {
          "path": "content/components/onboarding/onboarding-07.tsx",
          "type": "registry:component",
          "target": "components/onboarding-07.tsx",
          "content": "'use client';\n\nimport {\n  IconCircleCheckFilled,\n  IconLoader2,\n  IconRefresh,\n} from '@tabler/icons-react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n  Accordion,\n  AccordionContent,\n  AccordionItem,\n  AccordionTrigger,\n} from '@/components/ui/accordion';\nimport { Button } from '@/components/ui/button';\nimport { Progress } from '@/components/ui/progress';\nimport { cn } from '@/lib/utils';\n\nconst initialSteps = [\n  {\n    id: 1,\n    type: 'created' as const,\n    description: 'Export records',\n    value: 100,\n    createdOn: '2024-03-10 09:32',\n    runTime: '12min 18s',\n  },\n  {\n    id: 2,\n    type: 'created' as const,\n    description: 'Transform schema',\n    value: 100,\n    createdOn: '2024-03-10 10:03',\n    runTime: '18min 45s',\n  },\n  {\n    id: 3,\n    type: 'in progress' as const,\n    description: 'Import to new system',\n    value: 45,\n    createdOn: null as string | null,\n    runTime: null as string | null,\n  },\n];\n\nexport function Onboarding07() {\n  const [steps, setSteps] = useState(initialSteps);\n  const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n  const allComplete = steps.every((s) => s.value === 100);\n\n  const startAnimation = useCallback(() => {\n    if (intervalRef.current) {\n      clearInterval(intervalRef.current);\n    }\n    intervalRef.current = setInterval(() => {\n      setSteps((prev) => {\n        const next = prev.map((step) => {\n          if (step.id !== 3 || step.value >= 100) {\n            return step;\n          }\n          const increment = Math.random() * 0.8 + 0.3;\n          const newValue = Math.min(step.value + increment, 100);\n          if (newValue >= 100) {\n            return {\n              ...step,\n              value: 100,\n              type: 'created' as const,\n              createdOn: '2024-03-10 10:47',\n              runTime: '6min 32s',\n            };\n          }\n          return { ...step, value: newValue };\n        });\n        if (next[2].value >= 100 && intervalRef.current) {\n          clearInterval(intervalRef.current);\n          intervalRef.current = null;\n        }\n        return next;\n      });\n    }, 50);\n  }, []);\n\n  useEffect(() => {\n    startAnimation();\n    return () => {\n      if (intervalRef.current) {\n        clearInterval(intervalRef.current);\n      }\n    };\n  }, [startAnimation]);\n\n  const handleRunAgain = () => {\n    setSteps(\n      initialSteps.map((step) =>\n        step.id === 3\n          ? {\n              ...step,\n              value: 45,\n              type: 'in progress' as const,\n              createdOn: null,\n              runTime: null,\n            }\n          : step\n      )\n    );\n    startAnimation();\n  };\n\n  return (\n    <div className=\"flex min-h-dvh items-center justify-center bg-background p-4\">\n      <div className=\"w-full max-w-xl\">\n        <div className=\"flex items-center justify-between\">\n          <h3 className=\"font-semibold text-foreground\">Data Migration</h3>\n          <Button\n            className={\n              allComplete ? 'opacity-100' : 'pointer-events-none opacity-0'\n            }\n            onClick={handleRunAgain}\n            size=\"icon\"\n            variant=\"secondary\"\n          >\n            <IconRefresh aria-hidden=\"true\" className=\"size-4\" />\n          </Button>\n        </div>\n        <p className=\"mt-1 text-muted-foreground text-sm leading-6\">\n          Migrating records from your legacy system\n        </p>\n        <div className=\"mt-6 flex items-center space-x-2\">\n          {steps.map((step) => (\n            <div className=\"w-full truncate\" key={step.id}>\n              <Progress className=\"h-1.5\" value={step.value} />\n              <div className=\"mt-2 flex items-center space-x-1 truncate\">\n                {step.value === 100 ? (\n                  <IconCircleCheckFilled\n                    aria-hidden={true}\n                    className=\"size-4 shrink-0 text-primary\"\n                  />\n                ) : (\n                  <IconLoader2\n                    aria-hidden={true}\n                    className=\"size-4 shrink-0 animate-spin text-primary\"\n                  />\n                )}\n                <p className=\"truncate text-muted-foreground text-xs\">\n                  {step.description}\n                </p>\n              </div>\n            </div>\n          ))}\n        </div>\n        <Accordion className=\"mt-8\" defaultValue={['logs']}>\n          <AccordionItem className=\"rounded-sm border-b-0\" value=\"logs\">\n            <AccordionTrigger className=\"font-medium text-foreground text-sm\">\n              Logs overview ({steps.length})\n            </AccordionTrigger>\n            <AccordionContent>\n              <ul className=\"mt-2 space-y-6 pb-2\">\n                {steps.map((step, stepIdx) => (\n                  <li className=\"relative flex gap-x-3\" key={step.id}>\n                    <div\n                      className={cn(\n                        'absolute top-0 left-0 flex w-6 justify-center',\n                        stepIdx === steps.length - 1 ? 'h-6' : '-bottom-6'\n                      )}\n                    >\n                      <span aria-hidden={true} className=\"w-px bg-border\" />\n                    </div>\n                    <div className=\"flex items-start space-x-2.5\">\n                      <div className=\"relative flex size-6 flex-none items-center justify-center bg-background\">\n                        {step.type === 'created' ? (\n                          <div className=\"size-3 rounded-full border border-border bg-muted/50 ring-4 ring-background\" />\n                        ) : (\n                          <div className=\"size-3 rounded-full border border-border bg-background ring-4 ring-background\" />\n                        )}\n                      </div>\n                      <div>\n                        <p className=\"mt-0.5 font-medium text-foreground text-sm\">\n                          {step.description}\n                        </p>\n                        {step.type === 'created' ? (\n                          <p className=\"text-muted-foreground text-sm leading-6\">\n                            Created on {step.createdOn}, Runtime: {step.runTime}\n                          </p>\n                        ) : (\n                          <p className=\"text-muted-foreground text-sm leading-6\">\n                            12,847 of 28,500 records processed...\n                          </p>\n                        )}\n                      </div>\n                    </div>\n                  </li>\n                ))}\n              </ul>\n            </AccordionContent>\n          </AccordionItem>\n        </Accordion>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "onboarding"
      ]
    },
    {
      "name": "sidebar-01",
      "type": "registry:block",
      "title": "Sidebar Collapsible Sections",
      "description": "A sidebar collapsible sections block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "avatar",
        "button",
        "collapsible",
        "command",
        "dropdown-menu",
        "sidebar",
        "tooltip"
      ],
      "dependencies": [
        "@tabler/icons-react",
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/sidebar/sidebar-01/nav-main.tsx",
          "type": "registry:component",
          "target": "components/sidebar-01/nav-main.tsx",
          "content": "'use client';\n\nimport {\n  SidebarGroup,\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n} from '@/components/ui/sidebar';\nimport type { NavItem } from '@/components/sidebar-01/types';\n\nexport function NavMain({ items }: { items: NavItem[] }) {\n  return (\n    <SidebarGroup>\n      <SidebarMenu>\n        {items.map((item) => {\n          const Icon = item.icon;\n\n          return (\n            <SidebarMenuItem key={item.id}>\n              <SidebarMenuButton tooltip={item.title}>\n                {Icon && <Icon className=\"mr-2 h-4 w-4\" />}\n                <span>{item.title}</span>\n              </SidebarMenuButton>\n            </SidebarMenuItem>\n          );\n        })}\n      </SidebarMenu>\n    </SidebarGroup>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-01/app-sidebar.tsx",
          "type": "registry:component",
          "target": "components/sidebar-01/app-sidebar.tsx",
          "content": "'use client';\n\nimport {\n  IconAd2,\n  IconBellRinging,\n  IconCalendar,\n  IconCalendarStats,\n  IconListDetails,\n  IconNews,\n  IconNotebook,\n  IconProgressCheck,\n  IconSettingsCode,\n} from '@tabler/icons-react';\nimport { LayoutDashboard, Package } from 'lucide-react';\nimport { Sidebar, SidebarContent } from '@/components/ui/sidebar';\nimport { NavCollapsible } from '@/components/sidebar-01/nav-collapsible';\nimport { NavFooter } from '@/components/sidebar-01/nav-footer';\nimport { NavHeader } from '@/components/sidebar-01/nav-header';\nimport { NavMain } from '@/components/sidebar-01/nav-main';\nimport type { SidebarData } from '@/components/sidebar-01/types';\n\nconst data: SidebarData = {\n  user: {\n    name: 'ephraim',\n    email: 'ephraim@blocks.so',\n    avatar: '/avatar-01.png',\n  },\n  navMain: [\n    {\n      id: 'overview',\n      title: 'Overview',\n      url: '#',\n      icon: LayoutDashboard,\n      isActive: true,\n    },\n    {\n      id: 'tasks',\n      title: 'Tasks',\n      url: '#',\n      icon: IconListDetails,\n    },\n    {\n      id: 'meetings',\n      title: 'Meetings',\n      url: '#',\n      icon: IconCalendarStats,\n    },\n    {\n      id: 'notes',\n      title: 'Notes',\n      url: '#',\n      icon: IconNotebook,\n    },\n    {\n      id: 'calendar',\n      title: 'Calendar',\n      url: '#',\n      icon: IconCalendar,\n    },\n    {\n      id: 'completed',\n      title: 'Completed',\n      url: '#',\n      icon: IconProgressCheck,\n    },\n    {\n      id: 'notifications',\n      title: 'Notifications',\n      url: '#',\n      icon: IconBellRinging,\n    },\n  ],\n  navCollapsible: {\n    favorites: [\n      {\n        id: 'design',\n        title: 'Design',\n        href: '#',\n        color: 'bg-green-400 dark:bg-green-300',\n      },\n      {\n        id: 'development',\n        title: 'Development',\n        href: '#',\n        color: 'bg-blue-400 dark:bg-blue-300',\n      },\n      {\n        id: 'workshop',\n        title: 'Workshop',\n        href: '#',\n        color: 'bg-orange-400 dark:bg-orange-300',\n      },\n      {\n        id: 'personal',\n        title: 'Personal',\n        href: '#',\n        color: 'bg-red-400 dark:bg-red-300',\n      },\n    ],\n    teams: [\n      {\n        id: 'engineering',\n        title: 'Engineering',\n        icon: IconSettingsCode,\n      },\n      {\n        id: 'marketing',\n        title: 'Marketing',\n        icon: IconAd2,\n      },\n    ],\n    topics: [\n      {\n        id: 'product-updates',\n        title: 'Product Updates',\n        icon: Package,\n      },\n      {\n        id: 'company-news',\n        title: 'Company News',\n        icon: IconNews,\n      },\n    ],\n  },\n};\n\nexport function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {\n  return (\n    <Sidebar {...props}>\n      <NavHeader data={data} />\n      <SidebarContent>\n        <NavMain items={data.navMain} />\n        <NavCollapsible\n          favorites={data.navCollapsible.favorites}\n          teams={data.navCollapsible.teams}\n          topics={data.navCollapsible.topics}\n        />\n      </SidebarContent>\n      <NavFooter user={data.user} />\n    </Sidebar>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-01/nav-header.tsx",
          "type": "registry:component",
          "target": "components/sidebar-01/nav-header.tsx",
          "content": "'use client';\n\nimport { Search } from 'lucide-react';\nimport * as React from 'react';\nimport { useEffect } from 'react';\nimport {\n  Command,\n  CommandDialog,\n  CommandEmpty,\n  CommandGroup,\n  CommandInput,\n  CommandItem,\n  CommandList,\n  CommandSeparator,\n} from '@/components/ui/command';\nimport { SidebarHeader } from '@/components/ui/sidebar';\nimport { cn } from '@/lib/utils';\nimport type { SidebarData } from '@/components/sidebar-01/types';\n\ninterface NavHeaderProps {\n  data: SidebarData;\n}\n\nexport function NavHeader({ data }: NavHeaderProps) {\n  const [open, setOpen] = React.useState(false);\n\n  useEffect(() => {\n    const down = (e: KeyboardEvent) => {\n      if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {\n        e.preventDefault();\n        setOpen((open) => !open);\n      }\n    };\n    document.addEventListener('keydown', down);\n    return () => document.removeEventListener('keydown', down);\n  }, []);\n\n  return (\n    <>\n      <SidebarHeader>\n        <div\n          className=\"flex cursor-pointer items-center justify-between px-2 pt-3 pb-0\"\n          onClick={() => setOpen(true)}\n        >\n          <div className=\"flex flex-1 items-center gap-3\">\n            <Search className=\"h-4 w-4 text-muted-foreground\" />\n            <span className=\"font-normal text-muted-foreground text-sm\">\n              Search\n            </span>\n          </div>\n          <div className=\"flex items-center justify-center rounded-md border border-border px-2 py-1\">\n            <kbd className=\"inline-flex font-[inherit] font-medium text-muted-foreground text-xs\">\n              <span className=\"opacity-70\">⌘K</span>\n            </kbd>\n          </div>\n        </div>\n      </SidebarHeader>\n\n      <CommandDialog onOpenChange={setOpen} open={open}>\n        <Command>\n          <CommandInput placeholder=\"Search everything...\" />\n          <CommandList>\n            <CommandEmpty>No results found.</CommandEmpty>\n            <CommandGroup heading=\"Navigation\">\n              {data.navMain.map((item) => (\n                <CommandItem\n                  className=\"py-2!\"\n                  key={item.id}\n                  onSelect={() => {\n                    setOpen(false);\n                  }}\n                >\n                  <item.icon className=\"mr-2 h-4 w-4\" />\n                  <span>{item.title}</span>\n                </CommandItem>\n              ))}\n            </CommandGroup>\n            <CommandSeparator className=\"my-2\" />\n            <CommandGroup heading=\"Favorites\">\n              {data.navCollapsible.favorites.map((item) => (\n                <CommandItem\n                  className=\"py-2!\"\n                  key={item.id}\n                  onSelect={() => {\n                    setOpen(false);\n                  }}\n                >\n                  <div\n                    className={cn('mr-2 h-3 w-3 rounded-full', item.color)}\n                  />\n                  <span>{item.title}</span>\n                </CommandItem>\n              ))}\n            </CommandGroup>\n            <CommandSeparator className=\"my-2\" />\n            <CommandGroup heading=\"Teams\">\n              {data.navCollapsible.teams.map((item) => (\n                <CommandItem\n                  className=\"py-2!\"\n                  key={item.id}\n                  onSelect={() => {\n                    setOpen(false);\n                  }}\n                >\n                  <item.icon className=\"mr-2 h-4 w-4\" />\n                  <span>{item.title}</span>\n                </CommandItem>\n              ))}\n            </CommandGroup>\n            <CommandSeparator className=\"my-2\" />\n            <CommandGroup heading=\"Topics\">\n              {data.navCollapsible.topics.map((item) => (\n                <CommandItem\n                  className=\"py-2!\"\n                  key={item.id}\n                  onSelect={() => {\n                    setOpen(false);\n                  }}\n                >\n                  <item.icon className=\"mr-2 h-4 w-4\" />\n                  <span>{item.title}</span>\n                </CommandItem>\n              ))}\n            </CommandGroup>\n          </CommandList>\n        </Command>\n      </CommandDialog>\n    </>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-01/index.tsx",
          "type": "registry:component",
          "target": "components/sidebar-01/index.tsx",
          "content": "import {\n  SidebarInset,\n  SidebarProvider,\n  SidebarTrigger,\n} from '@/components/ui/sidebar';\nimport { AppSidebar } from '@/components/sidebar-01/app-sidebar';\n\nexport default function Sidebar01() {\n  return (\n    <SidebarProvider>\n      <AppSidebar />\n      <SidebarInset>\n        <header className=\"flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12\">\n          <div className=\"flex items-center gap-2 px-4\">\n            <SidebarTrigger className=\"sm:hidden\" />\n          </div>\n        </header>\n      </SidebarInset>\n    </SidebarProvider>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-01/nav-footer.tsx",
          "type": "registry:component",
          "target": "components/sidebar-01/nav-footer.tsx",
          "content": "'use client';\n\nimport {\n  BookmarkPlus,\n  CircleHelp,\n  LogOut,\n  Plus,\n  PlusCircle,\n  Puzzle,\n  Settings,\n  User,\n} from 'lucide-react';\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';\nimport { Button } from '@/components/ui/button';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport {\n  SidebarFooter,\n  SidebarMenu,\n  SidebarMenuItem,\n} from '@/components/ui/sidebar';\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipProvider,\n  TooltipTrigger,\n} from '@/components/ui/tooltip';\n\nexport function NavFooter({\n  user,\n}: {\n  user: {\n    name: string;\n    email: string;\n    avatar: string;\n  };\n}) {\n  return (\n    <SidebarFooter className=\"p-4\">\n      <SidebarMenu>\n        <SidebarMenuItem>\n          <div className=\"flex items-center justify-between gap-2\">\n            <div className=\"flex items-center gap-2\">\n              <DropdownMenu>\n                <DropdownMenuTrigger\n                  nativeButton={false}\n                  render={<Avatar className=\"h-8 w-8 rounded-full\" />}\n                >\n                  <AvatarImage alt={user.name} src={user.avatar} />\n                  <AvatarFallback className=\"rounded-full\">CN</AvatarFallback>\n                </DropdownMenuTrigger>\n                <DropdownMenuContent className=\"m-2\">\n                  <DropdownMenuItem>\n                    <User aria-hidden=\"true\" className=\"opacity-80\" size={16} />\n                    Profile\n                  </DropdownMenuItem>\n                  <DropdownMenuItem>\n                    <Settings\n                      aria-hidden=\"true\"\n                      className=\"opacity-80\"\n                      size={16}\n                    />\n                    Settings\n                  </DropdownMenuItem>\n                  <DropdownMenuItem>\n                    <LogOut\n                      aria-hidden=\"true\"\n                      className=\"opacity-80\"\n                      size={16}\n                    />\n                    Logout\n                  </DropdownMenuItem>\n                </DropdownMenuContent>\n              </DropdownMenu>\n\n              <TooltipProvider delay={0}>\n                <Tooltip>\n                  <TooltipTrigger\n                    render={\n                      <CircleHelp\n                        aria-hidden=\"true\"\n                        className=\"cursor-pointer opacity-60 hover:opacity-100\"\n                        size={16}\n                      />\n                    }\n                  />\n                  <TooltipContent\n                    className=\"m-2 max-w-[150px] border bg-popover px-2 py-1 text-popover-foreground\"\n                    side=\"top\"\n                  >\n                    <div className=\"space-y-1 text-xs\">\n                      <p className=\"font-medium\">User Information</p>\n                      <p className=\"text-muted-foreground\">\n                        More details about the current user or section can be\n                        displayed here.\n                      </p>\n                    </div>\n                  </TooltipContent>\n                </Tooltip>\n              </TooltipProvider>\n            </div>\n            <DropdownMenu>\n              <DropdownMenuTrigger\n                render={\n                  <Button\n                    aria-label=\"Open edit menu\"\n                    className=\"rounded-full shadow-none focus-visible:ring-0 focus-visible:ring-offset-0\"\n                    size=\"icon\"\n                    variant=\"ghost\"\n                  />\n                }\n              >\n                <Plus aria-hidden=\"true\" size={16} />\n              </DropdownMenuTrigger>\n              <DropdownMenuContent className=\"pb-2\">\n                <DropdownMenuLabel>Add New</DropdownMenuLabel>\n                <DropdownMenuItem>\n                  <PlusCircle\n                    aria-hidden=\"true\"\n                    className=\"mr-2 opacity-80\"\n                    size={16}\n                  />\n                  Add New Item\n                </DropdownMenuItem>\n                <DropdownMenuItem>\n                  <BookmarkPlus\n                    aria-hidden=\"true\"\n                    className=\"mr-2 opacity-80\"\n                    size={16}\n                  />\n                  Add Bookmark\n                </DropdownMenuItem>\n                <DropdownMenuItem>\n                  <Puzzle\n                    aria-hidden=\"true\"\n                    className=\"mr-2 opacity-80\"\n                    size={16}\n                  />\n                  Add Integration\n                </DropdownMenuItem>\n              </DropdownMenuContent>\n            </DropdownMenu>\n          </div>\n        </SidebarMenuItem>\n      </SidebarMenu>\n    </SidebarFooter>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-01/nav-collapsible.tsx",
          "type": "registry:component",
          "target": "components/sidebar-01/nav-collapsible.tsx",
          "content": "'use client';\nimport { ChevronDown } from 'lucide-react';\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from '@/components/ui/collapsible';\nimport {\n  SidebarGroup,\n  SidebarGroupContent,\n  SidebarGroupLabel,\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n} from '@/components/ui/sidebar';\nimport type { FavoriteItem, TeamItem, TopicItem } from '@/components/sidebar-01/types';\n\ninterface NavCollapsibleProps {\n  favorites: FavoriteItem[];\n  teams: TeamItem[];\n  topics: TopicItem[];\n}\n\nexport function NavCollapsible({\n  favorites,\n  teams,\n  topics,\n}: NavCollapsibleProps) {\n  return (\n    <div className=\"space-y-0\">\n      {favorites && favorites.length > 0 && (\n        <Collapsible className=\"group/collapsible\" defaultOpen>\n          <SidebarGroup>\n            <SidebarGroupLabel\n              className=\"text-sm hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\"\n              render={<CollapsibleTrigger />}\n            >\n              Favorites\n              <ChevronDown className=\"ml-auto transition-transform group-data-open/collapsible:rotate-180\" />\n            </SidebarGroupLabel>\n            <CollapsibleContent>\n              <SidebarGroupContent>\n                <SidebarMenu>\n                  {favorites.map((item) => (\n                    <SidebarMenuItem key={item.id}>\n                      <SidebarMenuButton\n                        render={\n                          <a\n                            className=\"flex items-center gap-3\"\n                            href={item.href}\n                          />\n                        }\n                      >\n                        <div className={`h-3 w-3 rounded ${item.color}`} />\n                        <span>{item.title}</span>\n                      </SidebarMenuButton>\n                    </SidebarMenuItem>\n                  ))}\n                </SidebarMenu>\n              </SidebarGroupContent>\n            </CollapsibleContent>\n          </SidebarGroup>\n        </Collapsible>\n      )}\n\n      {teams && teams.length > 0 && (\n        <Collapsible className=\"group/collapsible\">\n          <SidebarGroup>\n            <SidebarGroupLabel\n              className=\"text-sm hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\"\n              render={<CollapsibleTrigger />}\n            >\n              Teams\n              <ChevronDown className=\"ml-auto transition-transform group-data-open/collapsible:rotate-180\" />\n            </SidebarGroupLabel>\n            <CollapsibleContent>\n              <SidebarGroupContent>\n                <SidebarMenu>\n                  {teams.map((item) => {\n                    const Icon = item.icon;\n                    return (\n                      <SidebarMenuItem key={item.id}>\n                        <SidebarMenuButton>\n                          <Icon className=\"mr-2 h-4 w-4\" />\n                          {item.title}\n                        </SidebarMenuButton>\n                      </SidebarMenuItem>\n                    );\n                  })}\n                </SidebarMenu>\n              </SidebarGroupContent>\n            </CollapsibleContent>\n          </SidebarGroup>\n        </Collapsible>\n      )}\n\n      {topics && topics.length > 0 && (\n        <Collapsible className=\"group/collapsible\">\n          <SidebarGroup>\n            <SidebarGroupLabel\n              className=\"text-sm hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\"\n              render={<CollapsibleTrigger />}\n            >\n              Topics\n              <ChevronDown className=\"ml-auto transition-transform group-data-open/collapsible:rotate-180\" />\n            </SidebarGroupLabel>\n            <CollapsibleContent>\n              <SidebarGroupContent>\n                <SidebarMenu>\n                  {topics.map((item) => {\n                    const Icon = item.icon;\n                    return (\n                      <SidebarMenuItem key={item.id}>\n                        <SidebarMenuButton>\n                          <Icon className=\"mr-2 h-4 w-4\" />\n                          {item.title}\n                        </SidebarMenuButton>\n                      </SidebarMenuItem>\n                    );\n                  })}\n                </SidebarMenu>\n              </SidebarGroupContent>\n            </CollapsibleContent>\n          </SidebarGroup>\n        </Collapsible>\n      )}\n    </div>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-01/types.ts",
          "type": "registry:file",
          "target": "components/sidebar-01/types.ts",
          "content": "import type { ElementType } from 'react';\n\nexport interface NavItem {\n  id: string;\n  title: string;\n  icon: ElementType;\n  url?: string;\n  isActive?: boolean;\n}\n\nexport interface User {\n  name: string;\n  email: string;\n  avatar: string;\n}\n\nexport interface FavoriteItem {\n  id: string;\n  title: string;\n  href: string;\n  color: string;\n}\n\nexport interface TeamItem {\n  id: string;\n  title: string;\n  icon: ElementType;\n}\n\nexport interface TopicItem {\n  id: string;\n  title: string;\n  icon: ElementType;\n}\n\nexport interface SidebarData {\n  user: User;\n  navMain: NavItem[];\n  navCollapsible: {\n    favorites: FavoriteItem[];\n    teams: TeamItem[];\n    topics: TopicItem[];\n  };\n}\n"
        }
      ],
      "categories": [
        "sidebar"
      ]
    },
    {
      "name": "sidebar-02",
      "type": "registry:block",
      "title": "Sidebar Dashboard Inset",
      "description": "A sidebar dashboard inset block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "avatar",
        "button",
        "collapsible",
        "dropdown-menu",
        "sidebar"
      ],
      "dependencies": [
        "framer-motion",
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/sidebar/sidebar-02/nav-main.tsx",
          "type": "registry:component",
          "target": "components/sidebar-02/nav-main.tsx",
          "content": "'use client';\n\nimport { ChevronDown, ChevronUp } from 'lucide-react';\nimport Link from 'next/link';\nimport type React from 'react';\nimport { useState } from 'react';\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from '@/components/ui/collapsible';\nimport {\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  SidebarMenuSub,\n  SidebarMenuSubButton,\n  SidebarMenuItem as SidebarMenuSubItem,\n  useSidebar,\n} from '@/components/ui/sidebar';\nimport { cn } from '@/lib/utils';\n\nexport type Route = {\n  id: string;\n  title: string;\n  icon?: React.ReactNode;\n  link: string;\n  subs?: {\n    title: string;\n    link: string;\n    icon?: React.ReactNode;\n  }[];\n};\n\nexport default function DashboardNavigation({ routes }: { routes: Route[] }) {\n  const { state } = useSidebar();\n  const isCollapsed = state === 'collapsed';\n  const [openCollapsible, setOpenCollapsible] = useState<string | null>(null);\n\n  return (\n    <SidebarMenu>\n      {routes.map((route) => {\n        const isOpen = !isCollapsed && openCollapsible === route.id;\n        const hasSubRoutes = !!route.subs?.length;\n\n        return (\n          <SidebarMenuItem key={route.id}>\n            {hasSubRoutes ? (\n              <Collapsible\n                className=\"w-full\"\n                onOpenChange={(open) =>\n                  setOpenCollapsible(open ? route.id : null)\n                }\n                open={isOpen}\n              >\n                <CollapsibleTrigger\n                  render={\n                    <SidebarMenuButton\n                      className={cn(\n                        'flex w-full items-center rounded-lg px-2 transition-colors',\n                        isOpen\n                          ? 'bg-sidebar-muted text-foreground'\n                          : 'text-muted-foreground hover:bg-sidebar-muted hover:text-foreground',\n                        isCollapsed && 'justify-center'\n                      )}\n                    />\n                  }\n                >\n                  {route.icon}\n                  {!isCollapsed && (\n                    <span className=\"ml-2 flex-1 font-medium text-sm\">\n                      {route.title}\n                    </span>\n                  )}\n                  {!isCollapsed && hasSubRoutes && (\n                    <span className=\"ml-auto\">\n                      {isOpen ? (\n                        <ChevronUp className=\"size-4\" />\n                      ) : (\n                        <ChevronDown className=\"size-4\" />\n                      )}\n                    </span>\n                  )}\n                </CollapsibleTrigger>\n\n                {!isCollapsed && (\n                  <CollapsibleContent>\n                    <SidebarMenuSub className=\"my-1 ml-3.5 \">\n                      {route.subs?.map((subRoute) => (\n                        <SidebarMenuSubItem\n                          className=\"h-auto\"\n                          key={`${route.id}-${subRoute.title}`}\n                        >\n                          <SidebarMenuSubButton\n                            render={\n                              <Link\n                                className=\"flex items-center rounded-md px-4 py-1.5 font-medium text-muted-foreground text-sm hover:bg-sidebar-muted hover:text-foreground\"\n                                href={subRoute.link}\n                                prefetch={true}\n                              />\n                            }\n                          >\n                            {subRoute.title}\n                          </SidebarMenuSubButton>\n                        </SidebarMenuSubItem>\n                      ))}\n                    </SidebarMenuSub>\n                  </CollapsibleContent>\n                )}\n              </Collapsible>\n            ) : (\n              <SidebarMenuButton\n                render={\n                  <Link\n                    className={cn(\n                      'flex items-center rounded-lg px-2 text-muted-foreground transition-colors hover:bg-sidebar-muted hover:text-foreground',\n                      isCollapsed && 'justify-center'\n                    )}\n                    href={route.link}\n                    prefetch={true}\n                  />\n                }\n                tooltip={route.title}\n              >\n                {route.icon}\n                {!isCollapsed && (\n                  <span className=\"ml-2 font-medium text-sm\">\n                    {route.title}\n                  </span>\n                )}\n              </SidebarMenuButton>\n            )}\n          </SidebarMenuItem>\n        );\n      })}\n    </SidebarMenu>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-02/app-sidebar.tsx",
          "type": "registry:component",
          "target": "components/sidebar-02/app-sidebar.tsx",
          "content": "'use client';\n\nimport { motion } from 'framer-motion';\nimport {\n  Activity,\n  DollarSign,\n  Home,\n  Infinity,\n  LinkIcon,\n  Package2,\n  Percent,\n  PieChart,\n  Settings,\n  ShoppingBag,\n  Sparkles,\n  Store,\n  TrendingUp,\n  Users,\n} from 'lucide-react';\nimport {\n  Sidebar,\n  SidebarContent,\n  SidebarFooter,\n  SidebarHeader,\n  SidebarTrigger,\n  useSidebar,\n} from '@/components/ui/sidebar';\nimport { cn } from '@/lib/utils';\nimport { Logo } from '@/components/sidebar-02/logo';\nimport type { Route } from '@/components/sidebar-02/nav-main';\nimport DashboardNavigation from '@/components/sidebar-02/nav-main';\nimport { NotificationsPopover } from '@/components/sidebar-02/nav-notifications';\nimport { TeamSwitcher } from '@/components/sidebar-02/team-switcher';\n\nconst sampleNotifications = [\n  {\n    id: '1',\n    avatar: '/avatars/01.png',\n    fallback: 'OM',\n    text: 'New order received.',\n    time: '10m ago',\n  },\n  {\n    id: '2',\n    avatar: '/avatars/02.png',\n    fallback: 'JL',\n    text: 'Server upgrade completed.',\n    time: '1h ago',\n  },\n  {\n    id: '3',\n    avatar: '/avatars/03.png',\n    fallback: 'HH',\n    text: 'New user signed up.',\n    time: '2h ago',\n  },\n];\n\nconst dashboardRoutes: Route[] = [\n  {\n    id: 'home',\n    title: 'Home',\n    icon: <Home className=\"size-4\" />,\n    link: '#',\n  },\n  {\n    id: 'products',\n    title: 'Products',\n    icon: <Package2 className=\"size-4\" />,\n    link: '#',\n    subs: [\n      {\n        title: 'Catalogue',\n        link: '#',\n        icon: <Package2 className=\"size-4\" />,\n      },\n      {\n        title: 'Checkout Links',\n        link: '#',\n        icon: <LinkIcon className=\"size-4\" />,\n      },\n      {\n        title: 'Discounts',\n        link: '#',\n        icon: <Percent className=\"size-4\" />,\n      },\n    ],\n  },\n  {\n    id: 'usage-billing',\n    title: 'Usage Billing',\n    icon: <PieChart className=\"size-4\" />,\n    link: '#',\n    subs: [\n      {\n        title: 'Meters',\n        link: '#',\n        icon: <PieChart className=\"size-4\" />,\n      },\n      {\n        title: 'Events',\n        link: '#',\n        icon: <Activity className=\"size-4\" />,\n      },\n    ],\n  },\n  {\n    id: 'benefits',\n    title: 'Benefits',\n    icon: <Sparkles className=\"size-4\" />,\n    link: '#',\n  },\n  {\n    id: 'customers',\n    title: 'Customers',\n    icon: <Users className=\"size-4\" />,\n    link: '#',\n  },\n  {\n    id: 'sales',\n    title: 'Sales',\n    icon: <ShoppingBag className=\"size-4\" />,\n    link: '#',\n    subs: [\n      {\n        title: 'Orders',\n        link: '#',\n        icon: <ShoppingBag className=\"size-4\" />,\n      },\n      {\n        title: 'Subscriptions',\n        link: '#',\n        icon: <Infinity className=\"size-4\" />,\n      },\n    ],\n  },\n  {\n    id: 'storefront',\n    title: 'Storefront',\n    icon: <Store className=\"size-4\" />,\n    link: '#',\n  },\n  {\n    id: 'analytics',\n    title: 'Analytics',\n    icon: <TrendingUp className=\"size-4\" />,\n    link: '#',\n  },\n  {\n    id: 'finance',\n    title: 'Finance',\n    icon: <DollarSign className=\"size-4\" />,\n    link: '#',\n    subs: [\n      { title: 'Incoming', link: '#' },\n      { title: 'Outgoing', link: '#' },\n      { title: 'Payout Account', link: '#' },\n    ],\n  },\n  {\n    id: 'settings',\n    title: 'Settings',\n    icon: <Settings className=\"size-4\" />,\n    link: '#',\n    subs: [\n      { title: 'General', link: '#' },\n      { title: 'Webhooks', link: '#' },\n      { title: 'Custom Fields', link: '#' },\n    ],\n  },\n];\n\nconst teams = [\n  { id: '1', name: 'Alpha Inc.', logo: Logo, plan: 'Free' },\n  { id: '2', name: 'Beta Corp.', logo: Logo, plan: 'Free' },\n  { id: '3', name: 'Gamma Tech', logo: Logo, plan: 'Free' },\n];\n\nexport function DashboardSidebar() {\n  const { state } = useSidebar();\n  const isCollapsed = state === 'collapsed';\n\n  return (\n    <Sidebar collapsible=\"icon\" variant=\"inset\">\n      <SidebarHeader\n        className={cn(\n          'flex md:pt-3.5',\n          isCollapsed\n            ? 'flex-row items-center justify-between gap-y-4 md:flex-col md:items-start md:justify-start'\n            : 'flex-row items-center justify-between'\n        )}\n      >\n        <a className=\"flex items-center gap-2\" href=\"#\">\n          <Logo className=\"h-8 w-8\" />\n          {!isCollapsed && (\n            <span className=\"font-semibold text-black dark:text-white\">\n              Acme\n            </span>\n          )}\n        </a>\n\n        <motion.div\n          animate={{ opacity: 1 }}\n          className={cn(\n            'flex items-center gap-2',\n            isCollapsed ? 'flex-row md:flex-col-reverse' : 'flex-row'\n          )}\n          initial={{ opacity: 0 }}\n          key={isCollapsed ? 'header-collapsed' : 'header-expanded'}\n          transition={{ duration: 0.8 }}\n        >\n          <NotificationsPopover notifications={sampleNotifications} />\n          <SidebarTrigger />\n        </motion.div>\n      </SidebarHeader>\n      <SidebarContent className=\"gap-4 px-2 py-4\">\n        <DashboardNavigation routes={dashboardRoutes} />\n      </SidebarContent>\n      <SidebarFooter className=\"px-2\">\n        <TeamSwitcher teams={teams} />\n      </SidebarFooter>\n    </Sidebar>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-02/nav-notifications.tsx",
          "type": "registry:component",
          "target": "components/sidebar-02/nav-notifications.tsx",
          "content": "'use client';\n\nimport { BellIcon } from 'lucide-react';\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';\nimport { Button } from '@/components/ui/button';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\n\ntype Notification = {\n  id: string;\n  avatar: string;\n  fallback: string;\n  text: string;\n  time: string;\n};\n\nexport function NotificationsPopover({\n  notifications,\n}: {\n  notifications: Notification[];\n}) {\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger\n        render={\n          <Button\n            aria-label=\"Open notifications\"\n            className=\"rounded-full\"\n            size=\"icon\"\n            variant=\"ghost\"\n          />\n        }\n      >\n        <BellIcon className=\"size-5\" />\n      </DropdownMenuTrigger>\n      <DropdownMenuContent className=\"my-6 w-80\" side=\"right\">\n        <DropdownMenuLabel>Notifications</DropdownMenuLabel>\n        <DropdownMenuSeparator />\n        {notifications.map(({ id, avatar, fallback, text, time }) => (\n          <DropdownMenuItem className=\"flex items-start gap-3\" key={id}>\n            <Avatar className=\"size-8\">\n              <AvatarImage alt=\"Avatar\" src={avatar} />\n              <AvatarFallback>{fallback}</AvatarFallback>\n            </Avatar>\n            <div className=\"flex flex-col\">\n              <span className=\"font-medium text-sm\">{text}</span>\n              <span className=\"text-muted-foreground text-xs\">{time}</span>\n            </div>\n          </DropdownMenuItem>\n        ))}\n        <DropdownMenuSeparator />\n        <DropdownMenuItem className=\"justify-center text-muted-foreground text-sm hover:text-primary\">\n          View all notifications\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-02/index.tsx",
          "type": "registry:component",
          "target": "components/sidebar-02/index.tsx",
          "content": "import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar';\nimport { DashboardSidebar } from '@/components/sidebar-02/app-sidebar';\n\nexport default function Sidebar02() {\n  return (\n    <SidebarProvider>\n      <div className=\"relative flex h-dvh w-full\">\n        <DashboardSidebar />\n        <SidebarInset className=\"flex flex-col\" />\n      </div>\n    </SidebarProvider>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-02/team-switcher.tsx",
          "type": "registry:component",
          "target": "components/sidebar-02/team-switcher.tsx",
          "content": "'use client';\n\nimport { ChevronsUpDown, Plus } from 'lucide-react';\nimport * as React from 'react';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport {\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  useSidebar,\n} from '@/components/ui/sidebar';\n\ntype Team = {\n  name: string;\n  logo: React.ElementType;\n  plan: string;\n};\n\nexport function TeamSwitcher({ teams }: { teams: Team[] }) {\n  const { isMobile } = useSidebar();\n  const [activeTeam, setActiveTeam] = React.useState(teams[0]);\n\n  if (!activeTeam) return null;\n\n  const Logo = activeTeam.logo;\n\n  return (\n    <SidebarMenu>\n      <SidebarMenuItem>\n        <DropdownMenu>\n          <DropdownMenuTrigger\n            render={\n              <SidebarMenuButton\n                className=\"data-popup-open:bg-sidebar-accent data-popup-open:text-sidebar-accent-foreground\"\n                size=\"lg\"\n              />\n            }\n          >\n            <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg bg-background text-foreground\">\n              <Logo className=\"size-4\" />\n            </div>\n            <div className=\"grid flex-1 text-left text-sm leading-tight\">\n              <span className=\"truncate font-semibold\">{activeTeam.name}</span>\n              <span className=\"truncate text-xs\">{activeTeam.plan}</span>\n            </div>\n            <ChevronsUpDown className=\"ml-auto\" />\n          </DropdownMenuTrigger>\n          <DropdownMenuContent\n            align=\"start\"\n            className=\"mb-4 w-(--anchor-width) min-w-56 rounded-lg\"\n            side={isMobile ? 'bottom' : 'right'}\n            sideOffset={4}\n          >\n            <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n              Teams\n            </DropdownMenuLabel>\n            {teams.map((team, index) => (\n              <DropdownMenuItem\n                className=\"gap-2 p-2\"\n                key={team.name}\n                onClick={() => setActiveTeam(team)}\n              >\n                <div className=\"flex size-6 items-center justify-center rounded-sm border\">\n                  <team.logo className=\"size-4 shrink-0\" />\n                </div>\n                {team.name}\n                <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>\n              </DropdownMenuItem>\n            ))}\n            <DropdownMenuSeparator />\n            <DropdownMenuItem className=\"gap-2 p-2\">\n              <div className=\"flex size-6 items-center justify-center rounded-md border bg-background\">\n                <Plus className=\"size-4\" />\n              </div>\n              <div className=\"font-medium text-muted-foreground\">Add team</div>\n            </DropdownMenuItem>\n          </DropdownMenuContent>\n        </DropdownMenu>\n      </SidebarMenuItem>\n    </SidebarMenu>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-02/logo.tsx",
          "type": "registry:component",
          "target": "components/sidebar-02/logo.tsx",
          "content": "import type { SVGProps } from 'react';\n\nexport const Logo = (props: SVGProps<SVGSVGElement>) => (\n  <svg\n    fill=\"currentColor\"\n    height=\"48\"\n    viewBox=\"0 0 40 48\"\n    width=\"40\"\n    {...props}\n  >\n    <clipPath id=\"a\">\n      <path d=\"m0 0h40v48h-40z\" />\n    </clipPath>\n    <g clipPath=\"url(#a)\">\n      <path d=\"m25.0887 5.05386-3.933-1.05386-3.3145 12.3696-2.9923-11.16736-3.9331 1.05386 3.233 12.0655-8.05262-8.0526-2.87919 2.8792 8.83271 8.8328-10.99975-2.9474-1.05385625 3.933 12.01860625 3.2204c-.1376-.5935-.2104-1.2119-.2104-1.8473 0-4.4976 3.646-8.1436 8.1437-8.1436 4.4976 0 8.1436 3.646 8.1436 8.1436 0 .6313-.0719 1.2459-.2078 1.8359l10.9227 2.9267 1.0538-3.933-12.0664-3.2332 11.0005-2.9476-1.0539-3.933-12.0659 3.233 8.0526-8.0526-2.8792-2.87916-8.7102 8.71026z\" />\n      <path d=\"m27.8723 26.2214c-.3372 1.4256-1.0491 2.7063-2.0259 3.7324l7.913 7.9131 2.8792-2.8792z\" />\n      <path d=\"m25.7665 30.0366c-.9886 1.0097-2.2379 1.7632-3.6389 2.1515l2.8794 10.746 3.933-1.0539z\" />\n      <path d=\"m21.9807 32.2274c-.65.1671-1.3313.2559-2.0334.2559-.7522 0-1.4806-.102-2.1721-.2929l-2.882 10.7558 3.933 1.0538z\" />\n      <path d=\"m17.6361 32.1507c-1.3796-.4076-2.6067-1.1707-3.5751-2.1833l-7.9325 7.9325 2.87919 2.8792z\" />\n      <path d=\"m13.9956 29.8973c-.9518-1.019-1.6451-2.2826-1.9751-3.6862l-10.95836 2.9363 1.05385 3.933z\" />\n    </g>\n  </svg>\n);\n"
        }
      ],
      "categories": [
        "sidebar"
      ]
    },
    {
      "name": "sidebar-03",
      "type": "registry:block",
      "title": "Sidebar Dashboard Floating",
      "description": "A sidebar dashboard floating block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "avatar",
        "button",
        "collapsible",
        "dropdown-menu",
        "sidebar"
      ],
      "dependencies": [
        "framer-motion",
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/sidebar/sidebar-03/nav-main.tsx",
          "type": "registry:component",
          "target": "components/sidebar-03/nav-main.tsx",
          "content": "'use client';\n\nimport { ChevronDown, ChevronUp } from 'lucide-react';\nimport Link from 'next/link';\nimport type React from 'react';\nimport { useState } from 'react';\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from '@/components/ui/collapsible';\nimport {\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  SidebarMenuSub,\n  SidebarMenuSubButton,\n  SidebarMenuItem as SidebarMenuSubItem,\n  useSidebar,\n} from '@/components/ui/sidebar';\nimport { cn } from '@/lib/utils';\n\nexport type Route = {\n  id: string;\n  title: string;\n  icon?: React.ReactNode;\n  link: string;\n  subs?: {\n    title: string;\n    link: string;\n    icon?: React.ReactNode;\n  }[];\n};\n\nexport default function DashboardNavigation({ routes }: { routes: Route[] }) {\n  const { state } = useSidebar();\n  const isCollapsed = state === 'collapsed';\n  const [openCollapsible, setOpenCollapsible] = useState<string | null>(null);\n\n  return (\n    <SidebarMenu>\n      {routes.map((route) => {\n        const isOpen = !isCollapsed && openCollapsible === route.id;\n        const hasSubRoutes = !!route.subs?.length;\n\n        return (\n          <SidebarMenuItem key={route.id}>\n            {hasSubRoutes ? (\n              <Collapsible\n                className=\"w-full\"\n                onOpenChange={(open) =>\n                  setOpenCollapsible(open ? route.id : null)\n                }\n                open={isOpen}\n              >\n                <CollapsibleTrigger\n                  render={\n                    <SidebarMenuButton\n                      className={cn(\n                        'flex w-full items-center rounded-lg px-2 transition-colors',\n                        isOpen\n                          ? 'bg-sidebar-muted text-foreground'\n                          : 'text-muted-foreground hover:bg-sidebar-muted hover:text-foreground',\n                        isCollapsed && 'justify-center'\n                      )}\n                    />\n                  }\n                >\n                  {route.icon}\n                  {!isCollapsed && (\n                    <span className=\"ml-2 flex-1 font-medium text-sm\">\n                      {route.title}\n                    </span>\n                  )}\n                  {!isCollapsed && hasSubRoutes && (\n                    <span className=\"ml-auto\">\n                      {isOpen ? (\n                        <ChevronUp className=\"size-4\" />\n                      ) : (\n                        <ChevronDown className=\"size-4\" />\n                      )}\n                    </span>\n                  )}\n                </CollapsibleTrigger>\n\n                {!isCollapsed && (\n                  <CollapsibleContent>\n                    <SidebarMenuSub className=\"my-1 ml-3.5 \">\n                      {route.subs?.map((subRoute) => (\n                        <SidebarMenuSubItem\n                          className=\"h-auto\"\n                          key={`${route.id}-${subRoute.title}`}\n                        >\n                          <SidebarMenuSubButton\n                            render={\n                              <Link\n                                className=\"flex items-center rounded-md px-4 py-1.5 font-medium text-muted-foreground text-sm hover:bg-sidebar-muted hover:text-foreground\"\n                                href={subRoute.link}\n                                prefetch={true}\n                              />\n                            }\n                          >\n                            {subRoute.title}\n                          </SidebarMenuSubButton>\n                        </SidebarMenuSubItem>\n                      ))}\n                    </SidebarMenuSub>\n                  </CollapsibleContent>\n                )}\n              </Collapsible>\n            ) : (\n              <SidebarMenuButton\n                render={\n                  <Link\n                    className={cn(\n                      'flex items-center rounded-lg px-2 text-muted-foreground transition-colors hover:bg-sidebar-muted hover:text-foreground',\n                      isCollapsed && 'justify-center'\n                    )}\n                    href={route.link}\n                    prefetch={true}\n                  />\n                }\n                tooltip={route.title}\n              >\n                {route.icon}\n                {!isCollapsed && (\n                  <span className=\"ml-2 font-medium text-sm\">\n                    {route.title}\n                  </span>\n                )}\n              </SidebarMenuButton>\n            )}\n          </SidebarMenuItem>\n        );\n      })}\n    </SidebarMenu>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-03/app-sidebar.tsx",
          "type": "registry:component",
          "target": "components/sidebar-03/app-sidebar.tsx",
          "content": "'use client';\n\nimport { motion } from 'framer-motion';\nimport {\n  Activity,\n  DollarSign,\n  Home,\n  Infinity,\n  LinkIcon,\n  Package2,\n  Percent,\n  PieChart,\n  Settings,\n  ShoppingBag,\n  Sparkles,\n  Store,\n  TrendingUp,\n  Users,\n} from 'lucide-react';\nimport {\n  Sidebar,\n  SidebarContent,\n  SidebarFooter,\n  SidebarHeader,\n  SidebarTrigger,\n  useSidebar,\n} from '@/components/ui/sidebar';\nimport { cn } from '@/lib/utils';\nimport { Logo } from '@/components/sidebar-03/logo';\nimport type { Route } from '@/components/sidebar-03/nav-main';\nimport DashboardNavigation from '@/components/sidebar-03/nav-main';\nimport { NotificationsPopover } from '@/components/sidebar-03/nav-notifications';\nimport { TeamSwitcher } from '@/components/sidebar-03/team-switcher';\n\nconst sampleNotifications = [\n  {\n    id: '1',\n    avatar: '/avatars/01.png',\n    fallback: 'OM',\n    text: 'New order received.',\n    time: '10m ago',\n  },\n  {\n    id: '2',\n    avatar: '/avatars/02.png',\n    fallback: 'JL',\n    text: 'Server upgrade completed.',\n    time: '1h ago',\n  },\n  {\n    id: '3',\n    avatar: '/avatars/03.png',\n    fallback: 'HH',\n    text: 'New user signed up.',\n    time: '2h ago',\n  },\n];\n\nconst dashboardRoutes: Route[] = [\n  {\n    id: 'home',\n    title: 'Home',\n    icon: <Home className=\"size-4\" />,\n    link: '#',\n  },\n  {\n    id: 'products',\n    title: 'Products',\n    icon: <Package2 className=\"size-4\" />,\n    link: '#',\n    subs: [\n      {\n        title: 'Catalogue',\n        link: '#',\n        icon: <Package2 className=\"size-4\" />,\n      },\n      {\n        title: 'Checkout Links',\n        link: '#',\n        icon: <LinkIcon className=\"size-4\" />,\n      },\n      {\n        title: 'Discounts',\n        link: '#',\n        icon: <Percent className=\"size-4\" />,\n      },\n    ],\n  },\n  {\n    id: 'usage-billing',\n    title: 'Usage Billing',\n    icon: <PieChart className=\"size-4\" />,\n    link: '#',\n    subs: [\n      {\n        title: 'Meters',\n        link: '#',\n        icon: <PieChart className=\"size-4\" />,\n      },\n      {\n        title: 'Events',\n        link: '#',\n        icon: <Activity className=\"size-4\" />,\n      },\n    ],\n  },\n  {\n    id: 'benefits',\n    title: 'Benefits',\n    icon: <Sparkles className=\"size-4\" />,\n    link: '#',\n  },\n  {\n    id: 'customers',\n    title: 'Customers',\n    icon: <Users className=\"size-4\" />,\n    link: '#',\n  },\n  {\n    id: 'sales',\n    title: 'Sales',\n    icon: <ShoppingBag className=\"size-4\" />,\n    link: '#',\n    subs: [\n      {\n        title: 'Orders',\n        link: '#',\n        icon: <ShoppingBag className=\"size-4\" />,\n      },\n      {\n        title: 'Subscriptions',\n        link: '#',\n        icon: <Infinity className=\"size-4\" />,\n      },\n    ],\n  },\n  {\n    id: 'storefront',\n    title: 'Storefront',\n    icon: <Store className=\"size-4\" />,\n    link: '#',\n  },\n  {\n    id: 'analytics',\n    title: 'Analytics',\n    icon: <TrendingUp className=\"size-4\" />,\n    link: '#',\n  },\n  {\n    id: 'finance',\n    title: 'Finance',\n    icon: <DollarSign className=\"size-4\" />,\n    link: '#',\n    subs: [\n      { title: 'Incoming', link: '#' },\n      { title: 'Outgoing', link: '#' },\n      { title: 'Payout Account', link: '#' },\n    ],\n  },\n  {\n    id: 'settings',\n    title: 'Settings',\n    icon: <Settings className=\"size-4\" />,\n    link: '#',\n    subs: [\n      { title: 'General', link: '#' },\n      { title: 'Webhooks', link: '#' },\n      { title: 'Custom Fields', link: '#' },\n    ],\n  },\n];\n\nconst teams = [\n  { id: '1', name: 'Alpha Inc.', logo: Logo, plan: 'Free' },\n  { id: '2', name: 'Beta Corp.', logo: Logo, plan: 'Free' },\n  { id: '3', name: 'Gamma Tech', logo: Logo, plan: 'Free' },\n];\n\nexport function DashboardSidebar() {\n  const { state } = useSidebar();\n  const isCollapsed = state === 'collapsed';\n\n  return (\n    <Sidebar collapsible=\"icon\" variant=\"floating\">\n      <SidebarHeader\n        className={cn(\n          'flex md:pt-3.5',\n          isCollapsed\n            ? 'flex-row items-center justify-between gap-y-4 md:flex-col md:items-start md:justify-start'\n            : 'flex-row items-center justify-between'\n        )}\n      >\n        <a className=\"flex items-center gap-2\" href=\"#\">\n          <Logo className=\"h-8 w-8\" />\n          {!isCollapsed && (\n            <span className=\"font-semibold text-black dark:text-white\">\n              Acme\n            </span>\n          )}\n        </a>\n\n        <motion.div\n          animate={{ opacity: 1 }}\n          className={cn(\n            'flex items-center gap-2',\n            isCollapsed ? 'flex-row md:flex-col-reverse' : 'flex-row'\n          )}\n          initial={{ opacity: 0 }}\n          key={isCollapsed ? 'header-collapsed' : 'header-expanded'}\n          transition={{ duration: 0.8 }}\n        >\n          <NotificationsPopover notifications={sampleNotifications} />\n          <SidebarTrigger />\n        </motion.div>\n      </SidebarHeader>\n      <SidebarContent className=\"gap-4 px-2 py-4\">\n        <DashboardNavigation routes={dashboardRoutes} />\n      </SidebarContent>\n      <SidebarFooter className=\"px-2\">\n        <TeamSwitcher teams={teams} />\n      </SidebarFooter>\n    </Sidebar>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-03/nav-notifications.tsx",
          "type": "registry:component",
          "target": "components/sidebar-03/nav-notifications.tsx",
          "content": "'use client';\n\nimport { BellIcon } from 'lucide-react';\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';\nimport { Button } from '@/components/ui/button';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\n\ntype Notification = {\n  id: string;\n  avatar: string;\n  fallback: string;\n  text: string;\n  time: string;\n};\n\nexport function NotificationsPopover({\n  notifications,\n}: {\n  notifications: Notification[];\n}) {\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger\n        render={\n          <Button\n            aria-label=\"Open notifications\"\n            className=\"rounded-full\"\n            size=\"icon\"\n            variant=\"ghost\"\n          />\n        }\n      >\n        <BellIcon className=\"size-5\" />\n      </DropdownMenuTrigger>\n      <DropdownMenuContent className=\"my-6 w-80\" side=\"right\">\n        <DropdownMenuLabel>Notifications</DropdownMenuLabel>\n        <DropdownMenuSeparator />\n        {notifications.map(({ id, avatar, fallback, text, time }) => (\n          <DropdownMenuItem className=\"flex items-start gap-3\" key={id}>\n            <Avatar className=\"size-8\">\n              <AvatarImage alt=\"Avatar\" src={avatar} />\n              <AvatarFallback>{fallback}</AvatarFallback>\n            </Avatar>\n            <div className=\"flex flex-col\">\n              <span className=\"font-medium text-sm\">{text}</span>\n              <span className=\"text-muted-foreground text-xs\">{time}</span>\n            </div>\n          </DropdownMenuItem>\n        ))}\n        <DropdownMenuSeparator />\n        <DropdownMenuItem className=\"justify-center text-muted-foreground text-sm hover:text-primary\">\n          View all notifications\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-03/index.tsx",
          "type": "registry:component",
          "target": "components/sidebar-03/index.tsx",
          "content": "import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar';\nimport { DashboardSidebar } from '@/components/sidebar-03/app-sidebar';\n\nexport default function Sidebar03() {\n  return (\n    <SidebarProvider>\n      <div className=\"relative flex h-dvh w-full\">\n        <DashboardSidebar />\n        <SidebarInset className=\"flex flex-col\" />\n      </div>\n    </SidebarProvider>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-03/team-switcher.tsx",
          "type": "registry:component",
          "target": "components/sidebar-03/team-switcher.tsx",
          "content": "'use client';\n\nimport { ChevronsUpDown, Plus } from 'lucide-react';\nimport * as React from 'react';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport {\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  useSidebar,\n} from '@/components/ui/sidebar';\n\ntype Team = {\n  name: string;\n  logo: React.ElementType;\n  plan: string;\n};\n\nexport function TeamSwitcher({ teams }: { teams: Team[] }) {\n  const { isMobile } = useSidebar();\n  const [activeTeam, setActiveTeam] = React.useState(teams[0]);\n\n  if (!activeTeam) return null;\n\n  const Logo = activeTeam.logo;\n\n  return (\n    <SidebarMenu>\n      <SidebarMenuItem>\n        <DropdownMenu>\n          <DropdownMenuTrigger\n            render={\n              <SidebarMenuButton\n                className=\"data-popup-open:bg-sidebar-accent data-popup-open:text-sidebar-accent-foreground\"\n                size=\"lg\"\n              />\n            }\n          >\n            <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg bg-background text-foreground\">\n              <Logo className=\"size-4\" />\n            </div>\n            <div className=\"grid flex-1 text-left text-sm leading-tight\">\n              <span className=\"truncate font-semibold\">{activeTeam.name}</span>\n              <span className=\"truncate text-xs\">{activeTeam.plan}</span>\n            </div>\n            <ChevronsUpDown className=\"ml-auto\" />\n          </DropdownMenuTrigger>\n          <DropdownMenuContent\n            align=\"start\"\n            className=\"mb-4 w-(--anchor-width) min-w-56 rounded-lg\"\n            side={isMobile ? 'bottom' : 'right'}\n            sideOffset={4}\n          >\n            <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n              Teams\n            </DropdownMenuLabel>\n            {teams.map((team, index) => (\n              <DropdownMenuItem\n                className=\"gap-2 p-2\"\n                key={team.name}\n                onClick={() => setActiveTeam(team)}\n              >\n                <div className=\"flex size-6 items-center justify-center rounded-sm border\">\n                  <team.logo className=\"size-4 shrink-0\" />\n                </div>\n                {team.name}\n                <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>\n              </DropdownMenuItem>\n            ))}\n            <DropdownMenuSeparator />\n            <DropdownMenuItem className=\"gap-2 p-2\">\n              <div className=\"flex size-6 items-center justify-center rounded-md border bg-background\">\n                <Plus className=\"size-4\" />\n              </div>\n              <div className=\"font-medium text-muted-foreground\">Add team</div>\n            </DropdownMenuItem>\n          </DropdownMenuContent>\n        </DropdownMenu>\n      </SidebarMenuItem>\n    </SidebarMenu>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-03/logo.tsx",
          "type": "registry:component",
          "target": "components/sidebar-03/logo.tsx",
          "content": "import type { SVGProps } from 'react';\n\nexport const Logo = (props: SVGProps<SVGSVGElement>) => (\n  <svg\n    fill=\"currentColor\"\n    height=\"48\"\n    viewBox=\"0 0 40 48\"\n    width=\"40\"\n    {...props}\n  >\n    <title>Logo</title>\n    <clipPath id=\"a\">\n      <path d=\"m0 0h40v48h-40z\" />\n    </clipPath>\n    <g clipPath=\"url(#a)\">\n      <path d=\"m25.0887 5.05386-3.933-1.05386-3.3145 12.3696-2.9923-11.16736-3.9331 1.05386 3.233 12.0655-8.05262-8.0526-2.87919 2.8792 8.83271 8.8328-10.99975-2.9474-1.05385625 3.933 12.01860625 3.2204c-.1376-.5935-.2104-1.2119-.2104-1.8473 0-4.4976 3.646-8.1436 8.1437-8.1436 4.4976 0 8.1436 3.646 8.1436 8.1436 0 .6313-.0719 1.2459-.2078 1.8359l10.9227 2.9267 1.0538-3.933-12.0664-3.2332 11.0005-2.9476-1.0539-3.933-12.0659 3.233 8.0526-8.0526-2.8792-2.87916-8.7102 8.71026z\" />\n      <path d=\"m27.8723 26.2214c-.3372 1.4256-1.0491 2.7063-2.0259 3.7324l7.913 7.9131 2.8792-2.8792z\" />\n      <path d=\"m25.7665 30.0366c-.9886 1.0097-2.2379 1.7632-3.6389 2.1515l2.8794 10.746 3.933-1.0539z\" />\n      <path d=\"m21.9807 32.2274c-.65.1671-1.3313.2559-2.0334.2559-.7522 0-1.4806-.102-2.1721-.2929l-2.882 10.7558 3.933 1.0538z\" />\n      <path d=\"m17.6361 32.1507c-1.3796-.4076-2.6067-1.1707-3.5751-2.1833l-7.9325 7.9325 2.87919 2.8792z\" />\n      <path d=\"m13.9956 29.8973c-.9518-1.019-1.6451-2.2826-1.9751-3.6862l-10.95836 2.9363 1.05385 3.933z\" />\n    </g>\n  </svg>\n);\n"
        }
      ],
      "categories": [
        "sidebar"
      ]
    },
    {
      "name": "sidebar-04",
      "type": "registry:block",
      "title": "Sidebar Double-Sided Mail",
      "description": "A sidebar double-sided mail block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "avatar",
        "dropdown-menu",
        "sidebar"
      ],
      "dependencies": [
        "@tabler/icons-react",
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/sidebar/sidebar-04/nav-user.tsx",
          "type": "registry:component",
          "target": "components/sidebar-04/nav-user.tsx",
          "content": "'use client';\n\nimport {\n  BadgeCheck,\n  Bell,\n  ChevronsUpDown,\n  CreditCard,\n  LogOut,\n  Sparkles,\n} from 'lucide-react';\n\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport {\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  useSidebar,\n} from '@/components/ui/sidebar';\n\nexport function NavUser({\n  user,\n}: {\n  user: {\n    name: string;\n    email: string;\n    avatar: string;\n  };\n}) {\n  const { isMobile } = useSidebar();\n\n  return (\n    <SidebarMenu>\n      <SidebarMenuItem>\n        <DropdownMenu>\n          <DropdownMenuTrigger\n            render={\n              <SidebarMenuButton\n                className=\"data-popup-open:bg-sidebar-accent data-popup-open:text-sidebar-accent-foreground md:h-8 md:p-0\"\n                size=\"lg\"\n              />\n            }\n          >\n            <Avatar className=\"h-8 w-8 rounded-lg\">\n              <AvatarImage alt={user.name} src={user.avatar} />\n              <AvatarFallback className=\"rounded-lg\">CN</AvatarFallback>\n            </Avatar>\n            <div className=\"grid flex-1 text-left text-sm leading-tight\">\n              <span className=\"truncate font-medium\">{user.name}</span>\n              <span className=\"truncate text-xs\">{user.email}</span>\n            </div>\n            <ChevronsUpDown className=\"ml-auto size-4\" />\n          </DropdownMenuTrigger>\n          <DropdownMenuContent\n            align=\"end\"\n            className=\"w-(--anchor-width) min-w-56 rounded-lg\"\n            side={isMobile ? 'bottom' : 'right'}\n            sideOffset={4}\n          >\n            <DropdownMenuLabel className=\"p-0 font-normal\">\n              <div className=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n                <Avatar className=\"h-8 w-8 rounded-lg\">\n                  <AvatarImage alt={user.name} src={user.avatar} />\n                  <AvatarFallback className=\"rounded-lg\">CN</AvatarFallback>\n                </Avatar>\n                <div className=\"grid flex-1 text-left text-sm leading-tight\">\n                  <span className=\"truncate font-medium\">{user.name}</span>\n                  <span className=\"truncate text-xs\">{user.email}</span>\n                </div>\n              </div>\n            </DropdownMenuLabel>\n            <DropdownMenuSeparator />\n            <DropdownMenuGroup>\n              <DropdownMenuItem>\n                <Sparkles />\n                Upgrade to Pro\n              </DropdownMenuItem>\n            </DropdownMenuGroup>\n            <DropdownMenuSeparator />\n            <DropdownMenuGroup>\n              <DropdownMenuItem>\n                <BadgeCheck />\n                Account\n              </DropdownMenuItem>\n              <DropdownMenuItem>\n                <CreditCard />\n                Billing\n              </DropdownMenuItem>\n              <DropdownMenuItem>\n                <Bell />\n                Notifications\n              </DropdownMenuItem>\n            </DropdownMenuGroup>\n            <DropdownMenuSeparator />\n            <DropdownMenuItem>\n              <LogOut />\n              Log out\n            </DropdownMenuItem>\n          </DropdownMenuContent>\n        </DropdownMenu>\n      </SidebarMenuItem>\n    </SidebarMenu>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-04/app-sidebar.tsx",
          "type": "registry:component",
          "target": "components/sidebar-04/app-sidebar.tsx",
          "content": "'use client';\n\nimport {\n  IconBrandAmongUs,\n  IconCarambola,\n  IconHourglassHigh,\n  IconMailbox,\n} from '@tabler/icons-react';\nimport { Archive, Flag } from 'lucide-react';\nimport * as React from 'react';\nimport {\n  Sidebar,\n  SidebarContent,\n  SidebarFooter,\n  SidebarGroup,\n  SidebarGroupContent,\n  SidebarGroupLabel,\n  SidebarHeader,\n  SidebarInput,\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  useSidebar,\n} from '@/components/ui/sidebar';\nimport { useMail } from '@/components/sidebar-04/mail-context';\nimport { NavUser } from '@/components/sidebar-04/nav-user';\n\n// This is sample data\nconst data = {\n  user: {\n    name: 'ephraim',\n    email: 'ephraim@blocks.so',\n    avatar: '/avatar-01.png',\n  },\n  navMain: [\n    {\n      title: 'Inbox',\n      url: '#',\n      icon: IconMailbox,\n      isActive: true,\n    },\n    {\n      title: 'Starred',\n      url: '#',\n      icon: IconCarambola,\n      isActive: false,\n    },\n    {\n      title: 'Important',\n      url: '#',\n      icon: Flag,\n      isActive: false,\n    },\n    {\n      title: 'Scheduled',\n      url: '#',\n      icon: IconHourglassHigh,\n      isActive: false,\n    },\n    {\n      title: 'Archive',\n      url: '#',\n      icon: Archive,\n      isActive: false,\n    },\n  ],\n  labels: [\n    { title: 'Personal', color: 'bg-green-400 dark:bg-green-300' },\n    { title: 'Work', color: 'bg-blue-400 dark:bg-blue-300' },\n    { title: 'Travel', color: 'bg-orange-400 dark:bg-orange-300' },\n    { title: 'Receipts', color: 'bg-purple-400 dark:bg-purple-300' },\n  ],\n  mails: [\n    {\n      name: 'Nora Patel',\n      email: 'nora@acme.co',\n      subject: 'Welcome to Acme Mail',\n      date: '08:15 AM',\n      teaser:\n        \"Hi there — here's a quick tour of your new inbox.\\nPin, label, and schedule messages to stay organized.\",\n    },\n    {\n      name: 'Stripe',\n      email: 'no-reply@stripe.com',\n      subject: 'Your payout has arrived',\n      date: 'Yesterday',\n      teaser:\n        'A payout of $3,245.90 was sent to your bank account.\\nView details in your dashboard.',\n    },\n    {\n      name: 'GitHub',\n      email: 'noreply@github.com',\n      subject: 'New activity on acme/app',\n      date: 'Tue',\n      teaser:\n        '3 pull requests need your review. CI passed on main.\\nClick to open the review queue.',\n    },\n    {\n      name: 'Ava Chen',\n      email: 'ava.chen@example.com',\n      subject: 'Agenda for Friday standup',\n      date: 'Mon',\n      teaser:\n        \"Let's cover onboarding, billing bugs, and Q4 goals.\\nReply with anything you want to add.\",\n    },\n    {\n      name: 'Figma',\n      email: 'updates@figma.com',\n      subject: \"What's new in Figma\",\n      date: 'Sep 12',\n      teaser:\n        'Variables, auto layout improvements, and dev mode updates.\\nWatch the recap to learn more.',\n    },\n    {\n      name: 'Linear',\n      email: 'bot@linear.app',\n      subject: '[ACME-432] Edit modal broken',\n      date: 'Sep 11',\n      teaser:\n        'Issue created by Wendy. Repro steps included.\\nSeverity: high, priority: P1.',\n    },\n    {\n      name: 'Airbnb',\n      email: 'booking@airbnb.com',\n      subject: 'Your trip to Kyoto',\n      date: 'Sep 10',\n      teaser:\n        'Get ready for your stay. Check-in details and local recommendations inside.',\n    },\n    {\n      name: 'Notion',\n      email: 'team@notion.so',\n      subject: 'Weekly team recap',\n      date: 'Sep 09',\n      teaser:\n        'Marketing shipped pricing page revamp. Eng closed 14 issues.\\nSee full notes in the doc.',\n    },\n    {\n      name: 'Google Calendar',\n      email: 'calendar@google.com',\n      subject: 'Design sync moved',\n      date: 'Sep 09',\n      teaser:\n        \"Event 'Design sync' moved to 3:30 PM. Meet link updated in the invite.\",\n    },\n    {\n      name: 'HN Daily',\n      email: 'digest@ycombinator.com',\n      subject: 'Top stories today',\n      date: 'Sep 08',\n      teaser:\n        'OpenAI releases new API, SQLite 3.46, and why we left Kubernetes.\\nRead the full digest.',\n    },\n  ],\n};\n\nexport function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {\n  // Note: I'm using state to show active item.\n  // IRL you should use the url/router.\n  const [activeItem, setActiveItem] = React.useState(data.navMain[0]);\n  const [mails, setMails] = React.useState(data.mails);\n  const [query, setQuery] = React.useState('');\n  const { setOpen } = useSidebar();\n  const { setSelectedMail } = useMail();\n\n  const filteredMails = React.useMemo(() => {\n    const q = query.trim().toLowerCase();\n    if (!q) return mails;\n    return mails.filter((m) =>\n      [m.name, m.email, m.subject, m.teaser]\n        .join('\\n')\n        .toLowerCase()\n        .includes(q)\n    );\n  }, [mails, query]);\n\n  return (\n    <div className=\"flex\">\n      {/* This is the first sidebar */}\n      <Sidebar\n        className=\"border-r p-2 px-1\"\n        collapsible=\"none\"\n        style={{ '--sidebar-width': '12rem' } as React.CSSProperties}\n      >\n        <SidebarHeader>\n          <SidebarMenu>\n            <SidebarMenuItem>\n              <SidebarMenuButton\n                className=\"md:h-8 md:p-0\"\n                render={<a href=\"#\" />}\n                size=\"lg\"\n              >\n                <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-accent text-sidebar-accent-foreground\">\n                  <IconBrandAmongUs className=\"size-4\" />\n                </div>\n                <div className=\"grid flex-1 text-left text-sm leading-tight\">\n                  <span className=\"truncate font-medium\">Acme Inc</span>\n                  <span className=\"truncate text-xs\">Enterprise</span>\n                </div>\n              </SidebarMenuButton>\n            </SidebarMenuItem>\n          </SidebarMenu>\n        </SidebarHeader>\n        <SidebarContent>\n          <SidebarGroup>\n            <SidebarGroupContent className=\"px-1.5 md:px-0\">\n              <SidebarMenu>\n                {data.navMain.map((item) => (\n                  <SidebarMenuItem key={item.title}>\n                    <SidebarMenuButton\n                      className=\"px-2.5 md:px-2\"\n                      isActive={activeItem?.title === item.title}\n                      onClick={() => {\n                        setActiveItem(item);\n                        const mail = data.mails.sort(() => Math.random() - 0.5);\n                        setMails(\n                          mail.slice(\n                            0,\n                            Math.max(5, Math.floor(Math.random() * 10) + 1)\n                          )\n                        );\n                        setOpen(true);\n                      }}\n                    >\n                      <item.icon />\n                      <span>{item.title}</span>\n                    </SidebarMenuButton>\n                  </SidebarMenuItem>\n                ))}\n              </SidebarMenu>\n            </SidebarGroupContent>\n          </SidebarGroup>\n          <SidebarGroup>\n            <SidebarGroupLabel className=\"px-1.5 text-xs md:px-0\">\n              Labels\n            </SidebarGroupLabel>\n            <SidebarGroupContent className=\"px-1.5 md:px-0\">\n              <SidebarMenu>\n                {data.labels.map((label) => (\n                  <SidebarMenuItem key={label.title}>\n                    <SidebarMenuButton\n                      className=\"px-2.5 md:px-2\"\n                      render={<div className=\"flex items-center gap-3\" />}\n                    >\n                      <div className={`h-3 w-3 rounded ${label.color}`} />\n                      <span>{label.title}</span>\n                    </SidebarMenuButton>\n                  </SidebarMenuItem>\n                ))}\n              </SidebarMenu>\n            </SidebarGroupContent>\n          </SidebarGroup>\n        </SidebarContent>\n        <SidebarFooter>\n          <NavUser user={data.user} />\n        </SidebarFooter>\n      </Sidebar>\n\n      {/* This is the second sidebar */}\n      {/* We disable collapsible and let it fill remaining space */}\n      <Sidebar\n        className=\"hidden min-w-96 flex-1 border-r md:flex\"\n        collapsible=\"none\"\n      >\n        <SidebarHeader className=\"gap-3.5 border-b p-4\">\n          <div className=\"flex w-full items-center justify-between\">\n            <div className=\"font-medium text-base text-foreground\">\n              {activeItem?.title}\n            </div>\n          </div>\n          <SidebarInput\n            onChange={(e) => setQuery(e.target.value)}\n            placeholder=\"Type to search...\"\n            value={query}\n          />\n        </SidebarHeader>\n        <SidebarContent>\n          <SidebarGroup className=\"px-0 pt-0\">\n            <SidebarGroupContent>\n              {filteredMails.length === 0 && (\n                <div className=\"p-4 text-muted-foreground text-sm\">\n                  No results\n                </div>\n              )}\n              {filteredMails.map((mail) => (\n                <a\n                  className=\"flex flex-col items-start gap-2 whitespace-nowrap border-b p-4 text-sm leading-tight hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\"\n                  href=\"#\"\n                  key={mail.email}\n                  onClick={(e) => {\n                    e.preventDefault();\n                    setSelectedMail(mail);\n                  }}\n                >\n                  <div className=\"flex w-full items-center gap-2\">\n                    <span>{mail.name}</span>{' '}\n                    <span className=\"ml-auto text-xs\">{mail.date}</span>\n                  </div>\n                  <span className=\"font-medium\">{mail.subject}</span>\n                  <span className=\"line-clamp-2 w-[260px] whitespace-break-spaces text-xs\">\n                    {mail.teaser}\n                  </span>\n                </a>\n              ))}\n            </SidebarGroupContent>\n          </SidebarGroup>\n        </SidebarContent>\n      </Sidebar>\n    </div>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-04/app/page.tsx",
          "type": "registry:page",
          "target": "app/page.tsx",
          "content": "'use client';\n\nimport { SidebarInset, SidebarProvider } from '@/components/ui/sidebar';\nimport { AppSidebar } from '@/components/sidebar-04/app-sidebar';\nimport { MailProvider, useMail } from '@/components/sidebar-04/mail-context';\n\nfunction MailPreview() {\n  const { selectedMail } = useMail();\n  if (!selectedMail) {\n    return (\n      <div className=\"flex h-full items-center justify-center text-muted-foreground text-sm\">\n        Select an email to preview\n      </div>\n    );\n  }\n  return (\n    <div className=\"flex h-full flex-col\">\n      <div className=\"border-b p-4\">\n        <div className=\"font-semibold text-lg\">{selectedMail.subject}</div>\n        <div className=\"text-muted-foreground text-sm\">\n          From: {selectedMail.name} ({selectedMail.email})\n        </div>\n      </div>\n      <div className=\"whitespace-pre-wrap p-4 text-sm\">{`${selectedMail.teaser}\\n\\nThis is a sample message body for the selected email.\\nIt demonstrates the preview area on the right side.`}</div>\n    </div>\n  );\n}\n\nexport default function Page() {\n  return (\n    <SidebarProvider>\n      <MailProvider>\n        <div className=\"flex h-dvh w-full\">\n          <AppSidebar />\n          <SidebarInset>\n            <div className=\"m-2 flex-1 rounded-xl border\">\n              <MailPreview />\n            </div>\n          </SidebarInset>\n        </div>\n      </MailProvider>\n    </SidebarProvider>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-04/mail-context.tsx",
          "type": "registry:component",
          "target": "components/sidebar-04/mail-context.tsx",
          "content": "'use client';\n\nimport * as React from 'react';\n\nexport type Mail = {\n  name: string;\n  email: string;\n  subject: string;\n  date: string;\n  teaser: string;\n  labels?: string[];\n};\n\ntype MailContextValue = {\n  selectedMail: Mail | null;\n  setSelectedMail: (mail: Mail | null) => void;\n};\n\nconst MailContext = React.createContext<MailContextValue | undefined>(\n  undefined\n);\n\nexport function MailProvider({ children }: { children: React.ReactNode }) {\n  const [selectedMail, setSelectedMail] = React.useState<Mail | null>(null);\n  const value = React.useMemo(\n    () => ({ selectedMail, setSelectedMail }),\n    [selectedMail]\n  );\n  return <MailContext.Provider value={value}>{children}</MailContext.Provider>;\n}\n\nexport function useMail() {\n  const ctx = React.useContext(MailContext);\n  if (!ctx) throw new Error('useMail must be used within MailProvider');\n  return ctx;\n}\n"
        }
      ],
      "categories": [
        "sidebar"
      ]
    },
    {
      "name": "sidebar-05",
      "type": "registry:block",
      "title": "Sidebar Double-Sided",
      "description": "A sidebar double-sided block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "avatar",
        "dropdown-menu",
        "sidebar"
      ],
      "dependencies": [
        "@tabler/icons-react",
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/sidebar/sidebar-05/app-sidebar.tsx",
          "type": "registry:component",
          "target": "components/sidebar-05/app-sidebar.tsx",
          "content": "'use client';\n\nimport {\n  IconActivityHeartbeat,\n  IconArchive,\n  IconBackground,\n  IconBellRinging,\n  IconBrandGoogle,\n  IconBrandMeta,\n  IconBrandNpm,\n  IconBrandOpenai,\n  IconBug,\n  IconChartBar,\n  IconChevronRight,\n  IconCloud,\n  IconDatabase,\n  IconFileText,\n  IconFolder,\n  IconFolders,\n  IconGitCommit,\n  IconGitMerge,\n  IconGitPullRequest,\n  IconHome,\n  IconKey,\n  IconLockExclamation,\n  IconLockPassword,\n  IconLogout,\n  IconNorthStar,\n  IconPackageExport,\n  IconPackages,\n  IconPasswordFingerprint,\n  IconPlayerPlay,\n  IconScanEye,\n  IconSettings,\n  IconShieldLock,\n  IconStar,\n  IconTarget,\n  IconTerminal2,\n  IconUser,\n  IconUserPlus,\n  IconWebhook,\n  IconX,\n} from '@tabler/icons-react';\nimport type React from 'react';\nimport { useState } from 'react';\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';\nimport {\n  Sidebar,\n  SidebarContent,\n  SidebarFooter,\n  SidebarGroup,\n  SidebarGroupContent,\n  SidebarHeader,\n  SidebarMenu,\n  SidebarMenuBadge,\n  SidebarMenuButton,\n  SidebarMenuItem,\n} from '@/components/ui/sidebar';\nimport { cn } from '@/lib/utils';\nimport { TeamSwitcher } from '@/components/sidebar-05/team-switcher';\n\nconst data = {\n  teams: [\n    {\n      name: 'OpenAI',\n      logo: IconBrandOpenai,\n      plan: 'Enterprise',\n    },\n    {\n      name: 'Anthropic',\n      logo: IconNorthStar,\n      plan: 'Pro',\n    },\n    {\n      name: 'Google',\n      logo: IconBrandGoogle,\n      plan: 'Free',\n    },\n    {\n      name: 'Meta',\n      logo: IconBrandMeta,\n      plan: 'Free',\n    },\n  ],\n};\n\ninterface SidebarItem {\n  id: string;\n  label: string;\n  icon: React.ComponentType<{ className?: string }>;\n  badge?: string;\n  hasSubItems?: boolean;\n  route?: string;\n  subItems?: {\n    id: string;\n    label: string;\n    icon: React.ComponentType<{ className?: string }>;\n    description?: string;\n    route?: string;\n  }[];\n}\n\nconst sidebarItems: SidebarItem[] = [\n  {\n    id: 'overview',\n    label: 'Overview',\n    icon: IconHome,\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'dashboard',\n        label: 'Dashboard',\n        icon: IconChartBar,\n        description: 'Project overview and activity',\n        route: '/overview/dashboard',\n      },\n      {\n        id: 'activity',\n        label: 'Activity',\n        icon: IconActivityHeartbeat,\n        description: 'Recent commits and changes',\n        route: '/overview/activity',\n      },\n      {\n        id: 'insights',\n        label: 'Insights',\n        icon: IconTarget,\n        description: 'Code analytics and metrics',\n        route: '/overview/insights',\n      },\n    ],\n  },\n  {\n    id: 'repositories',\n    label: 'Repositories',\n    icon: IconFolders,\n    badge: '12',\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'all-repos',\n        label: 'All Repositories',\n        icon: IconFolder,\n        description: 'Browse all your repositories',\n        route: '/repositories',\n      },\n      {\n        id: 'starred',\n        label: 'Starred',\n        icon: IconStar,\n        description: 'Your starred repositories',\n        route: '/repositories/starred',\n      },\n      {\n        id: 'archived',\n        label: 'Archived',\n        icon: IconArchive,\n        description: 'Archived repositories',\n        route: '/repositories/archived',\n      },\n    ],\n  },\n  {\n    id: 'pull-requests',\n    label: 'Pull Requests',\n    icon: IconGitPullRequest,\n    badge: '3',\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'open-prs',\n        label: 'Open',\n        icon: IconGitPullRequest,\n        description: 'Open pull requests',\n        route: '/pull-requests/open',\n      },\n      {\n        id: 'review-requests',\n        label: 'Review Requests',\n        icon: IconScanEye,\n        description: 'PRs awaiting your review',\n        route: '/pull-requests/review',\n      },\n      {\n        id: 'merged',\n        label: 'Merged',\n        icon: IconGitMerge,\n        description: 'Recently merged PRs',\n        route: '/pull-requests/merged',\n      },\n    ],\n  },\n  {\n    id: 'issues',\n    label: 'Issues',\n    icon: IconBug,\n    badge: '7',\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'open-issues',\n        label: 'Open Issues',\n        icon: IconBug,\n        description: 'Active issues and bugs',\n        route: '/issues/open',\n      },\n      {\n        id: 'assigned',\n        label: 'Assigned to Me',\n        icon: IconUserPlus,\n        description: 'Issues assigned to you',\n        route: '/issues/assigned',\n      },\n      {\n        id: 'created',\n        label: 'Created by Me',\n        icon: IconGitCommit,\n        description: \"Issues you've created\",\n        route: '/issues/created',\n      },\n    ],\n  },\n  {\n    id: 'actions',\n    label: 'Actions',\n    icon: IconBackground,\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'workflows',\n        label: 'Workflows',\n        icon: IconPlayerPlay,\n        description: 'CI/CD workflows and pipelines',\n        route: '/actions/workflows',\n      },\n      {\n        id: 'runners',\n        label: 'Runners',\n        icon: IconTerminal2,\n        description: 'Self-hosted runners',\n        route: '/actions/runners',\n      },\n      {\n        id: 'deployments',\n        label: 'Deployments',\n        icon: IconCloud,\n        description: 'Deployment history',\n        route: '/actions/deployments',\n      },\n    ],\n  },\n  {\n    id: 'packages',\n    label: 'Packages',\n    icon: IconPackages,\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'published',\n        label: 'Published',\n        icon: IconPackageExport,\n        description: 'Your published packages',\n        route: '/packages/published',\n      },\n      {\n        id: 'container-registry',\n        label: 'Container Registry',\n        icon: IconDatabase,\n        description: 'Docker images and containers',\n        route: '/packages/containers',\n      },\n      {\n        id: 'npm-packages',\n        label: 'npm Packages',\n        icon: IconBrandNpm,\n        description: 'Node.js packages',\n        route: '/packages/npm',\n      },\n    ],\n  },\n  {\n    id: 'security',\n    label: 'Security',\n    icon: IconLockPassword,\n    badge: '2',\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'alerts',\n        label: 'Security Alerts',\n        icon: IconLockExclamation,\n        description: 'Vulnerability alerts',\n        route: '/security/alerts',\n      },\n      {\n        id: 'advisories',\n        label: 'Advisories',\n        icon: IconShieldLock,\n        description: 'Security advisories',\n        route: '/security/advisories',\n      },\n      {\n        id: 'secrets',\n        label: 'Secrets',\n        icon: IconPasswordFingerprint,\n        description: 'Repository secrets',\n        route: '/security/secrets',\n      },\n    ],\n  },\n  {\n    id: 'settings',\n    label: 'Settings',\n    icon: IconSettings,\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'profile',\n        label: 'Profile',\n        icon: IconUser,\n        description: 'Your profile settings',\n        route: '/settings/profile',\n      },\n      {\n        id: 'notifications',\n        label: 'Notifications',\n        icon: IconBellRinging,\n        description: 'Notification preferences',\n        route: '/settings/notifications',\n      },\n      {\n        id: 'webhooks',\n        label: 'Webhooks',\n        icon: IconWebhook,\n        description: 'Webhook configurations',\n        route: '/settings/webhooks',\n      },\n      {\n        id: 'api-keys',\n        label: 'API Keys',\n        icon: IconKey,\n        description: 'Personal access tokens',\n        route: '/settings/api-keys',\n      },\n    ],\n  },\n  {\n    id: 'docs',\n    label: 'Documentation',\n    icon: IconFileText,\n    hasSubItems: false,\n    route: '/docs',\n  },\n];\n\nexport function AppSidebar() {\n  const [activeItem, setActiveItem] = useState<string | null>('overview');\n  const [selectedSubItem, setSelectedSubItem] = useState<string | null>(null);\n\n  const activeItemData = sidebarItems.find((item) => item.id === activeItem);\n\n  const handleItemClick = (item: SidebarItem) => {\n    if (item.hasSubItems) {\n      const isActive = activeItem === item.id;\n      setActiveItem(isActive ? null : item.id);\n      if (isActive) {\n        setSelectedSubItem(null);\n      }\n    } else {\n      if (activeItem) {\n        setActiveItem(null);\n        setSelectedSubItem(null);\n      }\n      console.log(`[v0] Navigating to: ${item.route}`);\n    }\n  };\n\n  const handleSubItemClick = (subItem: { id: string; route?: string }) => {\n    setSelectedSubItem(selectedSubItem === subItem.id ? null : subItem.id);\n    if (subItem.route) {\n      console.log(`[v0] Navigating to: ${subItem.route}`);\n    }\n  };\n\n  return (\n    <div className=\"flex h-dvh bg-background\">\n      <Sidebar\n        className=\"w-64 border-r\"\n        collapsible=\"none\"\n        side=\"left\"\n        variant=\"sidebar\"\n      >\n        <SidebarHeader>\n          <TeamSwitcher teams={data.teams} />\n        </SidebarHeader>\n\n        <SidebarContent>\n          <SidebarGroup>\n            <SidebarGroupContent>\n              <SidebarMenu>\n                {sidebarItems.map((item) => {\n                  const Icon = item.icon;\n                  const isActive = activeItem === item.id;\n                  const chevronIndicator = (\n                    <IconChevronRight\n                      className={cn(\n                        'h-4 w-4 shrink-0 transition-transform',\n                        isActive && 'rotate-90'\n                      )}\n                    />\n                  );\n\n                  return (\n                    <SidebarMenuItem key={item.id}>\n                      <SidebarMenuButton\n                        className=\"h-10 w-full px-3\"\n                        isActive={isActive}\n                        onClick={() => handleItemClick(item)}\n                      >\n                        <div className=\"flex min-w-0 flex-1 items-center gap-3\">\n                          <Icon className=\"h-4 w-4 shrink-0\" />\n                          <span className=\"truncate\">{item.label}</span>\n                        </div>\n                        <div className=\"ml-auto flex min-w-fit shrink-0 items-center gap-1\">\n                          {(item.badge || item.hasSubItems) &&\n                            (item.badge ? (\n                              <SidebarMenuBadge\n                                className={cn(\n                                  'min-w-fit',\n                                  item.hasSubItems && 'gap-x-3'\n                                )}\n                              >\n                                {item.badge}\n                                {item.hasSubItems && chevronIndicator}\n                              </SidebarMenuBadge>\n                            ) : (\n                              chevronIndicator\n                            ))}\n                        </div>\n                      </SidebarMenuButton>\n                    </SidebarMenuItem>\n                  );\n                })}\n              </SidebarMenu>\n            </SidebarGroupContent>\n          </SidebarGroup>\n        </SidebarContent>\n\n        <SidebarFooter>\n          <SidebarMenu>\n            <SidebarMenuItem>\n              <SidebarMenuButton className=\"h-12 w-full px-3\">\n                <div className=\"flex min-w-0 flex-1 items-center gap-3\">\n                  <Avatar className=\"h-8 w-8 rounded-full\">\n                    <AvatarImage alt=\"ephraim\" src=\"/avatar-01.png\" />\n                    <AvatarFallback className=\"rounded-full\">E</AvatarFallback>\n                  </Avatar>\n                  <div className=\"min-w-0 flex-1 text-left\">\n                    <div className=\"truncate font-medium text-sm\">ephraim</div>\n                    <div className=\"truncate text-muted-foreground text-xs\">\n                      ephraim@blocks.so\n                    </div>\n                  </div>\n                </div>\n                <IconLogout className=\"h-4 w-4 shrink-0\" />\n              </SidebarMenuButton>\n            </SidebarMenuItem>\n          </SidebarMenu>\n        </SidebarFooter>\n      </Sidebar>\n\n      {activeItem && activeItemData?.subItems && (\n        <Sidebar\n          className=\"slide-in-from-left-5 w-72 animate-in border-r duration-200\"\n          collapsible=\"none\"\n          side=\"left\"\n          variant=\"sidebar\"\n        >\n          <SidebarHeader className=\"flex flex-row items-center justify-between border-b px-4\">\n            <h3 className=\"font-medium\">{activeItemData.label}</h3>\n            <button\n              className=\"flex h-6 w-6 items-center justify-center rounded-md p-0 hover:bg-sidebar-accent\"\n              onClick={() => setActiveItem(null)}\n            >\n              <IconX className=\"h-4 w-4\" />\n            </button>\n          </SidebarHeader>\n\n          <SidebarContent>\n            <SidebarGroup>\n              <SidebarGroupContent>\n                <SidebarMenu>\n                  {activeItemData.subItems.map((subItem) => {\n                    const SubIcon = subItem.icon;\n                    const isSelected = selectedSubItem === subItem.id;\n\n                    return (\n                      <SidebarMenuItem key={subItem.id}>\n                        <SidebarMenuButton\n                          className=\"h-auto w-full justify-start gap-3 px-3 py-2\"\n                          isActive={isSelected}\n                          onClick={() => handleSubItemClick(subItem)}\n                        >\n                          <SubIcon className=\"mt-0.5 h-5 w-5 shrink-0 self-start\" />\n\n                          <div className=\"min-w-0 flex-1 text-left\">\n                            <div className=\"font-medium\">{subItem.label}</div>\n                            {subItem.description && (\n                              <div className=\"mt-0.5 text-muted-foreground text-xs\">\n                                {subItem.description}\n                              </div>\n                            )}\n                          </div>\n                        </SidebarMenuButton>\n                      </SidebarMenuItem>\n                    );\n                  })}\n                </SidebarMenu>\n              </SidebarGroupContent>\n            </SidebarGroup>\n          </SidebarContent>\n        </Sidebar>\n      )}\n    </div>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-05/app/page.tsx",
          "type": "registry:page",
          "target": "app/page.tsx",
          "content": "'use client';\n\nimport { SidebarProvider } from '@/components/ui/sidebar';\nimport { AppSidebar } from '@/components/sidebar-05/app-sidebar';\n\nexport default function Page() {\n  return (\n    <SidebarProvider>\n      <div className=\"flex h-dvh w-full\">\n        <AppSidebar />\n      </div>\n    </SidebarProvider>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-05/team-switcher.tsx",
          "type": "registry:component",
          "target": "components/sidebar-05/team-switcher.tsx",
          "content": "'use client';\n\nimport { ChevronsUpDown, Plus } from 'lucide-react';\nimport * as React from 'react';\n\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport {\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  useSidebar,\n} from '@/components/ui/sidebar';\n\nexport function TeamSwitcher({\n  teams,\n}: {\n  teams: {\n    name: string;\n    logo: React.ElementType;\n    plan: string;\n  }[];\n}) {\n  const { isMobile } = useSidebar();\n  const [activeTeam, setActiveTeam] = React.useState(teams[0]);\n\n  if (!activeTeam) {\n    return null;\n  }\n\n  return (\n    <SidebarMenu>\n      <SidebarMenuItem>\n        <DropdownMenu>\n          <DropdownMenuTrigger\n            render={\n              <SidebarMenuButton\n                className=\"data-popup-open:bg-sidebar-accent data-popup-open:text-sidebar-accent-foreground\"\n                size=\"lg\"\n              />\n            }\n          >\n            <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-accent text-sidebar-accent-foreground\">\n              <activeTeam.logo className=\"size-4\" />\n            </div>\n            <div className=\"grid flex-1 text-left text-sm leading-tight\">\n              <span className=\"truncate font-medium\">{activeTeam.name}</span>\n              <span className=\"truncate text-xs\">{activeTeam.plan}</span>\n            </div>\n            <ChevronsUpDown className=\"ml-auto\" />\n          </DropdownMenuTrigger>\n          <DropdownMenuContent\n            align=\"start\"\n            className=\"w-(--anchor-width) min-w-56 rounded-lg\"\n            side={isMobile ? 'bottom' : 'right'}\n            sideOffset={4}\n          >\n            <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n              Teams\n            </DropdownMenuLabel>\n            {teams.map((team, index) => (\n              <DropdownMenuItem\n                className=\"gap-2 p-2\"\n                key={team.name}\n                onClick={() => setActiveTeam(team)}\n              >\n                <div className=\"flex size-6 items-center justify-center rounded-md border\">\n                  <team.logo className=\"size-3.5 shrink-0\" />\n                </div>\n                {team.name}\n                <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>\n              </DropdownMenuItem>\n            ))}\n            <DropdownMenuSeparator />\n            <DropdownMenuItem className=\"gap-2 p-2\">\n              <div className=\"flex size-6 items-center justify-center rounded-md border bg-transparent\">\n                <Plus className=\"size-4\" />\n              </div>\n              <div className=\"font-medium text-muted-foreground\">Add team</div>\n            </DropdownMenuItem>\n          </DropdownMenuContent>\n        </DropdownMenu>\n      </SidebarMenuItem>\n    </SidebarMenu>\n  );\n}\n"
        }
      ],
      "categories": [
        "sidebar"
      ]
    },
    {
      "name": "sidebar-06",
      "type": "registry:block",
      "title": "Sidebar Replacement",
      "description": "A sidebar replacement block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "avatar",
        "dropdown-menu",
        "sidebar"
      ],
      "dependencies": [
        "@tabler/icons-react",
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/sidebar/sidebar-06/app-sidebar.tsx",
          "type": "registry:component",
          "target": "components/sidebar-06/app-sidebar.tsx",
          "content": "'use client';\n\nimport {\n  IconActivityHeartbeat,\n  IconArchive,\n  IconArrowLeft,\n  IconBackground,\n  IconBellRinging,\n  IconBrandGoogle,\n  IconBrandMeta,\n  IconBrandNpm,\n  IconBrandOpenai,\n  IconBug,\n  IconChartBar,\n  IconChevronRight,\n  IconCloud,\n  IconDatabase,\n  IconFileText,\n  IconFolder,\n  IconFolders,\n  IconGitCommit,\n  IconGitMerge,\n  IconGitPullRequest,\n  IconHome,\n  IconKey,\n  IconLockExclamation,\n  IconLockPassword,\n  IconLogout,\n  IconNorthStar,\n  IconPackageExport,\n  IconPackages,\n  IconPasswordFingerprint,\n  IconPlayerPlay,\n  IconScanEye,\n  IconSettings,\n  IconShieldLock,\n  IconStar,\n  IconTarget,\n  IconTerminal2,\n  IconUser,\n  IconUserPlus,\n  IconWebhook,\n} from '@tabler/icons-react';\nimport type React from 'react';\nimport { useState } from 'react';\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';\nimport {\n  Sidebar,\n  SidebarContent,\n  SidebarFooter,\n  SidebarGroup,\n  SidebarGroupContent,\n  SidebarHeader,\n  SidebarMenu,\n  SidebarMenuBadge,\n  SidebarMenuButton,\n  SidebarMenuItem,\n} from '@/components/ui/sidebar';\nimport { cn } from '@/lib/utils';\nimport { TeamSwitcher } from '@/components/sidebar-06/team-switcher';\n\nconst data = {\n  teams: [\n    {\n      name: 'OpenAI',\n      logo: IconBrandOpenai,\n      plan: 'Enterprise',\n    },\n    {\n      name: 'Anthropic',\n      logo: IconNorthStar,\n      plan: 'Pro',\n    },\n    {\n      name: 'Google',\n      logo: IconBrandGoogle,\n      plan: 'Free',\n    },\n    {\n      name: 'Meta',\n      logo: IconBrandMeta,\n      plan: 'Free',\n    },\n  ],\n};\n\ninterface SidebarItem {\n  id: string;\n  label: string;\n  icon: React.ComponentType<{ className?: string }>;\n  badge?: string;\n  hasSubItems?: boolean;\n  route?: string;\n  subItems?: {\n    id: string;\n    label: string;\n    icon: React.ComponentType<{ className?: string }>;\n    route?: string;\n  }[];\n}\n\nconst sidebarItems: SidebarItem[] = [\n  {\n    id: 'overview',\n    label: 'Overview',\n    icon: IconHome,\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'dashboard',\n        label: 'Dashboard',\n        icon: IconChartBar,\n        route: '/overview/dashboard',\n      },\n      {\n        id: 'activity',\n        label: 'Activity',\n        icon: IconActivityHeartbeat,\n        route: '/overview/activity',\n      },\n      {\n        id: 'insights',\n        label: 'Insights',\n        icon: IconTarget,\n        route: '/overview/insights',\n      },\n    ],\n  },\n  {\n    id: 'repositories',\n    label: 'Repositories',\n    icon: IconFolders,\n    badge: '12',\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'all-repos',\n        label: 'All Repositories',\n        icon: IconFolder,\n        route: '/repositories',\n      },\n      {\n        id: 'starred',\n        label: 'Starred',\n        icon: IconStar,\n        route: '/repositories/starred',\n      },\n      {\n        id: 'archived',\n        label: 'Archived',\n        icon: IconArchive,\n        route: '/repositories/archived',\n      },\n    ],\n  },\n  {\n    id: 'pull-requests',\n    label: 'Pull Requests',\n    icon: IconGitPullRequest,\n    badge: '3',\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'open-prs',\n        label: 'Open',\n        icon: IconGitPullRequest,\n        route: '/pull-requests/open',\n      },\n      {\n        id: 'review-requests',\n        label: 'Review Requests',\n        icon: IconScanEye,\n        route: '/pull-requests/review',\n      },\n      {\n        id: 'merged',\n        label: 'Merged',\n        icon: IconGitMerge,\n        route: '/pull-requests/merged',\n      },\n    ],\n  },\n  {\n    id: 'issues',\n    label: 'Issues',\n    icon: IconBug,\n    badge: '7',\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'open-issues',\n        label: 'Open Issues',\n        icon: IconBug,\n        route: '/issues/open',\n      },\n      {\n        id: 'assigned',\n        label: 'Assigned to Me',\n        icon: IconUserPlus,\n        route: '/issues/assigned',\n      },\n      {\n        id: 'created',\n        label: 'Created by Me',\n        icon: IconGitCommit,\n        route: '/issues/created',\n      },\n    ],\n  },\n  {\n    id: 'actions',\n    label: 'Actions',\n    icon: IconBackground,\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'workflows',\n        label: 'Workflows',\n        icon: IconPlayerPlay,\n        route: '/actions/workflows',\n      },\n      {\n        id: 'runners',\n        label: 'Runners',\n        icon: IconTerminal2,\n        route: '/actions/runners',\n      },\n      {\n        id: 'deployments',\n        label: 'Deployments',\n        icon: IconCloud,\n        route: '/actions/deployments',\n      },\n    ],\n  },\n  {\n    id: 'packages',\n    label: 'Packages',\n    icon: IconPackages,\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'published',\n        label: 'Published',\n        icon: IconPackageExport,\n        route: '/packages/published',\n      },\n      {\n        id: 'container-registry',\n        label: 'Container Registry',\n        icon: IconDatabase,\n        route: '/packages/containers',\n      },\n      {\n        id: 'npm-packages',\n        label: 'npm Packages',\n        icon: IconBrandNpm,\n        route: '/packages/npm',\n      },\n    ],\n  },\n  {\n    id: 'security',\n    label: 'Security',\n    icon: IconLockPassword,\n    badge: '2',\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'alerts',\n        label: 'Security Alerts',\n        icon: IconLockExclamation,\n        route: '/security/alerts',\n      },\n      {\n        id: 'advisories',\n        label: 'Advisories',\n        icon: IconShieldLock,\n        route: '/security/advisories',\n      },\n      {\n        id: 'secrets',\n        label: 'Secrets',\n        icon: IconPasswordFingerprint,\n        route: '/security/secrets',\n      },\n    ],\n  },\n  {\n    id: 'settings',\n    label: 'Settings',\n    icon: IconSettings,\n    hasSubItems: true,\n    subItems: [\n      {\n        id: 'profile',\n        label: 'Profile',\n        icon: IconUser,\n        route: '/settings/profile',\n      },\n      {\n        id: 'notifications',\n        label: 'Notifications',\n        icon: IconBellRinging,\n        route: '/settings/notifications',\n      },\n      {\n        id: 'webhooks',\n        label: 'Webhooks',\n        icon: IconWebhook,\n        route: '/settings/webhooks',\n      },\n      {\n        id: 'api-keys',\n        label: 'API Keys',\n        icon: IconKey,\n        route: '/settings/api-keys',\n      },\n    ],\n  },\n  {\n    id: 'docs',\n    label: 'Documentation',\n    icon: IconFileText,\n    hasSubItems: false,\n    route: '/docs',\n  },\n];\n\nexport function AppSidebar() {\n  const [activeItem, setActiveItem] = useState<string | null>(null);\n  const [selectedSubItem, setSelectedSubItem] = useState<string | null>(null);\n\n  const activeItemData = sidebarItems.find((item) => item.id === activeItem);\n\n  const handleItemClick = (item: SidebarItem) => {\n    if (item.hasSubItems) {\n      setActiveItem(item.id);\n      setSelectedSubItem(null);\n    } else {\n      console.log(`[v0] Navigating to: ${item.route}`);\n    }\n  };\n\n  const handleSubItemClick = (subItem: { id: string; route?: string }) => {\n    setSelectedSubItem(selectedSubItem === subItem.id ? null : subItem.id);\n    if (subItem.route) {\n      console.log(`[v0] Navigating to: ${subItem.route}`);\n    }\n  };\n\n  const handleBackToMain = () => {\n    setActiveItem(null);\n    setSelectedSubItem(null);\n  };\n\n  return (\n    <div className=\"flex h-dvh bg-background\">\n      <Sidebar\n        className=\"w-64 border-r\"\n        collapsible=\"none\"\n        side=\"left\"\n        variant=\"sidebar\"\n      >\n        {activeItem ? (\n          activeItemData?.subItems && (\n            <>\n              <SidebarHeader className=\"flex flex-row items-center justify-between border-b px-4\">\n                <button\n                  className=\"flex h-8 w-8 items-center justify-center rounded-md p-0 hover:bg-sidebar-accent\"\n                  onClick={handleBackToMain}\n                >\n                  <IconArrowLeft className=\"h-4 w-4\" />\n                </button>\n                <h3 className=\"flex-1 text-center font-medium\">\n                  {activeItemData.label}\n                </h3>\n                <div className=\"w-8\" />\n              </SidebarHeader>\n\n              <SidebarContent>\n                <SidebarGroup>\n                  <SidebarGroupContent>\n                    <SidebarMenu>\n                      {activeItemData.subItems.map((subItem) => {\n                        const SubIcon = subItem.icon;\n                        const isSelected = selectedSubItem === subItem.id;\n\n                        return (\n                          <SidebarMenuItem key={subItem.id}>\n                            <SidebarMenuButton\n                              className=\"h-10 w-full px-3\"\n                              isActive={isSelected}\n                              onClick={() => handleSubItemClick(subItem)}\n                            >\n                              <div className=\"flex min-w-0 flex-1 items-center gap-3\">\n                                <SubIcon className=\"h-4 w-4 shrink-0\" />\n                                <span className=\"truncate\">\n                                  {subItem.label}\n                                </span>\n                              </div>\n                            </SidebarMenuButton>\n                          </SidebarMenuItem>\n                        );\n                      })}\n                    </SidebarMenu>\n                  </SidebarGroupContent>\n                </SidebarGroup>\n              </SidebarContent>\n            </>\n          )\n        ) : (\n          <>\n            <SidebarHeader>\n              <TeamSwitcher teams={data.teams} />\n            </SidebarHeader>\n\n            <SidebarContent>\n              <SidebarGroup>\n                <SidebarGroupContent>\n                  <SidebarMenu>\n                    {sidebarItems.map((item) => {\n                      const Icon = item.icon;\n                      const chevronIndicator = (\n                        <IconChevronRight className=\"h-4 w-4 shrink-0 transition-transform\" />\n                      );\n\n                      return (\n                        <SidebarMenuItem key={item.id}>\n                          <SidebarMenuButton\n                            className=\"h-10 w-full px-3\"\n                            onClick={() => handleItemClick(item)}\n                          >\n                            <div className=\"flex min-w-0 flex-1 items-center gap-3\">\n                              <Icon className=\"h-4 w-4 shrink-0\" />\n                              <span className=\"truncate\">{item.label}</span>\n                            </div>\n                            <div className=\"ml-auto flex min-w-fit shrink-0 items-center gap-1\">\n                              {(item.badge || item.hasSubItems) &&\n                                (item.badge ? (\n                                  <SidebarMenuBadge\n                                    className={cn(\n                                      'min-w-fit',\n                                      item.hasSubItems && 'gap-x-3'\n                                    )}\n                                  >\n                                    {item.badge}\n                                    {item.hasSubItems && chevronIndicator}\n                                  </SidebarMenuBadge>\n                                ) : (\n                                  chevronIndicator\n                                ))}\n                            </div>\n                          </SidebarMenuButton>\n                        </SidebarMenuItem>\n                      );\n                    })}\n                  </SidebarMenu>\n                </SidebarGroupContent>\n              </SidebarGroup>\n            </SidebarContent>\n\n            <SidebarFooter>\n              <SidebarMenu>\n                <SidebarMenuItem>\n                  <SidebarMenuButton className=\"h-12 w-full px-3\">\n                    <div className=\"flex min-w-0 flex-1 items-center gap-3\">\n                      <Avatar className=\"h-8 w-8 rounded-full\">\n                        <AvatarImage alt=\"ephraim\" src=\"/avatar-01.png\" />\n                        <AvatarFallback className=\"rounded-full\">\n                          E\n                        </AvatarFallback>\n                      </Avatar>\n                      <div className=\"min-w-0 flex-1 text-left\">\n                        <div className=\"truncate font-medium text-sm\">\n                          ephraim\n                        </div>\n                        <div className=\"truncate text-muted-foreground text-xs\">\n                          ephraim@blocks.so\n                        </div>\n                      </div>\n                    </div>\n                    <IconLogout className=\"h-4 w-4 shrink-0\" />\n                  </SidebarMenuButton>\n                </SidebarMenuItem>\n              </SidebarMenu>\n            </SidebarFooter>\n          </>\n        )}\n      </Sidebar>\n    </div>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-06/app/page.tsx",
          "type": "registry:page",
          "target": "app/page.tsx",
          "content": "'use client';\n\nimport { SidebarProvider } from '@/components/ui/sidebar';\nimport { AppSidebar } from '@/components/sidebar-06/app-sidebar';\n\nexport default function Page() {\n  return (\n    <SidebarProvider>\n      <div className=\"flex h-dvh w-full\">\n        <AppSidebar />\n      </div>\n    </SidebarProvider>\n  );\n}\n"
        },
        {
          "path": "content/components/sidebar/sidebar-06/team-switcher.tsx",
          "type": "registry:component",
          "target": "components/sidebar-06/team-switcher.tsx",
          "content": "'use client';\n\nimport { ChevronsUpDown, Plus } from 'lucide-react';\nimport * as React from 'react';\n\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport {\n  SidebarMenu,\n  SidebarMenuButton,\n  SidebarMenuItem,\n  useSidebar,\n} from '@/components/ui/sidebar';\n\nexport function TeamSwitcher({\n  teams,\n}: {\n  teams: {\n    name: string;\n    logo: React.ElementType;\n    plan: string;\n  }[];\n}) {\n  const { isMobile } = useSidebar();\n  const [activeTeam, setActiveTeam] = React.useState(teams[0]);\n\n  if (!activeTeam) {\n    return null;\n  }\n\n  return (\n    <SidebarMenu>\n      <SidebarMenuItem>\n        <DropdownMenu>\n          <DropdownMenuTrigger\n            render={\n              <SidebarMenuButton\n                className=\"data-popup-open:bg-sidebar-accent data-popup-open:text-sidebar-accent-foreground\"\n                size=\"lg\"\n              />\n            }\n          >\n            <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-accent text-sidebar-accent-foreground\">\n              <activeTeam.logo className=\"size-4\" />\n            </div>\n            <div className=\"grid flex-1 text-left text-sm leading-tight\">\n              <span className=\"truncate font-medium\">{activeTeam.name}</span>\n              <span className=\"truncate text-xs\">{activeTeam.plan}</span>\n            </div>\n            <ChevronsUpDown className=\"ml-auto\" />\n          </DropdownMenuTrigger>\n          <DropdownMenuContent\n            align=\"start\"\n            className=\"w-(--anchor-width) min-w-56 rounded-lg\"\n            side={isMobile ? 'bottom' : 'right'}\n            sideOffset={4}\n          >\n            <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n              Teams\n            </DropdownMenuLabel>\n            {teams.map((team, index) => (\n              <DropdownMenuItem\n                className=\"gap-2 p-2\"\n                key={team.name}\n                onClick={() => setActiveTeam(team)}\n              >\n                <div className=\"flex size-6 items-center justify-center rounded-md border\">\n                  <team.logo className=\"size-3.5 shrink-0\" />\n                </div>\n                {team.name}\n                <DropdownMenuShortcut>⌘{index + 1}</DropdownMenuShortcut>\n              </DropdownMenuItem>\n            ))}\n            <DropdownMenuSeparator />\n            <DropdownMenuItem className=\"gap-2 p-2\">\n              <div className=\"flex size-6 items-center justify-center rounded-md border bg-transparent\">\n                <Plus className=\"size-4\" />\n              </div>\n              <div className=\"font-medium text-muted-foreground\">Add team</div>\n            </DropdownMenuItem>\n          </DropdownMenuContent>\n        </DropdownMenu>\n      </SidebarMenuItem>\n    </SidebarMenu>\n  );\n}\n"
        }
      ],
      "categories": [
        "sidebar"
      ]
    },
    {
      "name": "stats-01",
      "type": "registry:block",
      "title": "Stats with Trending",
      "description": "A stats with trending block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "card"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/stats/stats-01.tsx",
          "type": "registry:component",
          "target": "components/stats-01.tsx",
          "content": "import { Card, CardContent } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\nconst data = [\n  {\n    name: 'Profit',\n    value: '$287,654.00',\n    change: '+8.32%',\n    changeType: 'positive',\n  },\n  {\n    name: 'Late payments',\n    value: '$9,435.00',\n    change: '-12.64%',\n    changeType: 'negative',\n  },\n  {\n    name: 'Pending orders',\n    value: '$173,229.00',\n    change: '+2.87%',\n    changeType: 'positive',\n  },\n  {\n    name: 'Operating costs',\n    value: '$52,891.00',\n    change: '-5.73%',\n    changeType: 'negative',\n  },\n];\n\nexport default function Stats01() {\n  return (\n    <div className=\"flex items-center justify-center p-10\">\n      <div className=\"mx-auto grid grid-cols-1 gap-px rounded-xl bg-border sm:grid-cols-2 lg:grid-cols-4\">\n        {data.map((stat, index) => (\n          <Card\n            className={cn(\n              'rounded-none border-0 py-0 shadow-none',\n              index === 0 && 'rounded-l-xl',\n              index === data.length - 1 && 'rounded-r-xl'\n            )}\n            key={stat.name}\n          >\n            <CardContent className=\"flex flex-wrap items-baseline justify-between gap-x-4 gap-y-2 p-4 sm:p-6\">\n              <div className=\"font-medium text-muted-foreground text-sm\">\n                {stat.name}\n              </div>\n              <div\n                className={cn(\n                  'font-medium text-xs tabular-nums',\n                  stat.changeType === 'positive'\n                    ? 'text-green-800 dark:text-green-400'\n                    : 'text-red-800 dark:text-red-400'\n                )}\n              >\n                {stat.change}\n              </div>\n              <div className=\"w-full flex-none font-medium text-3xl text-foreground tabular-nums tracking-tight\">\n                {stat.value}\n              </div>\n            </CardContent>\n          </Card>\n        ))}\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-02",
      "type": "registry:block",
      "title": "Stats with Borders",
      "description": "A stats with borders block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "badge",
        "card"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/stats/stats-02.tsx",
          "type": "registry:component",
          "target": "components/stats-02.tsx",
          "content": "import { TrendingDown, TrendingUp } from 'lucide-react';\nimport { Badge } from '@/components/ui/badge';\nimport { Card, CardContent, CardTitle } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\nconst stats = [\n  {\n    metric: 'Active Users',\n    current: '128,456',\n    previous: '115,789',\n    difference: '10.9%',\n    trend: 'up',\n  },\n  {\n    metric: 'Conversion Rate',\n    current: '5.32%',\n    previous: '6.18%',\n    difference: '0.86%',\n    trend: 'down',\n  },\n  {\n    metric: 'Avg. Session Duration',\n    current: '3m 42s',\n    previous: '3m 15s',\n    difference: '13.8%',\n    trend: 'up',\n  },\n];\n\nexport default function Stats02() {\n  return (\n    <div className=\"flex items-center justify-center p-10\">\n      <div className=\"grid grid-cols-1 divide-y divide-border overflow-hidden rounded-lg bg-border md:grid-cols-3 md:divide-x md:divide-y-0\">\n        {stats.map((item) => (\n          <Card\n            className=\"rounded-none border-0 py-0 shadow-sm\"\n            key={item.metric}\n          >\n            <CardContent className=\"p-4 sm:p-6\">\n              <CardTitle className=\"font-normal text-base\">\n                {item.metric}\n              </CardTitle>\n              <div className=\"mt-1 flex items-baseline gap-2 md:block lg:flex\">\n                <div className=\"flex items-baseline font-semibold text-2xl text-primary tabular-nums\">\n                  {item.current}\n                  <span className=\"ml-2 font-medium text-muted-foreground text-sm tabular-nums\">\n                    from {item.previous}\n                  </span>\n                </div>\n\n                <Badge\n                  className={cn(\n                    'inline-flex items-center px-1.5 py-0.5 ps-2.5 font-medium text-xs tabular-nums md:mt-2 lg:mt-0',\n                    item.trend === 'up'\n                      ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400'\n                      : 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400'\n                  )}\n                  variant=\"outline\"\n                >\n                  {item.trend === 'up' ? (\n                    <TrendingUp className=\"-ml-1 mr-0.5 h-5 w-5 shrink-0 self-center text-green-500\" />\n                  ) : (\n                    <TrendingDown className=\"-ml-1 mr-0.5 h-5 w-5 shrink-0 self-center text-red-500\" />\n                  )}\n\n                  <span className=\"sr-only\">\n                    {' '}\n                    {item.trend === 'up' ? 'Increased' : 'Decreased'} by{' '}\n                  </span>\n                  {item.difference}\n                </Badge>\n              </div>\n            </CardContent>\n          </Card>\n        ))}\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-03",
      "type": "registry:block",
      "title": "Stats with Card Layout",
      "description": "A stats with card layout block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "card"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/stats/stats-03.tsx",
          "type": "registry:component",
          "target": "components/stats-03.tsx",
          "content": "'use client';\n\nimport { Card, CardContent } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\nconst data = [\n  {\n    name: 'Unique visitors',\n    stat: '10,450',\n    change: '-12.5%',\n    changeType: 'negative',\n  },\n  {\n    name: 'Bounce rate',\n    stat: '56.1%',\n    change: '+1.8%',\n    changeType: 'positive',\n  },\n  {\n    name: 'Visit duration',\n    stat: '5.2min',\n    change: '+19.7%',\n    changeType: 'positive',\n  },\n  {\n    name: 'Conversion rate',\n    stat: '3.2%',\n    change: '-2.4%',\n    changeType: 'negative',\n  },\n];\n\nexport default function Stats03() {\n  return (\n    <div className=\"flex w-full items-center justify-center p-10\">\n      <dl className=\"grid w-full grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4\">\n        {data.map((item) => (\n          <Card className=\"p-6 py-4 shadow-2xs\" key={item.name}>\n            <CardContent className=\"p-0\">\n              <dt className=\"font-medium text-muted-foreground text-sm\">\n                {item.name}\n              </dt>\n              <dd className=\"mt-2 flex items-baseline space-x-2.5\">\n                <span className=\"font-semibold text-3xl text-foreground tabular-nums\">\n                  {item.stat}\n                </span>\n                <span\n                  className={cn(\n                    item.changeType === 'positive'\n                      ? 'text-green-800 dark:text-green-400'\n                      : 'text-red-800 dark:text-red-400',\n                    'font-medium text-sm'\n                  )}\n                >\n                  {item.change}\n                </span>\n              </dd>\n            </CardContent>\n          </Card>\n        ))}\n      </dl>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-04",
      "type": "registry:block",
      "title": "Stats with Badges",
      "description": "A stats with badges block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "badge",
        "card"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/stats/stats-04.tsx",
          "type": "registry:component",
          "target": "components/stats-04.tsx",
          "content": "'use client';\n\nimport { TrendingDown, TrendingUp } from 'lucide-react';\nimport { Badge } from '@/components/ui/badge';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\nconst data = [\n  {\n    name: 'Daily active users',\n    stat: '3,450',\n    change: '+12.1%',\n    changeType: 'positive',\n  },\n  {\n    name: 'Weekly sessions',\n    stat: '1,342',\n    change: '-9.8%',\n    changeType: 'negative',\n  },\n  {\n    name: 'Duration',\n    stat: '5.2min',\n    change: '+7.7%',\n    changeType: 'positive',\n  },\n];\n\nexport default function Stats04() {\n  return (\n    <div className=\"flex w-full items-center justify-center p-10\">\n      <dl className=\"grid w-full grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3\">\n        {data.map((item) => (\n          <Card className=\"w-full p-6 py-4 shadow-2xs\" key={item.name}>\n            <CardContent className=\"p-0\">\n              <div className=\"flex items-center justify-between\">\n                <dt className=\"font-medium text-muted-foreground text-sm\">\n                  {item.name}\n                </dt>\n                <Badge\n                  className={cn(\n                    'inline-flex items-center px-1.5 py-0.5 ps-2.5 font-medium text-xs',\n                    item.changeType === 'positive'\n                      ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400'\n                      : 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400'\n                  )}\n                  variant=\"outline\"\n                >\n                  {item.changeType === 'positive' ? (\n                    <TrendingUp className=\"-ml-1 mr-0.5 h-5 w-5 shrink-0 self-center text-green-500\" />\n                  ) : (\n                    <TrendingDown className=\"-ml-1 mr-0.5 h-5 w-5 shrink-0 self-center text-red-500\" />\n                  )}\n                  <span className=\"sr-only\">\n                    {' '}\n                    {item.changeType === 'positive' ? 'Increased' : 'Decreased'}{' '}\n                    by{' '}\n                  </span>\n                  {item.change}\n                </Badge>\n              </div>\n              <dd className=\"mt-2 font-semibold text-3xl text-foreground tabular-nums\">\n                {item.stat}\n              </dd>\n            </CardContent>\n          </Card>\n        ))}\n      </dl>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-05",
      "type": "registry:block",
      "title": "Stats with Links",
      "description": "A stats with links block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "card"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/stats/stats-05.tsx",
          "type": "registry:component",
          "target": "components/stats-05.tsx",
          "content": "'use client';\n\nimport { Card, CardContent, CardFooter } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\nconst data = [\n  {\n    name: 'Monthly recurring revenue',\n    value: '$34.1K',\n    change: '+6.1%',\n    changeType: 'positive',\n    href: '#',\n  },\n  {\n    name: 'Users',\n    value: '500.1K',\n    change: '+19.2%',\n    changeType: 'positive',\n    href: '#',\n  },\n  {\n    name: 'User growth',\n    value: '11.3%',\n    change: '-1.2%',\n    changeType: 'negative',\n    href: '#',\n  },\n];\n\nexport default function Stats05() {\n  return (\n    <div className=\"flex w-full items-center justify-center p-10\">\n      <dl className=\"grid w-full grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3\">\n        {data.map((item) => (\n          <Card className=\"gap-0 p-0 shadow-2xs\" key={item.name}>\n            <CardContent className=\"p-6\">\n              <dd className=\"flex items-start justify-between space-x-2\">\n                <span className=\"truncate text-muted-foreground text-sm\">\n                  {item.name}\n                </span>\n                <span\n                  className={cn(\n                    'font-medium text-sm',\n                    item.changeType === 'positive'\n                      ? 'text-emerald-700 dark:text-emerald-500'\n                      : 'text-red-700 dark:text-red-500'\n                  )}\n                >\n                  {item.change}\n                </span>\n              </dd>\n              <dd className=\"mt-1 font-semibold text-3xl text-foreground tabular-nums\">\n                {item.value}\n              </dd>\n            </CardContent>\n            <CardFooter className=\"flex justify-end border-border border-t p-0!\">\n              <a\n                className=\"px-6 py-3 font-medium text-primary text-sm hover:text-primary/90\"\n                href={item.href}\n              >\n                View more &#8594;\n              </a>\n            </CardFooter>\n          </Card>\n        ))}\n      </dl>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-06",
      "type": "registry:block",
      "title": "Stats with Status",
      "description": "A stats with status block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "card"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/stats/stats-06.tsx",
          "type": "registry:component",
          "target": "components/stats-06.tsx",
          "content": "'use client';\n\nimport { AlertTriangle, Check, ChevronRight, Eye } from 'lucide-react';\nimport Link from 'next/link';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\nconst data = [\n  {\n    name: 'Europe',\n    stat: '$10,023',\n    goalsAchieved: 3,\n    status: 'observe',\n    href: '#',\n  },\n  {\n    name: 'North America',\n    stat: '$14,092',\n    goalsAchieved: 5,\n    status: 'within',\n    href: '#',\n  },\n  {\n    name: 'Asia',\n    stat: '$113,232',\n    goalsAchieved: 1,\n    status: 'critical',\n    href: '#',\n  },\n];\n\nexport default function Stats06() {\n  return (\n    <div className=\"flex w-full items-center justify-center p-10\">\n      <dl className=\"grid w-full grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3\">\n        {data.map((item) => (\n          <Card className=\"relative p-6 shadow-2xs\" key={item.name}>\n            <CardContent className=\"p-0\">\n              <dt className=\"font-medium text-muted-foreground text-sm\">\n                {item.name}\n              </dt>\n              <dd className=\"font-semibold text-3xl text-foreground tabular-nums\">\n                {item.stat}\n              </dd>\n              <div className=\"group relative mt-6 flex items-center space-x-4 rounded-md bg-muted/60 p-2 hover:bg-muted\">\n                <div className=\"flex w-full items-center justify-between truncate\">\n                  <div className=\"flex items-center space-x-3\">\n                    <span\n                      className={cn(\n                        'flex h-9 w-9 shrink-0 items-center justify-center rounded',\n                        item.status === 'within'\n                          ? 'bg-emerald-500 text-white'\n                          : item.status === 'observe'\n                            ? 'bg-yellow-500 text-white'\n                            : 'bg-red-500 text-white'\n                      )}\n                    >\n                      {item.status === 'within' ? (\n                        <Check aria-hidden={true} className=\"size-4 shrink-0\" />\n                      ) : item.status === 'observe' ? (\n                        <Eye aria-hidden={true} className=\"size-4 shrink-0\" />\n                      ) : (\n                        <AlertTriangle\n                          aria-hidden={true}\n                          className=\"size-4 shrink-0\"\n                        />\n                      )}\n                    </span>\n                    <dd>\n                      <p className=\"text-pretty text-muted-foreground text-sm\">\n                        <Link className=\"focus:outline-none\" href={item.href}>\n                          {/* Extend link to entire card */}\n                          <span\n                            aria-hidden={true}\n                            className=\"absolute inset-0\"\n                          />\n                          {item.goalsAchieved}/5 goals\n                        </Link>\n                      </p>\n                      <p\n                        className={cn(\n                          'font-medium text-sm',\n                          item.status === 'within'\n                            ? 'text-emerald-800 dark:text-emerald-500'\n                            : item.status === 'observe'\n                              ? 'text-yellow-800 dark:text-yellow-500'\n                              : 'text-red-800 dark:text-red-500'\n                        )}\n                      >\n                        {item.status}\n                      </p>\n                    </dd>\n                  </div>\n                  <ChevronRight\n                    aria-hidden={true}\n                    className=\"size-5 shrink-0 text-muted-foreground/60 group-hover:text-muted-foreground\"\n                  />\n                </div>\n              </div>\n            </CardContent>\n          </Card>\n        ))}\n      </dl>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-07",
      "type": "registry:block",
      "title": "Stats with Circular Progress",
      "description": "A stats with circular progress block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "card",
        "chart"
      ],
      "dependencies": [
        "lucide-react",
        "recharts"
      ],
      "files": [
        {
          "path": "content/components/stats/stats-07.tsx",
          "type": "registry:component",
          "target": "components/stats-07.tsx",
          "content": "'use client';\n\nimport { ExternalLink } from 'lucide-react';\nimport Link from 'next/link';\nimport { PolarAngleAxis, RadialBar, RadialBarChart } from 'recharts';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { type ChartConfig, ChartContainer } from '@/components/ui/chart';\n\nconst data = [\n  {\n    name: 'Workspaces',\n    capacity: 20,\n    current: 1,\n    allowed: 5,\n    fill: 'var(--chart-1)',\n  },\n  {\n    name: 'Dashboards',\n    capacity: 10,\n    current: 2,\n    allowed: 20,\n    fill: 'var(--chart-2)',\n  },\n  {\n    name: 'Chart widgets',\n    capacity: 30,\n    current: 15,\n    allowed: 50,\n    fill: 'var(--chart-3)',\n  },\n  {\n    name: 'Storage',\n    capacity: 50,\n    current: 25,\n    allowed: 100,\n    fill: 'var(--chart-4)',\n  },\n];\n\nconst chartConfig = {\n  capacity: {\n    label: 'Capacity',\n    color: 'hsl(var(--primary))',\n  },\n} satisfies ChartConfig;\n\nexport default function Stats07() {\n  return (\n    <div className=\"flex w-full items-center justify-center p-10\">\n      <div className=\"w-full\">\n        <h2 className=\"text-balance font-medium text-foreground text-xl\">\n          Plan overview\n        </h2>\n        <p className=\"mt-1 text-pretty text-muted-foreground text-sm leading-6\">\n          You are currently on the{' '}\n          <span className=\"font-medium text-foreground\">starter plan</span>.{' '}\n          <Link\n            className=\"inline-flex items-center gap-1 text-primary hover:underline hover:underline-offset-4\"\n            href=\"#\"\n          >\n            View other plans\n            <ExternalLink aria-hidden={true} className=\"size-4\" />\n          </Link>\n        </p>\n        <dl className=\"mt-6 grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4\">\n          {data.map((item) => (\n            <Card className=\"p-4 shadow-2xs\" key={item.name}>\n              <CardContent className=\"flex items-center space-x-4 p-0\">\n                <div className=\"relative flex items-center justify-center\">\n                  <ChartContainer\n                    className=\"h-[80px] w-[80px]\"\n                    config={chartConfig}\n                  >\n                    <RadialBarChart\n                      barSize={6}\n                      data={[item]}\n                      endAngle={-270}\n                      innerRadius={30}\n                      outerRadius={60}\n                      startAngle={90}\n                    >\n                      <PolarAngleAxis\n                        angleAxisId={0}\n                        axisLine={false}\n                        domain={[0, 100]}\n                        tick={false}\n                        type=\"number\"\n                      />\n                      <RadialBar\n                        angleAxisId={0}\n                        background\n                        cornerRadius={10}\n                        dataKey=\"capacity\"\n                        fill=\"var(--primary)\"\n                      />\n                    </RadialBarChart>\n                  </ChartContainer>\n                  <div className=\"absolute inset-0 flex items-center justify-center\">\n                    <span className=\"font-medium text-base text-foreground\">\n                      {item.capacity}%\n                    </span>\n                  </div>\n                </div>\n                <div>\n                  <dt className=\"font-medium text-foreground text-sm\">\n                    {item.name}\n                  </dt>\n                  <dd className=\"text-muted-foreground text-sm\">\n                    {item.current} of {item.allowed} used\n                  </dd>\n                </div>\n              </CardContent>\n            </Card>\n          ))}\n        </dl>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-08",
      "type": "registry:block",
      "title": "Stats with Circular Progress and Links",
      "description": "A stats with circular progress and links block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "card",
        "chart"
      ],
      "dependencies": [
        "recharts"
      ],
      "files": [
        {
          "path": "content/components/stats/stats-08.tsx",
          "type": "registry:component",
          "target": "components/stats-08.tsx",
          "content": "'use client';\n\nimport { PolarAngleAxis, RadialBar, RadialBarChart } from 'recharts';\nimport { Card, CardContent, CardFooter } from '@/components/ui/card';\nimport { type ChartConfig, ChartContainer } from '@/components/ui/chart';\n\nconst data = [\n  {\n    name: 'HR',\n    progress: 25,\n    budget: '$1,000',\n    current: '$250',\n    href: '#',\n    fill: 'var(--chart-1)',\n  },\n  {\n    name: 'Marketing',\n    progress: 55,\n    budget: '$1,000',\n    current: '$550',\n    href: '#',\n    fill: 'var(--chart-2)',\n  },\n  {\n    name: 'Finance',\n    progress: 85,\n    budget: '$1,000',\n    current: '$850',\n    href: '#',\n    fill: 'var(--chart-3)',\n  },\n  {\n    name: 'Engineering',\n    progress: 70,\n    budget: '$2,000',\n    current: '$1,400',\n    href: '#',\n    fill: 'var(--chart-4)',\n  },\n];\n\nconst chartConfig = {\n  progress: {\n    label: 'Progress',\n    color: 'var(--primary)',\n  },\n} satisfies ChartConfig;\n\nexport default function Stats08() {\n  return (\n    <div className=\"flex w-full items-center justify-center p-10\">\n      <dl className=\"grid w-full grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4\">\n        {data.map((item) => (\n          <Card className=\"gap-0 p-0 shadow-2xs\" key={item.name}>\n            <CardContent className=\"p-4\">\n              <div className=\"flex items-center space-x-3\">\n                <div className=\"relative flex items-center justify-center\">\n                  <ChartContainer\n                    className=\"h-[80px] w-[80px]\"\n                    config={chartConfig}\n                  >\n                    <RadialBarChart\n                      barSize={6}\n                      data={[item]}\n                      endAngle={-270}\n                      innerRadius={30}\n                      outerRadius={60}\n                      startAngle={90}\n                    >\n                      <PolarAngleAxis\n                        angleAxisId={0}\n                        axisLine={false}\n                        domain={[0, 100]}\n                        tick={false}\n                        type=\"number\"\n                      />\n                      <RadialBar\n                        angleAxisId={0}\n                        background\n                        cornerRadius={10}\n                        dataKey=\"progress\"\n                        fill={item.fill}\n                      />\n                    </RadialBarChart>\n                  </ChartContainer>\n                  <div className=\"absolute inset-0 flex items-center justify-center\">\n                    <span className=\"font-medium text-base text-foreground\">\n                      {item.progress}%\n                    </span>\n                  </div>\n                </div>\n                <div>\n                  <dd className=\"font-medium text-base text-foreground\">\n                    {item.current} / {item.budget}\n                  </dd>\n                  <dt className=\"text-muted-foreground text-sm\">\n                    Budget {item.name}\n                  </dt>\n                </div>\n              </div>\n            </CardContent>\n            <CardFooter className=\"flex items-center justify-end border-border border-t p-0!\">\n              <a\n                className=\"px-6 py-3 font-medium text-primary text-sm hover:text-primary/90\"\n                href={item.href}\n              >\n                View more &#8594;\n              </a>\n            </CardFooter>\n          </Card>\n        ))}\n      </dl>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-09",
      "type": "registry:block",
      "title": "Stats with Progress",
      "description": "A stats with progress block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "card",
        "progress"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/stats/stats-09.tsx",
          "type": "registry:component",
          "target": "components/stats-09.tsx",
          "content": "'use client';\n\nimport { Card, CardContent } from '@/components/ui/card';\nimport { Progress } from '@/components/ui/progress';\n\nconst data = [\n  {\n    name: 'Requests',\n    stat: '996',\n    limit: '10,000',\n    percentage: 9.96,\n  },\n  {\n    name: 'Credits',\n    stat: '$672',\n    limit: '$1,000',\n    percentage: 67.2,\n  },\n  {\n    name: 'Storage',\n    stat: '1.85',\n    limit: '10GB',\n    percentage: 18.5,\n  },\n  {\n    name: 'API Calls',\n    stat: '4,328',\n    limit: '5,000',\n    percentage: 86.56,\n  },\n];\n\nexport default function Stats09() {\n  return (\n    <div className=\"flex w-full items-center justify-center p-10\">\n      <dl className=\"grid w-full grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4\">\n        {data.map((item) => (\n          <Card className=\"py-4 shadow-2xs\" key={item.name}>\n            <CardContent className=\"\">\n              <dt className=\"text-muted-foreground text-sm\">{item.name}</dt>\n              <dd className=\"font-semibold text-2xl text-foreground tabular-nums\">\n                {item.stat}\n              </dd>\n              <Progress className=\"mt-6 h-2\" value={item.percentage} />\n              <dd className=\"mt-2 flex items-center justify-between text-sm\">\n                <span className=\"text-primary\">{item.percentage}&#37;</span>\n                <span className=\"text-muted-foreground\">\n                  {item.stat} of {item.limit}\n                </span>\n              </dd>\n            </CardContent>\n          </Card>\n        ))}\n      </dl>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-10",
      "type": "registry:block",
      "title": "Stats with Area Chart",
      "description": "A stats with area chart block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "card",
        "chart"
      ],
      "dependencies": [
        "recharts"
      ],
      "files": [
        {
          "path": "content/components/stats/stats-10.tsx",
          "type": "registry:component",
          "target": "components/stats-10.tsx",
          "content": "'use client';\n\nimport { Area, AreaChart, XAxis } from 'recharts';\nimport { Card, CardContent } from '@/components/ui/card';\nimport { ChartContainer } from '@/components/ui/chart';\nimport { cn } from '@/lib/utils';\n\nconst data = [\n  {\n    date: 'Nov 24, 2023',\n    'Alpha Corp': 142.87,\n    'Beta Solutions': 65.32,\n    'Gamma Industries': 83.25,\n  },\n  {\n    date: 'Nov 25, 2023',\n    'Alpha Corp': 151.43,\n    'Beta Solutions': 59.78,\n    'Gamma Industries': 79.64,\n  },\n  {\n    date: 'Nov 26, 2023',\n    'Alpha Corp': 157.28,\n    'Beta Solutions': 64.21,\n    'Gamma Industries': 76.19,\n  },\n  {\n    date: 'Nov 27, 2023',\n    'Alpha Corp': 162.94,\n    'Beta Solutions': 57.46,\n    'Gamma Industries': 72.84,\n  },\n  {\n    date: 'Nov 28, 2023',\n    'Alpha Corp': 148.37,\n    'Beta Solutions': 49.82,\n    'Gamma Industries': 81.56,\n  },\n  {\n    date: 'Nov 29, 2023',\n    'Alpha Corp': 139.56,\n    'Beta Solutions': 55.63,\n    'Gamma Industries': 92.38,\n  },\n  {\n    date: 'Nov 30, 2023',\n    'Alpha Corp': 145.83,\n    'Beta Solutions': 61.27,\n    'Gamma Industries': 88.75,\n  },\n  {\n    date: 'Dec 01, 2023',\n    'Alpha Corp': 138.29,\n    'Beta Solutions': 68.94,\n    'Gamma Industries': 93.42,\n  },\n  {\n    date: 'Dec 02, 2023',\n    'Alpha Corp': 129.64,\n    'Beta Solutions': 74.56,\n    'Gamma Industries': 97.18,\n  },\n  {\n    date: 'Dec 03, 2023',\n    'Alpha Corp': 119.82,\n    'Beta Solutions': 71.38,\n    'Gamma Industries': 89.43,\n  },\n  {\n    date: 'Dec 04, 2023',\n    'Alpha Corp': 128.54,\n    'Beta Solutions': 63.95,\n    'Gamma Industries': 92.76,\n  },\n  {\n    date: 'Dec 05, 2023',\n    'Alpha Corp': 137.21,\n    'Beta Solutions': 58.47,\n    'Gamma Industries': 84.29,\n  },\n  {\n    date: 'Dec 06, 2023',\n    'Alpha Corp': 134.68,\n    'Beta Solutions': 69.12,\n    'Gamma Industries': 79.38,\n  },\n  {\n    date: 'Dec 07, 2023',\n    'Alpha Corp': 152.73,\n    'Beta Solutions': 73.89,\n    'Gamma Industries': 81.42,\n  },\n  {\n    date: 'Dec 08, 2023',\n    'Alpha Corp': 168.59,\n    'Beta Solutions': 78.54,\n    'Gamma Industries': 75.68,\n  },\n];\n\nconst summary = [\n  {\n    name: 'Alpha Corp',\n    tickerSymbol: 'ACP',\n    value: '$168.59',\n    change: '+15.86',\n    percentageChange: '+10.4%',\n    changeType: 'positive',\n  },\n  {\n    name: 'Beta Solutions',\n    tickerSymbol: 'BTS',\n    value: '$78.54',\n    change: '+4.65',\n    percentageChange: '+6.3%',\n    changeType: 'positive',\n  },\n  {\n    name: 'Gamma Industries',\n    tickerSymbol: 'GMI',\n    value: '$75.68',\n    change: '-5.74',\n    percentageChange: '-7.1%',\n    changeType: 'negative',\n  },\n];\n\nconst sanitizeName = (name: string) => {\n  return name\n    .replace(/\\\\s+/g, '-')\n    .replace(/[^a-zA-Z0-9-]/g, '_')\n    .toLowerCase();\n};\n\nexport default function Stats10() {\n  return (\n    <div className=\"flex w-full items-center justify-center p-10\">\n      <dl className=\"grid w-full grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3\">\n        {summary.map((item) => {\n          const sanitizedName = sanitizeName(item.name);\n          const gradientId = `gradient-${sanitizedName}`;\n\n          const color =\n            item.changeType === 'positive'\n              ? 'hsl(142.1 76.2% 36.3%)'\n              : 'hsl(0 72.2% 50.6%)';\n\n          return (\n            <Card className=\"p-0 shadow-2xs\" key={item.name}>\n              <CardContent className=\"p-4 pb-0\">\n                <div>\n                  <dt className=\"font-medium text-foreground text-sm\">\n                    {item.name}{' '}\n                    <span className=\"font-normal text-muted-foreground\">\n                      ({item.tickerSymbol})\n                    </span>\n                  </dt>\n                  <div className=\"flex items-baseline justify-between\">\n                    <dd\n                      className={cn(\n                        item.changeType === 'positive'\n                          ? 'text-green-600 dark:text-green-500'\n                          : 'text-red-600 dark:text-red-500',\n                        'font-semibold text-lg'\n                      )}\n                    >\n                      {item.value}\n                    </dd>\n                    <dd className=\"flex items-center space-x-1 text-sm\">\n                      <span className=\"font-medium text-foreground\">\n                        {item.change}\n                      </span>\n                      <span\n                        className={cn(\n                          item.changeType === 'positive'\n                            ? 'text-green-600 dark:text-green-500'\n                            : 'text-red-600 dark:text-red-500'\n                        )}\n                      >\n                        ({item.percentageChange})\n                      </span>\n                    </dd>\n                  </div>\n                </div>\n\n                <div className=\"mt-2 h-16 overflow-hidden\">\n                  <ChartContainer\n                    className=\"h-full w-full\"\n                    config={{\n                      [item.name]: {\n                        label: item.name,\n                        color,\n                      },\n                    }}\n                  >\n                    <AreaChart data={data}>\n                      <defs>\n                        <linearGradient\n                          id={gradientId}\n                          x1=\"0\"\n                          x2=\"0\"\n                          y1=\"0\"\n                          y2=\"1\"\n                        >\n                          <stop\n                            offset=\"5%\"\n                            stopColor={color}\n                            stopOpacity={0.3}\n                          />\n                          <stop\n                            offset=\"95%\"\n                            stopColor={color}\n                            stopOpacity={0}\n                          />\n                        </linearGradient>\n                      </defs>\n                      <XAxis dataKey=\"date\" hide={true} />\n                      <Area\n                        dataKey={item.name}\n                        fill={`url(#${gradientId})`}\n                        fillOpacity={0.4}\n                        stroke={color}\n                        strokeWidth={1.5}\n                        type=\"monotone\"\n                      />\n                    </AreaChart>\n                  </ChartContainer>\n                </div>\n              </CardContent>\n            </Card>\n          );\n        })}\n      </dl>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-11",
      "type": "registry:block",
      "title": "Stats Dashboard with Progress Bars",
      "description": "A stats dashboard with progress bars block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "dialog",
        "input",
        "label"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/stats/stats-11.tsx",
          "type": "registry:component",
          "target": "components/stats-11.tsx",
          "content": "'use client';\n\nimport { Box, Edit } from 'lucide-react';\nimport type React from 'react';\nimport { useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent } from '@/components/ui/card';\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\n\ninterface MetricCardProps {\n  title: string;\n  value: string;\n  limit: string;\n  percentage: number;\n  status?: string;\n  statusColor?: string;\n  progressColor: string;\n  details?: Array<{ label: string; value: string; color: string }>;\n  actionLabel: string;\n  actionIcon: React.ReactNode;\n  warningMessage?: string;\n  onActionClick?: () => void;\n}\n\nfunction MetricCard({\n  title,\n  value,\n  limit,\n  percentage,\n  status,\n  statusColor = 'text-emerald-600 dark:text-emerald-400',\n  progressColor,\n  details,\n  actionLabel,\n  actionIcon,\n  warningMessage,\n  onActionClick,\n}: MetricCardProps) {\n  const renderProgressBar = () => {\n    if (details && title === 'Commands') {\n      const writes = Number.parseInt(details[0].value.replace(/,/g, ''));\n      const reads = Number.parseInt(details[1].value.replace(/,/g, ''));\n      const total = writes + reads;\n      const writesPercentage = (writes / total) * 100;\n      const readsPercentage = (reads / total) * 100;\n\n      return (\n        <div className=\"relative h-1 w-full overflow-hidden rounded-full bg-muted\">\n          <div\n            className=\"absolute left-0 h-full w-full origin-left bg-emerald-500 transition-transform duration-200 ease-out\"\n            style={{ transform: `scaleX(${writesPercentage / 100})` }}\n          />\n          <div\n            className=\"absolute left-0 h-full w-full origin-left bg-blue-500 transition-transform duration-200 ease-out\"\n            style={{\n              transform: `translateX(${writesPercentage}%) scaleX(${readsPercentage / 100})`,\n            }}\n          />\n        </div>\n      );\n    }\n\n    return (\n      <div className=\"relative h-1 w-full overflow-hidden rounded-full bg-muted\">\n        <div\n          className={`h-full w-full origin-left transition-transform duration-200 ease-out ${progressColor}`}\n          style={{ transform: `scaleX(${Math.min(percentage, 100) / 100})` }}\n        />\n      </div>\n    );\n  };\n\n  return (\n    <Card className=\"relative max-w-[280px] overflow-hidden shadow-2xs\">\n      <CardContent className=\"p-4 py-0\">\n        <h5 className=\"font-normal text-muted-foreground text-xs uppercase leading-none tracking-wide dark:text-foreground/80\">\n          {title}\n        </h5>\n\n        <div className=\"mt-2 flex items-baseline gap-1\">\n          <div className=\"font-medium text-[1.2rem] text-foreground tabular-nums leading-none\">\n            {value}\n          </div>\n          <div className=\"text-muted-foreground text-xs leading-none\">\n            / {limit}\n          </div>\n        </div>\n\n        <div className=\"mt-3\">\n          {renderProgressBar()}\n\n          {details && (\n            <div className=\"my-6 mb-8\">\n              <div className=\"flex flex-col gap-3\">\n                {details.map((detail, index) => (\n                  <div\n                    className=\"flex w-full items-center text-muted-foreground text-xs leading-none dark:text-foreground/70\"\n                    key={index}\n                  >\n                    <div\n                      className={`mr-[6px] h-2 w-2 rounded-full ${detail.color}`}\n                    />\n                    <div className=\"mr-1\">{detail.label}</div>\n                    <div className=\"h-[9px] flex-1 border-border border-b-2 border-dotted\" />\n                    <div className=\"ml-1 tabular-nums\">{detail.value}</div>\n                  </div>\n                ))}\n              </div>\n            </div>\n          )}\n\n          {status && (\n            <div className=\"pt-2\">\n              <div className={statusColor}>{status}</div>\n            </div>\n          )}\n\n          {warningMessage && (\n            <div className=\"pt-2\">\n              <div className=\"text-amber-700 text-sm dark:text-amber-400\">\n                {warningMessage}\n              </div>\n            </div>\n          )}\n        </div>\n\n        <div className=\"absolute right-0 bottom-0 left-0\">\n          <Button\n            className=\"h-8 w-full justify-start gap-0 rounded-none bg-muted/50 text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300\"\n            onClick={onActionClick}\n            variant=\"ghost\"\n          >\n            {actionIcon}\n            <span className=\"ml-1 text-xs\">{actionLabel}</span>\n          </Button>\n        </div>\n      </CardContent>\n    </Card>\n  );\n}\n\nfunction BudgetDialog({\n  open,\n  onOpenChange,\n}: {\n  open: boolean;\n  onOpenChange: (open: boolean) => void;\n}) {\n  const [budget, setBudget] = useState('150');\n\n  const handleUpdate = () => {\n    onOpenChange(false);\n  };\n\n  return (\n    <Dialog onOpenChange={onOpenChange} open={open}>\n      <DialogContent className=\"sm:max-w-md\">\n        <DialogHeader>\n          <DialogTitle>Update budget</DialogTitle>\n          <DialogDescription>\n            When your monthly cost reaches the max budget, we send an email and\n            throttle your database. You will not be charged beyond your set\n            budget for this database.\n          </DialogDescription>\n        </DialogHeader>\n\n        <div className=\"space-y-2\">\n          <Label htmlFor=\"budget\">Max budget per month</Label>\n          <Input\n            id=\"budget\"\n            onChange={(e) => setBudget(e.target.value)}\n            placeholder=\"150\"\n            type=\"number\"\n            value={budget}\n          />\n        </div>\n\n        <DialogFooter className=\"pt-2\">\n          <Button onClick={() => onOpenChange(false)} variant=\"outline\">\n            Cancel\n          </Button>\n          <Button onClick={handleUpdate}>Update</Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  );\n}\n\nexport default function Stats11() {\n  const [budgetDialogOpen, setBudgetDialogOpen] = useState(false);\n\n  return (\n    <>\n      <div className=\"grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-4\">\n        <MetricCard\n          actionIcon={<Box className=\"h-4 w-4\" />}\n          actionLabel=\"Upgrade\"\n          details={[\n            { label: 'Writes', value: '11,276,493', color: 'bg-emerald-500' },\n            { label: 'Reads', value: '2,548,921', color: 'bg-blue-500' },\n          ]}\n          limit=\"Unlimited\"\n          percentage={67}\n          progressColor=\"bg-blue-500\"\n          title=\"Commands\"\n          value=\"13.8M\"\n        />\n\n        <MetricCard\n          actionIcon={<Box className=\"h-4 w-4\" />}\n          actionLabel=\"Upgrade\"\n          limit=\"150 GB\"\n          percentage={94}\n          progressColor=\"bg-orange-500\"\n          title=\"Bandwidth\"\n          value=\"141 GB\"\n          warningMessage=\"There will be a charge for the excessive bandwidth over the limit.\"\n        />\n\n        <MetricCard\n          actionIcon={<Box className=\"h-4 w-4\" />}\n          actionLabel=\"Upgrade\"\n          limit=\"500 GB\"\n          percentage={7.4}\n          progressColor=\"bg-emerald-500\"\n          status=\"It's all right.\"\n          title=\"Storage\"\n          value=\"37 GB\"\n        />\n\n        <MetricCard\n          actionIcon={<Edit className=\"h-4 w-4\" />}\n          actionLabel=\"Change Budget\"\n          limit=\"$150 Budget\"\n          onActionClick={() => setBudgetDialogOpen(true)}\n          percentage={48.95}\n          progressColor=\"bg-emerald-500\"\n          status=\"It's all right.\"\n          title=\"Cost\"\n          value=\"$73.42\"\n        />\n      </div>\n\n      <BudgetDialog\n        onOpenChange={setBudgetDialogOpen}\n        open={budgetDialogOpen}\n      />\n    </>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-12",
      "type": "registry:block",
      "title": "Stats Usage Dashboard",
      "description": "A stats usage dashboard block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "card",
        "chart"
      ],
      "dependencies": [
        "recharts"
      ],
      "files": [
        {
          "path": "content/components/stats/stats-12.tsx",
          "type": "registry:component",
          "target": "components/stats-12.tsx",
          "content": "'use client';\n\nimport { Cell, Pie, PieChart } from 'recharts';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent, CardHeader } from '@/components/ui/card';\nimport { type ChartConfig, ChartContainer } from '@/components/ui/chart';\n\ninterface UsageItem {\n  name: string;\n  current: string;\n  limit: string;\n  percentage: number;\n  href?: string;\n}\n\nconst usageData: UsageItem[] = [\n  { name: 'ISR Reads', current: '358K', limit: '1M', percentage: 35.8 },\n  { name: 'Edge Requests', current: '317K', limit: '1M', percentage: 31.7 },\n  {\n    name: 'Fast Origin Transfer',\n    current: '3.07 GB',\n    limit: '10 GB',\n    percentage: 30.7,\n  },\n  {\n    name: 'Speed Insights Data Points',\n    current: '791',\n    limit: '10K',\n    percentage: 7.9,\n  },\n  {\n    name: 'Fast Data Transfer',\n    current: '4.98 GB',\n    limit: '100 GB',\n    percentage: 5.0,\n  },\n  {\n    name: 'Function Duration',\n    current: '3.1 GB-Hrs',\n    limit: '100 GB-Hrs',\n    percentage: 3.1,\n  },\n  {\n    name: 'Web Analytics Events',\n    current: '1.3K',\n    limit: '50K',\n    percentage: 2.6,\n  },\n  { name: 'ISR Writes', current: '4.8K', limit: '200K', percentage: 2.4 },\n  {\n    name: 'Function Invocations',\n    current: '19K',\n    limit: '1M',\n    percentage: 1.9,\n  },\n  {\n    name: 'Image Optimization - Cache Reads',\n    current: '4.3K',\n    limit: '300K',\n    percentage: 1.4,\n  },\n];\n\nconst chartConfig = {\n  used: {\n    label: 'Used',\n    color: 'hsl(var(--primary))',\n  },\n  remaining: {\n    label: 'Remaining',\n    color: 'hsl(var(--muted))',\n  },\n} satisfies ChartConfig;\n\nfunction DonutChart({ percentage }: { percentage: number }) {\n  const backgroundData = [{ name: 'background', value: 100, fill: '#E5E7EB' }];\n  const foregroundData = [\n    {\n      name: 'used',\n      value: Math.max(0, Math.min(100, Number(percentage))),\n      fill: '#3B82F6',\n    },\n    {\n      name: 'empty',\n      value: 100 - Math.max(0, Math.min(100, Number(percentage))),\n      fill: 'transparent',\n    },\n  ];\n\n  return (\n    <ChartContainer\n      className=\"aspect-square h-6 w-6 shrink-0\"\n      config={chartConfig}\n    >\n      <PieChart>\n        <Pie\n          cx=\"50%\"\n          cy=\"50%\"\n          data={backgroundData}\n          dataKey=\"value\"\n          innerRadius={6}\n          isAnimationActive={false}\n          nameKey=\"name\"\n          outerRadius={10}\n        >\n          {backgroundData.map((entry, index) => (\n            <Cell fill={entry.fill} key={`bg-cell-${index}`} />\n          ))}\n        </Pie>\n        <Pie\n          cx=\"50%\"\n          cy=\"50%\"\n          data={foregroundData}\n          dataKey=\"value\"\n          endAngle={-270}\n          innerRadius={6}\n          nameKey=\"name\"\n          outerRadius={10}\n          startAngle={90}\n        >\n          {foregroundData.map((entry, index) => (\n            <Cell fill={entry.fill} key={`fg-cell-${index}`} />\n          ))}\n        </Pie>\n      </PieChart>\n    </ChartContainer>\n  );\n}\n\nexport default function Stats12() {\n  return (\n    <Card className=\"w-full max-w-md gap-3 py-5 shadow-2xs\">\n      <CardHeader className=\"px-5\">\n        <div className=\"flex items-center justify-between\">\n          <div className=\"flex flex-col\">\n            <h3 className=\"text-balance font-medium text-sm\">Last 30 days</h3>\n            <p className=\"text-pretty font-medium text-muted-foreground text-xs\">\n              Updated just now\n            </p>\n          </div>\n          <Button className=\"h-6 font-medium text-xs\" size=\"sm\">\n            Upgrade\n          </Button>\n        </div>\n      </CardHeader>\n\n      <CardContent className=\"px-3 pt-0\">\n        <div className=\"space-y-0\">\n          {usageData.map((item, index) => (\n            <div\n              className={`flex items-center gap-3 rounded-sm p-2 transition-colors hover:bg-muted/50 ${\n                index % 2 === 1 ? 'bg-muted/20' : ''\n              }`}\n              key={item.name}\n            >\n              <DonutChart percentage={item.percentage} />\n              <span className=\"flex-1 truncate text-sm leading-4\">\n                {item.name}\n              </span>\n              <span className=\"font-medium text-muted-foreground text-xs tabular-nums tracking-tighter\">\n                {item.current} /{' '}\n                <span className=\"text-foreground\">{item.limit}</span>\n              </span>\n            </div>\n          ))}\n        </div>\n      </CardContent>\n    </Card>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-13",
      "type": "registry:block",
      "title": "Stats with Segmented Progress",
      "description": "A stats with segmented progress block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "card"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/stats/stats-13.tsx",
          "type": "registry:component",
          "target": "components/stats-13.tsx",
          "content": "'use client';\n\nimport { Card, CardContent } from '@/components/ui/card';\nimport { cn } from '@/lib/utils';\n\ninterface Props {\n  title?: string;\n  used?: number;\n  total?: number;\n  usedLabel?: string;\n  totalLabel?: string;\n  segments?: {\n    label: string;\n    value: number;\n    color: string;\n  }[];\n  className?: string;\n}\n\nconst defaultSegments: NonNullable<Props['segments']> = [\n  { label: 'Documents', value: 2400, color: 'bg-blue-500' },\n  { label: 'Photos', value: 1800, color: 'bg-emerald-500' },\n  { label: 'Videos', value: 3200, color: 'bg-amber-500' },\n  { label: 'Music', value: 900, color: 'bg-purple-500' },\n];\n\nexport default function Stats13({\n  title = 'Using Storage',\n  used = 8300,\n  total = 15,\n  usedLabel = 'MB',\n  totalLabel = 'GB',\n  segments = defaultSegments,\n  className,\n}: Props) {\n  const totalValue = total * 1000;\n  const freeValue = totalValue - used;\n\n  return (\n    <Card className={cn('w-full max-w-4xl shadow-sm', className)}>\n      <CardContent className=\"py-0\">\n        <p className=\"mb-4 text-pretty text-base text-muted-foreground\">\n          {title}{' '}\n          <span className=\"font-semibold text-foreground tabular-nums\">\n            {used.toLocaleString(undefined, {\n              minimumFractionDigits: 0,\n              maximumFractionDigits: 2,\n            })}{' '}\n            {usedLabel}\n          </span>{' '}\n          of {total} {totalLabel}\n        </p>\n\n        <div className=\"mb-4 flex h-2.5 w-full overflow-hidden rounded-full bg-muted\">\n          {segments.map((segment) => {\n            const percentage = (segment.value / totalValue) * 100;\n            return (\n              <div\n                aria-label={segment.label}\n                aria-valuemax={totalValue}\n                aria-valuemin={0}\n                aria-valuenow={segment.value}\n                className={cn('h-full', segment.color)}\n                key={segment.label}\n                role=\"progressbar\"\n                style={{ width: `${percentage}%` }}\n              />\n            );\n          })}\n        </div>\n\n        <div className=\"flex flex-wrap items-center gap-x-8 gap-y-2\">\n          {segments.map((segment) => (\n            <div className=\"flex items-center gap-2\" key={segment.label}>\n              <span\n                aria-hidden=\"true\"\n                className={cn('size-3 shrink-0 rounded', segment.color)}\n              />\n              <span className=\"text-muted-foreground text-sm\">\n                {segment.label}\n              </span>\n              <span className=\"text-muted-foreground text-sm tabular-nums\">\n                {Math.round(segment.value)}\n                {usedLabel}\n              </span>\n            </div>\n          ))}\n          <div className=\"flex items-center gap-2\">\n            <span\n              aria-hidden=\"true\"\n              className=\"size-3 shrink-0 rounded-sm bg-muted\"\n            />\n            <span className=\"text-muted-foreground text-sm\">Free</span>\n            <span className=\"text-muted-foreground text-sm tabular-nums\">\n              {Math.round(freeValue)}\n              {usedLabel}\n            </span>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-14",
      "type": "registry:block",
      "title": "Stats with Usage Breakdown",
      "description": "A stats with usage breakdown block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "badge",
        "card"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/stats/stats-14.tsx",
          "type": "registry:component",
          "target": "components/stats-14.tsx",
          "content": "import { Badge } from '@/components/ui/badge';\nimport { Card, CardContent } from '@/components/ui/card';\n\ninterface UsageItem {\n  label: string;\n  amount: number;\n  percentage: number;\n  color: 'emerald' | 'amber' | 'rose';\n}\n\nconst data: UsageItem[] = [\n  { label: 'Compute', amount: 450, percentage: 52.3, color: 'emerald' },\n  { label: 'Storage', amount: 285, percentage: 33.1, color: 'amber' },\n  { label: 'Bandwidth', amount: 125, percentage: 14.6, color: 'rose' },\n];\n\nconst colorClasses = {\n  emerald: 'bg-emerald-500 dark:bg-emerald-400',\n  amber: 'bg-amber-500 dark:bg-amber-400',\n  rose: 'bg-rose-500 dark:bg-rose-400',\n};\n\nexport function Stats14() {\n  return (\n    <Card className=\"w-full max-w-sm shadow-none\">\n      <CardContent className=\"flex flex-col justify-between pt-0\">\n        <div>\n          <div className=\"flex items-center gap-2\">\n            <h3 className=\"text-balance font-bold text-foreground text-sm\">\n              Usage\n            </h3>\n            <Badge\n              className=\"bg-amber-50 text-amber-700 ring-1 ring-amber-500/30 dark:bg-amber-400/10 dark:text-amber-300 dark:ring-amber-400/20\"\n              variant=\"secondary\"\n            >\n              +12.5%\n            </Badge>\n          </div>\n\n          <p className=\"mt-2 flex items-baseline gap-2 text-pretty\">\n            <span className=\"text-foreground text-xl\">$860</span>\n            <span className=\"text-muted-foreground text-sm\">this month</span>\n          </p>\n\n          <div className=\"mt-4\">\n            <p className=\"text-pretty font-medium text-foreground text-sm\">\n              Resource breakdown\n            </p>\n            <div className=\"mt-2 flex items-center gap-0.5\">\n              {data.map((item, index) => (\n                <div\n                  className={`${colorClasses[item.color]} h-1.5 rounded-xs`}\n                  key={index}\n                  style={{ width: `${item.percentage}%` }}\n                />\n              ))}\n            </div>\n          </div>\n\n          <ul className=\"mt-5 space-y-2\" role=\"list\">\n            {data.map((item, index) => (\n              <li className=\"flex items-center gap-2 text-xs\" key={index}>\n                <span\n                  aria-hidden=\"true\"\n                  className={`${colorClasses[item.color]} size-2.5 rounded-xs`}\n                />\n                <span className=\"text-foreground\">{item.label}</span>\n                <span className=\"text-muted-foreground\">\n                  (${item.amount} / {item.percentage}%)\n                </span>\n              </li>\n            ))}\n          </ul>\n        </div>\n\n        <p className=\"mt-6 text-pretty text-muted-foreground text-xs\">\n          Configure limits in{' '}\n          <a\n            className=\"text-emerald-600 hover:underline dark:text-emerald-400\"\n            href=\"#\"\n          >\n            resource settings.\n          </a>\n        </p>\n      </CardContent>\n    </Card>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "stats-15",
      "type": "registry:block",
      "title": "Stats with Value Breakdown",
      "description": "A stats with value breakdown block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/stats/stats-15.tsx",
          "type": "registry:component",
          "target": "components/stats-15.tsx",
          "content": "import { cn } from '@/lib/utils';\n\nconst data = [\n  {\n    label: 'After 1 year',\n    value: '$2,400',\n    percentage: '+8.2%',\n  },\n  {\n    label: 'After 5 years',\n    value: '$14,800',\n    percentage: '+24.6%',\n  },\n  {\n    label: 'After 10 years',\n    value: '$38,500',\n    percentage: '+52.1%',\n  },\n];\n\nexport function Stats15() {\n  return (\n    <div className=\"w-full max-w-2xs\">\n      <h3 className=\"text-balance font-medium text-foreground text-sm\">\n        Investment growth projection\n      </h3>\n      <ul className=\"mt-2 divide-y divide-border text-sm\" role=\"list\">\n        {data.map((item, index) => (\n          <li className=\"flex items-center justify-between py-3\" key={index}>\n            <span className=\"text-muted-foreground\">{item.label}</span>\n            <span className=\"flex items-center gap-3 tabular-nums\">\n              <span className=\"text-right font-medium text-foreground\">\n                {item.value}\n              </span>\n              <span aria-hidden=\"true\" className=\"h-5 w-px bg-border\" />\n              <span\n                className={cn(\n                  'w-15 rounded px-1.5 py-1 text-center font-semibold text-xs',\n                  'bg-emerald-50 text-emerald-600 dark:bg-emerald-400/10 dark:text-emerald-400'\n                )}\n              >\n                {item.percentage}\n              </span>\n            </span>\n          </li>\n        ))}\n      </ul>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "stats"
      ]
    },
    {
      "name": "table-01",
      "type": "registry:block",
      "title": "Table with Accordion",
      "description": "A table with accordion block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "button",
        "collapsible",
        "table"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/tables/table-01.tsx",
          "type": "registry:component",
          "target": "components/table-01.tsx",
          "content": "'use client';\n\nimport { ChevronDown, ChevronRight } from 'lucide-react';\nimport { useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Collapsible, CollapsibleContent } from '@/components/ui/collapsible';\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow,\n} from '@/components/ui/table';\nimport { cn } from '@/lib/utils';\n\ninterface TableRowData {\n  id: string;\n  name: string;\n  category: string;\n  value: number;\n  date: string;\n  children?: TableRowData[];\n}\n\nconst sampleData: TableRowData[] = [\n  {\n    id: '001',\n    name: 'Project Alpha',\n    category: 'Development',\n    value: 45_000,\n    date: '2024-01-15',\n    children: [\n      {\n        id: '001-01',\n        name: 'Frontend Module',\n        category: 'Development',\n        value: 15_000,\n        date: '2024-01-16',\n      },\n      {\n        id: '001-02',\n        name: 'Backend Module',\n        category: 'Development',\n        value: 20_000,\n        date: '2024-01-21',\n      },\n      {\n        id: '001-03',\n        name: 'Testing Suite',\n        category: 'Development',\n        value: 10_000,\n        date: '2024-01-24',\n      },\n    ],\n  },\n  {\n    id: '002',\n    name: 'Marketing Campaign',\n    category: 'Marketing',\n    value: 28_500,\n    date: '2024-01-18',\n    children: [\n      {\n        id: '002-01',\n        name: 'Social Media',\n        category: 'Marketing',\n        value: 12_000,\n        date: '2024-01-19',\n      },\n      {\n        id: '002-02',\n        name: 'Email Marketing',\n        category: 'Marketing',\n        value: 8500,\n        date: '2024-01-22',\n      },\n      {\n        id: '002-03',\n        name: 'SEO Optimization',\n        category: 'Marketing',\n        value: 8000,\n        date: '2024-01-23',\n      },\n    ],\n  },\n  {\n    id: '003',\n    name: 'Infrastructure Upgrade',\n    category: 'Operations',\n    value: 67_200,\n    date: '2024-01-20',\n    children: [\n      {\n        id: '003-01',\n        name: 'Cloud Migration',\n        category: 'Operations',\n        value: 35_000,\n        date: '2024-01-21',\n      },\n      {\n        id: '003-02',\n        name: 'Security Enhancement',\n        category: 'Operations',\n        value: 32_200,\n        date: '2024-01-24',\n      },\n    ],\n  },\n  {\n    id: '004',\n    name: 'Customer Support',\n    category: 'Service',\n    value: 19_800,\n    date: '2024-01-25',\n  },\n];\n\ninterface AccordionRowProps {\n  row: TableRowData;\n  defaultOpen?: boolean;\n}\n\nfunction AccordionRow({ row, defaultOpen = false }: AccordionRowProps) {\n  const [isOpen, setIsOpen] = useState(defaultOpen);\n  const hasChildren = row.children && row.children.length > 0;\n\n  return (\n    <Collapsible\n      onOpenChange={setIsOpen}\n      open={isOpen}\n      render={\n        <TableBody className=\"[&_tr:last-child]:border-b last:[&_tr:last-child]:border-0\" />\n      }\n    >\n      <TableRow\n        className={cn(\n          'grid grid-cols-[40px_80px_180px_110px_100px_110px] bg-muted/50 hover:bg-muted/50',\n          isOpen && 'border-b-0'\n        )}\n      >\n        <TableCell className=\"p-0\">\n          <Button\n            aria-label={isOpen ? 'Collapse row' : 'Expand row'}\n            className={cn(\n              'h-full w-full rounded-none p-3 text-muted-foreground transition-colors',\n              hasChildren && 'hover:bg-transparent hover:text-foreground',\n              !hasChildren && 'cursor-default opacity-30'\n            )}\n            disabled={!hasChildren}\n            onClick={() => setIsOpen(!isOpen)}\n            size=\"icon\"\n            variant=\"ghost\"\n          >\n            {hasChildren ? (\n              isOpen ? (\n                <ChevronDown className=\"h-4 w-4 transition-transform duration-200\" />\n              ) : (\n                <ChevronRight className=\"h-4 w-4 transition-transform duration-200\" />\n              )\n            ) : (\n              <div className=\"h-4 w-4\" />\n            )}\n          </Button>\n        </TableCell>\n        <TableCell className=\"p-3 font-medium font-mono text-muted-foreground text-sm\">\n          {row.id}\n        </TableCell>\n        <TableCell className=\"p-3 font-medium text-sm\">{row.name}</TableCell>\n        <TableCell className=\"p-3 text-muted-foreground text-sm\">\n          {row.category}\n        </TableCell>\n        <TableCell className=\"p-3 text-right font-mono font-semibold text-sm tabular-nums\">\n          ${row.value.toLocaleString()}\n        </TableCell>\n        <TableCell className=\"p-3 text-muted-foreground text-sm\">\n          {row.date}\n        </TableCell>\n      </TableRow>\n\n      {hasChildren && (\n        <TableRow className=\"grid grid-cols-[40px_80px_180px_110px_100px_110px] border-b-0 hover:bg-transparent\">\n          <TableCell className=\"col-span-6 p-0\" colSpan={6}>\n            <CollapsibleContent>\n              <div className=\"w-full border-border border-b bg-muted/20\">\n                <Table>\n                  <TableHeader>\n                    <TableRow className=\"grid grid-cols-[40px_80px_180px_110px_100px_110px] border-b-0 bg-muted/30\">\n                      <TableHead className=\"flex h-7 items-center border-border border-y px-3 py-1.5\" />\n                      <TableHead className=\"flex h-7 items-center border-border border-y px-3 py-1.5 text-xs\">\n                        ID\n                      </TableHead>\n                      <TableHead className=\"flex h-7 items-center border-border border-y px-3 py-1.5 text-xs\">\n                        Name\n                      </TableHead>\n                      <TableHead className=\"flex h-7 items-center border-border border-y px-3 py-1.5 text-xs\">\n                        Category\n                      </TableHead>\n                      <TableHead className=\"flex h-7 items-center justify-end border-border border-y px-3 py-1.5 text-right text-xs\">\n                        Value\n                      </TableHead>\n                      <TableHead className=\"flex h-7 items-center border-border border-y px-3 py-1.5 text-xs\">\n                        Date\n                      </TableHead>\n                    </TableRow>\n                  </TableHeader>\n                  <TableBody>\n                    {row.children?.map((childRow) => (\n                      <TableRow\n                        className=\"grid grid-cols-[40px_80px_180px_110px_100px_110px]\"\n                        key={childRow.id}\n                      >\n                        <TableCell className=\"px-3 py-2\" />\n                        <TableCell className=\"px-3 py-2 font-mono text-muted-foreground text-xs tabular-nums\">\n                          {childRow.id}\n                        </TableCell>\n                        <TableCell className=\"px-3 py-2 font-medium text-xs\">\n                          {childRow.name}\n                        </TableCell>\n                        <TableCell className=\"px-3 py-2 text-muted-foreground text-xs\">\n                          {childRow.category}\n                        </TableCell>\n                        <TableCell className=\"px-3 py-2 text-right font-mono font-semibold text-xs tabular-nums\">\n                          ${childRow.value.toLocaleString()}\n                        </TableCell>\n                        <TableCell className=\"px-3 py-2 text-muted-foreground text-xs\">\n                          {childRow.date}\n                        </TableCell>\n                      </TableRow>\n                    ))}\n                  </TableBody>\n                </Table>\n              </div>\n            </CollapsibleContent>\n          </TableCell>\n        </TableRow>\n      )}\n    </Collapsible>\n  );\n}\n\nexport default function Table01() {\n  return (\n    <div className=\"max-w-fit overflow-hidden rounded-lg border border-border bg-card shadow-sm\">\n      <div className=\"overflow-x-auto\">\n        <Table>\n          <TableHeader>\n            <TableRow className=\"grid grid-cols-[40px_80px_180px_110px_100px_110px] bg-muted/50\">\n              <TableHead className=\"p-3\" />\n              <TableHead className=\"p-3 font-semibold text-foreground text-sm\">\n                ID\n              </TableHead>\n              <TableHead className=\"p-3 font-semibold text-foreground text-sm\">\n                Name\n              </TableHead>\n              <TableHead className=\"p-3 font-semibold text-foreground text-sm\">\n                Category\n              </TableHead>\n              <TableHead className=\"p-3 text-right font-semibold text-foreground text-sm\">\n                Value\n              </TableHead>\n              <TableHead className=\"p-3 font-semibold text-foreground text-sm\">\n                Date\n              </TableHead>\n            </TableRow>\n          </TableHeader>\n          {sampleData.map((row, index) => (\n            <AccordionRow defaultOpen={index === 0} key={row.id} row={row} />\n          ))}\n        </Table>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "tables"
      ]
    },
    {
      "name": "table-02",
      "type": "registry:block",
      "title": "Table with Actions",
      "description": "A table with actions block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "badge",
        "button",
        "table",
        "tooltip"
      ],
      "dependencies": [
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/tables/table-02.tsx",
          "type": "registry:component",
          "target": "components/table-02.tsx",
          "content": "'use client';\n\nimport {\n  CheckCircle,\n  FileTextIcon,\n  Loader2,\n  PauseIcon,\n  PlayIcon,\n  Trash2Icon,\n} from 'lucide-react';\nimport { useState } from 'react';\n\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow,\n} from '@/components/ui/table';\nimport {\n  Tooltip,\n  TooltipContent,\n  TooltipProvider,\n  TooltipTrigger,\n} from '@/components/ui/tooltip';\n\ninterface Task {\n  id: string;\n  title: string;\n  assignee: string;\n  status: 'pending' | 'in-progress' | 'completed' | 'blocked';\n  priority: 'low' | 'medium' | 'high' | 'urgent';\n  dueDate: string;\n  notes: string;\n}\n\ntype TaskActionType = 'start' | 'pause' | 'complete' | 'delete' | 'view';\n\nconst tasks: Task[] = [\n  {\n    id: 'TASK-001',\n    title: 'Implement User Authentication',\n    assignee: 'Sarah Chen',\n    status: 'in-progress',\n    priority: 'high',\n    dueDate: '2024-03-25',\n    notes: 'OAuth 2.0 integration with Google and GitHub providers',\n  },\n  {\n    id: 'TASK-002',\n    title: 'Design Dashboard UI',\n    assignee: 'Michael Torres',\n    status: 'completed',\n    priority: 'medium',\n    dueDate: '2024-03-20',\n    notes: 'Finalize dashboard layout with responsive grid system',\n  },\n  {\n    id: 'TASK-003',\n    title: 'API Performance Optimization',\n    assignee: 'Emma Rodriguez',\n    status: 'pending',\n    priority: 'urgent',\n    dueDate: '2024-03-22',\n    notes: 'Reduce API response time by implementing caching strategy',\n  },\n  {\n    id: 'TASK-004',\n    title: 'Write Unit Tests',\n    assignee: 'James Wilson',\n    status: 'in-progress',\n    priority: 'medium',\n    dueDate: '2024-03-28',\n    notes: 'Achieve 80% code coverage for authentication module',\n  },\n  {\n    id: 'TASK-005',\n    title: 'Database Migration',\n    assignee: 'Olivia Martinez',\n    status: 'blocked',\n    priority: 'high',\n    dueDate: '2024-03-24',\n    notes: 'Waiting for infrastructure team approval before proceeding',\n  },\n  {\n    id: 'TASK-006',\n    title: 'Update Documentation',\n    assignee: 'Lucas Anderson',\n    status: 'pending',\n    priority: 'low',\n    dueDate: '2024-03-30',\n    notes: 'Document new API endpoints and authentication flow',\n  },\n  {\n    id: 'TASK-007',\n    title: 'Security Audit',\n    assignee: 'Sophia Taylor',\n    status: 'completed',\n    priority: 'urgent',\n    dueDate: '2024-03-19',\n    notes:\n      'Conducted comprehensive security review and vulnerability assessment',\n  },\n];\n\nfunction getStatusBadge(status: Task['status']) {\n  switch (status) {\n    case 'pending':\n      return (\n        <Badge\n          className=\"border-0 bg-amber-500/15 text-amber-700 hover:bg-amber-500/25 dark:bg-amber-500/10 dark:text-amber-300 dark:hover:bg-amber-500/20\"\n          variant=\"outline\"\n        >\n          Pending\n        </Badge>\n      );\n    case 'in-progress':\n      return (\n        <Badge\n          className=\"border-0 bg-blue-500/15 text-blue-700 hover:bg-blue-500/25 dark:bg-blue-500/10 dark:text-blue-400 dark:hover:bg-blue-500/20\"\n          variant=\"outline\"\n        >\n          In Progress\n        </Badge>\n      );\n    case 'completed':\n      return (\n        <Badge\n          className=\"border-0 bg-green-500/15 text-green-700 hover:bg-green-500/25 dark:bg-green-500/10 dark:text-green-400 dark:hover:bg-green-500/20\"\n          variant=\"outline\"\n        >\n          Completed\n        </Badge>\n      );\n    case 'blocked':\n      return (\n        <Badge\n          className=\"border-0 bg-rose-500/15 text-rose-700 hover:bg-rose-500/25 dark:bg-rose-500/10 dark:text-rose-400 dark:hover:bg-rose-500/20\"\n          variant=\"outline\"\n        >\n          Blocked\n        </Badge>\n      );\n    default:\n      return <Badge variant=\"secondary\">{status}</Badge>;\n  }\n}\n\nexport default function Table02() {\n  const [pendingAction, setPendingAction] = useState<{\n    id: string;\n    type: TaskActionType;\n  } | null>(null);\n\n  const isTaskActionPending = (action: TaskActionType, taskId: string) =>\n    pendingAction?.id === taskId && pendingAction.type === action;\n\n  const isTaskBusy = (taskId: string) => pendingAction?.id === taskId;\n\n  const handleAction = (task: Task, actionType: TaskActionType) => {\n    setPendingAction({ id: task.id, type: actionType });\n    setTimeout(() => {\n      setPendingAction(null);\n      console.log(`Action \"${actionType}\" completed for task:`, task.title);\n    }, 1000);\n  };\n\n  const renderTaskRow = (task: Task) => {\n    const busy = isTaskBusy(task.id);\n    const startPending = isTaskActionPending('start', task.id);\n    const pausePending = isTaskActionPending('pause', task.id);\n    const completePending = isTaskActionPending('complete', task.id);\n    const deletePending = isTaskActionPending('delete', task.id);\n\n    return (\n      <TableRow className=\"hover:bg-muted/50\" key={task.id}>\n        <TableCell className=\"h-16 px-4 font-medium\">{task.title}</TableCell>\n        <TableCell className=\"h-16 px-4 text-muted-foreground text-sm\">\n          {task.assignee}\n        </TableCell>\n        <TableCell className=\"h-16 px-4\">\n          {getStatusBadge(task.status)}\n        </TableCell>\n\n        <TableCell className=\"h-16 px-4 text-muted-foreground text-sm\">\n          {task.dueDate}\n        </TableCell>\n        <TableCell className=\"h-16 max-w-[300px] px-4 text-muted-foreground text-sm\">\n          <TooltipProvider>\n            <Tooltip>\n              <TooltipTrigger\n                render={<span className=\"block cursor-help truncate\" />}\n              >\n                {task.notes}\n              </TooltipTrigger>\n              <TooltipContent className=\"max-w-md\">{task.notes}</TooltipContent>\n            </Tooltip>\n          </TooltipProvider>\n        </TableCell>\n        <TableCell className=\"h-16 px-4\">\n          <TooltipProvider>\n            <div className=\"flex items-center gap-1\">\n              {(task.status === 'pending' || task.status === 'blocked') && (\n                <Tooltip>\n                  <TooltipTrigger\n                    render={\n                      <Button\n                        aria-label=\"Start\"\n                        className=\"h-8 w-8\"\n                        disabled={busy}\n                        onClick={() => handleAction(task, 'start')}\n                        size=\"icon\"\n                        variant=\"outline\"\n                      />\n                    }\n                  >\n                    {startPending ? (\n                      <Loader2 className=\"size-4 animate-spin\" />\n                    ) : (\n                      <PlayIcon className=\"size-4\" />\n                    )}\n                  </TooltipTrigger>\n                  <TooltipContent>Start</TooltipContent>\n                </Tooltip>\n              )}\n              {task.status === 'in-progress' && (\n                <>\n                  <Tooltip>\n                    <TooltipTrigger\n                      render={\n                        <Button\n                          aria-label=\"Pause\"\n                          className=\"h-8 w-8\"\n                          disabled={busy}\n                          onClick={() => handleAction(task, 'pause')}\n                          size=\"icon\"\n                          variant=\"outline\"\n                        />\n                      }\n                    >\n                      {pausePending ? (\n                        <Loader2 className=\"size-4 animate-spin\" />\n                      ) : (\n                        <PauseIcon className=\"size-4\" />\n                      )}\n                    </TooltipTrigger>\n                    <TooltipContent>Pause</TooltipContent>\n                  </Tooltip>\n                  <Tooltip>\n                    <TooltipTrigger\n                      render={\n                        <Button\n                          aria-label=\"Complete\"\n                          className=\"h-8 w-8\"\n                          disabled={busy}\n                          onClick={() => handleAction(task, 'complete')}\n                          size=\"icon\"\n                          variant=\"outline\"\n                        />\n                      }\n                    >\n                      {completePending ? (\n                        <Loader2 className=\"size-4 animate-spin\" />\n                      ) : (\n                        <CheckCircle className=\"size-4\" />\n                      )}\n                    </TooltipTrigger>\n                    <TooltipContent>Complete</TooltipContent>\n                  </Tooltip>\n                </>\n              )}\n              <Tooltip>\n                <TooltipTrigger\n                  render={\n                    <Button\n                      aria-label=\"Delete\"\n                      className=\"h-8 w-8 text-destructive hover:bg-destructive hover:text-white\"\n                      disabled={busy}\n                      onClick={() => handleAction(task, 'delete')}\n                      size=\"icon\"\n                      variant=\"outline\"\n                    />\n                  }\n                >\n                  {deletePending ? (\n                    <Loader2 className=\"size-4 animate-spin\" />\n                  ) : (\n                    <Trash2Icon className=\"size-4\" />\n                  )}\n                </TooltipTrigger>\n                <TooltipContent>Delete</TooltipContent>\n              </Tooltip>\n              <Tooltip>\n                <TooltipTrigger\n                  render={\n                    <Button\n                      aria-label=\"View details\"\n                      className=\"h-8 w-8\"\n                      disabled={busy}\n                      onClick={() => handleAction(task, 'view')}\n                      size=\"icon\"\n                      variant=\"outline\"\n                    />\n                  }\n                >\n                  <FileTextIcon className=\"size-4\" />\n                </TooltipTrigger>\n                <TooltipContent>View Details</TooltipContent>\n              </Tooltip>\n            </div>\n          </TooltipProvider>\n        </TableCell>\n      </TableRow>\n    );\n  };\n\n  return (\n    <div className=\"w-[95%] rounded-lg border bg-card\">\n      <Table>\n        <TableHeader>\n          <TableRow className=\"border-b hover:bg-transparent\">\n            <TableHead className=\"h-12 px-4 font-medium\">Title</TableHead>\n            <TableHead className=\"h-12 px-4 font-medium\">Assignee</TableHead>\n            <TableHead className=\"h-12 w-[120px] px-4 font-medium\">\n              Status\n            </TableHead>\n\n            <TableHead className=\"h-12 px-4 font-medium\">Due Date</TableHead>\n            <TableHead className=\"h-12 px-4 font-medium\">Notes</TableHead>\n            <TableHead className=\"h-12 w-[180px] px-4 font-medium\">\n              Actions\n            </TableHead>\n          </TableRow>\n        </TableHeader>\n        <TableBody>{tasks.map(renderTaskRow)}</TableBody>\n      </Table>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "tables"
      ]
    },
    {
      "name": "table-03",
      "type": "registry:block",
      "title": "Table with Filters",
      "description": "A table with filters block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "badge",
        "select",
        "table"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/tables/table-03.tsx",
          "type": "registry:component",
          "target": "components/table-03.tsx",
          "content": "'use client';\n\nimport { useState } from 'react';\nimport { Badge } from '@/components/ui/badge';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow,\n} from '@/components/ui/table';\nimport { cn } from '@/lib/utils';\n\ntype Status = 'active' | 'pending' | 'discontinued' | 'on-hold';\n\ninterface Product {\n  sku: string;\n  productName: string;\n  stockLevel: number;\n  category: string;\n  status: Status;\n  unitPrice: string;\n  lastRestocked: string;\n}\n\nconst data: Product[] = [\n  {\n    sku: 'SKU-8472',\n    productName: 'Wireless Mouse Pro',\n    stockLevel: 245,\n    category: 'Electronics',\n    status: 'active',\n    unitPrice: '$24.99',\n    lastRestocked: 'Oct 15, 2024',\n  },\n  {\n    sku: 'SKU-3391',\n    productName: 'Ergonomic Keyboard',\n    stockLevel: 89,\n    category: 'Electronics',\n    status: 'active',\n    unitPrice: '$79.99',\n    lastRestocked: 'Oct 18, 2024',\n  },\n  {\n    sku: 'SKU-7156',\n    productName: 'Office Chair Deluxe',\n    stockLevel: 12,\n    category: 'Furniture',\n    status: 'pending',\n    unitPrice: '$299.99',\n    lastRestocked: 'Oct 12, 2024',\n  },\n  {\n    sku: 'SKU-9204',\n    productName: 'USB-C Hub Adapter',\n    stockLevel: 456,\n    category: 'Accessories',\n    status: 'active',\n    unitPrice: '$34.50',\n    lastRestocked: 'Oct 19, 2024',\n  },\n  {\n    sku: 'SKU-1638',\n    productName: 'Standing Desk Frame',\n    stockLevel: 5,\n    category: 'Furniture',\n    status: 'on-hold',\n    unitPrice: '$449.00',\n    lastRestocked: 'Oct 10, 2024',\n  },\n  {\n    sku: 'SKU-5529',\n    productName: 'Laptop Stand Aluminum',\n    stockLevel: 178,\n    category: 'Accessories',\n    status: 'active',\n    unitPrice: '$45.99',\n    lastRestocked: 'Oct 17, 2024',\n  },\n  {\n    sku: 'SKU-4817',\n    productName: 'Mechanical Keyboard RGB',\n    stockLevel: 0,\n    category: 'Electronics',\n    status: 'discontinued',\n    unitPrice: '$129.99',\n    lastRestocked: 'Oct 05, 2024',\n  },\n];\n\nfunction getStatusBadge(status: Status) {\n  switch (status) {\n    case 'active':\n      return (\n        <Badge\n          className=\"border-0 bg-green-500/15 text-green-700 hover:bg-green-500/25 dark:bg-green-500/10 dark:text-green-400 dark:hover:bg-green-500/20\"\n          variant=\"outline\"\n        >\n          Active\n        </Badge>\n      );\n    case 'pending':\n      return (\n        <Badge\n          className=\"border-0 bg-amber-500/15 text-amber-700 hover:bg-amber-500/25 dark:bg-amber-500/10 dark:text-amber-300 dark:hover:bg-amber-500/20\"\n          variant=\"outline\"\n        >\n          Pending\n        </Badge>\n      );\n    case 'discontinued':\n      return (\n        <Badge\n          className=\"border-0 bg-rose-500/15 text-rose-700 hover:bg-rose-500/25 dark:bg-rose-500/10 dark:text-rose-400 dark:hover:bg-rose-500/20\"\n          variant=\"outline\"\n        >\n          Discontinued\n        </Badge>\n      );\n    case 'on-hold':\n      return (\n        <Badge\n          className=\"border-0 bg-blue-500/15 text-blue-700 hover:bg-blue-500/25 dark:bg-blue-500/10 dark:text-blue-400 dark:hover:bg-blue-500/20\"\n          variant=\"outline\"\n        >\n          On Hold\n        </Badge>\n      );\n    default:\n      return null;\n  }\n}\n\nexport default function Table03() {\n  const [selectedCategory, setSelectedCategory] = useState<string>('all');\n\n  const filteredData = data.filter((item) => {\n    const categoryMatch =\n      selectedCategory === 'all' || item.category === selectedCategory;\n    return categoryMatch;\n  });\n\n  const uniqueCategories = Array.from(\n    new Set(data.map((item) => item.category))\n  );\n\n  return (\n    <div className=\"space-y-6\">\n      <div className=\"flex flex-col gap-4 md:flex-row md:items-center md:justify-between\">\n        <div>\n          <h3 className=\"text-balance font-semibold text-foreground text-lg\">\n            Product Inventory\n          </h3>\n          <p className=\"mt-1 text-pretty text-muted-foreground text-sm\">\n            Track and manage product stock levels across all warehouse\n            locations.\n          </p>\n        </div>\n        <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center\">\n          <Select\n            items={[\n              { value: 'all', label: 'All Categories' },\n              ...uniqueCategories.map((c) => ({ value: c, label: c })),\n            ]}\n            onValueChange={(value) => {\n              if (value) {\n                setSelectedCategory(value);\n              }\n            }}\n            value={selectedCategory}\n          >\n            <SelectTrigger className=\"w-full sm:w-[180px]\">\n              <SelectValue placeholder=\"Filter by category\" />\n            </SelectTrigger>\n            <SelectContent>\n              <SelectItem value=\"all\">All Categories</SelectItem>\n              {uniqueCategories.map((category) => (\n                <SelectItem key={category} value={category}>\n                  {category}\n                </SelectItem>\n              ))}\n            </SelectContent>\n          </Select>\n        </div>\n      </div>\n\n      <div className=\"rounded-lg border bg-card\">\n        <Table>\n          <TableHeader>\n            <TableRow className=\"border-b hover:bg-transparent\">\n              <TableHead className=\"h-12 px-4 font-medium\">SKU</TableHead>\n              <TableHead className=\"h-12 px-4 font-medium\">\n                Product Name\n              </TableHead>\n              <TableHead className=\"h-12 px-4 font-medium\">Category</TableHead>\n              <TableHead className=\"h-12 px-4 font-medium\">Status</TableHead>\n              <TableHead className=\"h-12 px-4 text-right font-medium\">\n                Unit Price\n              </TableHead>\n              <TableHead className=\"h-12 px-4 text-right font-medium\">\n                Last Restocked\n              </TableHead>\n            </TableRow>\n          </TableHeader>\n          <TableBody>\n            {filteredData.length > 0 ? (\n              filteredData.map((item) => (\n                <TableRow className=\"hover:bg-muted/50\" key={item.sku}>\n                  <TableCell className=\"h-14 px-4 font-medium font-mono text-sm tabular-nums\">\n                    {item.sku}\n                  </TableCell>\n                  <TableCell className=\"h-14 px-4 font-medium\">\n                    {item.productName}\n                  </TableCell>\n                  <TableCell className=\"h-14 px-4 text-muted-foreground text-sm\">\n                    {item.category}\n                  </TableCell>\n                  <TableCell className=\"h-14 px-4\">\n                    {getStatusBadge(item.status)}\n                  </TableCell>\n                  <TableCell className=\"h-14 px-4 text-right font-mono font-semibold text-sm tabular-nums\">\n                    {item.unitPrice}\n                  </TableCell>\n                  <TableCell className=\"h-14 px-4 text-right text-muted-foreground text-sm\">\n                    {item.lastRestocked}\n                  </TableCell>\n                </TableRow>\n              ))\n            ) : (\n              <TableRow>\n                <TableCell\n                  className=\"h-24 text-center text-muted-foreground\"\n                  colSpan={6}\n                >\n                  No products found matching the selected filters.\n                </TableCell>\n              </TableRow>\n            )}\n          </TableBody>\n        </Table>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "tables"
      ]
    },
    {
      "name": "table-04",
      "type": "registry:block",
      "title": "Table with Grouped Rows",
      "description": "A table with grouped rows block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "avatar",
        "badge",
        "table"
      ],
      "dependencies": [],
      "files": [
        {
          "path": "content/components/tables/table-04.tsx",
          "type": "registry:component",
          "target": "components/table-04.tsx",
          "content": "'use client';\n\nimport { Fragment } from 'react';\nimport { Avatar, AvatarFallback } from '@/components/ui/avatar';\nimport { Badge } from '@/components/ui/badge';\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow,\n} from '@/components/ui/table';\nimport { cn } from '@/lib/utils';\n\ninterface AssignedPerson {\n  name: string;\n  initials: string;\n}\n\ninterface TaskItem {\n  id: string;\n  task: string;\n  budget: string;\n  deadline: string;\n  assigned: AssignedPerson[];\n  status: string;\n}\n\ninterface TaskGroup {\n  name: string;\n  items: TaskItem[];\n}\n\ntype StatusVariant = 'success' | 'warning' | 'default' | 'secondary';\n\nconst avatarColors = [\n  'bg-blue-500',\n  'bg-purple-500',\n  'bg-emerald-500',\n  'bg-cyan-500',\n  'bg-rose-500',\n  'bg-indigo-500',\n];\n\nfunction getAvatarColor(initials: string) {\n  const seed = initials\n    .split('')\n    .reduce((acc, char) => acc + char.charCodeAt(0), 0);\n  return avatarColors[seed % avatarColors.length];\n}\n\nfunction AvatarStack({ people }: { people: AssignedPerson[] }) {\n  return (\n    <div className=\"-space-x-2 flex\">\n      {people.map((person, index) => (\n        <Avatar\n          className={cn(\n            'h-6 w-6 border-2 border-background text-[10px]',\n            getAvatarColor(person.initials)\n          )}\n          key={index}\n        >\n          <AvatarFallback\n            className={cn(\n              'font-medium text-white',\n              getAvatarColor(person.initials)\n            )}\n          >\n            {person.initials}\n          </AvatarFallback>\n        </Avatar>\n      ))}\n    </div>\n  );\n}\n\nconst statusStyles: Record<StatusVariant, { badge: string; dot: string }> = {\n  success: {\n    badge:\n      'bg-emerald-50 text-emerald-700 dark:bg-emerald-950 dark:text-emerald-300',\n    dot: 'bg-emerald-500',\n  },\n  warning: {\n    badge: 'bg-amber-50 text-amber-700 dark:bg-amber-950 dark:text-amber-300',\n    dot: 'bg-amber-500',\n  },\n  default: {\n    badge: 'bg-blue-50 text-blue-700 dark:bg-blue-950 dark:text-blue-300',\n    dot: 'bg-blue-500',\n  },\n  secondary: {\n    badge: 'bg-muted text-muted-foreground',\n    dot: 'bg-muted-foreground',\n  },\n};\n\nfunction StatusBadge({\n  status,\n  variant = 'default',\n}: {\n  status: string;\n  variant?: StatusVariant;\n}) {\n  const styles = statusStyles[variant];\n  return (\n    <Badge\n      className={cn('gap-1.5 rounded-full', styles.badge)}\n      variant=\"outline\"\n    >\n      <span\n        aria-hidden=\"true\"\n        className={cn('size-1.5 rounded-full', styles.dot)}\n      />\n      {status}\n    </Badge>\n  );\n}\n\nconst data: TaskGroup[] = [\n  {\n    name: 'Engineering',\n    items: [\n      {\n        id: '1',\n        task: 'API Integration Overhaul',\n        budget: '$32,000',\n        deadline: 'Dec 15, 2024',\n        assigned: [\n          { name: 'Marcus Chen', initials: 'MC' },\n          { name: 'Priya Sharma', initials: 'PS' },\n        ],\n        status: 'In Progress',\n      },\n      {\n        id: '2',\n        task: 'Database Migration',\n        budget: '$18,500',\n        deadline: 'Jan 20, 2025',\n        assigned: [{ name: 'David Kim', initials: 'DK' }],\n        status: 'Completed',\n      },\n      {\n        id: '3',\n        task: 'Mobile App Redesign',\n        budget: '$55,000',\n        deadline: 'Feb 28, 2025',\n        assigned: [\n          { name: 'Lena Rodriguez', initials: 'LR' },\n          { name: 'Tom Anderson', initials: 'TA' },\n          { name: 'Nina Patel', initials: 'NP' },\n        ],\n        status: 'Planning',\n      },\n    ],\n  },\n  {\n    name: 'Marketing',\n    items: [\n      {\n        id: '4',\n        task: 'Q1 Campaign Launch',\n        budget: '$24,000',\n        deadline: 'Jan 5, 2025',\n        assigned: [\n          { name: 'Rachel Green', initials: 'RG' },\n          { name: 'Chris Evans', initials: 'CE' },\n        ],\n        status: 'In Progress',\n      },\n      {\n        id: '5',\n        task: 'Brand Refresh Project',\n        budget: '$42,000',\n        deadline: 'Mar 1, 2025',\n        assigned: [{ name: 'Monica Geller', initials: 'MG' }],\n        status: 'Planning',\n      },\n    ],\n  },\n  {\n    name: 'Operations',\n    items: [\n      {\n        id: '6',\n        task: 'Vendor Contract Review',\n        budget: '$8,000',\n        deadline: 'Dec 30, 2024',\n        assigned: [\n          { name: 'Joe Tribbiani', initials: 'JT' },\n          { name: 'Phoebe Buffay', initials: 'PB' },\n        ],\n        status: 'Completed',\n      },\n      {\n        id: '7',\n        task: 'Office Expansion Setup',\n        budget: '$120,000',\n        deadline: 'Apr 15, 2025',\n        assigned: [{ name: 'Ross Geller', initials: 'RG' }],\n        status: 'On Hold',\n      },\n    ],\n  },\n];\n\nfunction getStatusVariant(status: string): StatusVariant {\n  switch (status) {\n    case 'Completed':\n      return 'success';\n    case 'In Progress':\n      return 'default';\n    case 'Planning':\n      return 'secondary';\n    case 'On Hold':\n      return 'warning';\n    default:\n      return 'default';\n  }\n}\n\nexport default function Table04() {\n  return (\n    <div className=\"rounded-lg border\">\n      <Table>\n        <TableHeader>\n          <TableRow>\n            <TableHead className=\"w-48 font-medium\">Task</TableHead>\n            <TableHead className=\"font-medium\">Budget</TableHead>\n            <TableHead className=\"font-medium\">Deadline</TableHead>\n            <TableHead className=\"font-medium\">Assigned</TableHead>\n            <TableHead className=\"w-28 font-medium\">Status</TableHead>\n          </TableRow>\n        </TableHeader>\n        <TableBody>\n          {data.map((group) => (\n            <Fragment key={group.name}>\n              <TableRow className=\"bg-muted/50 hover:bg-muted/50\">\n                <TableCell className=\"py-2 font-semibold\" colSpan={5}>\n                  {group.name}\n                  <span className=\"ml-2 font-normal text-muted-foreground\">\n                    {group.items.length}\n                  </span>\n                </TableCell>\n              </TableRow>\n              {group.items.map((item) => (\n                <TableRow key={item.id}>\n                  <TableCell className=\"font-medium\">{item.task}</TableCell>\n                  <TableCell>{item.budget}</TableCell>\n                  <TableCell>{item.deadline}</TableCell>\n                  <TableCell>\n                    <AvatarStack people={item.assigned} />\n                  </TableCell>\n                  <TableCell>\n                    <StatusBadge\n                      status={item.status}\n                      variant={getStatusVariant(item.status)}\n                    />\n                  </TableCell>\n                </TableRow>\n              ))}\n            </Fragment>\n          ))}\n        </TableBody>\n      </Table>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "tables"
      ]
    },
    {
      "name": "table-05",
      "type": "registry:block",
      "title": "Data Table",
      "description": "A data table block.",
      "author": "ephraim duncan <https://ephraimduncan.com>",
      "registryDependencies": [
        "badge",
        "button",
        "checkbox",
        "dropdown-menu",
        "input",
        "select",
        "table"
      ],
      "dependencies": [
        "@tanstack/react-table",
        "lucide-react"
      ],
      "files": [
        {
          "path": "content/components/tables/table-05.tsx",
          "type": "registry:component",
          "target": "components/table-05.tsx",
          "content": "'use client';\n\nimport {\n  type ColumnDef,\n  flexRender,\n  getCoreRowModel,\n  getFilteredRowModel,\n  getPaginationRowModel,\n  getSortedRowModel,\n  type SortingState,\n  useReactTable,\n} from '@tanstack/react-table';\nimport {\n  ChevronLeft,\n  ChevronRight,\n  Eye,\n  MoreHorizontal,\n  Pencil,\n  Trash2,\n} from 'lucide-react';\nimport { useState } from 'react';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { Checkbox } from '@/components/ui/checkbox';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Input } from '@/components/ui/input';\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue,\n} from '@/components/ui/select';\nimport {\n  Table,\n  TableBody,\n  TableCell,\n  TableHead,\n  TableHeader,\n  TableRow,\n} from '@/components/ui/table';\nimport { cn } from '@/lib/utils';\n\ntype Status = 'completed' | 'pending' | 'processing' | 'cancelled';\n\ninterface Item {\n  id: string;\n  name: string;\n  date: string;\n  status: Status;\n  amount: string;\n}\n\nconst statusConfig: Record<Status, { label: string; className: string }> = {\n  completed: {\n    label: 'Completed',\n    className:\n      'bg-emerald-500/15 text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-400',\n  },\n  pending: {\n    label: 'Pending',\n    className:\n      'bg-amber-500/15 text-amber-700 dark:bg-amber-500/10 dark:text-amber-400',\n  },\n  processing: {\n    label: 'Processing',\n    className:\n      'bg-blue-500/15 text-blue-700 dark:bg-blue-500/10 dark:text-blue-400',\n  },\n  cancelled: {\n    label: 'Cancelled',\n    className:\n      'bg-rose-500/15 text-rose-700 dark:bg-rose-500/10 dark:text-rose-400',\n  },\n};\n\nfunction StatusBadge({ status }: { status: Status }) {\n  const config = statusConfig[status];\n  return (\n    <Badge className={cn('border-0', config.className)} variant=\"outline\">\n      {config.label}\n    </Badge>\n  );\n}\n\nconst columns: ColumnDef<Item>[] = [\n  {\n    id: 'select',\n    header: ({ table }) => (\n      <Checkbox\n        aria-label=\"Select all\"\n        checked={table.getIsAllPageRowsSelected()}\n        indeterminate={\n          table.getIsSomePageRowsSelected() && !table.getIsAllPageRowsSelected()\n        }\n        onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}\n      />\n    ),\n    cell: ({ row }) => (\n      <Checkbox\n        aria-label=\"Select row\"\n        checked={row.getIsSelected()}\n        onCheckedChange={(value) => row.toggleSelected(!!value)}\n      />\n    ),\n    enableSorting: false,\n    enableHiding: false,\n  },\n  {\n    accessorKey: 'name',\n    header: 'Name',\n    cell: ({ row }) => (\n      <span className=\"font-medium\">{row.getValue('name')}</span>\n    ),\n  },\n  {\n    accessorKey: 'date',\n    header: 'Date',\n  },\n  {\n    accessorKey: 'status',\n    header: 'Status',\n    cell: ({ row }) => <StatusBadge status={row.getValue('status')} />,\n  },\n  {\n    accessorKey: 'amount',\n    header: () => <div className=\"text-right\">Amount</div>,\n    cell: ({ row }) => (\n      <div className=\"text-right font-medium\">{row.getValue('amount')}</div>\n    ),\n  },\n  {\n    id: 'actions',\n    cell: () => (\n      <div className=\"text-right\">\n        <DropdownMenu>\n          <DropdownMenuTrigger\n            render={<Button className=\"h-8 w-8\" size=\"icon\" variant=\"ghost\" />}\n          >\n            <MoreHorizontal className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Open menu</span>\n          </DropdownMenuTrigger>\n          <DropdownMenuContent align=\"end\">\n            <DropdownMenuItem>\n              <Eye className=\"mr-2 h-4 w-4\" />\n              View details\n            </DropdownMenuItem>\n            <DropdownMenuItem>\n              <Pencil className=\"mr-2 h-4 w-4\" />\n              Edit\n            </DropdownMenuItem>\n            <DropdownMenuSeparator />\n            <DropdownMenuItem className=\"text-destructive\">\n              <Trash2 className=\"mr-2 h-4 w-4\" />\n              Delete\n            </DropdownMenuItem>\n          </DropdownMenuContent>\n        </DropdownMenu>\n      </div>\n    ),\n  },\n];\n\nconst data: Item[] = [\n  {\n    id: '1',\n    name: 'Project Alpha',\n    date: 'Jan 15, 2024',\n    status: 'completed',\n    amount: '$2,500',\n  },\n  {\n    id: '2',\n    name: 'Website Redesign',\n    date: 'Feb 3, 2024',\n    status: 'processing',\n    amount: '$4,200',\n  },\n  {\n    id: '3',\n    name: 'Mobile App MVP',\n    date: 'Feb 18, 2024',\n    status: 'pending',\n    amount: '$8,750',\n  },\n  {\n    id: '4',\n    name: 'Brand Identity',\n    date: 'Mar 5, 2024',\n    status: 'completed',\n    amount: '$1,800',\n  },\n  {\n    id: '5',\n    name: 'Marketing Campaign',\n    date: 'Mar 22, 2024',\n    status: 'cancelled',\n    amount: '$3,400',\n  },\n  {\n    id: '6',\n    name: 'Analytics Dashboard',\n    date: 'Apr 8, 2024',\n    status: 'processing',\n    amount: '$5,600',\n  },\n  {\n    id: '7',\n    name: 'E-commerce Platform',\n    date: 'Apr 25, 2024',\n    status: 'pending',\n    amount: '$12,000',\n  },\n  {\n    id: '8',\n    name: 'API Integration',\n    date: 'May 10, 2024',\n    status: 'completed',\n    amount: '$3,200',\n  },\n];\n\nexport default function Table05() {\n  const [sorting, setSorting] = useState<SortingState>([]);\n  const [rowSelection, setRowSelection] = useState({});\n  const [globalFilter, setGlobalFilter] = useState('');\n\n  const table = useReactTable({\n    data,\n    columns,\n    getCoreRowModel: getCoreRowModel(),\n    getPaginationRowModel: getPaginationRowModel(),\n    getSortedRowModel: getSortedRowModel(),\n    getFilteredRowModel: getFilteredRowModel(),\n    onSortingChange: setSorting,\n    onRowSelectionChange: setRowSelection,\n    onGlobalFilterChange: setGlobalFilter,\n    globalFilterFn: 'includesString',\n    state: {\n      sorting,\n      rowSelection,\n      globalFilter,\n    },\n    initialState: {\n      pagination: { pageSize: 5 },\n    },\n  });\n\n  const pageCount = table.getPageCount();\n  const currentPage = table.getState().pagination.pageIndex + 1;\n\n  return (\n    <div className=\"w-full max-w-3xl space-y-4\">\n      <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <div className=\"flex items-center gap-2\">\n          <span className=\"text-muted-foreground text-sm\">Show</span>\n          <Select\n            onValueChange={(value) => table.setPageSize(Number(value))}\n            value={String(table.getState().pagination.pageSize)}\n          >\n            <SelectTrigger className=\"h-8 w-16\">\n              <SelectValue />\n            </SelectTrigger>\n            <SelectContent>\n              {[5, 10, 20].map((size) => (\n                <SelectItem key={size} value={String(size)}>\n                  {size}\n                </SelectItem>\n              ))}\n            </SelectContent>\n          </Select>\n          <span className=\"text-muted-foreground text-sm\">entries</span>\n        </div>\n        <Input\n          className=\"h-8 w-full sm:w-64\"\n          onChange={(e) => setGlobalFilter(e.target.value)}\n          placeholder=\"Search...\"\n          value={globalFilter}\n        />\n      </div>\n\n      <div className=\"rounded-lg border\">\n        <Table>\n          <TableHeader>\n            {table.getHeaderGroups().map((headerGroup) => (\n              <TableRow key={headerGroup.id}>\n                {headerGroup.headers.map((header) => (\n                  <TableHead key={header.id}>\n                    {header.isPlaceholder\n                      ? null\n                      : flexRender(\n                          header.column.columnDef.header,\n                          header.getContext()\n                        )}\n                  </TableHead>\n                ))}\n              </TableRow>\n            ))}\n          </TableHeader>\n          <TableBody>\n            {table.getRowModel().rows.length ? (\n              table.getRowModel().rows.map((row) => (\n                <TableRow\n                  data-state={row.getIsSelected() && 'selected'}\n                  key={row.id}\n                >\n                  {row.getVisibleCells().map((cell) => (\n                    <TableCell key={cell.id}>\n                      {flexRender(\n                        cell.column.columnDef.cell,\n                        cell.getContext()\n                      )}\n                    </TableCell>\n                  ))}\n                </TableRow>\n              ))\n            ) : (\n              <TableRow>\n                <TableCell\n                  className=\"h-24 text-center\"\n                  colSpan={columns.length}\n                >\n                  No results.\n                </TableCell>\n              </TableRow>\n            )}\n          </TableBody>\n        </Table>\n      </div>\n\n      <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <p className=\"text-pretty text-muted-foreground text-sm\">\n          Showing{' '}\n          {table.getState().pagination.pageIndex *\n            table.getState().pagination.pageSize +\n            1}{' '}\n          to{' '}\n          {Math.min(\n            (table.getState().pagination.pageIndex + 1) *\n              table.getState().pagination.pageSize,\n            table.getFilteredRowModel().rows.length\n          )}{' '}\n          of {table.getFilteredRowModel().rows.length} entries\n        </p>\n        <div className=\"flex items-center gap-1\">\n          <Button\n            aria-label=\"Previous page\"\n            className=\"h-8 w-8\"\n            disabled={!table.getCanPreviousPage()}\n            onClick={() => table.previousPage()}\n            size=\"icon\"\n            variant=\"outline\"\n          >\n            <ChevronLeft className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Previous page</span>\n          </Button>\n          {Array.from({ length: pageCount }, (_, i) => i + 1).map((page) => (\n            <Button\n              aria-label={`Go to page ${page}`}\n              className=\"h-8 w-8\"\n              key={page}\n              onClick={() => table.setPageIndex(page - 1)}\n              size=\"icon\"\n              variant={currentPage === page ? 'default' : 'outline'}\n            >\n              {page}\n            </Button>\n          ))}\n          <Button\n            aria-label=\"Next page\"\n            className=\"h-8 w-8\"\n            disabled={!table.getCanNextPage()}\n            onClick={() => table.nextPage()}\n            size=\"icon\"\n            variant=\"outline\"\n          >\n            <ChevronRight className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Next page</span>\n          </Button>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
        }
      ],
      "categories": [
        "tables"
      ]
    }
  ]
}