{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "rolling-text", "type": "registry:ui", "title": "Rolling Text", "description": "A text component that reveals content through an engaging rolling animation.", "dependencies": [ "motion" ], "files": [ { "path": "registry/text/rolling/index.tsx", "content": "'use client';\n\nimport * as React from 'react';\nimport {\n motion,\n useInView,\n type UseInViewOptions,\n type Transition,\n} from 'motion/react';\n\nconst ENTRY_ANIMATION = {\n initial: { rotateX: 0 },\n animate: { rotateX: 90 },\n};\n\nconst EXIT_ANIMATION = {\n initial: { rotateX: 90 },\n animate: { rotateX: 0 },\n};\n\nconst formatCharacter = (char: string) => (char === ' ' ? '\\u00A0' : char);\n\ntype RollingTextProps = Omit, 'children'> & {\n transition?: Transition;\n inView?: boolean;\n inViewMargin?: UseInViewOptions['margin'];\n inViewOnce?: boolean;\n text: string;\n};\n\nfunction RollingText({\n ref,\n transition = { duration: 0.5, delay: 0.1, ease: 'easeOut' },\n inView = false,\n inViewMargin = '0px',\n inViewOnce = true,\n text,\n ...props\n}: RollingTextProps) {\n const localRef = React.useRef(null);\n React.useImperativeHandle(ref, () => localRef.current!);\n\n const inViewResult = useInView(localRef, {\n once: inViewOnce,\n margin: inViewMargin,\n });\n const isInView = !inView || inViewResult;\n\n const characters = React.useMemo(() => text.split(''), [text]);\n\n return (\n \n {characters.map((char, idx) => (\n \n \n {formatCharacter(char)}\n \n \n {formatCharacter(char)}\n \n {formatCharacter(char)}\n \n ))}\n\n {text}\n \n );\n}\n\nexport { RollingText, type RollingTextProps };\n", "type": "registry:ui", "target": "components/animate-ui/text/rolling.tsx" } ] }