import { Pressable, StyleSheet, Text, TextInput, View, type TextInputProps, type ViewStyle } from "react-native"; import { C, radius, shadow, space, type } from "../lib/theme"; /** * Screen background + consistent gutter. Every screen sits on the grouped * background so white cards read as raised paper. */ export function Screen({ children, style }: { children: React.ReactNode; style?: ViewStyle }) { return {children}; } /** * Large in-content heading. Nav-bar titles are tiny and centred; Things puts * the screen name in the content at display size, which is what gives each * screen its sense of place. */ export function Title({ children, count }: { children: React.ReactNode; count?: number }) { return ( {children} {count !== undefined && count > 0 && {count}} ); } /** Small caps label above a group. Sentence case — SHOUTING CAPS reads dated. */ export function SectionHeader({ children, tone }: { children: React.ReactNode; tone?: string }) { return {children}; } /** * Rounded white group. Rows inside are separated by inset hairlines rather * than full-bleed dividers, so the card keeps a clean silhouette. */ export function Card({ children, style }: { children: React.ReactNode; style?: ViewStyle }) { return {children}; } /** Inset hairline for use between rows inside a `Card`. */ export function Separator({ inset = 0 }: { inset?: number }) { return ; } /** Compact count/status pill. */ export function Pill({ label, tone }: { label: string; tone?: string }) { return ( {label} ); } /** Centred empty state. One quiet line — no illustration, no exclamation. */ export function Empty({ children }: { children: React.ReactNode }) { return {children}; } export function Field({ label, ...props }: TextInputProps & { label: string }) { return ( {label} ); } export function Chips({ label, options, value, onChange, labels, }: { label: string; options: T[]; value: T | null; onChange: (v: T) => void; labels?: Record; }) { return ( {label} {options.map((o) => { const active = value === o; return ( [u.chip, active && u.chipActive, pressed && !active && u.chipPressed]} onPress={() => onChange(o)} > {labels?.[o] ?? o} ); })} ); } export function Button({ title, onPress, danger, secondary, }: { title: string; onPress: () => void; danger?: boolean; secondary?: boolean; }) { const variant = danger ? u.buttonDanger : secondary ? u.buttonSecondary : null; const textVariant = danger ? u.buttonTextDanger : secondary ? u.buttonTextSecondary : null; return ( [u.button, variant, pressed && { opacity: 0.75 }]} onPress={onPress} > {title} ); } const u = StyleSheet.create({ screen: { flex: 1, backgroundColor: C.bg }, titleRow: { flexDirection: "row", alignItems: "center", gap: space.md, paddingHorizontal: space.lg, paddingTop: space.md, paddingBottom: space.lg, }, title: { ...type.title, color: C.text }, titleCount: { ...type.title, color: C.muted, fontWeight: "600" }, sectionHeader: { ...type.section, color: C.textSecondary, paddingHorizontal: space.xs, paddingTop: space.xl, paddingBottom: space.sm, }, card: { backgroundColor: C.surface, borderRadius: radius.lg, borderWidth: StyleSheet.hairlineWidth, borderColor: C.border, overflow: "hidden", ...shadow.card, }, separator: { height: StyleSheet.hairlineWidth, backgroundColor: C.separator }, pill: { paddingHorizontal: space.sm, paddingVertical: 3, borderRadius: radius.pill, backgroundColor: C.surface2, }, pillText: { ...type.meta, color: C.textSecondary, fontWeight: "500" }, empty: { color: C.muted, textAlign: "center", marginTop: 56, ...type.body }, label: { ...type.section, color: C.textSecondary, marginBottom: space.sm, }, input: { backgroundColor: C.surface, color: C.text, borderRadius: radius.md, borderWidth: StyleSheet.hairlineWidth, borderColor: C.border, paddingHorizontal: space.md, paddingVertical: space.md, fontSize: 16, }, chipRow: { flexDirection: "row", flexWrap: "wrap", gap: space.sm }, chip: { paddingVertical: space.sm, paddingHorizontal: space.lg - 2, borderRadius: radius.pill, backgroundColor: C.surface, borderWidth: StyleSheet.hairlineWidth, borderColor: C.border, }, chipActive: { backgroundColor: C.accentSoft, borderColor: C.accent }, chipPressed: { backgroundColor: C.surface2 }, chipText: { ...type.chip, color: C.textSecondary }, chipTextActive: { color: C.accent, fontWeight: "600" }, button: { backgroundColor: C.accent, borderRadius: radius.md, paddingVertical: space.lg - 2, alignItems: "center", marginTop: space.sm, marginBottom: space.md, }, buttonDanger: { backgroundColor: "transparent", borderWidth: StyleSheet.hairlineWidth, borderColor: C.danger }, buttonSecondary: { backgroundColor: C.surface, borderWidth: StyleSheet.hairlineWidth, borderColor: C.border }, buttonText: { fontSize: 16, fontWeight: "600", color: C.onAccent }, buttonTextDanger: { color: C.danger }, buttonTextSecondary: { color: C.text }, });