Поставьте зависимости:
npm install @shopify/react-native-skia react-native-reanimatedpnpm add @shopify/react-native-skia react-native-reanimatedyarn add @shopify/react-native-skia react-native-reanimatedbun add @shopify/react-native-skia react-native-reanimatedСкопируйте эти файлы в src/shared/components/organisms/staggered-text/:
Проверьте алиас путей. Импорты в коде выше записаны так, как их пишет astra-rn add: @/shared/components, @/shared/utils и @/shared/hooks. Нужен алиас "@/*": ["./src/*"] в tsconfig.json — или поправьте импорты под свои пути.
import React, { useEffect, useMemo, useState } from "react";
import { StyleSheet, View, useWindowDimensions } from "react-native";
import { StaggeredText } from "@/shared/components/organisms/staggered-text";
import type { TStaggerFrom } from "@/shared/components/organisms/staggered-text/types";
import { Showcase, useCustomize } from "~/showcase";
const TEXTS: string[] = [
"Do you love Astra!",
"Isn't it amazing?",
"Try it out now!",
];
const ANIMATION_CONFIG = { characterDelay: 50 };
const ENTER_TO = { translateY: 1, opacity: 0, blur: 10, scale: 0.1 };
const EXIT_TO = { translateY: -1, opacity: 0, blur: 10, scale: 0 };
const CUSTOMIZE = [
{ key: "text1", label: "Фраза 1", type: "text", default: TEXTS[0], maxLength: 40 },
{ key: "text2", label: "Фраза 2", type: "text", default: TEXTS[1], maxLength: 40 },
{ key: "text3", label: "Фраза 3", type: "text", default: TEXTS[2], maxLength: 40 },
{ key: "color", label: "Цвет текста", type: "color", default: "#ffffff" },
{ key: "fontSize", label: "Размер шрифта", type: "slider", min: 16, max: 64, step: 1, unit: "px", default: 35 },
{ key: "letterSpacing", label: "Межбуквенный", type: "slider", min: -4, max: 10, step: 0.5, unit: "px", default: 1 },
{
key: "staggerFrom",
label: "Порядок букв",
type: "select",
options: [
{ value: "leading", label: "С начала" },
{ value: "trailing", label: "С конца" },
{ value: "center", label: "От центра" },
{ value: "edges", label: "С краёв" },
{ value: "random", label: "Случайно" },
],
default: "trailing",
},
{ key: "characterDelay", label: "Задержка букв", type: "slider", min: 0, max: 100, step: 1, unit: "ms", default: 50 },
{ key: "blur", label: "Размытие", type: "slider", min: 0, max: 30, step: 1, default: 10 },
{ key: "interval", label: "Смена фразы", type: "slider", min: 800, max: 6000, step: 100, unit: "ms", default: 2000 },
] as const;
export default function App(): React.ReactElement {
const [index, setIndex] = useState<number>(0);
const custom = useCustomize(CUSTOMIZE);
const { text1, text2, text3, characterDelay, blur } = custom;
const texts = useMemo(
() =>
text1 === TEXTS[0] && text2 === TEXTS[1] && text3 === TEXTS[2]
? TEXTS
: [text1, text2, text3],
[text1, text2, text3],
);
const animationConfig = useMemo(
() => (characterDelay === 50 ? ANIMATION_CONFIG : { characterDelay }),
[characterDelay],
);
const { width: screenWidth } = useWindowDimensions();
const longest = Math.max(1, ...texts.map((text) => text.length));
const fontSize = Math.max(
14,
Math.min(custom.fontSize, Math.floor(((screenWidth - 32) / longest - custom.letterSpacing) / 0.52)),
);
const enterTo = useMemo(() => (blur === 10 ? ENTER_TO : { ...ENTER_TO, blur }), [blur]);
const exitTo = useMemo(() => (blur === 10 ? EXIT_TO : { ...EXIT_TO, blur }), [blur]);
useEffect(() => {
const interval = setInterval(() => {
setIndex((prevIndex) => (prevIndex + 1) % TEXTS.length);
}, custom.interval);
return () => clearInterval(interval);
}, [custom.interval]);
return (
<Showcase>
<View style={styles.container}>
<StaggeredText
texts={texts}
activeIndex={index}
fontSize={fontSize}
height={500}
animationConfig={animationConfig}
enterTo={enterTo}
exitTo={exitTo}
color={custom.color}
letterSpacing={custom.letterSpacing}
staggerFrom={custom.staggerFrom as TStaggerFrom}
/>
</View>
</Showcase>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#0b0b0e",
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
},
});textsТип string[]
activeIndex?Тип number
fontSize?Тип number
color?Тип string
fontPath?Тип ReturnType<typeof require>
height?Тип number
staggerFrom?Тип TStaggerFrom
letterSpacing?Тип number
enterFrom?Тип ICharacterAnimationParams
enterTo?Тип ICharacterAnimationParams
exitFrom?Тип ICharacterAnimationParams
exitTo?Тип ICharacterAnimationParams
animationConfig?Тип IAnimationConfig
textsТип string[]
activeIndexТип number
fontSizeТип number
colorТип string
fontТип NonNullable<T>
heightТип number
staggerFromТип TStaggerFrom
enterFromТип TResolvedChar
enterToТип TResolvedChar
exitFromТип TResolvedChar
exitToТип TResolvedChar
configТип TResolvedConfig
letterSpacingТип number