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 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-reviso

v0.3.2

Published

React component for document restoration QA, review, and correction

Readme

react-reviso

An embeddable React component for reviewing and correcting OCR text on restored document images. Designed for QA workflows — users preview restored documents, validate regions, compare original vs restored, and edit corrections when needed.

Features

  • Preview-First UX — default view shows restored documents for QA review, editing is entered explicitly
  • Side-by-Side Comparison — original (left) vs restored (right) with independent zoom/pan
  • Slider Comparison — drag slider overlay comparing original vs restored, horizontal or vertical orientation
  • Region Validation — click checkmarks to mark regions as validated; progress bar tracks review completion
  • Inline Editing — click a region to edit text, Tab/Shift+Tab to navigate between regions
  • Region Management — create, resize, move, delete text regions; customise font, color, border, background, text position
  • Auto Background Detection — restored preview automatically detects and fills region backgrounds from the document image
  • Export — JSON (structured data), PDF (text at original positions), PNG (restored page render)
  • Undo/Redo — Ctrl+Z / Ctrl+Shift+Z with full snapshot history
  • Fit to View — reset zoom across all view modes from toolbar
  • Theme Integration — inherits host app's MUI theme, accepts theme overrides
  • Feature Toggles — enable/disable editing, region creation, comparison, export via props
  • Keyboard Shortcuts — press ? to see all available shortcuts

Workflow

  1. Preview (default) — review restored documents in side-by-side or slider comparison mode
  2. Validate — click checkmarks on regions to confirm OCR corrections are accurate
  3. Edit (on demand) — enter edit mode to fix text, create/delete regions, adjust styles
  4. Export — download corrected document as JSON, PDF, or PNG

Installation

npm install react-reviso

Peer dependencies

npm install react react-dom @mui/material @mui/icons-material @emotion/react @emotion/styled framer-motion

Usage

import { Reviso } from 'react-reviso';
import type { RevisoDocument } from 'react-reviso';

const document: RevisoDocument = {
  id: 'doc-1',
  name: 'My Document',
  pages: [
    {
      id: 'page-1',
      pageNumber: 1,
      imageSrc: '/path/to/restored-image.png',
      originalImageSrc: '/path/to/original-image.png',
      width: 1200,
      height: 1600,
      regions: [
        {
          id: 'region-1',
          x: 100,
          y: 200,
          width: 300,
          height: 40,
          text: 'Corrected text',
          originalText: 'Original OCR text',
        },
      ],
    },
  ],
};

function App() {
  return (
    <Reviso
      document={document}
      onChange={(dirtyPages) => console.log('Dirty pages:', dirtyPages)}
      onPageChange={(pageId) => console.log('Page:', pageId)}
      onSelectionChange={(regionId) => console.log('Selection:', regionId)}
    />
  );
}

Theming

Reviso automatically inherits the MUI theme from a parent ThemeProvider. You can also pass a theme prop for component-level overrides — these are deep-merged on top of the inherited theme.

Option 1: Inherit from host app theme

Wrap your app (or a parent component) with MUI's ThemeProvider. Reviso picks up the palette, typography, and other tokens automatically.

import { ThemeProvider, createTheme } from '@mui/material/styles';

const appTheme = createTheme({
  palette: {
    mode: 'dark',
    primary: { main: '#90caf9' },
  },
});

function App() {
  return (
    <ThemeProvider theme={appTheme}>
      <Reviso document={document} />
    </ThemeProvider>
  );
}

Option 2: Override via theme prop

Pass MUI ThemeOptions directly to the theme prop. These overrides are deep-merged on top of whatever theme Reviso inherits from the parent.

<Reviso
  document={document}
  theme={{
    palette: {
      mode: 'dark',
      primary: { main: '#ce93d8' },
      background: { default: '#1a1a2e', paper: '#16213e' },
    },
    typography: {
      fontFamily: '"Fira Code", monospace',
    },
  }}
/>

Option 3: Combine both

Use a host theme for global styles and the theme prop for Reviso-specific tweaks.

const appTheme = createTheme({
  palette: { mode: 'dark' },
  typography: { fontFamily: '"Inter", sans-serif' },
});

<ThemeProvider theme={appTheme}>
  <Reviso
    document={document}
    theme={{
      palette: {
        primary: { main: '#ff7043' },
      },
    }}
  />
</ThemeProvider>

In this example, Reviso uses the host's dark mode and Inter font, but overrides the primary color to deep orange.

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | document | RevisoDocument | required | The document to display and review | | editable | boolean | true | Enable/disable editing (when false, preview and validation only) | | showSidebar | boolean | true | Show/hide page thumbnail sidebar | | showToolbar | boolean | true | Show/hide the inline toolbar | | features | { comparison?, export?, regionCreation? } | all true | Feature toggles | | defaultRegionStyles | object | — | Default styles for new regions (see below) | | theme | ThemeOptions | — | MUI theme overrides | | initialPageId | string | first page | Initial page to display | | onChange | (dirtyPages: RevisoPage[]) => void | — | Fired on any change, returns only modified pages | | onRegionChange | (event) => void | — | Granular per-region change event ({ type, pageId, regionId, region? }) | | onPageChange | (pageId: string) => void | — | Fired on page navigation | | onSelectionChange | (regionId: string \| null) => void | — | Fired on region select/deselect | | onExport | (format, data: Blob) => void | — | Intercept export (replaces auto-download) |

defaultRegionStyles

