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

@worksheet-js/react

v1.4.0

Published

Official React component for Worksheet.js, providing a seamless spreadsheet experience in React apps.

Downloads

897

Readme

@worksheet-js/react

Industrial-grade spreadsheet UI engine for React.

npm version npm downloads React TypeScript License: MIT

@worksheet-js/react provides a seamless integration of the Worksheet.js engine into React applications. It wraps the high-performance canvas renderer in a declarative component while giving you full imperative control via ref and the useWorksheet hook.


Table of Contents


Installation

npm install @worksheet-js/core @worksheet-js/react chart.js
# or
pnpm add @worksheet-js/core @worksheet-js/react chart.js
# or
yarn add @worksheet-js/core @worksheet-js/react chart.js

Peer dependencies:

| Package | Required Version | | :---------- | :--------------- | | react | >= 16.8.0 | | react-dom | >= 16.8.0 | | chart.js | >= 4.0.0 |


License Initialization

@worksheet-js/core is proprietary software. Call initializeLicense() once at application startup, before any spreadsheet is rendered.

// main.tsx — application entry point
import React from 'react';
import ReactDOM from 'react-dom/client';
import { initializeLicense } from '@worksheet-js/core';
import App from './App';

initializeLicense('YOUR-LICENSE-KEY');

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

To obtain a license key, contact [email protected].


Quick Start

import React from 'react';
import { Worksheet } from '@worksheet-js/react';
// initializeLicense() called in main.tsx

export function App() {
  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <Worksheet
        options={{
          worksheets: [{ worksheetName: 'Sheet1' }],
          toolbar: true,
          formulaBar: true,
        }}
      />
    </div>
  );
}

Advanced Usage

Using useWorksheet

useWorksheet() returns a typed ref that you attach to the component. Once mounted, ref.current exposes the full @worksheet-js/core instance API.

import React, { useEffect } from 'react';
import { Worksheet, useWorksheet } from '@worksheet-js/react';

export function Dashboard() {
  const ref = useWorksheet();

  useEffect(() => {
    const ws = ref.current;
    if (!ws) return;

    // Populate headers
    ws.setValue('A1', 'Product');
    ws.setValue('B1', 'Q1');
    ws.setValue('C1', 'Q2');
    ws.setValue('D1', 'Total');

    // Style headers
    ['A1', 'B1', 'C1', 'D1'].forEach((addr) => {
      ws.setStyle(addr, { bold: true, backgroundColor: '#1a1a2e', color: '#ffffff' });
    });

    // Data with formula
    ws.setValue('A2', 'Widget A');
    ws.setValue('B2', '15000');
    ws.setValue('C2', '18000');
    ws.setValue('D2', '=SUM(B2:C2)');

    // Listen for value changes
    ws.on('onchange', (_sheet, _cell, x, y, value) => {
      console.log(`[${x},${y}] → ${value}`);
    });
  }, [ref]);

  return (
    <div style={{ height: '600px' }}>
      <Worksheet ref={ref} options={{ worksheets: [{ worksheetName: 'Dashboard' }] }} />
    </div>
  );
}

Loading XLSX Files

import React, { useCallback } from 'react';
import { Worksheet, useWorksheet } from '@worksheet-js/react';

export function FileLoader() {
  const ref = useWorksheet();

  const handleFile = useCallback(
    async (e: React.ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files?.[0];
      if (!file || !ref.current) return;
      await ref.current.importFromFile(file);
    },
    [ref]
  );

  return (
    <div>
      <input type="file" accept=".xlsx,.csv" onChange={handleFile} />
      <div style={{ height: '500px' }}>
        <Worksheet ref={ref} options={{ worksheets: [{ worksheetName: 'Import' }] }} />
      </div>
    </div>
  );
}

Listening to Events

import React, { useEffect, useState } from 'react';
import { Worksheet, useWorksheet } from '@worksheet-js/react';

export function TrackedSheet() {
  const ref = useWorksheet();
  const [selection, setSelection] = useState('—');

  useEffect(() => {
    const ws = ref.current;
    if (!ws) return;

    ws.on('onselection', (_sheet, x1, y1, x2, y2) => {
      setSelection(`[${x1},${y1}] → [${x2},${y2}]`);
    });

    // Cleanup on unmount
    return () => ws.destroy();
  }, [ref]);

  return (
    <div>
      <p>
        Current selection: <strong>{selection}</strong>
      </p>
      <div style={{ height: '400px' }}>
        <Worksheet ref={ref} options={{ worksheets: [{ worksheetName: 'Data' }] }} />
      </div>
    </div>
  );
}

Performance Monitoring

import React, { useEffect } from 'react';
import { Worksheet, useWorksheet } from '@worksheet-js/react';

