https://github.com/patrik-piskay/react-truncate-markup
✂️ React component for truncating JSX markup
https://github.com/patrik-piskay/react-truncate-markup
Last synced: about 1 month ago
JSON representation
✂️ React component for truncating JSX markup
- Host: GitHub
- URL: https://github.com/patrik-piskay/react-truncate-markup
- Owner: patrik-piskay
- License: mit
- Created: 2017-10-19T18:30:04.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2022-07-11T15:15:46.000Z (almost 3 years ago)
- Last Synced: 2024-04-14T17:44:28.163Z (about 1 year ago)
- Language: JavaScript
- Homepage:
- Size: 819 KB
- Stars: 147
- Watchers: 5
- Forks: 24
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
Awesome Lists containing this project
- awesome-react-cn - react-truncate-markup - React component for truncating JSX markup. (Uncategorized / Uncategorized)
README
# React Truncate Markup
[](https://travis-ci.org/patrik-piskay/react-truncate-markup)
[](https://www.npmjs.com/package/react-truncate-markup)
[](https://github.com/patrik-piskay/react-truncate-markup/blob/master/LICENSE.md)React component for truncating JSX markup.
[Examples with code snippets](https://react-truncate-markup.patrik-piskay.now.sh)
[CodeSandbox demo](https://codesandbox.io/s/4w2jrplym4)## Why?
Few use cases for using JS truncating instead of the CSS one:
- you need to support IE, Firefox or Edge (and cannot use `webkit-line-clamp`) for multi-line truncation
- you need a custom ellipsis, potentially with more text (`show more` link, indicator of how many records were hidden by truncation, etc.)---
Most solutions that already exist (like [react-truncate](https://github.com/One-com/react-truncate) or [React-Text-Truncate](https://github.com/ShinyChang/React-Text-Truncate)) use HTML5 `canvas` (and its `measureText` method) for measuring text width to determine whether (and where) the provided text should be truncated.
While this approach is valid, it has its limitations - it works only for **plain text**, and not for **JSX markup**. You might want to use JSX when parts of the text have different style (like `color` or `font-weight`).
## How?
Because we need to determine how to truncate provided content _after_ all the layout and styles were applied, we need to actually render it in browser (instead of rendering it off-screen in canvas).
By using a binary search approach (_splitting JSX in half and checking if the text + ellipsis fit the container, and if not, splitting it in half again, and so on_), depending on the size (and depth) of the markup, it usually takes only a few rerenders to get the final, truncated markup.
Performance was not an issue for our use cases (e.g. using `TruncateMarkup` twice per list item in a dropdown list containing dozens of items), there is no text movement visible on the screen (but YMMV).
> **_Note:_** Because this package depends on browser rendering, all elements inside `` need to be visible. If you need to hide or show some parts of your UI, consider conditionally rendering them instead of setting `display: none`/`display: block` style on the elements.
## Installation
```bash
npm install --save react-truncate-markup
# or
yarn add react-truncate-markup
```> This package also depends on `react` and `prop-types`. Please make sure you have those installed as well.
Importing:
```js
// using ES6 modules
import TruncateMarkup from 'react-truncate-markup';// using CommonJS modules
const TruncateMarkup = require('react-truncate-markup').default;
```Or using script tags and globals:
```html
```
And accessing the global variable:
```js
const TruncateMarkup = ReactTruncateMarkup.default;
```## Usage
```jsx
/* or any wrapper */
/* ... any markup ... */
{this.props.subject}:
{` `}
{this.props.message}
```> #### :warning: Warning
>
> Only inlined [DOM elements](https://reactjs.org/docs/dom-elements.html) are supported when using this library. When trying to truncate React components (class or function), `` will warn about it, skip truncation and display the whole content instead. For more details, please read [this comment](https://github.com/patrik-piskay/react-truncate-markup/issues/12#issuecomment-444761758).
>
> Or, since version 5, you can take advantage of the [`` component](#truncatemarkupatom-).## Props
### `children`
It's required that only 1 element is passed as `children`.
> Correct:
```jsx
/* ... markup ... */
```
> Incorrect:
```jsx
/* ... markup ... */
/* ... */
/* ... */```
### `lines`
> default value: `1`
Maximum number of displayed lines of text.
### `ellipsis`
> default value: `...`
Appended to the truncated text.
One of type: `[string, JSX Element, function]`
- `string`: `...`
- `JSX Element`: `... read more`
- `function`: `function(jsxElement) { /* ... */ }`Ellipsis callback function receives new _(truncated)_ `` children as an argument so it can be used for determining what the final ellipsis should look like.
```jsx
const originalText = '/* ... */';const wordsLeftEllipsis = (rootEl) => {
const originalWordCount = originalText.match(/\S+/g).length;
const newTruncatedText = rootEl.props.children;
const currentWordCount = newTruncatedText.match(/\S+/g).length;return `... (+${originalWordCount - currentWordCount} words)`;
}
{originalText}
```
### `lineHeight`
> default value: auto-detected
Numeric value for desired line height in pixels. Generally it will be auto-detected but it can be useful in some cases when the auto-detected value needs to be overridden.
### `onTruncate`
> function(wasTruncated: bool) | optional
A callback that gets called after truncation. It receives a bool value - `true` if the input markup was truncated, `false` when no truncation was needed.
> _Note_: To prevent infinite loops, _onTruncate_ callback gets called only after the initial run (on mount), any subsequent props/children updates will trigger a recomputation, but _onTruncate_ won't get called for these updates.
>
> If you, however, wish to have _onTruncate_ called after some update, [change the `key` prop](https://reactjs.org/docs/reconciliation.html#keys) on the `` component - it will make React to remount the component, instead of updating it.### `tokenize`
> default value: `characters`
By default, any single character is considered the smallest, undividable entity, so the input markup can be truncated at any point (even midword).
To override this behaviour, you can set the `tokenize` prop to following values:
- `characters` - _[default]_ the input text can be truncated at any point
- `words` - each word, separated by a whitespace character, is undividable entity. The only exception to this are words separated by the ` ` character, which are still honored and can be used in case you want to keep the words together## ``
Atoms serve as a way to let `` know that the content they contain is not splittable - it either renders in full or does not render at all.
There are two main applications of Atoms:
1. you want to control at what level the truncation happens (and splitting on the word level using `tokenize="word"` is not enough), e.g. split text by paragraphs
2. you want/need to use other components inside ``On itself, `` will not truncate any content that contains other components (see the [warning box](#warning-warning) above). But it's still a useful feature.
Consider this case:
We want to render a list of avatars and if we run out of space, we want to render however many avatars fit, plus a custom message "+X more users", with X being the number of users that are not rendered.```jsx
{/* renders "+X more users" */}}>
{props.users.map((user) => (
))}
```
This would not work because `` cannot split anything inside other components _(in this case, ``)_, so it bails out and doesn't even attempt to truncate. But by explicitely wrapping these components in `` we say we are ok with it being treated as a single piece (rendered either in full or not rendered at all), whether they contain other components or not.
```jsx
{/* renders "+X more users" */}}>
{props.users.map((user) => (
))}
```
You can see this example in action in the [examples/demo app](#react-truncate-markup).
## Contributing
Read more about project setup and contributing in [CONTRIBUTING.md](https://github.com/patrik-piskay/react-truncate-markup/blob/master/CONTRIBUTING.md)
## License
Released under MIT license.
Copyright © 2022-present Patrik Piskay.