В покое это компактная кнопка с колокольчиком, который покачивается при касании. По нажатию кнопка на пружине растягивается в поле ввода почты и сразу ставит в него фокус. После отправки на кнопке появляется спиннер, затем галочка с сообщением об успехе, и через секунду форма сворачивается обратно.
Если onSubmit выбросит ошибку, поле останется открытым и покажет подсказку. Ширина и иконки анимируются на UI-потоке Reanimated; при включённом «Уменьшении движения» пружины заменяются короткими переходами без покачивания. Работает на iOS, Android и в вебе.
Поставьте зависимости:
npm install react-native-reanimated react-native-svgpnpm add react-native-reanimated react-native-svgyarn add react-native-reanimated react-native-svgbun add react-native-reanimated react-native-svgСкопируйте эти файлы в src/shared/components/molecules/email-capture/:
Проверьте алиас путей. Импорты в коде выше записаны так, как их пишет astra-rn add: @/shared/components, @/shared/utils и @/shared/hooks. Нужен алиас "@/*": ["./src/*"] в tsconfig.json — или поправьте импорты под свои пути.
import React from "react";
import { StyleSheet, View } from "react-native";
import { EmailCapture } from "@/shared/components/molecules/email-capture";
import { Showcase, useCustomize } from "~/showcase";
const CUSTOMIZE = [
{ key: "idleWidth", label: "Ширина кнопки", type: "slider", min: 140, max: 320, step: 2, unit: "px", default: 198 },
{ key: "maxOpenWidth", label: "Ширина поля", type: "slider", min: 260, max: 560, step: 10, unit: "px", default: 400 },
{ key: "delay", label: "Задержка отправки", type: "slider", min: 0, max: 3000, step: 100, unit: "мс", default: 0 },
{ key: "buttonLabel", label: "Текст кнопки", type: "text", default: "Сообщить", maxLength: 20 },
{ key: "placeholder", label: "Подсказка в поле", type: "text", default: "вы@пример.рф", maxLength: 32 },
{ key: "successMessage", label: "Сообщение об успехе", type: "text", default: "Вы в списке", maxLength: 20 },
] as const;
export default function EmailCaptureScreen() {
const custom = useCustomize(CUSTOMIZE);
const delay = custom.delay;
const onSubmit =
delay > 0 ? () => new Promise<void>((resolve) => setTimeout(resolve, delay)) : undefined;
return (
<Showcase>
<View style={styles.container}>
<EmailCapture
placeholder={custom.placeholder}
buttonLabel={custom.buttonLabel}
successMessage={custom.successMessage}
idleWidth={custom.idleWidth}
maxOpenWidth={custom.maxOpenWidth}
onSubmit={onSubmit}
/>
</View>
</Showcase>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
paddingHorizontal: 16,
paddingVertical: 48,
backgroundColor: "#0a0a0a",
},
});Передайте в onSubmit асинхронную функцию: пока она выполняется, кнопка показывает загрузку.
placeholder?Тип string
buttonLabel?Тип string
successMessage?Тип string
idleWidth?Тип number
maxOpenWidth?Тип number
onSubmit?Тип (email: string) => Promise<void> | void
theme?Тип "dark" | "light"
style?Тип StyleProp<ViewStyle>