npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

lisere

v0.1.2

Published

A lightweight and composable React component for selecting and highlighting text. Perfect for code documentation, tutorials, and interactive text highlighting and selection.

Readme

Liseré - Liseré is a lightweight and composable React component for text highlighting.

Liseré

Liseré is a lightweight and composable React component for text highlighting. It gives you precise control over how users select, annotate, and interact with text. Perfect for code documentation, tutorials, and interactive text highlighting and selection.

https://github.com/user-attachments/assets/8abe053a-c2f8-4946-bbee-dc1704111960

Install

To get started with the library, install it using:

# npm
npm install lisere
# yarn
yarn add lisere
# pnpm
pnpm add lisere

Usage

import { TextHighlighter } from 'lisere';

<TextHighlighter
  onTextHighlighted={selection => {
    console.log(selection.text)
  }}
  highlightStyle={{
    className: 'my-highlight',
    style: { backgroundColor: '#ffeb3b' },
  }}
>
  <p>Highlight this paragraph by selecting text.</p>
</TextHighlighter>

Props

<TextHighlighter />

| Prop | Type | Default | Description | | ------------------------------ | -------------------------------------------------------- | -------- | --------------------------------------- | | children | ReactNode | — | Content to make highlightable | | enabled | boolean | true | Whether highlighting is active | | containerElement | keyof JSX.IntrinsicElements | 'div' | Wrapper element for content | | selectionBoundary | 'word' \| 'cursor' | 'word' | Selection granularity | | highlightElement | string | 'span' | Tag used to wrap highlighted content | | highlightStyle | { className?: string; style?: CSSProperties } | — | Styles applied to highlights | | allowCrossElementSelection | boolean | false | Enable multi-node text selection | | clearSelectionAfterHighlight | boolean | true | Clears native selection after highlight | | removeHighlightOnClick | boolean | false | Click to remove highlights | | selectedContent | TextSelection[] | [] | Preloaded highlights | | onTextSelected | (selection: TextSelection) => void | — | Fires when text is selected | | onTextHighlighted | (selection: TextSelection) => void | — | Fires when highlight is confirmed | | onHighlightRemoved | (selection: TextSelection) => void | — | Fires when a highlight is removed | | renderSelectionUI | ({ selection, modifyHighlight, onClose }) => ReactNode | — | Custom floating UI on selection |

Examples

Basic Usage

import { TextHighlighter } from 'lisere';

<TextHighlighter
  onTextHighlighted={selection => {
    console.log('Highlighted:', selection.text);
  }}
>
  <p>Select any text in this paragraph to highlight it.</p>
</TextHighlighter>

Advanced Configuration

<TextHighlighter
  allowCrossElementSelection={true}
  selectionBoundary="cursor"
  removeHighlightOnClick={true}
  highlightStyle={{
    className: 'custom-highlight',
    style: { backgroundColor: '#ffeb3b', padding: '2px' },
  }}
>
  <div>
    <p>Cross-element</p>
    <p>selection</p>
  </div>
</TextHighlighter>

Custom Styling

<TextHighlighter
  highlightStyle={{
    className: 'custom-class',
    style: { backgroundColor: '#4caf50', padding: '2px' },
  }}
>
  <p>Custom highlight appearance.</p>
</TextHighlighter>

Custom Element Type

<TextHighlighter highlightElement="mark">
  <p>Rendered as <mark> elements.</p>
</TextHighlighter>

Floating Selection UI

<TextHighlighter
  renderSelectionUI={({ selection, modifyHighlight, onClose }) => (
    <div className="selection-popup">
      <span>Highlight "{selection.text}"?</span>
      <button onClick={() => modifyHighlight(selection, false)}>Confirm</button>
      <button onClick={() => modifyHighlight(selection, true)}>Cancel</button>
      <button onClick={onClose}>Close</button>
    </div>
  )}
>
  <p>Select to trigger overlay UI.</p>
</TextHighlighter>

Preloaded Content

<TextHighlighter
  selectedContent={[
    { text: 'Liseré', startOffset: 0, endOffset: 6 },
    { text: 'highlighting', startOffset: 10, endOffset: 21 },
  ]}
/>

Utility Functions

import {
  getCurrentTextSelection,
  highlightRange,
  removeHighlight,
  findTextInElement,
} from 'lisere';

const container = document.getElementById('content');
const ranges = findTextInElement(container, 'search term');
ranges.forEach(range => {
  const highlight = highlightRange(range, 'span', {
    className: 'manual-highlight',
    style: { backgroundColor: 'yellow' },
  })
});

const selection = getCurrentTextSelection();
if (selection) {
  console.log('Selected text:', selection.text);
}

const highlightElement = document.querySelector('.highlight');
if (highlightElement) {
  removeHighlight(highlightElement);
}

Error Handling

const handleHighlightError = (error: Error) => {
  console.error('Highlight failed:', error);
  showNotification('Failed to highlight text', 'error');
}

<TextHighlighter
  onTextHighlighted={selection => {
    try {
      saveHighlight(selection);
    } catch (error) {
      handleHighlightError(error);
    }
  }}
>
  <p>Content with error handling.</p>
</TextHighlighter>

Performance Optimization

const containerRef = useRef<HTMLDivElement>(null);
const { highlights, highlightText, clearHighlights } = useTextHighlighter({
  containerRef,
  highlightStyle: { className: 'optimized-highlight' },
})

const handleSearch = (searchTerm: string) => {
  highlightText(searchTerm);
}

const handleClear = () => {
  clearHighlights();
}

Hook Usage

import { useTextHighlighter } from 'lisere';

const {
  selection,
  highlights,
  highlightText,
  removeHighlight,
  clearHighlights,
} = useTextHighlighter({ containerRef });

TypeScript

The following types are exposed from the package:

import {
  TextHighlighter,
  useTextHighlighter,
  TextSelection,
  HighlightStyle,
} from 'lisere';