react-ws-canvas

Spreadsheet like react canvas datagrid optimized for performance built entirely typescript and react functional components with react hooks.

MIT License

Downloads
170
Stars
10
Committers
1

react ws canvas

Spreadsheet like react canvas datagrid optimized for performance built entirely typescript and react functional components with react hooks.

LIVE DEMO



recent changes

  • v0.23.6
    • fix custom render component visibiliy when column scrolls
  • v0.23.5
    • infinite rearrangement workaround ; repro start sample5 and size height of the window like the grid then add items until last in the grid will start infinite rearrange
  • v0.23.4
    • added margin when wrap custom rendere objects

issues and improvements roadmap

  • can't deselect cell ( a better negative selection should implement with a class that implements a contains operator that matches in order selection pattern, for example select all then deselect a cell )
  • smooth scroll ( actually scroll by row and col and not partial by pixel )
  • a complete refactoring with better state management ( collect all feature currently available and rewrite the code with better modularization and functional correspondance )

features

  • canvas based high performance datagrid ( able to scroll with ease millions of rows maintaining immediate cell focus and editing features )

50000 rows x 200 cols example ( LIVE EXAMPLE : click EX1 button )

  • direct cell editing, just click on a cell then type, hit ENTER or arrows keys to move next ( native cell types )

    • "text": type text to change cell ; CANC to clear cell ; CTRL+C / CTRL+V to copy/paste
    • "boolean": toggle boolean with keyboard space when cell focused
    • "date", "time", "datetime": smart date insertion ( typing 121030 results in 12/10/2030 ) browser locale supported
    • "number": sci numbers ( typing 12e-3 results in 0.012 displayed ) browser locale support for decimal separators
  • properties default values

  • cell or row selection mode

  • rows and cols numbering can be shown or hidden

  • if column numbering visible automatic sort can be customized through less-than-op ( helper )

  • column click behavior can be full column select, column toggle sort or none to disable sort/select behavior

  • column header can be customized ( helper )

  • canvas size can be specified through width, height ( fullwidth option available )

  • column width can be changed intractively using mouse

  • column width autoexpand

  • column custom initial sort ( note: prepareCellDataset, rowSetCellData, commitCellDataset must defined to make sort working ); also see example6 for tip about ensure initial sort on subsequent datasource applications

  • custom multi select with material-ui ( example )

  • custom date picker with material pickers ( example )

  • custom color picker with custom render ( example ) ; note: wrapText will use custom component height to autoresize row height ; filter can work as text mode defining renderTransform
  • support mobile touch scrolling rows, cols and scrollbars

todo

quickstart

  • create react app

eventually install create-react-app

npm install -g create-react-app
create-react-app test --template typescript
cd test
yarn add react-ws-canvas
  • edit App.tsx as follows
import React, { useState, useEffect } from 'react';
import { WSCanvas, useWindowSize, WSCanvasColumnClickBehavior } from 'react-ws-canvas';

const AppQuickStart: React.FC = () => {
  const [rows, setRows] = useState<any[][]>([]);
  const winSize = useWindowSize();

  const ROWS = 500000;
  const COLS = 20;

  useEffect(() => {

    const _rows = [];
    for (let ri = 0; ri < ROWS; ++ri) {
      const row = [];
      for (let ci = 0; ci < COLS; ++ci) {
        row.push("r:" + ri + " c:" + ci);
      }
      _rows.push(row);
    }

    setRows(_rows);
  }, []);

  return <WSCanvas
    width={winSize.width} height={winSize.height}
    rowsCount={rows.length} colsCount={COLS}
    showColNumber={true} showRowNumber={true}
    columnClickBehavior={WSCanvasColumnClickBehavior.ToggleSort}
    rows={rows}
    rowGetCellData={(row, colIdx) => row[colIdx]}
    prepareCellDataset={() => rows.slice()}
    commitCellDataset={(q) => setRows(q)}
    rowSetCellData={(row, colIdx, value) => row[colIdx] = value}
  />;
}

export default AppQuickStart;
  • run the app
yarn start

examples list

example description
quickstart 500000 x 20 grid with minimal props
Sample1 50000 x 200 grid with frozen row/col, filter, custom column width
Sample2 5000 x 6 grid db-record-like column mapping, initial sort, custom sort, api onMouseDown, global filter, cell changing/changed
Sample3 5000 x 7 grid db-record-like, data interact del/change row, custom cell editor, rowHover
Sample4 add/insert/del/move/currentRealRowSel rows using api
Sample5 custom multi select with material-ui ; custom render chip with color picker
Sample6 resetView behavior to force sync ds ; resetSorting and resetFilters resetView arguments

tips

prevent direct editing on editor customized cells

customize onPreviewKeyDown event handler on datagrid and preventDefault for matching cell

onPreviewKeyDown={(states, e) => {
  if (states.props.columns && api && api.isDirectEditingKey(e)) {
    const fieldname = states.props.columns[states.state.focusedCell.col].field;
    if (fieldname === "colname") {
      //const row = states.props.rows[states.state.focusedCell.row];
      e.preventDefault();
    }
  }
}}

how to contribute ( quickstart )

  • clone repo
git clone https://github.com/devel0/react-ws-canvas.git
  • open vscode
cd react-ws-canvas
code .
  • from vscode, open terminal ctrl+` and execute example application ( this allow you to set breakpoints directly on library source code from lib folder )
cd example
yarn install
yarn start
  • start chrome session using F5

local deploy

  • from library
cd lib
yarn build && yalc publish
  • from your project
npm uninstall react-ws-canvas --save && yalc add react-ws-canvas && npm install

how this project was built

yarn create react-app react-ws-canvas --template typescript

Because I need a library to publish and either a working example to test/debug the library project structured this way:

  • /package.json ( workspaces "example" and "lib" )
  • /example ( example and library sources )
    • /example/package.json
    • /example/.env with BROWSER=none to avoid browser start when issue yarn start because I use F5 from vscode to open debugging session
    • /example/lib ( library source codes )
  • /lib ( library publishing related files )
    • /lib/package.json
    • /lib/rollup.config.json ( specifically input: '../example/src/lib/index.tsx', )
    • /lib/tsconfig.json ( specifically "rootDirs": ["../example/src/lib"], and "include": ["../example/src/lib"], )
    • /lib/prepatch-and-publish ( helper script to prepatch version and publish with README.md )

development notes

  • key notes (old)
    • cs.width and cs.height variables represents canvas size and used as starting point for calculations
    • stateNfo, viewMap, overridenRowHeight are kept separate because stateNfo must light because frequently updated while viewMap and overridenRowHeight can be heavy struct for large grids
    • view mapping have a size less-or-equal than rowsCount depending on filtering and the order of view may different depending on sorting
    • some methods work with real cells ( the same as user configure through getCellData, setCellData ), some other methods works with view cells that is an internal representation convenient to deal on what-you-see-is-what-you-get
    • real and view coords can be transformed between
    • mkstates is an helper used primarly by handlers to ensure callback uses synced state
  • TODO
    • type 'select' for cell with combobox integrated
    • date picker when F2 (or double click) on date type cell
    • isOverCell should true on last row when showPartialRows
  • deployment
    • remove any from "react-ws-canvas";