### Running the Example Project Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/README.md Instructions to clone the repository, navigate to the example directory, install dependencies, and run the example on iOS or Android. ```bash git clone https://github.com/fawaz-ahmed/react-native-read-more.git cd react-native-read-more/example yarn install # or npm install # to run on iOS yarn ios #to run on android yarn android ``` -------------------------------- ### Install React Native Read More with npm Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/README.md Use this command to install the library using npm. ```bash npm i @fawazahmed/react-native-read-more --save ``` -------------------------------- ### Install React Native Read More with yarn Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/README.md Use this command to install the library using yarn. ```bash yarn add @fawazahmed/react-native-read-more ``` -------------------------------- ### Basic Usage Example Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/README.md Demonstrates how to import and use the ReadMore component in a React Native application. Configure the number of lines and text styles. ```javascript import React from 'react'; import {SafeAreaView, StyleSheet, View} from 'react-native'; import ReadMore from '@fawazahmed/react-native-read-more'; const Home = () => { return ( { "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum." } ); }; const styles = StyleSheet.create({ safe: { flex: 1, }, root: { flex: 1, padding: 16, }, textStyle: { fontSize: 14, }, }); export default Home; ``` -------------------------------- ### Styled Expansion Example Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/README.md Shows how to apply custom styles to the ReadMore component and its 'see more' link. Use `style` for the text container and `seeMoreStyle` for the expansion link. ```javascript {longText} ``` -------------------------------- ### Wrapper Style Prop: Responsive Example Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Props-Deep-Dive.md Use an array of styles with `wrapperStyle` to apply responsive styling to the outer View container, adapting to different screen sizes. ```javascript // Responsive wrapper {text} ``` -------------------------------- ### Basic Expansion Example Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/README.md Demonstrates the basic usage of the ReadMore component to expand text after a certain number of lines. Use `numberOfLines` to set the initial collapsed state. ```javascript Lorem ipsum dolor sit amet, consectetur adipiscing elit... ``` -------------------------------- ### Basic React Native Read More Usage Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/ReadMore.md Demonstrates the fundamental implementation of the ReadMore component with a specified number of lines. Ensure you have the component installed and imported. ```javascript import React from 'react'; import { SafeAreaView, StyleSheet, View } from 'react-native'; import ReadMore from '@fawazahmed/react-native-read-more'; const App = () => { return ( Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. ); }; const styles = StyleSheet.create({ container: { flex: 1 }, content: { padding: 16 }, }); export default App; ``` -------------------------------- ### Helper Function Integration Example Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Helper-Utilities.md Demonstrates the workflow of using `getTextByChildren`, `linesToCharacters`, and `insertAt` for text truncation in a React Native component. ```javascript // 1. Component measures full text and gets line data const lines = [ /* from onTextLayout */ ]; // 2. Convert lines to character string const fullText = linesToCharacters(lines); // fullText = "Lorem Ipsum is simply dummy text..." // 3. Determine break position (e.g., character 42) const breakPosition = 42; // 4. Extract children elements const children = "Lorem Ipsum is simply dummy text..."; const extracted = getTextByChildren(children, Text); // 5. Insert newline at break position const modified = insertAt(extracted[0].content, '\n', breakPosition); // modified = "Lorem Ipsum is simply dummy\n text..." // 6. Use modified children for truncated display ``` -------------------------------- ### ReadMore Component with onReady Callback Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/DOCUMENTATION-INDEX.txt Shows how to use the `onReady` callback to get information about the initial state of the text, such as whether it can be expanded. ```javascript import React from 'react'; import { View, Text } from 'react-native'; import ReadMore from 'react-native-read-more'; const MyComponent = () => ( { console.log(`Can expand: ${canExpand}, Initial lines: ${expandedLinesCount}`); }} > This text is used to test the onReady callback. It will log whether the text can be expanded and how many lines it initially occupies to the console. ); ``` -------------------------------- ### Example Usage of onReady Callback Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/types.md Demonstrates how to use the onReady callback prop with the ReadMore component. It logs whether the text fits within the line limit or the total expanded line count. ```jsx { if (!canExpand) { console.log('Text fits within the line limit, no expansion needed'); } else { console.log(`Text spans ${expandedLinesCount} lines total`); } }}> {textContent} ``` -------------------------------- ### Integrate Analytics Tracking Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Advanced-Usage.md Integrate analytics by using the `onReady`, `onExpand`, and `onCollapse` props to track user engagement metrics. This example shows how to track expansion/collapse counts and content details. ```javascript const [metrics, setMetrics] = useState({ canExpand: false, totalLines: 0, expandCount: 0, collapseCount: 0, }); { setMetrics(prev => ({ ...prev, canExpand, totalLines: expandedLinesCount, })); }} onExpand={() => { setMetrics(prev => ({ ...prev, expandCount: prev.expandCount + 1 })); analytics.track('read_more_expand', { totalLines: metrics.totalLines, contentLength: text.length, }); }} onCollapse={() => { setMetrics(prev => ({ ...prev, collapseCount: prev.collapseCount + 1 })); analytics.track('read_more_collapse'); }}> {text} ``` -------------------------------- ### Collapsed State Snapshot Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/State-Management.md An example of the internal state when the component is in its initial collapsed state, showing measurement data, control flags, and content structure. ```javascript { // Measurements lines: [{text: 'Lorem...', width: 300, ...}, ...], collapsedLines: [{text: 'Lorem...', width: 300, ...}, ...], textWidth: 350, seeMoreWidth: 80, truncatedLineOfImpact: 'dummy text of the', seeMoreRightPadding: 5, // Control seeMore: true, collapsed: true, afterCollapsed: true, isMeasured: true, isReady: true, // Content collapsedChildren: [/* modified children with \n */], hideEllipsis: false, // Hidden components mountHiddenTextOne: false, mountHiddenTextTwo: false, mountHiddenTextThree: false, mountHiddenTextFour: false, mountHiddenTextFive: false, mountHiddenTextSix: false, } ``` -------------------------------- ### Programmatic Control of Expansion Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/State-Management.md This example shows how to control the collapsed/expanded state of the ReadMore component programmatically using a parent component's state. It utilizes the `collapsed` prop and the `onExpand`/`onCollapse` callbacks to synchronize the parent's state with the ReadMore component's state. ```javascript const MyComponent = () => { const [showFull, setShowFull] = useState(false); return ( <> setShowFull(true)} onCollapse={() => setShowFull(false)}> {text} ); }; ``` -------------------------------- ### Manage Synchronized Multiple Instances Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Advanced-Usage.md For multiple ReadMore instances in a list, manage expansion state centrally using `collapsed`, `onExpand`, and `onCollapse` props. This example uses a Set to track expanded item IDs. ```javascript const MyList = () => { const [expandedIds, setExpandedIds] = useState(new Set()); const toggleExpand = (id) => { setExpandedIds(prev => { const next = new Set(prev); next.has(id) ? next.delete(id) : next.add(id); return next; }); }; return ( ( toggleExpand(item.id)} onCollapse={() => toggleExpand(item.id)}> {item.text} )} keyExtractor={item => item.id} /> ); }; ``` -------------------------------- ### Expanded State Snapshot Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/State-Management.md An example of the internal state when the component is fully expanded. Key changes include `collapsed` and `afterCollapsed` flags, and the unmounting of hidden measurement components. ```javascript { // Same measurements // Control - changed collapsed: false, afterCollapsed: false, // (during animation) // Content - full text used collapsedChildren: null, // Hidden components - unmounted mountHidden*: false (all), } ``` -------------------------------- ### Use onReady Callback to Check Truncation Status Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Advanced-Usage.md Use the `onReady` callback to get information about whether the text can expand and the number of expanded lines. This helps determine if `numberOfLines` needs adjustment or if there's a bug. ```javascript onReady={({ canExpand, expandedLinesCount }) => { console.log(`Lines: ${expandedLinesCount}, Can expand: ${canExpand}`); }} ``` -------------------------------- ### Implement Conditional Truncation Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Advanced-Usage.md Conditionally truncate content based on its length using the `numberOfLines` prop. This example shows how to set `numberOfLines` dynamically based on whether the content exceeds a certain line count. ```javascript const [shouldTruncate, setShouldTruncate] = useState(false); { setShouldTruncate(expandedLinesCount > 5); }}> {text} ``` -------------------------------- ### Analytics Tracking for Expansion Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/README.md Shows how to integrate analytics tracking for component readiness and expansion events. Use `onReady` to track initial state and `onExpand` for expansion events. ```javascript analytics.track('text_shown', { canExpand })} onExpand={() => analytics.track('text_expanded')} > {text} ``` -------------------------------- ### Ready Callback for Initialization Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/State-Management.md Fires the `onReady` callback with measurement results after a short delay, signaling that the component is fully initialized and ready for user interaction. ```javascript useEffect(() => { if (!isMeasured || isReady) return; const handle = setTimeout(() => { setIsReady(true); onReady({canExpand: seeMore, expandedLinesCount: lines.length}); }, debounceSeeMoreCalc); return () => clearTimeout(handle); }, [isMeasured, isReady]); ``` -------------------------------- ### Handling Read More Component Events Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/ReadMore.md Illustrates how to use callback functions for expansion, collapse, and readiness events. These callbacks can be used for analytics or triggering other actions. ```javascript { console.log('Text expanded'); analytics.track('read_more_expanded'); }} onCollapse={() => { console.log('Text collapsed'); analytics.track('read_more_collapsed'); }} onReady={({ canExpand, expandedLinesCount }) => { console.log(`Can expand: ${canExpand}, Total lines: ${expandedLinesCount}`); }} > {textContent} ``` -------------------------------- ### Minimal Configuration Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/configuration.md This snippet shows the most basic usage of the ReadMore component, relying on all default settings. ```javascript {textContent} ``` -------------------------------- ### Initializing Read More Component with `onReady` Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Advanced-Usage.md Utilizes the `onReady` prop to safely perform actions after the component has fully initialized and measured its content. This is the recommended way to update parent state or enable interactions based on the component's initial state. ```javascript { // Only now is the component fully initialized // Safe to update parent state or enable interactions }}> {text} ``` -------------------------------- ### Concatenate Lines to Characters Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Helper-Utilities.md Converts an array of line objects from React Native's onTextLayout event into a single concatenated string. Use this to get the total text content for truncation calculations. ```javascript import { linesToCharacters } from './helper.js'; const lines = [ { text: 'First line', x: 0, y: 0, width: 100, height: 20 }, { text: 'Second line', x: 0, y: 20, width: 120, height: 20 }, { text: 'Third line', x: 0, y: 40, width: 110, height: 20 }, ]; const combined = linesToCharacters(lines); // Returns: "First lineSecond lineThird line" ``` -------------------------------- ### onReady Callback with Metrics Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Props-Deep-Dive.md Use the onReady callback to log the expansion metrics, such as whether the text can expand and the total number of lines. This is useful for debugging and understanding component behavior. ```javascript { console.log(`Can expand: ${canExpand}, Lines: ${expandedLinesCount}`); }}> {text} ``` -------------------------------- ### ReadMore Component with Callbacks Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/README.md Illustrates how to use the onReady, onExpand, and onCollapse callbacks for event handling. ```javascript { console.log(`Text has ${expandedLinesCount} lines`); }} onExpand={() => analytics.track('text_expanded')} onCollapse={() => analytics.track('text_collapsed')} > {text} ``` -------------------------------- ### onExpand Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Props-Deep-Dive.md Callback executed when the user taps 'See more' and the text expands. It's useful for triggering actions like analytics or scrolling. ```APIDOC ## onExpand ### Description Callback executed when user taps "See more" and text expands. ### Type `() => void` ### Default `() => {}` ### When called After animation completes (if `animate={true}`) or immediately (if `animate={false}`). ### Conditions to call: - User must tap "See more" - Component must be in collapsed state - Custom `onSeeMore` handler must not be defined - Component must not be controlled via `collapsed` prop ### Example ```javascript { console.log('Text expanded'); }} > {text} ``` ``` -------------------------------- ### onReady Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Props-Deep-Dive.md Callback executed after measurements complete and the component is ready to be used. It provides information about whether the text can expand and the total expanded lines count. ```APIDOC ## onReady ### Description Callback executed after measurements complete and component is ready. ### Type `({ canExpand: boolean, expandedLinesCount: number }) => void` ### Parameters: - `canExpand` - boolean, true if text exceeds `numberOfLines` - `expandedLinesCount` - number, total lines in fully expanded state ### When called: Once per mount/prop change, after measurements complete and state settles. ### Use cases: - Hide UI elements based on text length - Enable/disable features - Analytics (track if content was truncated) - Initialize external state ### Example ```javascript { console.log(`Can expand: ${canExpand}, Lines: ${expandedLinesCount}`); }} > {text} ``` ``` -------------------------------- ### Basic Usage of ReadMore Component Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/DOCUMENTATION-INDEX.txt Demonstrates the fundamental implementation of the ReadMore component for truncating text with a 'See more'/'See less' toggle. ```javascript import React from 'react'; import { View, Text } from 'react-native'; import ReadMore from 'react-native-read-more'; const MyComponent = () => ( This is a long text that needs to be truncated. It will show only a few lines initially, and then expand when the user taps on 'See more'. This is a long text that needs to be truncated. It will show only a few lines initially, and then expand when the user taps on 'See more'. ); export default MyComponent; ``` -------------------------------- ### Detecting Component Ready State Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/State-Management.md This snippet demonstrates how to use the `onReady` prop to detect when the ReadMore component has finished its initial measurements and is ready to be displayed or interacted with. It shows setting a local `isReady` state based on the `canExpand` value provided by the callback. ```javascript const MyComponent = () => { const [isReady, setIsReady] = useState(false); return ( { setIsReady(true); }}> {text} ); }; ``` -------------------------------- ### Using Custom Text Components with Read More Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/ReadMore.md Shows how to integrate custom text rendering components, such as ParsedText, with the Read More component. This allows for rich text formatting within the expandable content. ```javascript import { ParsedText } from 'react-native-parsed-text'; {textContent} ``` -------------------------------- ### Custom Component for Expansion Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/README.md Demonstrates using a custom component for rendering the expandable text and handling interactions like URL presses. Pass your component to `customTextComponent` and configure patterns with `parsePatterns`. ```javascript {text} ``` -------------------------------- ### Importing with TypeScript Types Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/README.md Demonstrates how to import the `ReadMore` component along with its associated types for use in TypeScript projects. ```typescript import ReadMore, { ReadMoreProps } from '@fawazahmed/react-native-read-more'; ``` -------------------------------- ### Analytics Integration Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/README.md Track user interactions and component states using the 'onReady' and 'onExpand' callbacks. This allows for integration with analytics platforms. ```javascript { analytics.track('text_truncated', { canExpand }); }} onExpand={() => analytics.track('text_expanded')}> {text} ``` -------------------------------- ### Accessibility-Friendly Configuration Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/configuration.md Enhance accessibility by disabling animations, enabling font scaling, and providing clear text for 'Show full text' and 'Hide details'. ```javascript {textContent} ``` -------------------------------- ### Step 1: Initial Full Text Measurement Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Measurement-Algorithm.md Measures the total number of lines in the full, untruncated text. This step is triggered on component mount or when text-related props change. It collects line data including text, position, width, and height. ```javascript mountHiddenTextOne && ( {children} ) ``` -------------------------------- ### ReadMore Component with Callback Integration Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/DOCUMENTATION-INDEX.txt Illustrates how to use the `onExpand` and `onCollapse` callbacks to perform actions when the text state changes. ```javascript import React from 'react'; import { View, Text, Alert } from 'react-native'; import ReadMore from 'react-native-read-more'; const MyComponent = () => ( Alert.alert('Text expanded!')} onCollapse={() => Alert.alert('Text collapsed!')} > This text demonstrates the use of callbacks. When you expand or collapse this text, an alert will be shown to confirm the action. This allows for integrating custom logic based on the expansion state. ); ``` -------------------------------- ### Custom Expand/Collapse Handlers Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/ReadMore.md Provides custom functions to handle 'See more' and 'See less' actions, enabling alternative behaviors like opening modals instead of just expanding text. ```javascript { // Open modal instead of expanding showDetailModal(textContent); }} onSeeLess={() => { closeDetailModal(); }} > {textContent} ``` -------------------------------- ### onSeeMore for Analytics Only Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Props-Deep-Dive.md Log an analytics event when 'See more' is tapped, but allow the default expansion behavior to proceed. This tracks user interaction without altering the UI flow. ```javascript { analytics.logEvent('see_more_tapped'); // Don't call anything; default behavior continues }}> {text} ``` -------------------------------- ### onSeeMore Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Props-Deep-Dive.md Custom callback that replaces the default 'See more' behavior. Use this to implement custom expansion logic, such as opening a modal or navigating to a new page. ```APIDOC ## onSeeMore ### Description Custom callback replaces default "See more" behavior. ### Type `() => void` ### Default undefined (use default expand behavior) ### Behavior when defined: - When user taps "See more", this callback is called instead of default expand - Default expand behavior is completely disabled - Must manually update state if you want to expand programmatically **Note:** This disables inline expansion entirely. If you want to expand and also perform an action, you need to manually handle the expand state. ### Example ```javascript // Modal instead of inline expansion { showDetailModal(fullText); }} > {preview} ``` ``` -------------------------------- ### With Analytics Tracking Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/configuration.md Integrate analytics tracking for user interactions with the ReadMore component. Track expansion, collapse, and readiness events. ```javascript analytics.track('user_expanded_text')} onCollapse={() => analytics.track('user_collapsed_text')} onReady={({ canExpand }) => { if (canExpand) analytics.track('text_was_truncated'); }}> {textContent} ``` -------------------------------- ### Basic onExpand Callback Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Props-Deep-Dive.md Use the onExpand callback to log a message when the text expands. This is useful for simple event tracking. ```javascript { console.log('Text expanded'); }}> {text} ``` -------------------------------- ### onExpand for Analytics Integration Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Props-Deep-Dive.md Integrate analytics by logging an event with content details when the text expands. This helps track user engagement with truncated content. ```javascript { analytics.logEvent('read_more_expanded', { contentId: item.id, contentLength: text.length, }); }}> {text} ``` -------------------------------- ### OnReadyCallback Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/types.md Callback function signature for the `onReady` prop, providing information about text expansion capabilities and line counts. ```APIDOC ## OnReadyCallback ### Description Callback function signature for the `onReady` prop. ### Parameters | Parameter | Type | Description | |-----------|------|-------------| | `info.canExpand` | `boolean` | Whether the text content exceeds `numberOfLines` and can be expanded. | | `info.expandedLinesCount` | `number` | Total number of lines when text is in fully expanded state. | ### Example ```typescript { if (!canExpand) { console.log('Text fits within the line limit, no expansion needed'); } else { console.log(`Text spans ${expandedLinesCount} lines total`); } }}> {textContent} ``` ``` -------------------------------- ### Implement Modal-Based Expansion Source: https://github.com/fawaz-ahmed/react-native-read-more/blob/master/_autodocs/api-reference/Advanced-Usage.md Expand content in a modal instead of inline by using the `onSeeMore` prop to trigger modal visibility. This is useful for displaying full content in a separate view. ```javascript const [showDetailModal, setShowDetailModal] = useState(false); return ( <> setShowDetailModal(true)}> {summary} {fullText}