@fawazahmed/react-native-read-more
Advanced tools
Comparing version 2.0.3 to 2.1.0
@@ -11,9 +11,3 @@ import React, {memo, useState, useEffect, useCallback} from 'react'; | ||
} from 'react-native'; | ||
import { | ||
childrenToTextChildren, | ||
getText, | ||
insertAt, | ||
linesToCharacters, | ||
childrenObjectsToChildren, | ||
} from './helper'; | ||
import {getText, insertAt, linesToCharacters} from './helper'; | ||
@@ -42,3 +36,2 @@ if (Platform.OS === 'android') { | ||
animate, | ||
backgroundColor, | ||
customTextComponent: TextComponent, | ||
@@ -52,36 +45,28 @@ ellipsis, | ||
debounceSeeMoreCalc, | ||
preserveLinebreaks, | ||
...restProps | ||
}) => { | ||
const [additionalProps, setAdditionalProps] = useState({}); | ||
// hiddenTextHeightOne comes from hidden component one | ||
const [hiddenTextHeightOne, setHiddenTextHeightOne] = useState(0); | ||
// hiddenTextHeightWithSeeLess comes from hidden component two | ||
const [ | ||
hiddenTextHeightWithSeeLess, | ||
setHiddenTextHeightWithSeeLess, | ||
] = useState(0); | ||
// hiddenTextLinesWithSeeLess comes from hidden component two | ||
const [hiddenTextLinesWithSeeLess, setHiddenTextLinesWithSeeLess] = useState( | ||
[], | ||
); | ||
// textHeight and textWidth comes from hidden component three | ||
const [textHeight, setTextHeight] = useState(0); | ||
const [textWidth, setTextWidth] = useState(0); | ||
// lineOfImpact comes from hidden component four | ||
const [lineOfImpact, setLineOfImpact] = useState({}); | ||
// const [lineOfImpact, setLineOfImpact] = useState({}); | ||
const [truncatedLineOfImpact, setTruncatedLineOfImpact] = useState(''); | ||
const [truncatedLineOfImpactWidth, setTruncatedLineOfImpactWidth] = useState( | ||
0, | ||
); | ||
const [lines, setLines] = useState([]); | ||
const [truncatedLineOfImpact, setTruncatedLineOfImpact] = useState(''); | ||
// eslint-disable-next-line prettier/prettier | ||
const [truncatedLineOfImpactWidth, setTruncatedLineOfImpactWidth] = useState(0); | ||
const [reconciledLineOfImpact, setReconciledLineOfImpact] = useState(''); | ||
// eslint-disable-next-line prettier/prettier | ||
const [reconciledLineOfImpactWidth, setReconciledLineOfImpactWidth] = useState(0); | ||
const [collapsedLines, setCollapsedLines] = useState([]); | ||
const [seeMoreRightPadding, setSeeMoreRightPadding] = useState(0); | ||
// mount or unmount hidden components | ||
const [mountHiddenTextOne, setMountHiddenTextOne] = useState(true); | ||
const [mountHiddenTextTwo, setMountHiddenTextTwo] = useState(true); | ||
const [mountHiddenTextThree, setMountHiddenTextThree] = useState(true); | ||
const [mountHiddenTextFour, setMountHiddenTextFour] = useState(true); | ||
const [mountHiddenTextFive, setMountHiddenTextFive] = useState(false); | ||
const [mountHiddenTextOne, setMountHiddenTextOne] = useState(false); | ||
const [mountHiddenTextTwo, setMountHiddenTextTwo] = useState(false); | ||
const [mountHiddenTextThree, setMountHiddenTextThree] = useState(false); | ||
const [mountHiddenTextFour, setMountHiddenTextFour] = useState(false); | ||
const [mountHiddenTextSix, setMountHiddenTextSix] = useState(false); | ||
const [mountHiddenTextSeven, setMountHiddenTextSeven] = useState(false); | ||
// initial measurement is in progress | ||
const [isMeasuring, setIsMeasuring] = useState(true); | ||
const [isMeasured, setIsMeasured] = useState(false); | ||
@@ -93,10 +78,9 @@ // logic decisioning params | ||
// copy of children with only text | ||
const [collapsedChildren, setCollapsedChildren] = useState( | ||
childrenToTextChildren(children, TextComponent, preserveLinebreaks), | ||
); | ||
const [measuredCollapsedChildren, setMeasuredCollapsedChildren] = useState( | ||
null, | ||
); | ||
const [collapsedChildren, setCollapsedChildren] = useState(null); | ||
const [reconciledLineOfImpact, setReconciledLineOfImpact] = useState(''); | ||
// eslint-disable-next-line prettier/prettier | ||
const [reconciledLineOfImpactWidth, setReconciledLineOfImpactWidth] = useState(0); | ||
// width of see more component | ||
const [seeMoreWidth, setSeeMoreWidth] = useState(0); | ||
const [hideEllipsis, setHideEllipsis] = useState(false); | ||
@@ -114,27 +98,21 @@ const onSeeMoreViewLayout = useCallback( | ||
const onLayoutHiddenTextSeven = useCallback( | ||
({ | ||
nativeEvent: { | ||
layout: {width}, | ||
}, | ||
}) => { | ||
setMountHiddenTextSeven(false); | ||
setReconciledLineOfImpactWidth(width); | ||
const onTextLayoutOne = useCallback( | ||
({nativeEvent: {lines: _lines}}) => { | ||
setLines(_lines); | ||
setMountHiddenTextOne(false); | ||
setMountHiddenTextTwo(true); | ||
}, | ||
[setReconciledLineOfImpactWidth, setMountHiddenTextSeven], | ||
[setLines, setMountHiddenTextOne], | ||
); | ||
const onLayoutHiddenTextSix = useCallback(() => { | ||
setMountHiddenTextSix(false); | ||
}, [setMountHiddenTextSix]); | ||
const onTextLayoutHiddenTextSix = useCallback( | ||
const onTextLayoutTwo = useCallback( | ||
({nativeEvent: {lines: _lines}}) => { | ||
const _lineOfImpact = _lines[numberOfLines - 1]; | ||
setReconciledLineOfImpact(_lineOfImpact?.text || ''); | ||
setHiddenTextLinesWithSeeLess(_lines); | ||
setMountHiddenTextTwo(false); | ||
setMountHiddenTextFour(true); | ||
}, | ||
[numberOfLines, setReconciledLineOfImpact], | ||
[setHiddenTextLinesWithSeeLess, setMountHiddenTextTwo], | ||
); | ||
const onLayoutHiddenTextFive = useCallback( | ||
const onLayoutActualTextComponent = useCallback( | ||
({ | ||
@@ -145,56 +123,57 @@ nativeEvent: { | ||
}) => { | ||
setMountHiddenTextFive(false); | ||
setTruncatedLineOfImpactWidth(width); | ||
setTextWidth(width); | ||
setMountHiddenTextFour(false); | ||
if (Platform.OS === 'android') { | ||
setMountHiddenTextSix(true); | ||
} | ||
}, | ||
[setTruncatedLineOfImpactWidth, setMountHiddenTextFive], | ||
[setTextWidth], | ||
); | ||
const onTextLayoutHiddenTextFour = useCallback( | ||
const onTextLayoutActualTextComponent = useCallback( | ||
({nativeEvent: {lines: _lines}}) => { | ||
const _lineOfImpact = _lines[numberOfLines - 1]; | ||
setLineOfImpact(_lineOfImpact); | ||
setLines(_lines); | ||
if (!collapsed) { | ||
return; | ||
} | ||
setCollapsedLines(_lines); | ||
}, | ||
[numberOfLines, setLineOfImpact, setLines], | ||
[setCollapsedLines, collapsed], | ||
); | ||
const onLayoutHiddenTextFour = useCallback(() => { | ||
setMountHiddenTextFour(false); | ||
}, [setMountHiddenTextFour]); | ||
const onLayoutHiddenTextThree = useCallback( | ||
const onLayoutThree = useCallback( | ||
({ | ||
nativeEvent: { | ||
layout: {height, width}, | ||
layout: {width}, | ||
}, | ||
}) => { | ||
setTextHeight(height); | ||
setTextWidth(width); | ||
setTruncatedLineOfImpactWidth(width); | ||
setMountHiddenTextThree(false); | ||
}, | ||
[setTextHeight, setTextWidth, setMountHiddenTextThree], | ||
[setTruncatedLineOfImpactWidth, setMountHiddenTextThree], | ||
); | ||
const onHiddenTextLayoutOne = useCallback( | ||
({ | ||
nativeEvent: { | ||
layout: {height}, | ||
}, | ||
}) => { | ||
setHiddenTextHeightOne(height); | ||
setMountHiddenTextOne(false); | ||
const onLayoutHiddenTextSix = useCallback(() => { | ||
setMountHiddenTextSix(false); | ||
setMountHiddenTextSeven(true); | ||
}, [setMountHiddenTextSix, setMountHiddenTextSeven]); | ||
const onTextLayoutHiddenTextSix = useCallback( | ||
({nativeEvent: {lines: _lines}}) => { | ||
const _lineOfImpact = _lines[numberOfLines - 1]; | ||
setReconciledLineOfImpact(_lineOfImpact?.text || ''); | ||
}, | ||
[setHiddenTextHeightOne, setMountHiddenTextOne], | ||
[numberOfLines, setReconciledLineOfImpact], | ||
); | ||
const onHiddenSeeLessTextLayoutTwo = useCallback( | ||
const onLayoutHiddenTextSeven = useCallback( | ||
({ | ||
nativeEvent: { | ||
layout: {height}, | ||
layout: {width}, | ||
}, | ||
}) => { | ||
setHiddenTextHeightWithSeeLess(height); | ||
setMountHiddenTextTwo(false); | ||
setMountHiddenTextSeven(false); | ||
setReconciledLineOfImpactWidth(width); | ||
}, | ||
[setHiddenTextHeightWithSeeLess, setMountHiddenTextTwo], | ||
[setReconciledLineOfImpactWidth, setMountHiddenTextSeven], | ||
); | ||
@@ -208,90 +187,146 @@ | ||
if ( | ||
!seeMore || | ||
!textWidth || | ||
!numberOfLines || | ||
!seeMoreWidth || | ||
!lineOfImpact?.text | ||
numberOfLines < 1 || | ||
!lines.length || | ||
!collapsedLines.length || | ||
!seeMore | ||
) { | ||
setTruncatedLineOfImpact(''); | ||
setTruncatedLineOfImpactWidth(0); | ||
return setMeasuredCollapsedChildren(null); | ||
return; | ||
} | ||
// if line of impact | ||
// use number fo lines - 1 lines with wrap text and clip ellipsis | ||
// another text component with line of impact | ||
// width will be total width - see more width | ||
// show this ^^ on collapsed state | ||
const linesTillImpact = Array(numberOfLines) | ||
.fill({}) | ||
.map((_e, index) => lines[index]); | ||
const charactersBeforeSeeMore = linesToCharacters(linesTillImpact); | ||
const charactersLengthTillSeeMore = charactersBeforeSeeMore.trim().length; | ||
const seeMoreTextLength = | ||
`${ellipsis} ${seeMoreText}`.length + seeMoreOverlapCount; | ||
// text break position for collapsed text | ||
const textBreakPosition = charactersLengthTillSeeMore - seeMoreTextLength; | ||
const trimmedLineOfImpact = lineOfImpact.text.trim(); | ||
const _truncatedLineOfImpact = trimmedLineOfImpact.substring( | ||
0, | ||
trimmedLineOfImpact.length - seeMoreTextLength, | ||
); | ||
setTruncatedLineOfImpact(_truncatedLineOfImpact); | ||
// go to this position and insert a line break | ||
let charactersToTraverse = textBreakPosition; | ||
let nodeFound = false; | ||
const modifiedChildrenObjects = getText( | ||
children, | ||
TextComponent, | ||
preserveLinebreaks, | ||
).map((_childObject) => { | ||
if (nodeFound) { | ||
return _childObject; | ||
if (!lines[numberOfLines - 1] || !collapsedLines[numberOfLines - 1]) { | ||
return; | ||
} | ||
// find line of impact | ||
let _lineOfImpact = lines[numberOfLines - 1]; | ||
_lineOfImpact.index = numberOfLines - 1; | ||
if (Platform.OS === 'ios') { | ||
const modifiedIndex = lines.findIndex((_line, index) => { | ||
if (index + 1 < numberOfLines - 1) { | ||
return false; | ||
} | ||
return collapsedLines[numberOfLines - 1].text.includes(_line.text); | ||
}); | ||
_lineOfImpact = lines[modifiedIndex]; | ||
_lineOfImpact.index = modifiedIndex; | ||
} | ||
const availableWidth = textWidth - seeMoreWidth; | ||
// calculate how many characters to cut off if any | ||
// trim right before -> spaces and \n | ||
// width from line, textWidth, seeMoreWidth | ||
// if no text after right trim | ||
// hide ellipsis | ||
// move see more to beginning | ||
if (_lineOfImpact.text.trim().length === 0) { | ||
_lineOfImpact.width = 0; | ||
_lineOfImpact.text = ''; | ||
setHideEllipsis(true); | ||
} else { | ||
setHideEllipsis(false); | ||
} | ||
// todo | ||
// right trim and width adjustment | ||
// setLineOfImpact(_lineOfImpact); | ||
if (_lineOfImpact.width < availableWidth) { | ||
// if no need to cutoff, simply calculate see more right padding | ||
const _seeMoreRightPadding = | ||
textWidth - _lineOfImpact.width - seeMoreWidth; | ||
if (_seeMoreRightPadding > 0) { | ||
setTruncatedLineOfImpact(''); | ||
setTruncatedLineOfImpactWidth(0); | ||
setReconciledLineOfImpact(''); | ||
setReconciledLineOfImpactWidth(0); | ||
setSeeMoreRightPadding(_seeMoreRightPadding); | ||
// todo: remove this | ||
if (animate) { | ||
LayoutAnimation.configureNext(readmoreAnimation); | ||
} | ||
} | ||
if (_childObject.content.length > charactersToTraverse) { | ||
// this node is the one | ||
nodeFound = true; | ||
const childContent = insertAt( | ||
_childObject.content, | ||
'\n', | ||
charactersToTraverse, | ||
); | ||
return { | ||
type: _childObject?.type, | ||
content: childContent, | ||
child: | ||
_childObject?.type === 'string' | ||
? childContent | ||
: React.cloneElement( | ||
_childObject, | ||
_childObject.props, | ||
childContent, | ||
), | ||
}; | ||
} else { | ||
// todo | ||
// determine point, traverse through nodes | ||
// create collapsed children with spaces at the point | ||
const seeMoreTextLength = | ||
`${ellipsis} ${seeMoreText}`.length + seeMoreOverlapCount; | ||
const linesTillImpact = Array(_lineOfImpact.index + 1) | ||
.fill({}) | ||
.map((_e, index) => lines[index]); | ||
const charactersBeforeSeeMore = linesToCharacters(linesTillImpact); | ||
const charactersLengthTillSeeMore = charactersBeforeSeeMore.length; | ||
// text break position for collapsed text | ||
const textBreakPosition = charactersLengthTillSeeMore - seeMoreTextLength; | ||
const _truncatedText = _lineOfImpact.text.substr( | ||
0, | ||
_lineOfImpact.text.length - seeMoreTextLength, | ||
); | ||
if (truncatedLineOfImpact !== _truncatedText) { | ||
setTruncatedLineOfImpact(_truncatedText); | ||
} | ||
charactersToTraverse = charactersToTraverse - _childObject.content.length; | ||
return _childObject; | ||
}); | ||
// go to this position and insert spaces | ||
let charactersToTraverse = textBreakPosition; | ||
let nodeFound = false; | ||
const modifiedChildrenObjects = getText(children, TextComponent, true) | ||
?.map((_childObject) => { | ||
if (nodeFound) { | ||
return _childObject; | ||
} | ||
if (_childObject.content.length > charactersToTraverse) { | ||
// this node is the one | ||
nodeFound = true; | ||
const childContent = insertAt( | ||
_childObject.content, | ||
'\n', | ||
charactersToTraverse, | ||
); | ||
return { | ||
type: _childObject?.type, | ||
content: childContent, | ||
child: | ||
_childObject?.type === 'string' | ||
? childContent | ||
: React.cloneElement( | ||
_childObject, | ||
_childObject.props, | ||
childContent, | ||
), | ||
}; | ||
} | ||
charactersToTraverse = | ||
charactersToTraverse - _childObject.content.length; | ||
if (nodeFound) { | ||
return setMeasuredCollapsedChildren( | ||
childrenObjectsToChildren(modifiedChildrenObjects), | ||
); | ||
return _childObject; | ||
}) | ||
?.map((_updatedObjects) => { | ||
return _updatedObjects.child; | ||
}); | ||
if (nodeFound) { | ||
setCollapsedChildren(modifiedChildrenObjects); | ||
} | ||
} | ||
return setMeasuredCollapsedChildren(null); | ||
setIsMeasured(true); | ||
}, [ | ||
children, | ||
TextComponent, | ||
textWidth, | ||
numberOfLines, | ||
lines, | ||
collapsedLines, | ||
seeMore, | ||
textWidth, | ||
seeMoreWidth, | ||
lineOfImpact, | ||
lines, | ||
animate, | ||
ellipsis, | ||
seeMoreText, | ||
seeMoreOverlapCount, | ||
preserveLinebreaks, | ||
truncatedLineOfImpact, | ||
children, | ||
TextComponent, | ||
]); | ||
@@ -322,8 +357,10 @@ | ||
const seeMoreBackgroundStyle = | ||
isMeasuring || lineOfImpact?.text ? {} : {backgroundColor}; | ||
const seeMoreTextHidingStyle = isMeasured ? {} : {color: 'transparent'}; | ||
// use after measured here | ||
const seeMoreTextHidingStyle = !isMeasured | ||
? {color: 'transparent'} | ||
: { | ||
backgroundColor: 'transparent', | ||
}; | ||
const seeMoreContainerStyle = [ | ||
styles.seeMoreContainer, | ||
seeMoreBackgroundStyle, | ||
{ | ||
@@ -335,9 +372,5 @@ marginRight: seeMoreRightPadding, | ||
useEffect(() => { | ||
if (!hiddenTextHeightOne || !textHeight) { | ||
return; | ||
} | ||
setSeeMore(lines.length > numberOfLines); | ||
}, [numberOfLines, lines]); | ||
setSeeMore(hiddenTextHeightOne > textHeight); | ||
}, [textHeight, hiddenTextHeightOne]); | ||
useEffect(() => { | ||
@@ -361,5 +394,2 @@ if (collapsed === afterCollapsed) { | ||
setMountHiddenTextOne(true); | ||
setMountHiddenTextTwo(true); | ||
setMountHiddenTextThree(true); | ||
setMountHiddenTextFour(true); | ||
}, debounceSeeMoreCalc); | ||
@@ -382,27 +412,2 @@ return () => clearTimeout(handle); | ||
useEffect(() => { | ||
const checkIfStillMeasuring = () => { | ||
if ( | ||
!mountHiddenTextOne && | ||
!mountHiddenTextTwo && | ||
!mountHiddenTextThree && | ||
!mountHiddenTextFour | ||
) { | ||
setIsMeasuring(false); | ||
if (animate) { | ||
LayoutAnimation.configureNext(readmoreAnimation); | ||
} | ||
} | ||
}; | ||
const handler = setTimeout(checkIfStillMeasuring, debounceSeeMoreCalc); | ||
return () => clearTimeout(handler); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [ | ||
mountHiddenTextOne, | ||
mountHiddenTextTwo, | ||
mountHiddenTextThree, | ||
mountHiddenTextFour, | ||
]); | ||
// a map of additional props to be passed down | ||
@@ -423,18 +428,19 @@ // in hidden text components other than style | ||
useEffect(() => { | ||
if (mountHiddenTextOne || mountHiddenTextTwo || mountHiddenTextFour) { | ||
return; | ||
} | ||
const handle = setTimeout(measureSeeMoreLine, debounceSeeMoreCalc); | ||
return () => clearTimeout(handle); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [measureSeeMoreLine]); | ||
}, [ | ||
lines, | ||
numberOfLines, | ||
collapsedLines, | ||
seeMore, | ||
mountHiddenTextOne, | ||
mountHiddenTextTwo, | ||
mountHiddenTextFour, | ||
]); | ||
useEffect(() => { | ||
const _textChildren = childrenToTextChildren( | ||
children, | ||
TextComponent, | ||
preserveLinebreaks, | ||
); | ||
setCollapsedChildren(_textChildren); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [children]); | ||
useEffect(() => { | ||
if (!truncatedLineOfImpact) { | ||
@@ -444,39 +450,16 @@ return; | ||
setMountHiddenTextFive(true); | ||
setMountHiddenTextThree(true); | ||
}, [truncatedLineOfImpact]); | ||
useEffect(() => { | ||
if (!truncatedLineOfImpactWidth || !seeMoreWidth || !textWidth) { | ||
setSeeMoreRightPadding(0); | ||
if (!truncatedLineOfImpactWidth) { | ||
return; | ||
} | ||
const _seeMoreRightPadding = | ||
textWidth - truncatedLineOfImpactWidth - seeMoreWidth; | ||
if (_seeMoreRightPadding > 0) { | ||
setSeeMoreRightPadding(_seeMoreRightPadding); | ||
if (animate) { | ||
LayoutAnimation.configureNext(readmoreAnimation); | ||
} | ||
} | ||
const padding = textWidth - truncatedLineOfImpactWidth - seeMoreWidth; | ||
setSeeMoreRightPadding(padding); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [truncatedLineOfImpactWidth, seeMoreWidth, textWidth]); | ||
}, [truncatedLineOfImpactWidth]); | ||
useEffect(() => { | ||
if (!measuredCollapsedChildren) { | ||
return; | ||
} | ||
// start reconciliation | ||
setMountHiddenTextSix(true); | ||
}, [measuredCollapsedChildren]); | ||
useEffect(() => { | ||
if (!reconciledLineOfImpact) { | ||
return; | ||
} | ||
setMountHiddenTextSeven(true); | ||
}, [reconciledLineOfImpact]); | ||
useEffect(() => { | ||
if (!reconciledLineOfImpactWidth || !seeMoreWidth || !textWidth) { | ||
@@ -497,33 +480,17 @@ // setSeeMoreRightPadding(0); | ||
useEffect(() => { | ||
if (isMeasuring) { | ||
return; | ||
} | ||
const handle = setTimeout(() => { | ||
setIsMeasured(!isMeasuring); | ||
if (animate) { | ||
LayoutAnimation.configureNext(readmoreAnimation); | ||
} | ||
}, debounceSeeMoreCalc); | ||
return () => clearTimeout(handle); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [isMeasuring]); | ||
return ( | ||
<View style={wrapperStyle}> | ||
{/* text component to measure see if see more is applicable and get height */} | ||
{/* text component to measure see if see more is applicable and get lines */} | ||
{mountHiddenTextOne && ( | ||
<TextComponent | ||
{...commonHiddenComponentProps} | ||
ellipsizeMode={'clip'} | ||
onLayout={onHiddenTextLayoutOne}> | ||
onTextLayout={onTextLayoutOne}> | ||
{children || ''} | ||
</TextComponent> | ||
)} | ||
{/* text component to measure height with see less */} | ||
{/* text component to measure lines with see less */} | ||
{mountHiddenTextTwo && ( | ||
<TextComponent | ||
{...commonHiddenComponentProps} | ||
onLayout={onHiddenSeeLessTextLayoutTwo}> | ||
onTextLayout={onTextLayoutTwo}> | ||
{children || ''} | ||
@@ -534,31 +501,20 @@ {/* 3 spaces before see less are intentional */} | ||
)} | ||
{/* to remove all flickers add another hidden component with collapsed children to get seeMore and all hidden components to use collapsed children only */} | ||
{/* extract width of line of impact without see more line */} | ||
{mountHiddenTextThree && ( | ||
<TextComponent | ||
{...commonHiddenComponentProps} | ||
numberOfLines={numberOfLines} | ||
onLayout={onLayoutHiddenTextThree}> | ||
{collapsedChildren || ''} | ||
{/* no see less here since it's in collapsed state replicating original component */} | ||
{...hiddenComponentPropsLineOfImpact} | ||
onLayout={onLayoutThree}> | ||
{truncatedLineOfImpact} | ||
</TextComponent> | ||
)} | ||
{/* extract line of impact -> see more line */} | ||
{mountHiddenTextFour && ( | ||
<TextComponent | ||
{...commonHiddenComponentProps} | ||
numberOfLines={numberOfLines + 1} | ||
onLayout={onLayoutHiddenTextFour} | ||
onTextLayout={onTextLayoutHiddenTextFour}> | ||
{collapsedChildren || ''} | ||
{/* no see less here since it's in collapsed state replicating original component */} | ||
numberOfLines={numberOfLines} | ||
ellipsizeMode={'clip'} | ||
onLayout={onLayoutActualTextComponent} | ||
onTextLayout={onTextLayoutActualTextComponent}> | ||
{children || ''} | ||
</TextComponent> | ||
)} | ||
{/* extract width of line of impact without see more line */} | ||
{mountHiddenTextFive && ( | ||
<TextComponent | ||
{...hiddenComponentPropsLineOfImpact} | ||
onLayout={onLayoutHiddenTextFive}> | ||
{truncatedLineOfImpact} | ||
</TextComponent> | ||
)} | ||
{/* extract line of impact with measured children */} | ||
@@ -571,3 +527,3 @@ {mountHiddenTextSix && ( | ||
onTextLayout={onTextLayoutHiddenTextSix}> | ||
{measuredCollapsedChildren || ''} | ||
{collapsedChildren || ''} | ||
{/* no see less here since it's in collapsed state replicating original component */} | ||
@@ -590,4 +546,4 @@ </TextComponent> | ||
{...textProps}> | ||
{isMeasuring || (seeMore && collapsed) | ||
? measuredCollapsedChildren || collapsedChildren || '' | ||
{seeMore && collapsed | ||
? collapsedChildren || children || '' | ||
: children || ''} | ||
@@ -600,3 +556,3 @@ {seeMore && !collapsed && !expandOnly && ( | ||
style={seeLessStyle}> | ||
{hiddenTextHeightWithSeeLess > hiddenTextHeightOne ? '\n' : ' '} | ||
{hiddenTextLinesWithSeeLess.length > lines.length ? '\n' : ' '} | ||
{seeLessText} | ||
@@ -610,7 +566,8 @@ </TextComponent> | ||
<TextComponent | ||
key={`${isMeasured}`} | ||
{...additionalProps} | ||
{...restProps} | ||
onPress={toggle} | ||
style={style}> | ||
{`${ellipsis}`} | ||
style={[style, seeMoreTextHidingStyle]}> | ||
{`${hideEllipsis ? '' : ellipsis}`} | ||
</TextComponent> | ||
@@ -623,2 +580,3 @@ <TextComponent | ||
{` ${seeMoreText}`} | ||
{hideEllipsis ? ' ' : ''} | ||
</TextComponent> | ||
@@ -681,3 +639,2 @@ </View> | ||
animate: PropTypes.bool, | ||
backgroundColor: PropTypes.string, | ||
customTextComponent: PropTypes.oneOfType([ | ||
@@ -695,3 +652,2 @@ PropTypes.node, | ||
debounceSeeMoreCalc: PropTypes.number, | ||
preserveLinebreaks: PropTypes.bool, | ||
}; | ||
@@ -709,3 +665,2 @@ | ||
animate: true, | ||
backgroundColor: 'white', | ||
customTextComponent: Text, | ||
@@ -718,3 +673,2 @@ ellipsis: '...', | ||
debounceSeeMoreCalc: 300, | ||
preserveLinebreaks: false, | ||
allowFontScaling: Platform.select({ | ||
@@ -721,0 +675,0 @@ android: false, |
{ | ||
"name": "@fawazahmed/react-native-read-more", | ||
"version": "2.0.3", | ||
"version": "2.1.0", | ||
"description": "A simple react native library to show large blocks of text in a condensed manner with the ability to collapse and expand.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -73,3 +73,3 @@ ![NPM Downloads](https://img.shields.io/npm/dw/@fawazahmed/react-native-read-more) ![NPM License](https://img.shields.io/npm/l/@fawazahmed/react-native-read-more) ![NPM Version](https://img.shields.io/npm/v/@fawazahmed/react-native-read-more) | ||
| `animate` | `bool` | no | defaults to `true` => applies a subtle animation to see more and see less text, not the complete text itself | ||
| `backgroundColor` | `string` | no | defaults to `white` => supply `backgroundColor` if your background color is something other than white | ||
| `backgroundColor` | `string` | no | (deprecated) defaults to `white` => supply `backgroundColor` if your background color is something other than white | ||
| `customTextComponent` | `React component` | no | defaults to `Text` | ||
@@ -79,3 +79,3 @@ | `expandOnly` | `bool` | no | defaults to `false` => hide see less option similar to a linkedIn post | ||
| `onCollapse` | `func` | no | optional callback executed when collapsed | ||
| `preserveLinebreaks` | `bool` | no | defaults to `false` => preserves `\n` in the content while in the collapsed state. This prop is in experimental stage. | ||
| `preserveLinebreaks` | `bool` | no | (deprecated) defaults to `false` => preserves `\n` in the content while in the collapsed state. This prop is in experimental stage. | ||
@@ -82,0 +82,0 @@ Any additional props are passed down to underlying `Text` component. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
507243
790