export function MonitoredSheet() {
  const ref = useWorksheet();

  useEffect(() => {
    const ws = ref.current;
    if (!ws) return;

    const id = setInterval(() => {
      const snap = ws.getPerfSnapshot();
      console.table({
        'Render P95 (ms)': snap.renderMs.p95,
        'Paint P95 (ms)': snap.paintMs.p95,
        'Scroll FPS (mean)': snap.scrollFps.mean,
        'Formula P95 (ms)': snap.formulaMs.p95,
        'Cell Memory (KB)': snap.estimatedCellMemoryKB.mean,
      });
    }, 5000);

    return () => clearInterval(id);
  }, [ref]);

  return (
    <div style={{ height: '500px' }}>
      <Worksheet ref={ref} options={{ worksheets: [{ worksheetName: 'Monitor' }] }} />
    </div>
  );
}

Component API

<Worksheet> Props

| Prop | Type | Default | Description | | :---------- | :--------------------- | :------ | :--------------------------------------------------------------------------------------------------------------------- | | options | WorksheetOptions | — | Required. Configuration passed to @worksheet-js/core. Do not include container — it is managed internally. | | ref | React.Ref<Worksheet> | — | Attach a useWorksheet() ref to access the full core instance. | | className | string | '' | CSS class name applied to the wrapper <div>. | | style | React.CSSProperties | {} | Inline styles applied to the wrapper <div>. |

Ref Methods (via useWorksheet())

When a ref is attached, ref.current exposes the full Worksheet instance from @worksheet-js/core:

const ref = useWorksheet();

// Data
ref.current.getValue('A1');
ref.current.setValue('A1', 'Hello');
ref.current.setStyle('A1', { bold: true });

// I/O
ref.current.importFromFile(file);
ref.current.exportXlsx('report.xlsx');

// Sheet management
ref.current.addWorksheet({ worksheetName: 'Sheet2' });
ref.current.deleteWorksheet(1);
ref.current.renameWorksheet(0, 'Summary');

// Navigation
ref.current.goto(0, 0);
ref.current.setZoom(125);

// Performance
ref.current.getPerfSnapshot();

// Events
ref.current.on('onchange', handler);
ref.current.off('onchange', handler);

// Cleanup
ref.current.destroy();

See the @worksheet-js/core documentation for the complete API reference.


Options Reference

Pass all configuration via the options prop. The container property is managed by the component and must not be set.

| Option | Type | Default | Description | | :----------------- | :----------------------------- | :-------: | :--------------------------------------------------- | | worksheets | Partial<SheetMeta>[] | [{}] | Initial sheet tabs (name, dimensions, frozen panes). | | toolbar | boolean | true | Show the ribbon toolbar. | | formulaBar | boolean | true | Show the formula input bar. | | theme | 'light' \| 'dark' | 'light' | Color theme. | | defaultColWidth | number | 100 | Default column width in pixels. | | defaultRowHeight | number | 24 | Default row height in pixels. | | frozenRows | number | 0 | Rows frozen at the top. | | frozenCols | number | 0 | Columns frozen at the left. | | licenseKey | string | — | License key (alternative to initializeLicense()). | | onSave | (data: any) => Promise<void> | — | Callback for Ctrl+S / save button. |


TypeScript

All exports are fully typed. Import types from @worksheet-js/core:

import type {
  WorksheetOptions,
  CellStyle,
  SelectionRange,
  SheetMeta,
  CellAddress,
} from '@worksheet-js/core';
import { Worksheet, useWorksheet } from '@worksheet-js/react';

const options: WorksheetOptions = {
  worksheets: [{ worksheetName: 'Typed Sheet' }],
  toolbar: true,
  theme: 'dark',
};

function App() {
  const ref = useWorksheet(); // React.RefObject<Worksheet>
  return <Worksheet ref={ref} options={options} />;
}

Next.js / SSR

Because Worksheet.js uses canvas and Web Workers, it must run in a browser environment. In Next.js, use dynamic imports with ssr: false:

// components/SpreadsheetWrapper.tsx
'use client'; // App Router

import dynamic from 'next/dynamic';

const Worksheet = dynamic(() => import('@worksheet-js/react').then((m) => m.Worksheet), {
  ssr: false,
});

export function SpreadsheetWrapper() {
  return (
    <div style={{ height: '600px' }}>
      <Worksheet options={{ worksheets: [{ worksheetName: 'Sheet1' }] }} />
    </div>
  );
}

Call initializeLicense() inside a useEffect or in a client-only entry file when using SSR frameworks.


License

@worksheet-js/react is open-source software released under the MIT License.

The underlying engine (@worksheet-js/core) is proprietary software subject to the EULA. A valid license key is required to use it.

Copyright © 2024-present Worksheet Systems.