Поставьте зависимости:
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/unstable_orb/:
Проверьте алиас путей. Импорты в коде выше записаны так, как их пишет astra-rn add: @/shared/components, @/shared/utils и @/shared/hooks. Нужен алиас "@/*": ["./src/*"] в tsconfig.json — или поправьте импорты под свои пути.
import React, { useMemo, useRef, useState } from "react";
import { Pressable, StyleSheet, View } from "react-native";
import { StatusBar } from "expo-status-bar";
import { UnstableOrb } from "@/shared/components/organisms/unstable_orb";
import { Showcase, useAutoplay, useCustomize } from "~/showcase";
const colors = ["#1fc7ed", "#4D89FF", "#03629c"];
const CUSTOMIZE = [
{ key: "color1", label: "Цвет 1", type: "color", default: "#1fc7ed" },
{ key: "color2", label: "Цвет 2", type: "color", default: "#4d89ff" },
{ key: "color3", label: "Цвет 3", type: "color", default: "#03629c" },
{ key: "background", label: "Фон", type: "color", default: "#0a0a0a" },
{ key: "colorShift", label: "Сдвиг оттенка", type: "slider", min: 0, max: 360, step: 1, unit: "°", default: 10 },
{ key: "rest", label: "Покой", type: "slider", min: 0, max: 3, step: 0.1, default: 0 },
{ key: "active", label: "Возбуждение", type: "slider", min: 0, max: 5, step: 0.1, default: 2 },
{ key: "size", label: "Размер", type: "slider", min: 120, max: 400, step: 10, unit: "px", default: 250 },
{ key: "hold", label: "Длительность", type: "slider", min: 500, max: 6000, step: 100, unit: "ms", default: 2200 },
] as const;
export default function HomeScreen() {
const custom = useCustomize(CUSTOMIZE);
const [excited, setExcited] = useState<boolean>(false);
const holdRef = useRef(custom.hold);
holdRef.current = custom.hold;
const intensity = excited ? custom.active : custom.rest;
const { color1, color2, color3 } = custom;
const orbColors = useMemo(
() =>
[color1, color2, color3].map((hex, index) =>
hex.toLowerCase() === colors[index].toLowerCase() ? colors[index] : hex,
) as [string, string, string],
[color1, color2, color3],
);
useAutoplay(async ({ wait }) => {
await wait(700);
setExcited(true);
await wait(holdRef.current);
setExcited(false);
await wait(900);
});
return (
<Showcase>
<View style={[styles.container, { backgroundColor: custom.background }]}>
<StatusBar style="light" />
<Pressable
style={styles.orbWrapper}
onPress={() => setExcited(!excited)}
>
<UnstableOrb
intensity={intensity}
colorShift={custom.colorShift}
background={custom.background}
style={{
width: 550,
height: custom.size,
pointerEvents: "none",
position: "absolute",
}}
colors={orbColors}
/>
</Pressable>
</View>
</Showcase>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#0a0a0a",
overflow: "hidden",
justifyContent: "center",
alignItems: "center",
},
orbWrapper: {
width: 400,
height: 300,
justifyContent: "center",
alignItems: "center",
},
});colorShift?Тип number
intensity?Тип number
background?Тип string
colors?Тип [string, string, string]
style?Тип StyleProp<ViewStyle>