react-typical
react-typical copied to clipboard
feat: include props and style
Add props and style to forward styling and enable the use of custom components as a wrapper.
Example: Use with Chakra-UI
import { Heading } from '@chakra/react'
...
const [primary, secondary] = useToken("colors", ["gray.500", "blue.500"]);
...
<Typical
steps={["Hello", 1000, "Hello world!", 500]}
loop={Infinity}
wrapper={Heading}
props={{
bgGradient:`linear(to-t, ${primary}, ${secondary})`,
bgClip:"text"
}}
style={{
fontSize: "5rem"
}}
/>

Closes https://github.com/catalinmiron/react-typical/issues/18
I ended up rewriting it to the following code for TypeScript support:
import React, { useRef, useEffect, memo } from 'react'
import { type } from '@camwiegert/typical'
// const memo: <T>(component: T) => T = baseMemo
export interface Props<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends React.ComponentType<any> | keyof JSX.IntrinsicElements,
> {
steps: Parameters<typeof type>[1]
loop?: number
className?: string
wrapper?: T
}
const Typical = <
// eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends React.ComponentType<any> | keyof JSX.IntrinsicElements,
>({
steps,
loop,
className,
wrapper = 'p',
...props
}: Props<T> & React.ComponentProps<T>) => {
const typicalRef = useRef<HTMLElement>(null)
const Component = wrapper
useEffect(() => {
if (loop === Infinity) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
type(typicalRef.current!, ...steps, type)
} else if (typeof loop === 'number') {
const timesStep = Array(loop).fill(steps).flat()
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
type(typicalRef.current!, ...timesStep)
} else {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
type(typicalRef.current!, ...steps)
}
return () => {
// alive.current = false
}
}, [typicalRef, loop, steps])
return <Component ref={typicalRef} className={className} {...props} />
}
export default memo(Typical) as typeof Typical
and using it as follows:
<Typical<'span'>
steps={['Example', 800, 'Another', 800, 'Third', 800])}
loop={Infinity}
wrapper="span"
/>
Not only can you add props to the component without weird props prop, but it also dynamically checks all supported props of the wrapper!