import { Children, Fragment, isValidElement, useMemo, type ReactElement, type ReactNode, } from "react"; import { StyleSheet, View, type ViewStyle } from "react-native"; const styles = StyleSheet.create({ container: { flexDirection: "column", }, }); export interface VStackDividerProps { marginBottom: number; } export interface VStackProps { children: ReactNode; spacing?: number; alignItems?: ViewStyle["alignItems"]; justifyContent?: ViewStyle["justifyContent"]; /** If the VStack should `flex: 1` to fill the parent's height */ grow?: boolean; } function isFragment( child: ReactNode ): child is ReactElement<{ children?: ReactNode }> { return isValidElement(child) && child.type === Fragment; } export function VStack({ children, spacing = 0, alignItems, justifyContent, grow, }: VStackProps) { const containerStyles = useMemo( () => ({ ...styles.container, gap: spacing, alignItems, justifyContent, flex: grow ? 1 : undefined, }), [alignItems, grow, justifyContent, spacing] ); return ( {Children.toArray(children) .map((c) => (isFragment(c) ? c.props.children : c)) .flat() .filter((c) => c !== null && typeof c !== "undefined") .map((child, i) => ( {child} ))} ); }