Поставьте зависимости:
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/base/border-beam/:
Проверьте алиас путей. Импорты в коде выше записаны так, как их пишет astra-rn add: @/shared/components, @/shared/utils и @/shared/hooks. Нужен алиас "@/*": ["./src/*"] в tsconfig.json — или поправьте импорты под свои пути.
import React, { useMemo } from "react";
import { Dimensions, StyleSheet, Text, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { Feather } from "@expo/vector-icons";
import { BorderBeam } from "@/shared/components/base/border-beam";
import { Showcase, useCustomize } from "~/showcase";
import { SymbolView } from "expo-symbols";
import { useFonts } from "expo-font";
import sfProRounded from "@/assets/fonts/sf-pro-rounded.ttf";
import sfProRoundedBold from "~/assets/fonts/SF-Pro-Rounded-Bold.otf";
import sfProRoundedMedium from "~/assets/fonts/SF-Pro-Rounded-Medium.otf";
const RADIUS = 23;
const WIDTH = Dimensions.get("window").width;
const RAF_SIZE = 19;
const _ICON_SIZE = RAF_SIZE * 0.89;
const CUSTOMIZE = [
{ key: "color1", label: "Цвет луча 1", type: "color", default: "#c15f3c" },
{ key: "color2", label: "Цвет луча 2", type: "color", default: "#c15f3c" },
{ key: "color3", label: "Цвет луча 3", type: "color", default: "#c15f3c" },
{ key: "duration", label: "Круг", type: "slider", min: 0.5, max: 12, step: 0.5, unit: "s", default: 3 },
{ key: "beamLength", label: "Длина луча", type: "slider", min: 0.05, max: 1, step: 0.01, default: 0.36 },
{ key: "intensity", label: "Яркость", type: "slider", min: 0, max: 2, step: 0.05, default: 0.9 },
{ key: "glow", label: "Свечение", type: "slider", min: 0, max: 40, step: 1, unit: "px", default: 8 },
{ key: "ambient", label: "Фоновый свет", type: "slider", min: 0, max: 1, step: 0.01, default: 0 },
{ key: "borderWidth", label: "Толщина рамки", type: "slider", min: 0.5, max: 6, step: 0.5, unit: "px", default: 0.5 },
{ key: "radius", label: "Скругление", type: "slider", min: 0, max: 48, step: 1, unit: "px", default: RADIUS },
{ key: "placeholder", label: "Подсказка", type: "text", default: "Chat with Claude", maxLength: 40 },
{ key: "model", label: "Модель", type: "text", default: "Opus 4.8 Medium", maxLength: 30 },
{ key: "cardColor", label: "Фон карточки", type: "color", default: "#121212" },
] as const;
export default function BorderBeamScreen() {
const [fontLoaded] = useFonts({
SfProRounded: sfProRounded,
SfProRoundedBold: sfProRoundedBold,
SfProRoundedMedium: sfProRoundedMedium,
});
const insets = useSafeAreaInsets();
const custom = useCustomize(CUSTOMIZE);
const colors = useMemo(
() => [custom.color1, custom.color2, custom.color3],
[custom.color1, custom.color2, custom.color3],
);
return (
<Showcase>
<View
style={[
styles.stage,
{
justifyContent: "flex-end",
alignItems: "center",
flex: 1,
paddingBottom: Math.max(insets.bottom, 12) + 12,
},
]}
>
<BorderBeam
style={styles.beam}
borderRadius={custom.radius}
borderWidth={custom.borderWidth}
colors={colors}
ambient={custom.ambient}
duration={custom.duration}
beamLength={custom.beamLength}
intensity={custom.intensity}
glow={custom.glow}
>
<View
style={[
styles.card,
{ borderRadius: custom.radius, backgroundColor: custom.cardColor },
]}
>
<Text
style={[
styles.placeholder,
{
fontFamily: fontLoaded ? "SfProRounded" : undefined,
},
]}
>
{custom.placeholder}
</Text>
<View style={styles.row}>
<Feather name="plus" size={_ICON_SIZE} color="#e9e9ee" />
<View style={styles.model}>
<Text
style={[
styles.modelText,
{
fontFamily: fontLoaded ? "SfProRoundedMedium" : undefined,
},
]}
>
{custom.model}
</Text>
</View>
<View style={{ flex: 1 }} />
<View style={styles.actions}>
<Feather name="mic" size={_ICON_SIZE} color="#e9e9ee" />
<View style={styles.send}>
<SymbolView
name="waveform"
size={_ICON_SIZE}
tintColor="#000"
/>
</View>
</View>
</View>
</View>
</BorderBeam>
</View>
</Showcase>
);
}
const styles = StyleSheet.create({
beam: {
width: WIDTH * 0.9,
},
card: {
width: "100%",
borderRadius: RADIUS,
minHeight: 115,
backgroundColor: "#121212",
padding: 20,
},
placeholder: {
color: "#6b6b73",
fontSize: _ICON_SIZE * 0.87,
fontWeight: "400",
paddingBottom: _ICON_SIZE * 1.7,
top: _ICON_SIZE / 2,
},
row: {
flexDirection: "row",
alignItems: "center",
gap: 12,
},
model: {
backgroundColor: "#1f1f1f",
paddingHorizontal: 16,
paddingVertical: 8,
borderRadius: 22,
},
modelText: {
color: "#c9c9d1",
fontSize: 12,
fontWeight: "500",
},
actions: {
flexDirection: "row",
alignItems: "center",
gap: 14,
// flex: 1,
},
send: {
width: 28,
height: 28,
borderRadius: 19,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
stage: {
padding: 12,
},
});childrenТип React.ReactNode
borderRadius?Тип number
borderWidth?Тип number
glow?Тип number
duration?Тип number
beamLength?Тип number
colors?Тип string[]
intensity?Тип number
ambient?Тип number
style?Тип StyleProp<ViewStyle>