{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "shy-heart",
  "title": "Shy Heart",
  "description": "A resizable brand-outline heart that leans left on hover before revealing soft blush marks.",
  "files": [
    {
      "path": "registry/base/ui/shy-heart.tsx",
      "content": "import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport \"./shy-heart.css\";\n\ntype ShyHeartTimingValue = number | string;\ntype ShyHeartLengthValue = number | string;\n\ntype ShyHeartStyle = React.CSSProperties & {\n  \"--shy-heart-duration\"?: string;\n  \"--shy-heart-size\"?: string;\n  \"--shy-heart-tilt-duration\"?: string;\n};\n\nexport type ShyHeartProps = Omit<\n  React.ComponentProps<\"span\">,\n  \"children\"\n> & {\n  /** Enable the heart entrance and hover reaction. Defaults to true. */\n  animated?: boolean;\n  /** Entrance duration. Numeric values are converted to ms. */\n  duration?: ShyHeartTimingValue;\n  /** Heart width. Numeric values are converted to px. Defaults to 64px. */\n  size?: ShyHeartLengthValue;\n  /** Hover-tilt duration. Numeric values are converted to ms. */\n  tiltDuration?: ShyHeartTimingValue;\n  /** Accessible label. Omit for a decorative heart. */\n  label?: string;\n  /** Classes applied to the outlined heart body. */\n  heartClassName?: string;\n  /** Classes applied to both three-line blush groups. */\n  blushClassName?: string;\n};\n\nexport function ShyHeart({\n  animated = true,\n  \"aria-hidden\": ariaHidden,\n  \"aria-label\": ariaLabel,\n  blushClassName,\n  className,\n  duration,\n  heartClassName,\n  label,\n  ref,\n  size,\n  style,\n  tiltDuration,\n  ...props\n}: ShyHeartProps) {\n  const accessibleLabel = label ?? ariaLabel;\n  const shyHeartStyle: ShyHeartStyle = { ...style };\n\n  if (duration !== undefined) {\n    shyHeartStyle[\"--shy-heart-duration\"] = toCssTime(duration);\n  }\n\n  if (size !== undefined) {\n    shyHeartStyle[\"--shy-heart-size\"] = toCssLength(size);\n  }\n\n  if (tiltDuration !== undefined) {\n    shyHeartStyle[\"--shy-heart-tilt-duration\"] = toCssTime(tiltDuration);\n  }\n\n  return (\n    <span\n      ref={ref}\n      data-slot=\"shy-heart\"\n      data-animated={animated ? \"\" : undefined}\n      role={accessibleLabel ? \"img\" : undefined}\n      aria-label={accessibleLabel}\n      aria-hidden={accessibleLabel ? undefined : (ariaHidden ?? true)}\n      className={cn(\n        \"shy-heart relative inline-flex shrink-0 items-center justify-center text-foreground\",\n        className,\n      )}\n      style={shyHeartStyle}\n      {...props}\n    >\n      <svg\n        aria-hidden=\"true\"\n        className=\"shy-heart-svg h-auto w-full overflow-visible\"\n        viewBox=\"0 0 256 256\"\n      >\n        <g className=\"shy-heart-motion-stage\">\n          <g className=\"shy-heart-figure\">\n            <path\n              data-slot=\"shy-heart-body\"\n              className={cn(\"shy-heart-body\", heartClassName)}\n              d=\"M128 224.6L119.2 216.8C54 158.8 16 124 16 78.4C16 46 39.2 24 72 24C94.8 24 113.8 37.2 128 60C142.2 37.2 161.2 24 184 24C216.8 24 240 46 240 78.4C240 124 202 158.8 136.8 216.8L128 224.6Z\"\n            />\n            <g\n              data-slot=\"shy-heart-blush-left\"\n              className={cn(\n                \"shy-heart-blush shy-heart-blush-left\",\n                blushClassName,\n              )}\n            >\n              <path\n                className=\"shy-heart-blush-backdrop\"\n                d=\"M50 120H103\"\n              />\n              <g className=\"shy-heart-blush-lines\">\n                <path d=\"M65 108V127\" />\n                <path d=\"M77 108V127\" />\n                <path d=\"M89 108V127\" />\n              </g>\n            </g>\n            <g\n              data-slot=\"shy-heart-blush-right\"\n              className={cn(\n                \"shy-heart-blush shy-heart-blush-right\",\n                blushClassName,\n              )}\n            >\n              <path\n                className=\"shy-heart-blush-backdrop\"\n                d=\"M153 120H206\"\n              />\n              <g className=\"shy-heart-blush-lines\">\n                <path d=\"M191 108V127\" />\n                <path d=\"M179 108V127\" />\n                <path d=\"M167 108V127\" />\n              </g>\n            </g>\n          </g>\n        </g>\n      </svg>\n    </span>\n  );\n}\n\nfunction toCssTime(value: ShyHeartTimingValue) {\n  return typeof value === \"number\" ? `${value}ms` : value;\n}\n\nfunction toCssLength(value: ShyHeartLengthValue) {\n  return typeof value === \"number\" ? `${value}px` : value;\n}\n",
      "type": "registry:ui",
      "target": "@ui/shy-heart.tsx"
    },
    {
      "path": "registry/base/ui/shy-heart.css",
      "content": "/* Defaults are layered for customization. Normal unlayered styles and\n   utilities in a later layer can override them. */\n@layer components {\n  .shy-heart {\n    --shy-heart-size: 64px;\n    --shy-heart-duration: 240ms;\n    --shy-heart-tilt-duration: 220ms;\n    --shy-heart-ease-out: cubic-bezier(0.23, 1, 0.32, 1);\n    --shy-heart-ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);\n    --shy-heart-blush-color: var(--ericts-shy-heart-blush);\n    --shy-heart-blush-backdrop-color: var(\n      --ericts-shy-heart-blush-baseline\n    );\n    width: var(--shy-heart-size);\n  }\n\n  .shy-heart-svg {\n    display: block;\n  }\n\n  .shy-heart-motion-stage,\n  .shy-heart-figure,\n  .shy-heart-blush {\n    transform-box: view-box;\n  }\n\n  .shy-heart-motion-stage {\n    transform-origin: 52% 72%;\n  }\n\n  .shy-heart-figure,\n  .shy-heart-blush {\n    transform-origin: center;\n  }\n\n  .shy-heart-body {\n    fill: none;\n    stroke: currentColor;\n    stroke-linecap: round;\n    stroke-linejoin: round;\n    stroke-width: 16;\n  }\n\n  .shy-heart-blush {\n    color: var(--shy-heart-blush-color);\n    fill: none;\n    stroke-linecap: round;\n    stroke-linejoin: round;\n  }\n\n  .shy-heart-blush-backdrop {\n    stroke: var(--shy-heart-blush-backdrop-color);\n    stroke-width: 18;\n    opacity: 0.36;\n  }\n\n  .shy-heart-blush-lines {\n    stroke: currentColor;\n    stroke-width: 6;\n  }\n\n  .shy-heart[data-animated] .shy-heart-motion-stage {\n    transition: transform var(--shy-heart-tilt-duration)\n      var(--shy-heart-ease-in-out);\n  }\n\n  .shy-heart[data-animated] .shy-heart-figure {\n    animation: shy-heart-arrive var(--shy-heart-duration)\n      var(--shy-heart-ease-out) both;\n  }\n\n  .shy-heart[data-animated] .shy-heart-blush {\n    opacity: 0;\n    transform: translateY(2%) scale(0.96);\n    transition:\n      opacity 180ms var(--shy-heart-ease-out),\n      transform 180ms var(--shy-heart-ease-out);\n  }\n\n  .shy-heart[data-animated]:focus-visible .shy-heart-motion-stage {\n    transform: translate(-1%, 1%) rotate(-8deg);\n  }\n\n  .shy-heart[data-animated]:focus-visible .shy-heart-blush {\n    opacity: 1;\n    transform: translateY(0) scale(1);\n    transition-delay: 90ms;\n  }\n\n  .shy-heart[data-animated]:active .shy-heart-motion-stage {\n    transform: translate(-1%, 1%) rotate(-8deg) scale(0.96);\n    transition-duration: 140ms;\n  }\n\n  .shy-heart[data-animated]:active .shy-heart-blush {\n    opacity: 1;\n    transform: translateY(0) scale(1);\n    transition-delay: 0ms;\n    transition-duration: 140ms;\n  }\n\n  @keyframes shy-heart-arrive {\n    from {\n      opacity: 0.64;\n      transform: translateY(2%) scale(0.96);\n    }\n\n    72% {\n      opacity: 1;\n      transform: translateY(0) scale(1.025, 0.985);\n    }\n\n    to {\n      opacity: 1;\n      transform: translateY(0) scale(1);\n    }\n  }\n\n  @media (hover: hover) and (pointer: fine) {\n    .shy-heart[data-animated]:hover .shy-heart-motion-stage {\n      transform: translate(-1%, 1%) rotate(-8deg);\n      will-change: transform;\n    }\n\n    .shy-heart[data-animated]:hover .shy-heart-blush {\n      opacity: 1;\n      transform: translateY(0) scale(1);\n      transition-delay: 90ms;\n    }\n  }\n\n  @keyframes shy-heart-fade {\n    from {\n      opacity: 0.64;\n    }\n\n    to {\n      opacity: 1;\n    }\n  }\n}\n\n/* Motion guards override ordinary customization, including inline timing.\n   Keep these outside the defaults layer; only motion declarations are important. */\n@media (prefers-reduced-motion: reduce) {\n  .shy-heart[data-animated] .shy-heart-figure {\n    animation-name: shy-heart-fade !important;\n  }\n\n  .shy-heart[data-animated] .shy-heart-motion-stage {\n    transition: none !important;\n  }\n\n  .shy-heart[data-animated] .shy-heart-blush {\n    transform: none !important;\n    transition: opacity 160ms var(--shy-heart-ease-out) !important;\n  }\n\n  .shy-heart[data-animated]:focus-visible .shy-heart-motion-stage {\n    transform: none !important;\n  }\n\n  .shy-heart[data-animated]:active .shy-heart-motion-stage {\n    transform: none !important;\n  }\n\n  .shy-heart[data-animated]:focus-visible .shy-heart-blush {\n    transform: none !important;\n    transition-delay: 0ms !important;\n  }\n\n  .shy-heart[data-animated]:active .shy-heart-blush {\n    transform: none !important;\n    transition-delay: 0ms !important;\n  }\n}\n\n@media (prefers-reduced-motion: reduce) and (hover: hover) and (pointer: fine) {\n  .shy-heart[data-animated]:hover .shy-heart-motion-stage {\n    transform: none !important;\n    will-change: auto;\n  }\n\n  .shy-heart[data-animated]:hover .shy-heart-blush {\n    transform: none !important;\n    transition-delay: 0ms !important;\n  }\n}\n",
      "type": "registry:file",
      "target": "@ui/shy-heart.css"
    }
  ],
  "cssVars": {
    "light": {
      "ericts-shy-heart-blush": "oklch(0.82 0.1 10)",
      "ericts-shy-heart-blush-baseline": "oklch(0.82 0.1 10)"
    },
    "dark": {
      "ericts-shy-heart-blush": "oklch(0.82 0.1 10)",
      "ericts-shy-heart-blush-baseline": "oklch(0.82 0.1 10)"
    }
  },
  "meta": {
    "tags": [
      "heart",
      "brand",
      "logo",
      "outline",
      "blush",
      "svg",
      "icon",
      "illustration",
      "hover",
      "resizable",
      "cartoon",
      "shy",
      "tilt"
    ],
    "effects": [
      "fade",
      "scale",
      "hover-tilt",
      "blush-reveal",
      "reduced-motion"
    ]
  },
  "categories": [
    "display"
  ],
  "type": "registry:ui"
}