import React, { useEffect } from "react"; import { View } from "react-native"; import Svg, { Path } from "react-native-svg"; import Animated, { Easing, useAnimatedStyle, useSharedValue, withRepeat, withTiming, type SharedValue, } from "react-native-reanimated"; import { useColorScheme } from "nativewind"; import { ENTROPY_MARK_ASPECT, ENTROPY_MARK_PATH, ENTROPY_MARK_STEP, ENTROPY_MARK_VIEWBOX, } from "./entropy-mark"; // Boot/loading variant of the company mark: instead of all echoes drifting + // breathing at once (the website hover), exactly ONE layer is visible at a // time. A single pulse travels through the depth layers in sequence — furthest // echo → … → sharp source — then loops forever. Each layer sits at its own // echo offset (drifted up-left by depth × STEP), so the pulse reads as the mark // converging from the deep echoes into the source. interface MarkColors { src: string; echo: Record<1 | 2 | 3, string>; } const COLORS: Record<"light" | "dark", MarkColors> = { light: { src: "#000000", echo: { 3: "#cbcbcb", 2: "#a3a3a3", 1: "#525252" } }, dark: { src: "#ffffff", echo: { 3: "#373737", 2: "#5f5f5f", 1: "#8c8c8c" } }, }; // Order the pulse travels: sharp source first → out through the echoes. const DEPTHS = [0, 1, 2, 3] as const; // 0 = source const COUNT = DEPTHS.length; export interface EntropyMarkSequentialProps { /** Rendered height in px. Width follows the ~1.63:1 aspect. */ size?: number; /** Override the theme; defaults to the active color scheme. */ scheme?: "light" | "dark"; /** Full-cycle duration in ms (time to sweep through all layers once). */ durationMs?: number; } function Layer({ prog, index, width, size, color, offsetX, offsetY, }: { prog: SharedValue; index: number; width: number; size: number; color: string; offsetX: number; offsetY: number; }) { const style = useAnimatedStyle(() => { // Triangular pulse centered on this layer's slot; near-zero at the // neighbours' centers so only one layer is lit at a time. Wraps so the // loop has no seam. const center = (index + 0.5) / COUNT; let d = Math.abs(prog.value - center); d = Math.min(d, 1 - d); const opacity = Math.max(0, Math.min(1, 1 - d * COUNT * 1.15)); return { opacity }; }); return ( ); } export function EntropyMarkSequential({ size = 96, scheme, durationMs = 1000, }: EntropyMarkSequentialProps) { const { colorScheme } = useColorScheme(); const c = COLORS[scheme ?? (colorScheme === "dark" ? "dark" : "light")]; const width = Math.round(size * ENTROPY_MARK_ASPECT); const prog = useSharedValue(0); useEffect(() => { prog.value = withRepeat( withTiming(1, { duration: durationMs, easing: Easing.linear }), -1, false ); }, [prog, durationMs]); return ( {DEPTHS.map((depth, index) => ( ))} ); } export default EntropyMarkSequential;