UNPKG

@gfazioli/mantine-text-animate

Version:

The TextAnimate component allows you to animate text with various effects.

274 lines (273 loc) 9.78 kB
import { type BoxProps, type MantineSize, type PolymorphicFactory, type StylesApiProps, type TextProps, type TextStylesNames, type TextVariant } from '@mantine/core'; import React from 'react'; import { Gradient } from './Gradient/Gradient'; import { Highlight } from './Highlight/Highlight'; import { Morphing } from './Morphing/Morphing'; import { NumberTicker } from './NumberTicker/NumberTicker'; import { RotatingText } from './RotatingText/RotatingText'; import { Spinner } from './Spinner/Spinner'; import { SplitFlap } from './SplitFlap/SplitFlap'; import { TextTicker } from './TextTicker/TextTicker'; import { Typewriter } from './Typewriter/Typewriter'; /** * Type defining how text should be split for animation * - text: Animate the entire text as one unit * - word: Animate each word separately * - character: Animate each character separately * - line: Animate each line separately (split by newlines) */ export type TextAnimateAnimationType = 'text' | 'word' | 'character' | 'line'; /** * Available animation variants */ export type TextAnimateAnimationVariant = 'fade' | 'blur' | 'scale' | 'slideUp' | 'slideDown' | 'slideUpElastic' | 'slideDownElastic' | 'slideLeft' | 'slideRight' | 'slideLeftElastic' | 'slideRightElastic' | 'blurUp' | 'blurDown'; /** * Animation direction */ export type TextAnimateAnimationDirection = 'in' | 'out' | 'loop' | 'static' | 'none' | false | undefined; interface TextAnimateAnimateProps { /** * Controls the distance for slide animations (in pixels) * @default 20 */ translateDistance?: MantineSize; /** * Controls the scale factor for scale animations * For scaleUp: initial scale = 1 - scaleAmount (e.g., 0.8 means start at 0.2) * For scaleDown: initial scale = 1 + scaleAmount (e.g., 0.8 means start at 1.8) * @default 0.8 */ scaleAmount?: number; /** * Controls the blur amount for blur animations (in pixels) * @default 10 */ blurAmount?: MantineSize; } /** * Trigger mode for TextAnimate animation * - `mount`: Animate on mount (default behavior) * - `inView`: Animate when the element enters the viewport * - `manual`: Do not auto-animate; control via `animate` prop only */ export type TextAnimateTrigger = 'mount' | 'inView' | 'manual'; /** * Options for the IntersectionObserver when trigger is "inView" */ export interface TextAnimateTriggerOptions { /** * IntersectionObserver threshold (0-1) * @default 0.1 */ threshold?: number; /** * IntersectionObserver root margin * @default "0px" */ rootMargin?: string; } export type TextAnimateStylesNames = 'root' | 'segment' | TextStylesNames; export type TextAnimateCssVariables = { root: '--text-animate-translation-distance' | '--text-animate-blur-amount' | '--text-animate-scale-amount'; }; export type TextAnimateDirection = 'horizontal' | 'vertical'; export type TextAnimateIn = 'positive' | 'negative'; export type TextAnimateOut = TextAnimateIn; export interface TextAnimateBaseProps { /** * The text content to animate */ children: string; /** * The class name to be applied to each segment */ segmentClassName?: string; /** * The delay before the animation starts (in seconds) * @default 0 */ delay?: number; /** * The duration of the animation (in seconds) * @default 0.3 */ duration?: number; /** * How to split the text for animation * @default "word" */ by?: TextAnimateAnimationType; /** * Controls the animation direction * - `in`: Animate elements in (appear) * - `out`: Animate elements out (disappear) * - `static`: Do not animate * - `none`: Do not animate * @default undefined (no animation) */ animate?: TextAnimateAnimationDirection; /** * The animation preset to use * @default "fade" */ animation?: TextAnimateAnimationVariant; /** * The delay between each segment's animation (in seconds) * This controls the staggered timing between segments * @default Based on animation type (0.03-0.06) */ segmentDelay?: number; /** * Animation properties to control intensity of animations * @default Values are chosen to match the selected animation variant. */ animateProps?: TextAnimateAnimateProps; /** * Callback function to be called when the animation starts * @param animate The direction of the animation */ onAnimationStart?: (animate: 'in' | 'out') => void; /** * Callback function to be called when the animation ends * @param animate The direction of the animation */ onAnimationEnd?: (animate: 'in' | 'out') => void; /** * Callback function called when all segments have completed their animation * @param animate The direction of the animation */ onAnimationComplete?: (animate: 'in' | 'out') => void; /** * Trigger mode for animation * - `mount`: Animate on mount (default, preserves v2 behavior) * - `inView`: Animate when element enters the viewport via IntersectionObserver * - `manual`: Do not auto-animate; control via `animate` prop only * @default "mount" */ trigger?: TextAnimateTrigger; /** * Options for IntersectionObserver when trigger is "inView" */ triggerOptions?: TextAnimateTriggerOptions; /** * Delay in milliseconds between loop phases (in→pause→out→pause→in) * Only used when `animate="loop"` * @default 2000 */ loopDelay?: number; } export interface TextAnimateProps extends BoxProps, Omit<TextProps, 'classNames' | 'styles' | 'unstyled' | 'vars' | 'attributes'>, TextAnimateBaseProps, StylesApiProps<TextAnimateFactory> { } export type TextAnimateFactory = PolymorphicFactory<{ props: TextAnimateProps; defaultComponent: 'p'; defaultRef: HTMLParagraphElement; stylesNames: TextAnimateStylesNames; vars: TextAnimateCssVariables; variant: TextVariant; staticComponents: { Typewriter: typeof Typewriter; Spinner: typeof Spinner; NumberTicker: typeof NumberTicker; TextTicker: typeof TextTicker; Gradient: typeof Gradient; Highlight: typeof Highlight; SplitFlap: typeof SplitFlap; Morphing: typeof Morphing; RotatingText: typeof RotatingText; }; }>; export declare const TextAnimate: (<C = "p">(props: import("@mantine/core").PolymorphicComponentProps<C, TextAnimateProps>) => React.ReactElement) & Omit<React.FunctionComponent<(TextAnimateProps & { component?: any; } & Omit<any, "component" | keyof TextAnimateProps> & { ref?: any; renderRoot?: (props: any) => any; }) | (TextAnimateProps & { component: React.ElementType; renderRoot?: (props: Record<string, any>) => any; })>, never> & import("@mantine/core").ThemeExtend<{ props: TextAnimateProps; defaultComponent: "p"; defaultRef: HTMLParagraphElement; stylesNames: TextAnimateStylesNames; vars: TextAnimateCssVariables; variant: TextVariant; staticComponents: { Typewriter: typeof Typewriter; Spinner: typeof Spinner; NumberTicker: typeof NumberTicker; TextTicker: typeof TextTicker; Gradient: typeof Gradient; Highlight: typeof Highlight; SplitFlap: typeof SplitFlap; Morphing: typeof Morphing; RotatingText: typeof RotatingText; }; }> & import("@mantine/core").ComponentClasses<{ props: TextAnimateProps; defaultComponent: "p"; defaultRef: HTMLParagraphElement; stylesNames: TextAnimateStylesNames; vars: TextAnimateCssVariables; variant: TextVariant; staticComponents: { Typewriter: typeof Typewriter; Spinner: typeof Spinner; NumberTicker: typeof NumberTicker; TextTicker: typeof TextTicker; Gradient: typeof Gradient; Highlight: typeof Highlight; SplitFlap: typeof SplitFlap; Morphing: typeof Morphing; RotatingText: typeof RotatingText; }; }> & { varsResolver: import("@mantine/core").VarsResolver<{ props: TextAnimateProps; defaultComponent: "p"; defaultRef: HTMLParagraphElement; stylesNames: TextAnimateStylesNames; vars: TextAnimateCssVariables; variant: TextVariant; staticComponents: { Typewriter: typeof Typewriter; Spinner: typeof Spinner; NumberTicker: typeof NumberTicker; TextTicker: typeof TextTicker; Gradient: typeof Gradient; Highlight: typeof Highlight; SplitFlap: typeof SplitFlap; Morphing: typeof Morphing; RotatingText: typeof RotatingText; }; }>; } & import("@mantine/core").PolymorphicComponentWithProps<{ props: TextAnimateProps; defaultComponent: "p"; defaultRef: HTMLParagraphElement; stylesNames: TextAnimateStylesNames; vars: TextAnimateCssVariables; variant: TextVariant; staticComponents: { Typewriter: typeof Typewriter; Spinner: typeof Spinner; NumberTicker: typeof NumberTicker; TextTicker: typeof TextTicker; Gradient: typeof Gradient; Highlight: typeof Highlight; SplitFlap: typeof SplitFlap; Morphing: typeof Morphing; RotatingText: typeof RotatingText; }; }> & { Typewriter: typeof Typewriter; Spinner: typeof Spinner; NumberTicker: typeof NumberTicker; TextTicker: typeof TextTicker; Gradient: typeof Gradient; Highlight: typeof Highlight; SplitFlap: typeof SplitFlap; Morphing: typeof Morphing; RotatingText: typeof RotatingText; }; export {};