{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "button",
  "title": "Ninaero button",
  "dependencies": [
    "@base-ui/react@^1.9.0",
    "class-variance-authority@^0.7.1",
    "cn@^0.4.0"
  ],
  "registryDependencies": [
    "https://ninaero.pages.dev/r/theme.json",
    "https://ninaero.pages.dev/r/sound-provider.json"
  ],
  "files": [
    {
      "path": "registry/ninaero/ui/button.tsx",
      "content": "import type { Button as ButtonPrimitive } from \"@base-ui/react/button\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"cn\";\n\nimport { SoundButton } from \"./button-feedback\";\n\nconst buttonVariants = cva(\n  \"ninaero-button group/button inline-flex shrink-0 items-center justify-center bg-clip-padding text-sm type-label whitespace-nowrap select-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n  {\n    variants: {\n      variant: {\n        default: \"ninaero-button--primary\",\n        outline: \"ninaero-button--outline\",\n        secondary: \"ninaero-button--secondary\",\n        ghost: \"ninaero-button--ghost\",\n        destructive: \"ninaero-button--destructive\",\n        link: \"ninaero-button--link\",\n      },\n      size: {\n        default: \"h-8 gap-2 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n        xs: \"h-6 gap-1 [--button-corner:0.75rem] px-2 text-xs leading-4 [&_svg:not([class*='size-'])]:size-3\",\n        sm: \"h-7 gap-1 [--button-corner:0.875rem] px-2 text-[0.8rem] leading-4 [&_svg:not([class*='size-'])]:size-3.5\",\n        lg: \"h-9 gap-2 [--button-corner:1.125rem] px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n        xl: \"h-12 gap-2 [--button-corner:1.5rem] px-6 text-base leading-5 has-data-[icon=inline-end]:pr-5 has-data-[icon=inline-start]:pl-5 [&_svg:not([class*='size-'])]:size-5\",\n        icon: \"size-8\",\n        \"icon-xs\": \"size-6 [--button-corner:0.75rem] [&_svg:not([class*='size-'])]:size-3\",\n        \"icon-sm\": \"size-7 [--button-corner:0.875rem]\",\n        \"icon-lg\": \"size-9 [--button-corner:1.125rem]\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n      size: \"default\",\n    },\n  },\n);\n\nfunction Button({\n  className,\n  variant = \"default\",\n  size = \"default\",\n  sound = true,\n  ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants> & { sound?: boolean }) {\n  return (\n    <SoundButton\n      data-slot=\"button\"\n      data-variant={variant}\n      data-size={size}\n      className={cn(buttonVariants({ variant, size, className }))}\n      sound={sound}\n      {...props}\n    />\n  );\n}\n\nexport { Button, buttonVariants };\n",
      "type": "registry:ui"
    },
    {
      "path": "registry/ninaero/ui/button-feedback.tsx",
      "content": "\"use client\";\n\nimport { Button as ButtonPrimitive } from \"@base-ui/react/button\";\n\nimport { useControlSound, HoverSound } from \"./sound-feedback\";\n\n// Keep the feedback hook behind a client boundary so buttonVariants remains usable on the server.\nexport function SoundButton({\n  onClick,\n  sound,\n  ...props\n}: ButtonPrimitive.Props & { sound: boolean }) {\n  const { play } = useControlSound(sound);\n  return (\n    <HoverSound sound={sound}>\n      <ButtonPrimitive\n        {...props}\n        onClick={(event) => {\n          onClick?.(event);\n          if (\n            sound &&\n            !props.disabled &&\n            !event.defaultPrevented &&\n            !event.baseUIHandlerPrevented\n          ) {\n            play(\"tap\");\n          }\n        }}\n      />\n    </HoverSound>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}