diff options
Diffstat (limited to 'modules/react-native-ui-text-view/src')
-rw-r--r-- | modules/react-native-ui-text-view/src/UITextView.tsx | 76 | ||||
-rw-r--r-- | modules/react-native-ui-text-view/src/index.tsx | 42 |
2 files changed, 118 insertions, 0 deletions
diff --git a/modules/react-native-ui-text-view/src/UITextView.tsx b/modules/react-native-ui-text-view/src/UITextView.tsx new file mode 100644 index 000000000..bbb45dccc --- /dev/null +++ b/modules/react-native-ui-text-view/src/UITextView.tsx @@ -0,0 +1,76 @@ +import React from 'react' +import {Platform, StyleSheet, TextProps, ViewStyle} from 'react-native' +import {RNUITextView, RNUITextViewChild} from './index' + +const TextAncestorContext = React.createContext<[boolean, ViewStyle]>([ + false, + StyleSheet.create({}), +]) +const useTextAncestorContext = () => React.useContext(TextAncestorContext) + +const textDefaults: TextProps = { + allowFontScaling: true, + selectable: true, +} + +export function UITextView({style, children, ...rest}: TextProps) { + const [isAncestor, rootStyle] = useTextAncestorContext() + + // Flatten the styles, and apply the root styles when needed + const flattenedStyle = React.useMemo( + () => StyleSheet.flatten([rootStyle, style]), + [rootStyle, style], + ) + + if (Platform.OS !== 'ios') { + throw new Error('UITextView is only available on iOS') + } + + if (!isAncestor) { + return ( + <TextAncestorContext.Provider value={[true, flattenedStyle]}> + <RNUITextView + {...textDefaults} + {...rest} + ellipsizeMode={rest.ellipsizeMode ?? rest.lineBreakMode ?? 'tail'} + style={[{flex: 1}, flattenedStyle]} + onPress={undefined} // We want these to go to the children only + onLongPress={undefined}> + {React.Children.toArray(children).map((c, index) => { + if (React.isValidElement(c)) { + return c + } else if (typeof c === 'string') { + return ( + <RNUITextViewChild + key={index} + style={flattenedStyle} + text={c} + {...rest} + /> + ) + } + })} + </RNUITextView> + </TextAncestorContext.Provider> + ) + } else { + return ( + <> + {React.Children.toArray(children).map((c, index) => { + if (React.isValidElement(c)) { + return c + } else if (typeof c === 'string') { + return ( + <RNUITextViewChild + key={index} + style={flattenedStyle} + text={c} + {...rest} + /> + ) + } + })} + </> + ) + } +} diff --git a/modules/react-native-ui-text-view/src/index.tsx b/modules/react-native-ui-text-view/src/index.tsx new file mode 100644 index 000000000..d5bde136f --- /dev/null +++ b/modules/react-native-ui-text-view/src/index.tsx @@ -0,0 +1,42 @@ +import { + requireNativeComponent, + UIManager, + Platform, + type ViewStyle, + TextProps, +} from 'react-native' + +const LINKING_ERROR = + `The package 'react-native-ui-text-view' doesn't seem to be linked. Make sure: \n\n` + + Platform.select({ios: "- You have run 'pod install'\n", default: ''}) + + '- You rebuilt the app after installing the package\n' + + '- You are not using Expo Go\n' + +export interface RNUITextViewProps extends TextProps { + children: React.ReactNode + style: ViewStyle[] +} + +export interface RNUITextViewChildProps extends TextProps { + text: string + onTextPress?: (...args: any[]) => void + onTextLongPress?: (...args: any[]) => void +} + +export const RNUITextView = + UIManager.getViewManagerConfig && + UIManager.getViewManagerConfig('RNUITextView') != null + ? requireNativeComponent<RNUITextViewProps>('RNUITextView') + : () => { + throw new Error(LINKING_ERROR) + } + +export const RNUITextViewChild = + UIManager.getViewManagerConfig && + UIManager.getViewManagerConfig('RNUITextViewChild') != null + ? requireNativeComponent<RNUITextViewChildProps>('RNUITextViewChild') + : () => { + throw new Error(LINKING_ERROR) + } + +export * from './UITextView' |