Live video on the AT Protocol
at natb/fullscreen-fixes 132 lines 3.4 kB view raw
1import { ImageStyle, StyleSheet, TextStyle, ViewStyle } from "react-native"; 2 3// React Native style utilities 4type Style = ViewStyle | TextStyle | ImageStyle; 5 6/** 7 * Merges React Native styles similar to how cn() merges CSS classes 8 * Handles arrays, objects, and falsy values 9 */ 10export function mergeStyles( 11 ...styles: (Style | Style[] | undefined | null | false)[] 12): Style { 13 const validStyles = styles.filter(Boolean).flat() as Style[]; 14 return StyleSheet.flatten(validStyles) || {}; 15} 16 17/** 18 * Creates a style merger function that includes base styles 19 * Useful for component variants 20 */ 21export function createStyleMerger(baseStyle: Style) { 22 return (...styles: (Style | Style[] | undefined | null | false)[]) => { 23 return mergeStyles(baseStyle, ...styles); 24 }; 25} 26 27/** 28 * Conditionally applies styles based on boolean conditions 29 */ 30export function conditionalStyle( 31 condition: boolean, 32 trueStyle: Style, 33 falseStyle?: Style, 34): Style | undefined { 35 return condition ? trueStyle : falseStyle; 36} 37 38/** 39 * Creates responsive values based on screen dimensions 40 */ 41export function responsiveValue<T>( 42 values: { 43 sm?: T; 44 md?: T; 45 lg?: T; 46 xl?: T; 47 default: T; 48 }, 49 screenWidth: number, 50): T { 51 if (screenWidth >= 1280 && values.xl !== undefined) return values.xl; 52 if (screenWidth >= 1024 && values.lg !== undefined) return values.lg; 53 if (screenWidth >= 768 && values.md !== undefined) return values.md; 54 if (screenWidth >= 640 && values.sm !== undefined) return values.sm; 55 return values.default; 56} 57 58/** 59 * Creates platform-specific styles 60 */ 61export function platformStyle(styles: { 62 ios?: Style; 63 android?: Style; 64 web?: Style; 65 default?: Style; 66}): Style { 67 const Platform = require("react-native").Platform; 68 69 if (Platform.OS === "ios" && styles.ios) return styles.ios; 70 if (Platform.OS === "android" && styles.android) return styles.android; 71 if (Platform.OS === "web" && styles.web) return styles.web; 72 return styles.default || {}; 73} 74 75/** 76 * Converts hex color to rgba 77 */ 78export function hexToRgba(hex: string, alpha: number = 1): string { 79 const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 80 if (!result) return hex; 81 82 const r = parseInt(result[1], 16); 83 const g = parseInt(result[2], 16); 84 const b = parseInt(result[3], 16); 85 86 return `rgba(${r}, ${g}, ${b}, ${alpha})`; 87} 88 89/** 90 * Creates a debounced function for performance 91 */ 92export function debounce<T extends (...args: any[]) => any>( 93 func: T, 94 delay: number, 95): (...args: Parameters<T>) => void { 96 let timeoutId: NodeJS.Timeout; 97 98 return (...args: Parameters<T>) => { 99 clearTimeout(timeoutId); 100 timeoutId = setTimeout(() => func(...args), delay); 101 }; 102} 103 104/** 105 * Creates a throttled function for performance 106 */ 107export function throttle<T extends (...args: any[]) => any>( 108 func: T, 109 delay: number, 110): (...args: Parameters<T>) => void { 111 let lastCall = 0; 112 113 return (...args: Parameters<T>) => { 114 const now = Date.now(); 115 if (now - lastCall >= delay) { 116 lastCall = now; 117 func(...args); 118 } 119 }; 120} 121 122/** 123 * Type-safe component prop forwarding 124 */ 125export function forwardProps<T extends Record<string, any>>( 126 props: T, 127 omit: (keyof T)[], 128): Omit<T, keyof T extends string ? keyof T : never> { 129 const result = { ...props }; 130 omit.forEach((key) => delete result[key]); 131 return result; 132}