{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "signature",
  "type": "registry:ui",
  "title": "Signature",
  "dependencies": [
    "framer-motion",
    "opentype.js"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "Component for signature",
  "files": [
    {
      "path": "components/ui/signature.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useId, useState } from \"react\";\nimport { motion } from \"framer-motion\";\nimport opentype from \"opentype.js\";\nimport { cn } from \"@/lib/utils\";\n\ninterface SignatureProps {\n  /** Text to generate signature for */\n  text?: string;\n  /** Color of the signature path */\n  color?: string;\n  /** Font size of the signature */\n  fontSize?: number;\n  /** Animation duration in seconds */\n  duration?: number;\n  /** Delay before animation starts in seconds */\n  delay?: number;\n  /** Additional CSS classes */\n  className?: string;\n  /** Only animate when in view */\n  inView?: boolean;\n  /** Only animate once */\n  once?: boolean;\n  /** Custom font URL to load */\n  fontUrl?: string;\n}\n\nexport function Signature({\n  text = \"Signature\",\n  color = \"currentColor\",\n  fontSize = 32,\n  duration = 1.5,\n  delay = 0,\n  className,\n  inView = false,\n  once = true,\n  fontUrl,\n}: SignatureProps) {\n  const [paths, setPaths] = useState<string[]>([]);\n  const [width, setWidth] = useState<number>(300);\n  const height = fontSize * 3; // Give plenty of vertical space\n  const horizontalPadding = fontSize * 0.1;\n  const topMargin = fontSize * 1.5; // Shift down\n  const baseline = topMargin;\n  const maskId = `signature-reveal-${useId().replace(/:/g, \"\")}`;\n\n  useEffect(() => {\n    async function load() {\n      try {\n        let font;\n        const fontPaths = fontUrl \n          ? [fontUrl] \n          : [\n              \"/LastoriaBoldRegular.otf\",\n              \"./LastoriaBoldRegular.otf\",\n              \"https://www.componentry.fun/LastoriaBoldRegular.otf\",\n            ];\n\n        for (const path of fontPaths) {\n          try {\n            font = await opentype.load(path as string);\n            break;\n          } catch {\n            // Try next path\n          }\n        }\n\n        if (!font) {\n          throw new Error(\"Font could not be loaded from any path\");\n        }\n\n        let x = horizontalPadding;\n        const newPaths: string[] = [];\n\n        for (const char of text) {\n          const glyph = font.charToGlyph(char);\n          const path = glyph.getPath(x, baseline, fontSize);\n          newPaths.push(path.toPathData(3));\n\n          const advanceWidth = glyph.advanceWidth ?? font.unitsPerEm;\n          x += advanceWidth * (fontSize / font.unitsPerEm);\n        }\n\n        setPaths(newPaths);\n        setWidth(x + horizontalPadding);\n      } catch (error) {\n        console.error(\"Signature component font load error:\", error);\n        setPaths([]);\n        setWidth(text.length * fontSize * 0.6);\n      }\n    }\n\n    load();\n  }, [text, fontSize, baseline, horizontalPadding, fontUrl]);\n\n  const variants = {\n    hidden: { pathLength: 0, opacity: 0 },\n    visible: { pathLength: 1, opacity: 1 },\n  };\n\n  return (\n    <motion.svg\n      key={paths.length}\n      width={width}\n      height={height}\n      viewBox={`0 0 ${width} ${height}`}\n      fill=\"none\"\n      className={cn(\"text-foreground overflow-visible\", className)}\n      initial=\"hidden\"\n      whileInView={inView ? \"visible\" : undefined}\n      animate={inView ? undefined : \"visible\"}\n      viewport={{ once }}\n    >\n      <defs>\n        <mask id={maskId} maskUnits=\"userSpaceOnUse\">\n          {paths.map((d, i) => (\n            <motion.path\n              key={i}\n              d={d}\n              stroke=\"white\"\n              strokeWidth={fontSize * 0.22}\n              fill=\"none\"\n              variants={variants}\n              transition={{\n                pathLength: {\n                  delay: delay + i * 0.2,\n                  duration,\n                  ease: \"easeInOut\",\n                },\n                opacity: {\n                  delay: delay + i * 0.2 + 0.01,\n                  duration: 0.01,\n                },\n              }}\n              vectorEffect=\"non-scaling-stroke\"\n              strokeLinecap=\"round\"\n              strokeLinejoin=\"round\"\n            />\n          ))}\n        </mask>\n      </defs>\n\n      {paths.map((d, i) => (\n        <motion.path\n          key={i}\n          d={d}\n          stroke={color}\n          strokeWidth={2}\n          fill=\"none\"\n          variants={variants}\n          transition={{\n            pathLength: {\n              delay: delay + i * 0.2,\n              duration,\n              ease: \"easeInOut\",\n            },\n            opacity: {\n              delay: delay + i * 0.2 + 0.01,\n              duration: 0.01,\n            },\n          }}\n          vectorEffect=\"non-scaling-stroke\"\n          strokeLinecap=\"butt\"\n          strokeLinejoin=\"round\"\n        />\n      ))}\n\n      <g mask={`url(#${maskId})`}>\n        {paths.map((d, i) => <path key={i} d={d} fill={color} />)}\n      </g>\n    </motion.svg>\n  );\n}\n",
      "type": "registry:ui"
    }
  ]
}