{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"slide-text","type":"registry:ui","title":"Slide Text","description":"On hover every letter rolls out of view and a fresh copy slides in behind it, in a staggered wave.","dependencies":[],"registryDependencies":[],"files":[{"path":"registry/ui/slide-text.tsx","type":"registry:ui","content":"\"use client\";\n\nimport { Fragment, type CSSProperties } from \"react\";\n\nconst css = `\n.slide-text{display:inline-block;cursor:pointer}\n.slide-text .st-c{position:relative;display:inline-block;overflow:hidden;vertical-align:top;line-height:1.2}\n.slide-text .st-i{display:inline-block;white-space:pre;transition:transform var(--st-d) cubic-bezier(.7,0,.2,1) calc(var(--o)*var(--st-s))}\n.slide-text .st-i+.st-i{position:absolute;left:0;top:calc(100% * var(--st-dir));color:var(--st-c,inherit)}\n.slide-text:hover .st-i,:focus-visible>.slide-text .st-i,.slide-text[data-active] .st-i{transform:translateY(calc(-100% * var(--st-dir)))}\n@media (prefers-reduced-motion:reduce){.slide-text .st-i{transition-duration:0s;transition-delay:0s}}\n`;\n\nexport interface SlideTextProps {\n  text: string;\n  /** Color of the incoming letters. */\n  hoverColor?: string;\n  /** Direction the letters travel. */\n  direction?: \"up\" | \"down\";\n  /** Where the stagger starts. */\n  from?: \"start\" | \"center\" | \"end\";\n  /** Delay between letters, in ms. */\n  stagger?: number;\n  /** Slide duration of each letter, in ms. */\n  duration?: number;\n  /** Keep the swapped state, e.g. for an active link. */\n  active?: boolean;\n  className?: string;\n}\n\nexport function SlideText({\n  text,\n  hoverColor = \"#a3e635\",\n  direction = \"up\",\n  from = \"start\",\n  stagger = 25,\n  duration = 500,\n  active = false,\n  className,\n}: SlideTextProps) {\n  const chars = Array.from(text);\n  const n = chars.length;\n  const order = (i: number) =>\n    from === \"end\" ? n - 1 - i : from === \"center\" ? Math.abs(i - (n - 1) / 2) : i;\n  const words = text.split(\" \");\n  let i = 0;\n\n  return (\n    <span\n      className={`slide-text ${className ?? \"\"}`}\n      data-active={active || undefined}\n      style={\n        {\n          \"--st-s\": `${stagger}ms`,\n          \"--st-d\": `${duration}ms`,\n          \"--st-dir\": direction === \"up\" ? 1 : -1,\n          \"--st-c\": hoverColor || undefined,\n        } as CSSProperties\n      }\n    >\n      <style href=\"slide-text\" precedence=\"default\">\n        {css}\n      </style>\n      <span className=\"sr-only\">{text}</span>\n      {words.map((word, w) => {\n        const letters = Array.from(word).map((c, k) => {\n          const o = order(i++);\n          return (\n            <span key={k} className=\"st-c\" style={{ \"--o\": o } as CSSProperties}>\n              <span className=\"st-i\">{c}</span>\n              <span className=\"st-i\">{c}</span>\n            </span>\n          );\n        });\n        i++;\n        return (\n          <Fragment key={w}>\n            <span aria-hidden style={{ display: \"inline-block\", whiteSpace: \"nowrap\" }}>\n              {letters}\n            </span>\n            {w < words.length - 1 && \" \"}\n          </Fragment>\n        );\n      })}\n    </span>\n  );\n}\n"}]}