import { StyleSheet, type PressableStateCallbackType } from 'react-native'; import type { AnyProps, Style } from './types'; // -------------------------------------------------- export function isTextChildren( children: | React.ReactNode | ((state: PressableStateCallbackType) => React.ReactNode) ) { return Array.isArray(children) ? children.every((child) => typeof child === 'string') : typeof children === 'string'; } // -------------------------------------------------- export function composeRefs(...refs: (React.Ref | undefined)[]) { return (node: T) => refs.forEach((ref) => { if (typeof ref === 'function') { ref(node); } else if (ref != null) { (ref as React.MutableRefObject).current = node; } }); } // -------------------------------------------------- export function mergeProps(slotProps: AnyProps, childProps: AnyProps) { // all child props should override const overrideProps = { ...childProps }; for (const propName in childProps) { const slotPropValue = slotProps[propName]; const childPropValue = childProps[propName]; const isHandler = /^on[A-Z]/.test(propName); if (isHandler) { // if the handler exists on both, we compose them if (slotPropValue && childPropValue) { overrideProps[propName] = (...args: unknown[]) => { childPropValue(...args); slotPropValue(...args); }; } // but if it exists only on the slot, we use only this one else if (slotPropValue) { overrideProps[propName] = slotPropValue; } } // if it's `style`, we merge them else if (propName === 'style') { overrideProps[propName] = combineStyles(slotPropValue, childPropValue); } else if (propName === 'className') { overrideProps[propName] = [slotPropValue, childPropValue] .filter(Boolean) .join(' '); } } return { ...slotProps, ...overrideProps }; } // -------------------------------------------------- function combineStyles(slotStyle?: Style, childValue?: Style) { if (typeof slotStyle === 'function' && typeof childValue === 'function') { return (state: PressableStateCallbackType) => { return StyleSheet.flatten([slotStyle(state), childValue(state)]); }; } if (typeof slotStyle === 'function') { return (state: PressableStateCallbackType) => { return childValue ? StyleSheet.flatten([slotStyle(state), childValue]) : slotStyle(state); }; } if (typeof childValue === 'function') { return (state: PressableStateCallbackType) => { return slotStyle ? StyleSheet.flatten([slotStyle, childValue(state)]) : childValue(state); }; } return StyleSheet.flatten([slotStyle, childValue].filter(Boolean)); }