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-native-canvas-grid

v0.1.0

Published

Canvas-rendered data grid for React Native — virtualized rows and columns, live updates, sort, filter, search, pinned columns, themes, and a server-side data adapter.

Readme

react-native-canvas-grid

A canvas-rendered data grid for React Native. Built on React Native Skia for hardware-accelerated cell drawing, Reanimated for scroll physics, and Gesture Handler for pan, tap, and long-press interactions.

Highlights

  • Canvas rendering — every cell is drawn with Skia; no per-row native view hierarchy.
  • Two-axis virtualization — only rows and columns in the viewport + overscan are drawn each frame.
  • Scroll momentum — fling-and-decay on both axes; runs entirely on the UI thread.
  • Sort, filter, and search — client-side and server-side modes; advanced query string grammar.
  • Live data — useGridRowStore with patchCell / enqueuePatch and optional batch coalescing.
  • Pinned columns — fixed left columns that stay visible during horizontal scroll.
  • Column resize — drag the right border of any column header.
  • Column reorder — long-press a column header and drag to a new position.
  • Themes — built-in defaultGridTheme and darkGridTheme; fully customizable via mergeGridTheme.
  • Custom cells — Skia drawCell painter per column, or a React Native renderCell overlay.
  • Server pagination — GridDataSource adapter with abort-signal support.
  • Accessibility — accessibilityLabel on the grid container; screen-reader announcements for selection and edits.
  • TypeScript-first — fully typed generics for row shape, column definitions, and models.

Requirements

New Architecture (Fabric + JSI) is required. Old Architecture is not supported.

| Peer dependency | Tested version | |---|---| | react | 19.3.0 | | react-native | 0.88.0 | | react-native-skia | 3.7.4 | | react-native-reanimated | 4.7.1 | | react-native-worklets | 0.13.0 | | react-native-gesture-handler | 3.3.0 |

Expo Go is not supported — use a custom development build. React Native Web and SSR are not tested and not advertised.

Installation

npm install react-native-canvas-grid

Install all peer dependencies. In an Expo project use npx expo install to resolve compatible native versions, then rebuild your development client:

npx expo install react-native-skia react-native-reanimated react-native-worklets react-native-gesture-handler

Wrap your root component with GestureHandlerRootView:

import { GestureHandlerRootView } from 'react-native-gesture-handler';

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      {/* your app */}
    </GestureHandlerRootView>
  );
}

Quick start

import { DataGrid, type GridColDef } from 'react-native-canvas-grid';
import { View } from 'react-native';

type Trade = {
  id: string;
  symbol: string;
  price: number;
  quantity: number;
};

const columns: GridColDef<Trade>[] = [
  { field: 'id',       headerName: 'ID',       width: 80  },
  { field: 'symbol',   headerName: 'Symbol',   width: 120 },
  { field: 'price',    headerName: 'Price',    width: 120, type: 'number' },
  { field: 'quantity', headerName: 'Quantity', width: 120, type: 'number' },
];

const rows: Trade[] = [
  { id: 't-1', symbol: 'AAPL', price: 230.18, quantity: 100 },
  { id: 't-2', symbol: 'MSFT', price: 510.20, quantity: 25  },
];

export function TradesScreen() {
  return (
    <View style={{ flex: 1 }}>
      <DataGrid
        rows={rows}
        columns={columns}
        getRowId={(row) => row.id}
        style={{ flex: 1 }}
      />
    </View>
  );
}

Mount <DataGrid /> inside a container that provides a finite width and height (e.g. style={{ flex: 1 }}).

Live data

import { DataGrid, useGridRowStore } from 'react-native-canvas-grid';

const { rows, dataRevision, patchCell } = useGridRowStore(initialRows, {
  getRowId: (row) => row.id,
  columns,
  batchUpdates: true,
});

// Later — patch a single cell without recreating the row array:
patchCell(rowId, 'price', 231.04);

<DataGrid rows={rows} dataRevision={dataRevision} columns={columns} ... />

Sorting and filtering

const [sortModel, setSortModel] = useState<GridSortModel>([]);
const [filterModel, setFilterModel] = useState<GridFilterModel>({ items: [] });

<DataGrid
  rows={rows}
  columns={columns}
  sortModel={sortModel}
  onSortModelChange={setSortModel}
  filterModel={filterModel}
  searchQuery="price > 100"
  searchDebounceMs={200}
/>

Server-side data

const dataSource: GridDataSource<Row> = {
  getRows: async ({ paginationModel, sortModel, filterModel, searchQuery, signal }) => {
    const data = await fetchFromApi({ ...paginationModel, sort: sortModel, signal });
    return { rows: data.items, totalRowCount: data.total };
  },
};

<DataGrid
  processingMode="server"
  dataSource={dataSource}
  paginationModel={paginationModel}
  onPaginationModelChange={setPaginationModel}
  columns={columns}
/>

Theming

import { mergeGridTheme, defaultGridTheme, darkGridTheme } from 'react-native-canvas-grid';

const myTheme = mergeGridTheme(defaultGridTheme, {
  colors: { headerBackground: '#1e293b', text: '#f8fafc' },
});

<DataGrid theme={myTheme} ... />

Documentation

Full docs are in the repository under npm-docs/:

Known limitations

  • Old Architecture is not supported (Fabric + JSI required).
  • Expo Go is not supported — requires a custom development build.
  • React Native Web is not tested and not supported.
  • SSR (Node server rendering) is not supported. "Server-side data mode" (processingMode="server") is a client-side adapter that fetches data from a backend — it is not Node-side HTML rendering.
  • Row heights are fixed (rowHeight prop). Variable row heights are not supported.
  • Accessibility is partial — canvas content is not natively traversable by screen readers. A summary label and selection/edit announcements are provided via a hidden View overlay.

Contributing

See CONTRIBUTING.md. Bug reports must include versions, platform, New Architecture mode, a minimal reproduction, and expected vs actual behavior. Do not include secrets or customer data.

License

MIT