{"id":17788712,"url":"https://github.com/devel0/react-ws-canvas","last_synced_at":"2025-03-16T09:33:34.751Z","repository":{"id":57347878,"uuid":"222318801","full_name":"devel0/react-ws-canvas","owner":"devel0","description":"Spreadsheet like react canvas datagrid optimized for performance built entirely typescript and react functional components with react hooks.","archived":false,"fork":false,"pushed_at":"2021-11-04T10:58:57.000Z","size":5802,"stargazers_count":10,"open_issues_count":5,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-16T01:11:12.796Z","etag":null,"topics":["datagrid","editor","functional-component","react","typescript","worksheet"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devel0.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-11-17T22:07:32.000Z","updated_at":"2025-03-12T15:04:27.000Z","dependencies_parsed_at":"2022-08-28T03:01:47.948Z","dependency_job_id":null,"html_url":"https://github.com/devel0/react-ws-canvas","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devel0%2Freact-ws-canvas","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devel0%2Freact-ws-canvas/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devel0%2Freact-ws-canvas/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devel0%2Freact-ws-canvas/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devel0","download_url":"https://codeload.github.com/devel0/react-ws-canvas/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243852431,"owners_count":20358268,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["datagrid","editor","functional-component","react","typescript","worksheet"],"created_at":"2024-10-27T10:20:55.576Z","updated_at":"2025-03-16T09:33:33.736Z","avatar_url":"https://github.com/devel0.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react ws canvas\n\n[![NPM](https://img.shields.io/npm/v/react-ws-canvas.svg)](https://www.npmjs.com/package/react-ws-canvas) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)\n\nSpreadsheet like react canvas datagrid optimized for performance built entirely typescript and react functional components with react hooks.\n\n[**LIVE DEMO**](https://codesandbox.io/s/github/devel0/react-ws-canvas/tree/master/example)\n\n---\n\n- [recent changes](#recent-changes)\n- [features](#features)\n- [todo](#todo)\n- [quickstart](#quickstart)\n- [examples list](#examples-list)\n- [tips](#tips)\n- [how to contribute ( quickstart )](#how-to-contribute--quickstart-)\n- [local deploy](#local-deploy)\n- [how this project was built](#how-this-project-was-built)\n- [development notes](#development-notes)\n\n---\n\n## recent changes\n\n- v0.23.6\n  - fix custom render component visibiliy when column scrolls\n- v0.23.5\n  - infinite rearrangement workaround ; [repro](https://codesandbox.io/s/github/devel0/react-ws-canvas/tree/infinite_rearrange_repro/example) start sample5 and size height of the window like the grid then add items until last in the grid will start infinite rearrange\n- v0.23.4\n  - added margin when wrap custom rendere objects\n\n## issues and improvements roadmap\n\n- 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 )\n- smooth scroll ( actually scroll by row and col and not partial by pixel )\n- a complete refactoring with better state management ( collect all feature currently available and rewrite the code with better modularization and functional correspondance )\n\n## features\n\n- **canvas based** high performance datagrid ( able to scroll with ease millions of rows maintaining immediate cell focus and editing features )\n\n50000 rows x 200 cols example ( [LIVE EXAMPLE](https://codesandbox.io/s/github/devel0/react-ws-canvas/tree/master/example) : click *EX1* button )\n\n![](doc/50000rows_200cols.gif)\n\n- **direct cell editing**, just click on a cell then type, hit ENTER or arrows keys to move next ( [native cell types][1] )\n  - \"text\": type text to change cell ; CANC to clear cell ; CTRL+C / CTRL+V to copy/paste\n  - \"boolean\": toggle boolean with keyboard space when cell focused\n  - \"date\", \"time\", \"datetime\": smart date insertion ( typing 121030 results in 12/10/2030 ) browser locale supported\n  - \"number\": sci numbers ( typing 12e-3 results in 0.012 displayed ) browser locale support for decimal separators\n\n- [properties default values][22]\n\n- [cell or row][2] selection mode\n\n![](doc/selection-mode-cells.png)\n\n![](doc/selection-mode-rows.png)\n\n- selection [mode multi][9]\n\n![](doc/selection-mode-multi.png)\n\n- frozen [rows, cols][3]\n\n![](doc/frozen-rows-cols.png)\n\n- [wrap][21] text cells ( [helper][121] )\n\n![](doc/text-wrap.gif)\n\n- rows and cols numbering can be [shown or hidden][5]\n\n- if column numbering visible automatic sort can be customized through [less-than-op][6] ( [helper][106] )\n\n- [column click behavior][12] can be full column select, column toggle sort or none to disable sort/select behavior\n\n- [column header][15] can be customized ( [helper][115] )\n\n- canvas size can be specified through width, height ( [fullwidth][26] option available )\n\n- column width can be changed intractively using mouse\n\n![](doc/column-width-resize.png)\n\n- column width [autoexpand][16]\n\n- column custom [initial sort][18] ( *note*: prepareCellDataset, rowSetCellData, commitCellDataset must defined to make sort working ); also see [example6][36] for tip about ensure initial sort on subsequent datasource applications\n\n![](doc/initial-sort.png)\n\n- data getter/setter can follow a [worksheet][7] or a [db record type][8] ( [example of nested field][28] using [getFieldData][29] and [setFieldData][30] methods)\n\n- data [filter global][129]\n\n- optional dataset on external object with [ds rows getter mapper][32] useful in some circumstance when need to preserve rows array object ref\n\n- [api][10] and [handlers][27] available for control interactions ( [example][11] ) ; props can be accessed [inversely][31] through api; retrieve list of selected row idxs [example][38]\n\n![](doc/api.gif)\n\n- each individual cell [custom edit][13] ( F2 ) control can be customized also in [column helper][113] ( [example][24] : through keyboard F2, arrows then enter ) ; cell [editing/edited][128] also in [column helper][127]\n\n![](doc/custom-combobox.gif)\n\n- custom multi select with material-ui ( [example][35] )\n\n- custom date picker with material pickers ( [example][37] )\n\n![](doc/material-select-multi.gif)\n\n- custom color picker with **custom render** ( [example][130] ) ; note: wrapText will use custom component height to *autoresize row height* ; *filter* can work as text mode defining renderTransform\n\n![](doc/custom-color-picker.gif)\n\n- cell [background][19], [font and color][119], [readonly mode][126] customization and [text align][25] also with [helper][125]\n\n![](doc/cell-style-customization.png)\n\n- container [height min][23] and canvas [styles][20]\n\n- each individual [cell type][14] can be customized ( [column helper][114] )\n\n- clipboard copy to/from spreadsheet with ctrl-c and ctrl-v or [api][34] ( [example api][33] )\n\n![](doc/clipboard.png)\n\n- support mobile touch scrolling rows, cols and scrollbars\n\n[1]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasColumn.tsx#L7\n[2]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L45\n[3]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L38-L41\n[5]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L50-L55\n[6]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L90-L91\n[106]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasColumn.tsx#L36-L37\n[7]: https://github.com/devel0/react-ws-canvas/blob/cbd9d6d75100a45cb7d0ee073c6d5ab03f3a354e/example/src/Sample1.tsx#L31-L35\n[8]: https://github.com/devel0/react-ws-canvas/blob/e893299287fd041f84e900262d5915bf8670fc6b/example/src/Sample4.tsx#L231-L240\n[9]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L42-L43\n[10]: https://github.com/devel0/react-ws-canvas/blob/53639eb02d4df298b4591c6f231c63cf4db703b2/example/src/lib/WSCanvasApi.tsx#L13\n[11]: https://github.com/devel0/react-ws-canvas/blob/e893299287fd041f84e900262d5915bf8670fc6b/example/src/Sample4.tsx#L150\n[12]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L58-L59\n[13]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L85-L87\n[113]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasColumn.tsx#L57-L58\n[14]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L92-L93\n[114]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasColumn.tsx#L22-L23\n[15]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L88-L89\n[115]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasColumn.tsx#L25-L26\n[16]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L34-L35\n[18]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L96-L97\n[118]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasColumn.tsx#L44-L48\n[19]:https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L101-L102\n[119]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L131-L140\n[20]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L181-L184\n[21]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L129-L130\n[121]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasColumn.tsx#L50-L51\n[22]: https://github.com/devel0/react-ws-canvas/blob/cbd9d6d75100a45cb7d0ee073c6d5ab03f3a354e/example/src/lib/WSCanvasPropsDefault.tsx#L11\n[23]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/Sample3.tsx#L222\n[24]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/Sample3.tsx#L90-L122\n[25]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L98-L99\n[125]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasColumn.tsx#L39\n[26]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L18-L19\n[27]: https://github.com/devel0/react-ws-canvas/blob/513632060951df8a20b83dee39667529cc0ac883/example/src/lib/WSCanvasProps.tsx#L191-L219\n[28]: https://github.com/devel0/react-ws-canvas/blob/d0767d8e1327ff69090ad0dbd7f4eefd907c7a69/example/src/Sample3.tsx#L169-L171\n[29]: https://github.com/devel0/react-ws-canvas/blob/cbd9d6d75100a45cb7d0ee073c6d5ab03f3a354e/example/src/Sample3.tsx#L229\n[30]: https://github.com/devel0/react-ws-canvas/blob/cbd9d6d75100a45cb7d0ee073c6d5ab03f3a354e/example/src/Sample3.tsx#L235\n[31]: https://github.com/devel0/react-ws-canvas/blob/e893299287fd041f84e900262d5915bf8670fc6b/example/src/Sample4.tsx#L201\n[32]: https://github.com/devel0/react-ws-canvas/blob/1606876a64be83e6c1c9e78cfdeeea5f243f52f5/example/src/lib/WSCanvasProps.tsx#L79-L80\n[33]: https://github.com/devel0/react-ws-canvas/blob/a6d7e61ebc2371f4817e4ba632ff653738d26c55/example/src/Sample3.tsx#L211\n[34]: https://github.com/devel0/react-ws-canvas/blob/a6d7e61ebc2371f4817e4ba632ff653738d26c55/example/src/lib/WSCanvasApi.tsx#L108-L115\n[35]: https://github.com/devel0/react-ws-canvas/blob/ba1c4483045065f12fa3c59f1c910ad34fdeb213/example/src/Sample5.tsx#L63-L116\n[36]: https://github.com/devel0/react-ws-canvas/blob/d115874c761a250f280ced9f3798ad531ac59075/example/src/Sample6.tsx#L26-L28\n[37]: https://github.com/devel0/react-ws-canvas/blob/58f253259b6dc563dadbcdd598a9f0b81d3baa26/example/src/Sample5.tsx#L122-L160\n[38]: https://github.com/devel0/react-ws-canvas/blob/315d2d22075c042897652253469272d8e4ee9171/example/src/Sample4.tsx#L289\n[126]: https://github.com/devel0/react-ws-canvas/blob/4c6ca74106654cec114887b542f64fb41a8cdd0f/example/src/Sample3.tsx#L262-L268\n[127]: https://github.com/devel0/react-ws-canvas/blob/b123792518147670b918a392a8894a98e5442ca5/example/src/Sample2.tsx#L52-L59\n[128]: https://github.com/devel0/react-ws-canvas/blob/b123792518147670b918a392a8894a98e5442ca5/example/src/Sample2.tsx#L151-L157\n[129]: https://github.com/devel0/react-ws-canvas/blob/b123792518147670b918a392a8894a98e5442ca5/example/src/Sample2.tsx#L126-L132\n[130]: https://github.com/devel0/react-ws-canvas/blob/2d8ec23eb40a059825d6ac4dc2520ad696468595/example/src/Sample5.tsx#L129-L132\n\n## todo\n\n## quickstart\n\n![](doc/quickstart.png)\n\n- create react app\n\neventually install create-react-app\n\n```sh\nnpm install -g create-react-app\n```\n\n```sh\ncreate-react-app test --template typescript\ncd test\nyarn add react-ws-canvas\n```\n\n- edit `App.tsx` as follows\n\n```ts\nimport React, { useState, useEffect } from 'react';\nimport { WSCanvas, useWindowSize, WSCanvasColumnClickBehavior } from 'react-ws-canvas';\n\nconst AppQuickStart: React.FC = () =\u003e {\n  const [rows, setRows] = useState\u003cany[][]\u003e([]);\n  const winSize = useWindowSize();\n\n  const ROWS = 500000;\n  const COLS = 20;\n\n  useEffect(() =\u003e {\n\n    const _rows = [];\n    for (let ri = 0; ri \u003c ROWS; ++ri) {\n      const row = [];\n      for (let ci = 0; ci \u003c COLS; ++ci) {\n        row.push(\"r:\" + ri + \" c:\" + ci);\n      }\n      _rows.push(row);\n    }\n\n    setRows(_rows);\n  }, []);\n\n  return \u003cWSCanvas\n    width={winSize.width} height={winSize.height}\n    rowsCount={rows.length} colsCount={COLS}\n    showColNumber={true} showRowNumber={true}\n    columnClickBehavior={WSCanvasColumnClickBehavior.ToggleSort}\n    rows={rows}\n    rowGetCellData={(row, colIdx) =\u003e row[colIdx]}\n    prepareCellDataset={() =\u003e rows.slice()}\n    commitCellDataset={(q) =\u003e setRows(q)}\n    rowSetCellData={(row, colIdx, value) =\u003e row[colIdx] = value}\n  /\u003e;\n}\n\nexport default AppQuickStart;\n```\n\n- run the app\n\n```sh\nyarn start\n```\n\n## examples list\n\n| example | description |\n|---|---|\n| [quickstart](example/src/App.quickstart.tsx) | 500000 x 20 grid with minimal props |\n| [Sample1](example/src/Sample1.tsx) | 50000 x 200 grid with frozen row/col, filter, custom column width |\n| [Sample2](example/src/Sample2.tsx) | 5000 x 6 grid db-record-like column mapping, initial sort, custom sort, api onMouseDown, global filter, cell changing/changed |\n| [Sample3](example/src/Sample3.tsx) | 5000 x 7 grid db-record-like, data interact del/change row, custom cell editor, rowHover |\n| [Sample4](example/src/Sample4.tsx) | add/insert/del/move/currentRealRowSel rows using api |\n| [Sample5](example/src/Sample5.tsx) | custom multi select with material-ui ; custom render chip with color picker |\n| [Sample6](example/src/Sample6.tsx) | resetView behavior to force sync ds ; resetSorting and resetFilters resetView arguments |\n\n## tips\n\n**prevent direct editing on editor customized cells**\n\ncustomize onPreviewKeyDown event handler on datagrid and preventDefault for matching cell\n\n```ts\nonPreviewKeyDown={(states, e) =\u003e {\n  if (states.props.columns \u0026\u0026 api \u0026\u0026 api.isDirectEditingKey(e)) {\n    const fieldname = states.props.columns[states.state.focusedCell.col].field;\n    if (fieldname === \"colname\") {\n      //const row = states.props.rows[states.state.focusedCell.row];\n      e.preventDefault();\n    }\n  }\n}}\n```\n\n## how to contribute ( quickstart )\n\n- clone repo\n\n```sh\ngit clone https://github.com/devel0/react-ws-canvas.git\n```\n\n- open vscode\n\n```sh\ncd react-ws-canvas\ncode .\n```\n\n- from vscode, open terminal ctrl+\\` and execute example application ( this allow you to set **breakpoints** directly on library source code from `lib` folder )\n\n```sh\ncd example\nyarn install\nyarn start\n```\n\n- start chrome session using F5\n\n## local deploy\n\n- from library\n\n```sh\ncd lib\nyarn build \u0026\u0026 yalc publish\n```\n\n- from your project\n\n```sh\nnpm uninstall react-ws-canvas --save \u0026\u0026 yalc add react-ws-canvas \u0026\u0026 npm install\n```\n\n## how this project was built\n\n```sh\nyarn create react-app react-ws-canvas --template typescript\n```\n\nBecause I need a library to publish and either a working example to test/debug the library project structured this way:\n\n- `/package.json` ( workspaces \"example\" and \"lib\" )\n- `/example` ( example and library sources )\n  - `/example/package.json`\n  - `/example/.env` with BROWSER=none to avoid browser start when issue `yarn start` because I use F5 from vscode to open debugging session\n  - `/example/lib` ( library source codes )\n- `/lib` ( library publishing related files )\n  - `/lib/package.json`\n  - `/lib/rollup.config.json` ( specifically `input: '../example/src/lib/index.tsx',  ` )\n  - `/lib/tsconfig.json` ( specifically `\"rootDirs\": [\"../example/src/lib\"],` and `\"include\": [\"../example/src/lib\"],` )\n  - `/lib/prepatch-and-publish` ( helper script to prepatch version and publish with README.md )\n\n## development notes\n\n- **key notes** (old)\n  - [cs.width and cs.height][1508] variables represents [canvas size][1509] and used as starting point for [calculations][1510]\n  - [stateNfo, viewMap, overridenRowHeight][1500] are kept separate because stateNfo must light because frequently updated while viewMap and overridenRowHeight can be heavy struct for large grids\n  - [view][1501] mapping have a size less-or-equal than rowsCount depending on [filtering][1502] and the order of view may different depending on sorting\n  - some methods work with [real cells][1503] ( the same as user configure through getCellData, setCellData ), some other methods works with [view cells][1504] that is an internal representation convenient to deal on what-you-see-is-what-you-get\n  - [real and view coords][1505] can be transformed between\n  - [mkstates][1506] is an helper used primarly by [handlers][1507] to ensure callback uses synced state\n- **TODO**\n  - type 'select' for cell with combobox integrated\n  - date picker when F2 (or double click) on date type cell\n  - isOverCell should true on last row when showPartialRows\n- deployment\n  - remove any `from \"react-ws-canvas\";`\n\n[1500]: https://github.com/devel0/react-ws-canvas/blob/1c0200495ec75a6fe31f467884b9ac79b1e88ad6/example/src/lib/WSCanvas.tsx#L140-L146\n[1501]: https://github.com/devel0/react-ws-canvas/blob/1c0200495ec75a6fe31f467884b9ac79b1e88ad6/example/src/lib/WSCanvas.tsx#L159-L187\n[1502]: https://github.com/devel0/react-ws-canvas/blob/1c0200495ec75a6fe31f467884b9ac79b1e88ad6/example/src/lib/WSCanvas.tsx#L382\n[1503]: https://github.com/devel0/react-ws-canvas/blob/1c0200495ec75a6fe31f467884b9ac79b1e88ad6/example/src/lib/WSCanvas.tsx#L1053\n[1504]: https://github.com/devel0/react-ws-canvas/blob/1c0200495ec75a6fe31f467884b9ac79b1e88ad6/example/src/lib/WSCanvas.tsx#L648\n[1505]: https://github.com/devel0/react-ws-canvas/blob/1c0200495ec75a6fe31f467884b9ac79b1e88ad6/example/src/lib/WSCanvas.tsx#L183-L187\n[1506]: https://github.com/devel0/react-ws-canvas/blob/1c0200495ec75a6fe31f467884b9ac79b1e88ad6/example/src/lib/WSCanvas.tsx#L267\n[1507]: https://github.com/devel0/react-ws-canvas/blob/1c0200495ec75a6fe31f467884b9ac79b1e88ad6/example/src/lib/WSCanvas.tsx#L2039\n[1508]: https://github.com/devel0/react-ws-canvas/blob/dee24cfc21590793651abf21c6fecc9e32bc826d/example/src/lib/WSCanvas.tsx#L159-L169\n[1509]: https://github.com/devel0/react-ws-canvas/blob/5c1c29be00c6c3c4e55544df25e8c4087f0631a8/example/src/lib/WSCanvas.tsx#L2945-L2946\n[1510]: https://github.com/devel0/react-ws-canvas/blob/5c1c29be00c6c3c4e55544df25e8c4087f0631a8/example/src/lib/WSCanvas.tsx#L244\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevel0%2Freact-ws-canvas","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevel0%2Freact-ws-canvas","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevel0%2Freact-ws-canvas/lists"}