import React, { ReactElement } from 'react'; import { Platform } from 'react-native'; import { version } from '../../package.json'; import { ContentsquareModule } from '../core/nativeModules'; import { CSQMaskProps } from '../types/types'; type NamableConstructor

= React.JSXElementConstructor

& { displayName?: string; name?: string; }; /** * Extracts React Native version from Platform constants */ export const extractReactNativeVersion = ( Platform: typeof import('react-native').Platform | undefined ): string | null => { const v = Platform?.constants?.reactNativeVersion; if (v) { return `${v.major}.${v.minor}.${v.patch}`; } else { return null; } }; /** * Initialization of components */ export const initComponents = (): void => { const reactNativeVersion = extractReactNativeVersion(Platform) || 'unknown'; ContentsquareModule.initComponents({ xpf_type: 'reactnative', xpf_version: reactNativeVersion, xpf_bridge_version: version as string, }); }; /** * Validates if children is valid and it is only one */ export const hasOnlyOneChild = (children?: ReactElement): boolean => { if (children && React.Children.count(children) === 1) { return true; } return false; }; /** * Merges two functions, useful when cloning a child and you want to make sure * that the user callback is called * @param internalCallback * @param userCallback * @returns merged callback */ export const mergeCallbacks = ( internalCallback: (...args: any[]) => void, userCallback?: (...args: any[]) => void ) => { return (...args: any[]) => { internalCallback(...args); if (userCallback) userCallback(...args); }; }; /** * Gets the display name of a React component * @param WrappedComponent - The component to get the display name from * @param defaultName - The default name to use if no display name is found * @returns The display name of the component */ export const getComponentDisplayName =

( WrappedComponent: NamableConstructor

, defaultName: string = 'CSQMaskedComponent' ) => { return WrappedComponent.displayName || WrappedComponent.name || defaultName; }; /** * Determines HeapIgnore props based on masking configuration * When ignoreTextOnly is true, returns fixed props that capture hierarchy but ignore text * Otherwise, returns props based on explicit configuration with false defaults * @param maskOptions - The CSQMask options * @returns HeapIgnore props configuration */ export const getHeapIgnoreProps = (maskOptions?: CSQMaskProps) => { if (maskOptions?.ignoreTextOnly) { return { allowInnerHierarchy: true, allowProps: true, allowInteraction: true, allowText: false, allowAccessibilityLabel: false, }; } return { allowInnerHierarchy: maskOptions?.allowInnerHierarchy ?? false, allowProps: maskOptions?.allowProps ?? false, allowText: maskOptions?.allowText ?? false, allowInteraction: maskOptions?.allowInteraction ?? false, allowAccessibilityLabel: maskOptions?.allowAccessibilityLabel ?? false, }; };