{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "liquid",
  "dependencies": [
    "class-variance-authority",
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/watermelon-ui/liquid.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { isMotionComponent, motion, type HTMLMotionProps } from 'motion/react';\nimport { cn } from '@/lib/utils';\n\nconst buttonVariants = cva(\n  \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[box-shadow,_color,_background-color,_border-color,_outline-color,_text-decoration-color,_fill,_stroke] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n  {\n    variants: {\n      variant: {\n        default:\n          '[--liquid-button-background-color:var(--accent)] [--liquid-button-color:var(--primary)] text-primary hover:text-primary-foreground shadow-xs',\n        destructive:\n          '[--liquid-button-background-color:var(--accent)] [--liquid-button-color:var(--destructive)] text-white shadow-xs focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40',\n        secondary:\n          '[--liquid-button-background-color:var(--accent)] [--liquid-button-color:var(--secondary)] text-secondary hover:text-secondary-foreground shadow-xs',\n        ghost:\n          '[--liquid-button-background-color:var(--transparent)] [--liquid-button-color:var(--primary)] text-primary hover:text-primary-foreground shadow-xs',\n      },\n      size: {\n        default: 'h-9 px-4 py-2 has-[>svg]:px-3',\n        sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',\n        lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',\n        icon: 'size-9',\n        'icon-sm': 'size-8 rounded-md',\n        'icon-lg': 'size-10 rounded-md',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'default',\n    },\n  },\n);\n\ntype LiquidButtonProps = LiquidButtonPrimitiveProps &\n  VariantProps<typeof buttonVariants>;\n\nfunction LiquidButton({\n  className,\n  variant,\n  size,\n  ...props\n}: LiquidButtonProps) {\n  return (\n    <LiquidButtonPrimitive\n      className={cn(buttonVariants({ variant, size, className }))}\n      {...props}\n    />\n  );\n}\n\nexport { LiquidButton, buttonVariants, type LiquidButtonProps };\n\n\ntype LiquidButtonPrimitiveProps = WithAsChild<\n  HTMLMotionProps<'button'> & {\n    delay?: string;\n    fillHeight?: string;\n    hoverScale?: number;\n    tapScale?: number;\n  }\n>;\n\nfunction LiquidButtonPrimitive({\n  delay = '0.3s',\n  fillHeight = '3px',\n  hoverScale = 1.05,\n  tapScale = 0.95,\n  asChild = false,\n  ...props\n}: LiquidButtonPrimitiveProps) {\n  const Component = asChild ? Slot : motion.button;\n\n  return (\n    <Component\n      whileTap={{ scale: tapScale }}\n      whileHover={{\n        scale: hoverScale,\n        '--liquid-button-fill-width': '100%',\n        '--liquid-button-fill-height': '100%',\n        '--liquid-button-delay': delay,\n        transition: {\n          '--liquid-button-fill-width': { duration: 0 },\n          '--liquid-button-fill-height': { duration: 0 },\n          '--liquid-button-delay': { duration: 0 },\n        },\n      }}\n      style={\n        {\n          '--liquid-button-fill-width': '-1%',\n          '--liquid-button-fill-height': fillHeight,\n          '--liquid-button-delay': '0s',\n          background:\n            'linear-gradient(var(--liquid-button-color) 0 0) no-repeat calc(200% - var(--liquid-button-fill-width, -1%)) 100% / 200% var(--liquid-button-fill-height, 0.2em)',\n          backgroundColor: 'var(--liquid-button-background-color)',\n          transition: `background ${delay} var(--liquid-button-delay, 0s), color ${delay} ${delay}, background-position ${delay} calc(${delay} - var(--liquid-button-delay, 0s))`,\n        } as React.CSSProperties\n      }\n      {...props}\n    />\n  );\n}\n\n\n\ntype AnyProps = Record<string, unknown>;\n\ntype DOMMotionProps<T extends HTMLElement = HTMLElement> = Omit<\n  HTMLMotionProps<keyof HTMLElementTagNameMap>,\n  'ref'\n> & { ref?: React.Ref<T> };\n\ntype WithAsChild<Base extends object> =\n  | (Base & { asChild: true; children: React.ReactElement })\n  | (Base & { asChild?: false | undefined });\n\ntype SlotProps<T extends HTMLElement = HTMLElement> = {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  children?: any;\n} & DOMMotionProps<T>;\n\nfunction mergeRefs<T>(\n  ...refs: (React.Ref<T> | undefined)[]\n): React.RefCallback<T> {\n  return (node) => {\n    refs.forEach((ref) => {\n      if (!ref) return;\n      if (typeof ref === 'function') {\n        ref(node);\n      } else {\n        (ref as React.RefObject<T | null>).current = node;\n      }\n    });\n  };\n}\n\nfunction mergeProps<T extends HTMLElement>(\n  childProps: AnyProps,\n  slotProps: DOMMotionProps<T>,\n): AnyProps {\n  const merged: AnyProps = { ...childProps, ...slotProps };\n\n  if (childProps.className || slotProps.className) {\n    merged.className = cn(\n      childProps.className as string,\n      slotProps.className as string,\n    );\n  }\n\n  if (childProps.style || slotProps.style) {\n    merged.style = {\n      ...(childProps.style as React.CSSProperties),\n      ...(slotProps.style as React.CSSProperties),\n    };\n  }\n\n  return merged;\n}\n\nfunction Slot<T extends HTMLElement = HTMLElement>({\n  children,\n  ref,\n  ...props\n}: SlotProps<T>) {\n  const isAlreadyMotion =\n    typeof children.type === 'object' &&\n    children.type !== null &&\n    isMotionComponent(children.type);\n\n  const Base = React.useMemo(\n    () =>\n      isAlreadyMotion\n        ? (children.type as React.ElementType)\n        : motion.create(children.type as React.ElementType),\n    [isAlreadyMotion, children.type],\n  );\n\n  if (!React.isValidElement(children)) return null;\n\n  const { ref: childRef, ...childProps } = children.props as AnyProps;\n\n  const mergedProps = mergeProps(childProps, props);\n\n  return (\n    // eslint-disable-next-line react-hooks/static-components\n    <Base {...mergedProps} ref={mergeRefs(childRef as React.Ref<T>, ref)} />\n  );\n}\n\n",
      "type": "registry:ui",
      "target": "components/ui/liquid.tsx"
    }
  ],
  "type": "registry:ui"
}
