Поставьте зависимости:
npm install @expo/vector-icons @shopify/react-native-skia react-native-reanimatedpnpm add @expo/vector-icons @shopify/react-native-skia react-native-reanimatedyarn add @expo/vector-icons @shopify/react-native-skia react-native-reanimatedbun add @expo/vector-icons @shopify/react-native-skia react-native-reanimatedСкопируйте эти файлы в src/shared/components/molecules/gooey-search-tabs/:
Проверьте алиас путей. Импорты в коде выше записаны так, как их пишет astra-rn add: @/shared/components, @/shared/utils и @/shared/hooks. Нужен алиас "@/*": ["./src/*"] в tsconfig.json — или поправьте импорты под свои пути.
import React from "react";
import { StyleSheet, View } from "react-native";
import { Feather } from "@expo/vector-icons";
import { useFonts } from "expo-font";
import { GooeySearchTabs } from "@/shared/components/molecules/gooey-search-tabs";
import { useGooey } from "@/shared/components/molecules/gooey-search-tabs/context";
import { Showcase, useAutoplay, useCustomize } from "~/showcase";
const _TRIGGER_ICON_SIZE: number = 20;
const _ICON_SIZE: number = _TRIGGER_ICON_SIZE * 0.7_5;
const CUSTOMIZE = [
{ key: "intensity", label: "Вязкость", type: "slider", min: 0, max: 1, step: 0.05, default: 0.2 },
{ key: "damping", label: "Затухание", type: "slider", min: 4, max: 40, step: 1, default: 12 },
{ key: "stiffness", label: "Жёсткость", type: "slider", min: 40, max: 400, step: 5, default: 150 },
{ key: "mass", label: "Масса", type: "slider", min: 0.1, max: 3, step: 0.1, default: 0.5 },
{ key: "bg", label: "Фон", type: "color", default: "#1e1e1e" },
{ key: "fg", label: "Текст и иконки", type: "color", default: "#f5f5f7" },
{ key: "muted", label: "Неактивный", type: "color", default: "#8a8a90" },
{ key: "docsLabel", label: "Вкладка 1", type: "text", default: "Docs", maxLength: 16 },
{ key: "mediaLabel", label: "Вкладка 2", type: "text", default: "Media", maxLength: 16 },
] as const;
function SearchTabsAutoplay(): null {
const { selectTab, expand, collapse } = useGooey();
useAutoplay(async ({ wait }) => {
await wait(200);
selectTab("media");
await wait(650);
selectTab("docs");
await wait(550);
expand();
await wait(850);
collapse();
await wait(450);
});
return null;
}
export default function GooeySearchTabsScreen() {
const [iconsLoaded] = useFonts(Feather.font);
const custom = useCustomize(CUSTOMIZE);
if (!iconsLoaded) return null;
return (
<Showcase>
<View
style={[
styles.stage,
{
justifyContent: "center",
alignItems: "center",
flex: 1,
},
]}
>
<GooeySearchTabs
intensity={custom.intensity}
springConfig={{
damping: custom.damping,
stiffness: custom.stiffness,
mass: custom.mass,
}}
colorScheme={{
bg: custom.bg,
fg: custom.fg,
muted: custom.muted,
indicator: "rgba(255,255,255,0.10)",
}}
>
<GooeySearchTabs.Trigger>
<Feather
name="search"
size={_TRIGGER_ICON_SIZE}
color={custom.fg}
/>
</GooeySearchTabs.Trigger>
<GooeySearchTabs.Tabs>
<GooeySearchTabs.Tab value="docs">
<GooeySearchTabs.TabIcon>
<Feather name="file-text" size={_ICON_SIZE} color={custom.fg} />
</GooeySearchTabs.TabIcon>
<GooeySearchTabs.TabLabel>{custom.docsLabel}</GooeySearchTabs.TabLabel>
</GooeySearchTabs.Tab>
<GooeySearchTabs.Tab value="media">
<GooeySearchTabs.TabIcon>
<Feather name="image" size={_ICON_SIZE} color={custom.fg} />
</GooeySearchTabs.TabIcon>
<GooeySearchTabs.TabLabel>{custom.mediaLabel}</GooeySearchTabs.TabLabel>
</GooeySearchTabs.Tab>
</GooeySearchTabs.Tabs>
<SearchTabsAutoplay />
</GooeySearchTabs>
</View>
</Showcase>
);
}
const styles = StyleSheet.create({
stage: {
alignItems: "center",
justifyContent: "center",
},
});childrenТип ReactNode
value?Тип string
defaultValue?Тип string
onChange?Тип (value: string) => void
onSearch?Тип (value: string) => void
activeTab?Тип string
defaultActiveTab?Тип string
onTabChange?Тип (value: string) => void
defaultExpanded?Тип boolean
onExpandedChange?Тип (expanded: boolean) => void
placeholder?Тип string
intensity?Тип number
springConfig?Тип WithSpringConfig
colorScheme?Тип Partial<IColorScheme>
style?Тип StyleProp<ViewStyle>
textStyle?Тип StyleProp<TextStyle>