import _ from 'lodash'; import React, { useMemo } from 'react'; import { I18nManager, StyleProp, StyleSheet, Text, TextProps, View, ViewStyle } from 'react-native'; import { MathViewProps } from './common'; //@ts-ignore import MathView from './MathView'; type ElementOrRenderer = ((props: T) => JSX.Element) | JSX.Element export type Direction = 'ltr' | 'rtl' | 'auto'; export type MathTextRowRenderingProps = { value: string, isMath: boolean, index: number }; export type MathTextItemRenderingProps = MathTextRowRenderingProps & { rowIndex: number, inline: boolean }; export type MathTextItemProps = (T extends true ? Omit : TextProps) & { value: string, isMath: T, Component?: MathView, CellRendererComponent?: ElementOrRenderer, inline?: boolean } export type MathTextRowProps = MathTextItemProps & { direction?: Direction, containerStyle?: StyleProp, index: number, renderItem?: (props: MathTextItemRenderingProps) => JSX.Element } export type MathTextProps = Pick & { value?: string, math?: string, style?: StyleProp, renderRow?: (props: MathTextRowRenderingProps) => JSX.Element } export const InlineMathItem = React.memo(({ value, isMath, CellRendererComponent, Component, inline, style, ...props }: MathTextItemProps) => { if (value === '') return null; const config = useMemo(() => ({ inline }), [inline]); const Renderer = Component || MathView; const el = isMath ? : {value} ; const container = typeof CellRendererComponent === 'function' ? : CellRendererComponent || <>; return React.cloneElement(container, {}, el); }); export const MathTextRow = React.memo(({ value, isMath, direction, containerStyle, CellRendererComponent, renderItem, index, ...props }: MathTextRowProps) => { const parts = useMemo(() => _.flatten(_.map(_.split(value, /\$+/g), (value, i) => { if (isMath || i % 2 === 1) { return [{ value, isMath: true, inline: !isMath }]; } else { return _.map(_.split(_.trim(value), ' '), value => ({ value, isMath: false, inline: true })); } })), [value, isMath]); const Renderer = renderItem || InlineMathItem; return ( { _.map(parts, ({ value, isMath, inline }, i) => { const el = ; return React.cloneElement(i === parts.length - 1 ? el : <>{el} , { key: `InlineMath.${value}.${i}` }); }) } ) }); const MathText = React.memo(({ value, renderRow, style, math, ...props }: MathTextProps) => { if (__DEV__ && value && math) { console.warn('MathText has received both `value` and `math` props'); } else if (!value && !math) { __DEV__ && console.warn('MathText: please provide `value` or `math` prop'); return null; } const statements = useMemo(() => _.split(_.replace(value || `$${math}$`, /\\(\(|\))/g, '$'), /\$\$/g), [value]); const Container = renderRow || MathTextRow; return ( { _.map(statements, (value, i) => { if (value === '') return null; const isMath = i % 2 === 1; return _.map(_.split(value, /\n/g), (val, index) => ) }) } ); }); export default MathText; const styles = StyleSheet.create({ centerContent: { flex: 1, justifyContent: 'center', alignItems: 'center' }, flexLeft: { flexDirection: I18nManager.isRTL ? 'row-reverse' : 'row' }, flexRight: { flexDirection: I18nManager.isRTL ? 'row' : 'row-reverse' }, diverseContainer: { flexWrap: 'wrap', display: 'flex', flexDirection: 'row', marginVertical: 10 }, textMiddle: { textAlignVertical: 'center' } });