| Property | Type | Default | Description | |----------|------|---------|-------------| | fontColor | string | '#1565c0' | Text color (blue) | | fontFamily | string | 'Inter' | Font family | | fontWeight | 'normal' \| 'bold' | 'normal' | Font weight | | fontStyle | 'normal' \| 'italic' | 'normal' | Font style | | textDecoration | 'none' \| 'line-through' | 'none' | Text decoration | | borderColor | string | '#4caf50' | Region border color (green) | | borderVisible | boolean | true | Show/hide region border | | backgroundColor | string | 'transparent' | Region background fill | | textPosition | 'inside' \| 'top' \| 'bottom' | 'top' | Where text renders relative to the region box |

RevisoRegion

| Property | Type | Required | Description | |----------|------|----------|-------------| | id | string | yes | Unique region identifier | | x | number | yes | X position (pixels from left) | | y | number | yes | Y position (pixels from top) | | width | number | yes | Region width in pixels | | height | number | yes | Region height in pixels | | text | string | yes | Current text content | | originalText | string | no | Original text (for diff tracking) | | fontColor | string | no | Text color | | fontFamily | string | no | Font family | | fontWeight | 'normal' \| 'bold' | no | Font weight | | fontStyle | 'normal' \| 'italic' | no | Font style | | textDecoration | 'none' \| 'line-through' | no | Text decoration | | borderColor | string | no | Border color | | borderVisible | boolean | no | Show/hide border | | backgroundColor | string | no | Background fill | | textPosition | 'inside' \| 'top' \| 'bottom' \| 'left' \| 'right' | no | Text placement relative to region | | isValidated | boolean | no | Whether the region has been reviewed and confirmed |

When does onChange fire?

onChange fires once per discrete user action — it does not fire continuously during drag operations. It returns only dirty (modified) pages, not the full document. A page is considered dirty if any region was edited, created, or deleted. Dirty flags are reset after each onChange call, so the same changes are not re-emitted.

| Action | When it fires | |--------|---------------| | Edit text | On commit (Enter, Tab, or blur — not on every keystroke) | | Move region | On mouse release (not during drag) | | Resize region | On mouse release (not during drag) | | Create region | When the new region is added | | Delete region | Immediately on delete | | Change style | Immediately on each change (bold, italic, color, text position, etc.) | | Toggle validation | Immediately when region checkmark is clicked | | Undo / Redo | Immediately on restore |

View Modes

Preview Mode (default)

The default landing view for QA review. Two sub-layouts:

  • Side-by-Side — original image (left) + restored image (right) with independent zoom/pan. Validation checkmarks overlay the restored pane.
  • Slider — single overlay with a draggable comparison slider. Supports horizontal (left/right) and vertical (top/bottom) orientation. No validation checkmarks in this mode.

Edit Mode

Entered via the "Edit" button in the toolbar or Ctrl+E. Full editing capabilities:

  • Select, edit text, create/resize/delete regions
  • Undo/redo, style controls, text visibility toggle
  • Return to preview via the "Preview" button or Ctrl+E

Keyboard Shortcuts

| Shortcut | Action | |----------|--------| | Ctrl+E | Toggle Preview / Edit mode | | Escape | Exit edit mode (when nothing selected) | | ← / → | Previous / Next page | | PageUp / PageDown | Previous / Next page | | Ctrl+↑ / Ctrl+↓ | Previous / Next document | | Ctrl+Z | Undo | | Ctrl+Shift+Z | Redo | | N | Toggle create mode | | Delete | Delete selected region | | Tab / Shift+Tab | Next / Previous region | | Enter | Confirm edit | | ? | Show keyboard shortcuts help |

Development

Prerequisites

  • Node.js >= 18
  • npm >= 8

Setup

git clone https://github.com/zhernrong92/reviso.git
cd reviso
npm install
npm run dev

The dev server runs two demo routes:

  • / — Legacy standalone demo with file upload, multi-document support
  • /reviso — Embeddable component demo with a simulated host app layout

Commands

| Command | Description | |---------|-------------| | npm run dev | Start Vite dev server | | npm run build | Production build (type-check + bundle) | | npm run build:lib | Build library for publishing | | npm run preview | Preview production build | | npm run type-check | TypeScript type checking | | npm run lint | ESLint check |

Building the Library

The library build is separate from the demo app build. It produces ESM (.mjs) and CommonJS (.cjs) bundles with TypeScript declarations.

# Build the library (outputs to dist/)
npm run build:lib

This generates:

  • dist/index.mjs — ES module
  • dist/index.cjs — CommonJS module
  • dist/index.d.ts — TypeScript declarations

Peer dependencies (React, MUI, Emotion, Framer Motion) are not bundled — consumers must install them separately.

Testing Locally

To test the library in another project before publishing:

# 1. Build and pack
npm run build:lib
npm pack

# 2. In the consumer project, install from the tgz
npm install /path/to/react-reviso-x.x.x.tgz

Publishing to npm

# 1. Login
npm login

# 2. Bump version
npm version patch --no-git-tag-version

# 3. Build and publish
npm run build:lib
npm publish --access public

Tech Stack

| Technology | Purpose | |------------|---------| | React 18 | UI framework | | TypeScript 5 (strict) | Type safety | | Vite 5 | Dev server + library bundler | | MUI 6 | Component library, theming | | Zustand 5 + Immer | State management | | Framer Motion | Page transitions | | react-zoom-pan-pinch | Document viewer zoom/pan | | react-compare-slider | Before/after comparison slider | | pdf-lib | PDF export generation | | nanoid | Unique ID generation |