import { SymbolView } from "expo-symbols"; import type { ComponentProps, ReactNode } from "react"; import { useCallback, useMemo, useState } from "react"; import { Pressable, ScrollView, View, useColorScheme, type LayoutChangeEvent, type NativeScrollEvent, type NativeSyntheticEvent, type StyleProp, type ViewStyle, } from "react-native"; import { useThemeColor } from "../lib/useThemeColor"; import { cn } from "../lib/cn"; import { AppText as Text } from "./AppText"; export const COMPOSER_TOOLBAR_CONTROL_HEIGHT = 44; export const COMPOSER_TOOLBAR_GAP = 8; export const COMPOSER_TOOLBAR_FADE_WIDTH = 18; const COMPOSER_TOOLBAR_SCROLL_EPSILON = 4; export function ComposerToolbarRow(props: { readonly children: ReactNode; readonly paddingBottom?: number; readonly paddingHorizontal?: number; readonly paddingTop?: number; readonly style?: StyleProp; }) { return ( {props.children} ); } export function ComposerToolbarScroller(props: { readonly children: ReactNode; readonly fadeOpaque: string; readonly fadeTransparent: string; readonly contentPaddingRight?: number; }) { const [metrics, setMetrics] = useState({ contentWidth: 0, offsetX: 0, viewportWidth: 0, }); const scrollEdges = useMemo(() => { const maxOffset = Math.max(0, metrics.contentWidth - metrics.viewportWidth); return { showLeftFade: metrics.offsetX > COMPOSER_TOOLBAR_SCROLL_EPSILON, showRightFade: metrics.offsetX < maxOffset - COMPOSER_TOOLBAR_SCROLL_EPSILON, }; }, [metrics]); const handleLayout = useCallback((event: LayoutChangeEvent) => { const viewportWidth = event.nativeEvent.layout.width; setMetrics((current) => current.viewportWidth === viewportWidth ? current : { ...current, viewportWidth }, ); }, []); const handleContentSizeChange = useCallback((contentWidth: number) => { setMetrics((current) => current.contentWidth === contentWidth ? current : { ...current, contentWidth }, ); }, []); const handleScroll = useCallback((event: NativeSyntheticEvent) => { const offsetX = event.nativeEvent.contentOffset.x; setMetrics((current) => Math.abs(current.offsetX - offsetX) < 1 ? current : { ...current, offsetX }, ); }, []); return ( {props.children} {scrollEdges.showLeftFade ? ( ) : null} {scrollEdges.showRightFade ? ( ) : null} ); } export function ComposerToolbarButton(props: { readonly icon?: ComponentProps["name"]; readonly iconNode?: ReactNode; readonly label?: string; readonly accessibilityLabel?: string; readonly active?: boolean; readonly disabled?: boolean; readonly maxWidth?: number; readonly minWidth?: number; readonly onPress?: () => void; readonly showChevron?: boolean; readonly textTransform?: "none" | "uppercase"; readonly variant?: "default" | "primary" | "danger"; readonly style?: StyleProp; }) { const isDarkMode = useColorScheme() === "dark"; const iconColor = useThemeColor("--color-icon"); const iconSubtle = useThemeColor("--color-icon-subtle"); const primaryFg = useThemeColor("--color-primary-foreground"); const dangerFg = useThemeColor("--color-danger-foreground"); const variant = props.variant ?? "default"; const isCircle = !props.label && props.showChevron === false; const defaultBorderColor = isDarkMode ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.06)"; const activeBorderColor = isDarkMode ? "rgba(255,255,255,0.13)" : "rgba(0,0,0,0.1)"; const filledBorderColor = variant === "danger" ? "rgba(255,255,255,0.14)" : props.disabled ? defaultBorderColor : "rgba(255,255,255,0.18)"; const iconTintColor = variant === "primary" ? props.disabled ? iconSubtle : primaryFg : variant === "danger" ? dangerFg : iconColor; return ( [ { borderColor: variant === "default" ? props.active ? activeBorderColor : defaultBorderColor : filledBorderColor, borderWidth: 1, maxWidth: props.maxWidth ?? 172, minWidth: props.minWidth, opacity: props.disabled ? 0.55 : pressed ? 0.72 : 1, shadowColor: "#000", shadowOffset: { width: 0, height: isDarkMode ? 3 : 2 }, shadowOpacity: props.disabled ? 0 : isDarkMode ? 0.24 : 0.08, shadowRadius: isDarkMode ? 10 : 8, }, props.style, ]} > {props.iconNode ? ( {props.iconNode} ) : props.icon ? ( ) : null} {props.label ? ( {props.label} ) : null} {props.showChevron === false ? null : ( )} ); } export const ComposerToolbarTrigger = ComposerToolbarButton;