• Экраны
  • Доки
1Online
ПодпискаКаталог
  • Экраны
  • Доки
1Online
ПодпискаКаталог
  • Экраны
  • Доки
1Online
ПодпискаКаталог
Пустые подарки V1 — экран из раздела «Пустой экран»
Пустой экран

Пустые подарки V1

Что показывает список, почта или галерея, пока в них пусто.

Установка

src/shared/components/blocks/empty-gift-v1
npx astra-rn add empty-gift-v1
pnpm dlx astra-rn add empty-gift-v1
yarn dlx astra-rn add empty-gift-v1
bunx --bun astra-rn add empty-gift-v1

Зависимости

1 пакет
npm install expo-asset
pnpm add expo-asset
yarn add expo-asset
bun add expo-asset

Исходник

4 файла
import React, { memo, useCallback, useState } from "react";
import { Image, Pressable, StyleSheet, Text, View } from "react-native";
import type { IEmptyGiftState } from "./types";
import {
  ACTION_HEIGHT,
  ACTION_HORIZONTAL_PADDING,
  ARTWORK_SIZE,
  COLORS,
  CONTENT_HORIZONTAL_PADDING,
  DEFAULT_ACTION_LABEL,
  DEFAULT_ARTWORK_URI,
  DEFAULT_DESCRIPTION,
  DEFAULT_TITLE,
  HALO_CORE_SIZE,
  SCENE_SIZE,
} from "./const";

const EmptyGiftState: React.FC<IEmptyGiftState> = ({
  title = DEFAULT_TITLE,
  description = DEFAULT_DESCRIPTION,
  actionLabel = DEFAULT_ACTION_LABEL,
  artwork = { uri: DEFAULT_ARTWORK_URI },
  hideAction = false,
  hideHalo = false,
  style,
  onActionPress,
}: IEmptyGiftState) => {
  const [isActionPressed, setIsActionPressed] = useState<boolean>(false);

  const handlePressIn = useCallback((): void => setIsActionPressed(true), []);
  const handlePressOut = useCallback((): void => setIsActionPressed(false), []);

  return (
    <View style={[styles.container, style]}>
      <View style={styles.scene}>
        <Image
          source={artwork}
          style={styles.artwork}
          resizeMode="contain"
          accessibilityIgnoresInvertColors
        />
      </View>

      <Text style={styles.title}>{title}</Text>
      <Text style={styles.description}>{description}</Text>

      {hideAction ? null : (
        <Pressable
          accessibilityRole="button"
          accessibilityLabel={actionLabel}
          onPress={onActionPress}
          onPressIn={handlePressIn}
          onPressOut={handlePressOut}
          style={[styles.action, isActionPressed ? styles.actionPressed : null]}
        >
          <Text style={styles.actionLabel} numberOfLines={1}>
            {actionLabel}
          </Text>
        </Pressable>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
    paddingHorizontal: CONTENT_HORIZONTAL_PADDING,
    backgroundColor: COLORS.screen,
  },
  scene: {
    width: SCENE_SIZE,
    height: SCENE_SIZE,
    alignItems: "center",
    justifyContent: "center",
  },
  ring: {
    position: "absolute",
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: COLORS.halo,
  },
  haloCore: {
    position: "absolute",
    width: HALO_CORE_SIZE,
    height: HALO_CORE_SIZE,
    borderRadius: HALO_CORE_SIZE / 2,
    backgroundColor: COLORS.haloCore,
  },
  artwork: {
    width: ARTWORK_SIZE,
    height: ARTWORK_SIZE,
  },
  title: {
    marginTop: 4,
    fontSize: 21,
    lineHeight: 27,
    fontWeight: "700",
    letterSpacing: -0.5,
    color: COLORS.title,
    textAlign: "center",
  },
  description: {
    maxWidth: 268,
    marginTop: 8,
    fontSize: 15,
    lineHeight: 21,
    color: COLORS.description,
    textAlign: "center",
  },
  action: {
    marginTop: 28,
    height: ACTION_HEIGHT,
    paddingHorizontal: ACTION_HORIZONTAL_PADDING,
    borderRadius: ACTION_HEIGHT / 2,
    backgroundColor: COLORS.action,
    alignItems: "center",
    justifyContent: "center",
  },
  actionPressed: {
    backgroundColor: COLORS.actionPressed,
  },
  actionLabel: {
    fontSize: 15,
    fontWeight: "600",
    letterSpacing: -0.2,
    color: COLORS.actionLabel,
  },
});

export { EmptyGiftState };
export type { IEmptyGiftState, IHaloRing } from "./types";
export default memo(EmptyGiftState);
import type { IHaloRing } from "./types";
import { PHOTO_SOURCES } from "./photos";

export const DEFAULT_ARTWORK_URI =
  PHOTO_SOURCES["empty-gift-v1-1"];

export const DEFAULT_TITLE = "Nothing here yet";

export const DEFAULT_DESCRIPTION = "Make someone's day with a little surprise.";

export const DEFAULT_ACTION_LABEL = "Send a gift";

export const CONTENT_HORIZONTAL_PADDING = 32;
export const ARTWORK_SIZE = 120;
export const SCENE_SIZE = 200;
export const HALO_CORE_SIZE = 152;
export const HALO_RINGS: IHaloRing[] = [
  { size: 288, opacity: 0.35 },
  { size: 220, opacity: 0.6 },
];
export const ACTION_HEIGHT = 50;
export const ACTION_HORIZONTAL_PADDING = 30;

export const COLORS = {
  screen: "#ffffff",
  halo: "#e9ebef",
  haloCore: "#f6f7f9",
  title: "#0f1013",
  description: "#8e9198",
  action: "#111114",
  actionPressed: "#33343a",
  actionLabel: "#ffffff",
} as const;
import type { ImageSourcePropType, StyleProp, ViewStyle } from "react-native";

export interface IHaloRing {
  size: number;

  opacity: number;
}

export interface IEmptyGiftState {
  title?: string;

  description?: string;

  actionLabel?: string;

  artwork?: ImageSourcePropType;

  hideAction?: boolean;

  hideHalo?: boolean;

  style?: StyleProp<ViewStyle>;

  onActionPress?: () => void;
}
import { Asset } from "expo-asset";

const uri = (id: number): string => Asset.fromModule(id).uri;

export const PHOTO_SOURCES = {
  "empty-gift-v1-1": uri(require("./empty-gift-v1-1.webp")),
};

Ещё 1 файл с картинками или шрифтами. astra-rn add скачивает их сам, вручную положите их по этим путям:

  • src/shared/components/blocks/empty-gift-v1/photos/empty-gift-v1-1.webp20 КБСкачать

ПРИСОЕДИНЯЙТЕСЬ

ПолучитезначокAstra Proужесегодня

ASTRAPRO
Дизайн и разработка — ©Astra