diff --git a/README.md b/README.md index e93b761..02f46e0 100644 --- a/README.md +++ b/README.md @@ -75,10 +75,13 @@ export default Home; | `onExpand` | `func` | no | optional callback executed when expanded | `onCollapse` | `func` | no | optional callback executed when collapsed | `onReady` | `func` | no | optional callback executed when see more placement measurements are completed -| `seeMoreContainerStyleSecondary` | `object` | no | Incase of text overlap, pass { position: 'relative' } see [issue](https://github.com/fawaz-ahmed/react-native-read-more/issues/52) +| `seeMoreContainerStyleSecondary` | `object` | no | Incase of text overlap, pass { position: 'relative' } see [issue](https://github.com/fawaz-ahmed/react-native-read-more/issues/52) (not recommended) Any additional props are passed down to underlying `Text` component. +# Usage with HTML +HTML rendering is not part of this package, but can be done easily with the help of any custom html to text library. For sample code, refer to this [issue](https://github.com/fawaz-ahmed/react-native-read-more/issues/55#issuecomment-1046941770) + # Run example ``` git clone https://github.com/fawaz-ahmed/react-native-read-more.git @@ -93,13 +96,14 @@ yarn android ``` # Why another library ? -This module will calculate where to position `See more` and `See less` within the same paragraph instead of occupying another line. It is a drop-in replacement for `Text` component and you can control when to apply the see more functionality by configuring the `numberOfLines` prop. Moreover, you can also pass your own custom implementation of `Text` component like `ParsedText` etc. +This module will calculate where to position `See more` and `See less` within the same paragraph instead of occupying another line. It is a drop-in replacement for `Text` component and you can control when to apply the see more functionality by configuring the `numberOfLines` prop. Moreover, you can also pass your own custom implementation of `Text` component like `ParsedText` ([sample code](https://github.com/fawaz-ahmed/react-native-read-more/issues/37#issuecomment-1047029209)) etc. ## Seeing issues or any feedback or feature suggest ? Create an [issue](https://github.com/fawaz-ahmed/react-native-read-more/issues) with github. ## Troubleshooting - If you observe `See more` shown always in android, pass prop `allowFontScaling={false}`, refer to this [issue](https://github.com/fawaz-ahmed/react-native-read-more/issues/17) +- If you have any nested components other than `Text`, refer to this [issue](https://github.com/fawaz-ahmed/react-native-read-more/issues/52) ### jest - running unit tests This package is not transpiled. So inorder for your test cases to work, this package should be transpiled by babel. For this you need to add this path `!node_modules/@fawazahmed/react-native-read-more/` under `transformIgnorePatterns` option provided by `jest`. In your `package.json` you will see this `jest` config: diff --git a/example/src/ReadMore.js b/example/src/ReadMore.js index 104107c..ac79d56 100644 --- a/example/src/ReadMore.js +++ b/example/src/ReadMore.js @@ -7,8 +7,9 @@ import { LayoutAnimation, Platform, UIManager, + TextPropTypes, } from 'react-native'; -import {getText, insertAt, linesToCharacters} from './helper'; +import {getTextByChildren, insertAt, linesToCharacters} from './helper'; if (Platform.OS === 'android') { if (UIManager.setLayoutAnimationEnabledExperimental) { @@ -298,7 +299,7 @@ const ReadMore = ({ // go to this position and insert \n let charactersToTraverse = textBreakPosition; let nodeFound = false; - const modifiedChildrenObjects = getText(children, TextComponent, true) + const modifiedChildrenObjects = getTextByChildren(children, TextComponent) ?.map(_childObject => { if (nodeFound) { return _childObject; @@ -671,12 +672,10 @@ const styles = StyleSheet.create({ }); ReadMore.propTypes = { - style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), + ...TextPropTypes, seeMoreStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), seeLessStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), wrapperStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), - children: PropTypes.any, - numberOfLines: PropTypes.number, seeMoreText: PropTypes.string, seeLessText: PropTypes.string, animate: PropTypes.bool, @@ -686,14 +685,11 @@ ReadMore.propTypes = { PropTypes.elementType, ]), ellipsis: PropTypes.string, - allowFontScaling: PropTypes.bool, onExpand: PropTypes.func, onCollapse: PropTypes.func, expandOnly: PropTypes.bool, seeMoreOverlapCount: PropTypes.number, debounceSeeMoreCalc: PropTypes.number, - onLayout: PropTypes.func, - onTextLayout: PropTypes.func, onReady: PropTypes.func, seeMoreContainerStyleSecondary: PropTypes.object, }; @@ -703,7 +699,6 @@ ReadMore.defaultProps = { seeMoreStyle: StyleSheet.flatten([styles.defaultText, styles.seeMoreText]), seeLessStyle: StyleSheet.flatten([styles.defaultText, styles.seeLessText]), wrapperStyle: styles.container, - text: '', numberOfLines: 3, seeMoreText: 'See more', seeLessText: 'See less', diff --git a/example/src/helper.js b/example/src/helper.js index f831df5..972df2f 100644 --- a/example/src/helper.js +++ b/example/src/helper.js @@ -1,43 +1,42 @@ import React from 'react'; -const getStringChild = (child, preserveLinebreaks = false) => { - const content = preserveLinebreaks ? child : child?.split('\n').join(' '); +const getStringChild = child => { return { type: 'string', - content, - child: content, + content: child, + child, }; }; -const getTextChild = (child, preserveLinebreaks = false) => { - const content = preserveLinebreaks - ? child.props.children - : child.props.children?.split('\n').join(' '); +const getTextChild = child => { return { type: child?.type?.displayName, - content, - child: React.cloneElement(child, child.props, content), + content: child.props.children, + child: React.cloneElement(child, child.props, child.props.children), }; }; -export const getText = (children, TextComponent, preserveLinebreaks) => { +export const getTextByChildren = (children, TextComponent) => { if (typeof children === 'string') { - return [getStringChild(children, preserveLinebreaks)]; + return [getStringChild(children)]; + } + + if (typeof children === 'object' && children.props?.children) { + return getTextByChildren(React.Children.toArray(children.props.children)); } if (Array.isArray(children)) { return children - .filter((_child) => { + .filter(_child => { return ( typeof _child === 'string' || _child?.type?.displayName === TextComponent?.displayName ); }) - .map((_child) => { + .map(_child => { if (typeof _child === 'string') { - return getStringChild(_child, preserveLinebreaks); + return getStringChild(_child); } - return getTextChild(_child); }); } @@ -45,26 +44,8 @@ export const getText = (children, TextComponent, preserveLinebreaks) => { return null; }; -export const childrenToText = (children, TextComponent, preserveLinebreaks) => { - const _textChildren = getText(children, TextComponent, preserveLinebreaks); - return _textChildren.map((_t) => _t.content).join(' '); -}; - -export const childrenToTextChildren = ( - children, - TextComponent, - preserveLinebreaks, -) => { - const _textChildren = getText(children, TextComponent, preserveLinebreaks); - return _textChildren.map((_t) => _t.child); -}; - -export const childrenObjectsToChildren = (childrenObjects) => { - return childrenObjects.map((_t) => _t.child); -}; - -export const linesToCharacters = (lines) => { - return lines.map((_line) => _line?.text || '').join(''); +export const linesToCharacters = lines => { + return lines.map(_line => _line?.text || '').join(''); }; export const insertAt = (str, sub, pos) => diff --git a/index.d.ts b/index.d.ts index d917cc4..1717901 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,26 +1,20 @@ import React from 'react'; -import { StyleProp, TextStyle, ViewStyle, LayoutChangeEvent, NativeSyntheticEvent, TextLayoutEventData } from 'react-native'; +import { StyleProp, TextStyle, ViewStyle, TextProps } from 'react-native'; -export interface ReadMoreProps { - style?: StyleProp; +export interface ReadMoreProps extends TextProps { seeMoreStyle?: StyleProp; seeLessStyle?: StyleProp; wrapperStyle?: StyleProp; - children?: React.ReactNode; - numberOfLines?: number; seeMoreText?: string; seeLessText?: string; animate?: boolean; customTextComponent?: React.ReactNode; ellipsis?: string; - allowFontScaling?: boolean; onExpand?: () => void; onCollapse?: () => void; expandOnly?: boolean; seeMoreOverlapCount?: number; debounceSeeMoreCalc?: number; - onLayout?: (event: LayoutChangeEvent) => void; - onTextLayout?: (event: NativeSyntheticEvent) => void; onReady?: () => void; seeMoreContainerStyleSecondary: StyleProp; } diff --git a/package.json b/package.json index 962b439..01c9a65 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fawazahmed/react-native-read-more", - "version": "2.3.2", + "version": "2.3.3", "description": "A simple react native library to show large blocks of text in a condensed manner with the ability to collapse and expand.", "main": "index.js", "types": "index.d.ts",