{"id":19560063,"url":"https://github.com/plotdb/sheet","last_synced_at":"2026-06-06T20:32:18.512Z","repository":{"id":39451306,"uuid":"378661300","full_name":"plotdb/sheet","owner":"plotdb","description":"spreadsheet","archived":false,"fork":false,"pushed_at":"2025-01-16T07:19:49.000Z","size":3792,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-06T16:51:34.277Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/plotdb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-20T14:10:51.000Z","updated_at":"2025-08-25T16:59:20.000Z","dependencies_parsed_at":"2023-02-08T19:15:26.130Z","dependency_job_id":"40adbd0d-b1f0-4475-944b-33c4e49ab3f8","html_url":"https://github.com/plotdb/sheet","commit_stats":{"total_commits":71,"total_committers":1,"mean_commits":71.0,"dds":0.0,"last_synced_commit":"bc45355700f90c2d2309e12f0532e4a9109a450b"},"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"purl":"pkg:github/plotdb/sheet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plotdb%2Fsheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plotdb%2Fsheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plotdb%2Fsheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plotdb%2Fsheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/plotdb","download_url":"https://codeload.github.com/plotdb/sheet/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plotdb%2Fsheet/sbom","scorecard":{"id":738029,"data":{"date":"2025-08-11","repo":{"name":"github.com/plotdb/sheet","commit":"125444b8179bc2f246de738fef471042910b139b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.6,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.6.10 not signed: https://api.github.com/repos/plotdb/sheet/releases/176044142","Warn: release artifact v0.6.9 not signed: https://api.github.com/repos/plotdb/sheet/releases/152932744","Warn: release artifact v0.6.8 not signed: https://api.github.com/repos/plotdb/sheet/releases/151736479","Warn: release artifact v0.6.7 not signed: https://api.github.com/repos/plotdb/sheet/releases/132126317","Warn: release artifact v0.6.6 not signed: https://api.github.com/repos/plotdb/sheet/releases/132070405","Warn: release artifact v0.6.10 does not have provenance: https://api.github.com/repos/plotdb/sheet/releases/176044142","Warn: release artifact v0.6.9 does not have provenance: https://api.github.com/repos/plotdb/sheet/releases/152932744","Warn: release artifact v0.6.8 does not have provenance: https://api.github.com/repos/plotdb/sheet/releases/151736479","Warn: release artifact v0.6.7 does not have provenance: https://api.github.com/repos/plotdb/sheet/releases/132126317","Warn: release artifact v0.6.6 does not have provenance: https://api.github.com/repos/plotdb/sheet/releases/132070405"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":4,"reason":"6 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-vc8w-jr9v-vj7f","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-vhxf-7vqr-mrjg","Warn: Project is vulnerable to: GHSA-h7cp-r72f-jxh6","Warn: Project is vulnerable to: GHSA-v62p-rq8g-8h59"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T16:29:10.812Z","repository_id":39451306,"created_at":"2025-08-22T16:29:10.812Z","updated_at":"2025-08-22T16:29:10.812Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33999579,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-06T02:00:07.033Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-11-11T05:05:46.749Z","updated_at":"2026-06-06T20:32:18.476Z","avatar_url":"https://github.com/plotdb.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @plotdb/sheet\n\nsimple sheet UI in vanilla JS. Features:\n\n - fast, infinite scrolling.\n - small - \u003c 25KB when minimized\n - vanilla - only optional depends on Papaparse for CSV parsing\n - CSS-based layout - better user experience\n - size of column/row auto fit content yet still customizable\n - support frozen row/column for data, fixed row/column for custom content\n - support tsv/csv pasting (depends on Papaparse)\n\n\n## Usage\n\ninstall:\n\n    npm install @plotdb/sheet\n\n\ninclude:\n\n    \u003cscript src=\"path-to/sheet/index.min.js\"\u003e\u003c/script\u003e\n    \u003clink rel=\"stylesheet\" type=\"text/css\" href=\"path-to/sheet/index.min.css\"/\u003e\n    \u003cdiv class=\"container\"\u003e\u003c/div\u003e\n\n\ninitialize:\n\n    var s = new sheet({\n      root: '.container',\n      data: mydata = [[... ], ... /* array of arrays */]\n    })\n\n\n## Constructor Options\n\n - `root`: container element or selector.\n - `fixed`: {row, col}. default {row: 0, col: 0}\n - `frozen`: {row, col}. default {row: 0, col: 0}\n - `idx`: {row, col}. default {row: true, col: true}\n - `size`: {row, col}. force cell size, in array by order.\n   - default: {row: [], col: []}\n   - example: `{col: [\"300px\", \"12em\"]}`\n - `class`: {row, col}. additional cell class name, in array by order, as space separated string.\n   - default: {row: [], col: []}\n - `editing`: false to disable editing. default true.\n   - (TBD) in the future we should be able to:\n     - set edit permission ( e.g., edit, comment )\n     - apply on range\n - `scrollLock`: default true. prevent from horizontal scrolling of document.body if true.\n   - this affects how user interact with sheet with scrolling gestures. check src comment for more information.\n   - see also `enableScrolling`\n - `enableScrolling`: default true. enable scrolling if true.\n   - the difference between `scrollLock` and `enableScrolling` is that:\n     - `scrollLock` is for horizontal scrolling that may conflict with browser gesture.\n     - `enableScrolling` is for mouse / trackpad scrolling behavior\n - `data`: initial data, as array of arrays\n - `slider`: default false. show slider widgets if true.\n - `cellcfg(opt)`: custom cell definition function. return value based on the given `opt`, which contains:\n   - `row`: row of the cell to query\n   - `col`: col of the cell to query\n   - `type`: a string indicating what should we return. it can be:\n     - `class`: should return the CSS classes for the given cell\n     - `readonly`: return true if the given cell should be readonly.\n     - `format`: return cell format for number. Use `d3-format` syntax.\n       - depends on `d3.format`. if not available, no formatting will be applied.\n\n\n## API\n\n - `set({row, col, data, range})`: set cell data to `data` for cell(s) in row `row` and col `col`.\n   - update a range based on 2D array `data` when `range` is true.\n - `goto({row, col})`: set grid view starting from coordinate {row, col}\n - `render()`: force to re-render visible cells\n - `editing(v)`: set edit status to v, or return edit status if v is not provided.\n - `data(d)`: replace data completely with `d` and re-render.\n   - return current data if `d` is omitted.\n   - `d` is in the same format with the constructor `data` option\n - `size({row, col})`: update grid size.\n - `select(opt)`: set / get selection range\n   - if opt is omitted, return current selection status, which is:\n     - null, if no selection available.\n     - the selection object with fields as below:\n       - `col`: index of column. omitted for selecting everything on a row.\n       - `colspan`: span of column. will be 1 if omitted \n       - `row`: index of row. omitted for selecting everything on a column.\n       - `rowspan`: span of row. will be 1 if omitted \n     - `{}` = the whole table selected, based on the definition of the selection object.\n   - otherwise, set selection based on the `opt` selection range object described as above.\n - `slice()`: delete selected rows/columns\n - `insert()`: insert empty row/column at selected location.\n - `sort(opt)`: sort data based on selected column. `opt` is an object with following fields as options:\n   - `dir`: direction. either `asc` or `desc`, by default `asc`.\n - `edited(opt)`: force sheet enter non-edit mode. option:\n   - `cancel`: default false. if true, cancel current editing and remove content that are going to be inputted.\n\n## Event\n\nuse `sheet.on('event-name', callback)` to handle sheet related events, e.g.,\n\n    s = new sheet( ... );\n    s.on('change', function({row, col, data, range}) {\n      ....\n    });\n\n\nFollowing are a list of possible events:\n\n - `change`: fired when some cells are updated. callback function with following options, in object:\n   - `row`: base row of the updated cell\n   - `col`: base col of the updated cell\n   - `data`: data used to update. If it's a 2D array and `range` is true, then cells are updated with values in `data` correspondingly relative to `row` and `col` as the original cell\n   - `range`: true if a range of cells are updated.\n - `menu.on`: fired when a `contextmenu` event is fired within sheet. Option is an object with following fields:\n   - `evt`: corresponding event object\n   - `node`: target node from which this event was fired.\n - `menu.off`: fired when a context menu is expected to dismiss. Option is an object with following fields:\n   - `evt`: corresponding event object\n   - `node`: target node from which this event was fired.\n\n\n## Rich Text\n\nYou can add more than texts in the grid of the sheet, by having an object with following structure in data:\n\n    {\n      type: \"data-type\",\n      ... /* members according to type */\n    }\n\nCurrently, only `node` type is supported:\n\n    { type: \"dom\", node: SomeElement }\n\n\n# Swipe Back Issue\n\nOn Chrome in Mac, scrolling left with trackpad with two finger gesture may also triggers swipe back action, which navigate the page back in browsing history. This happens in all websites needing similar actions, including Airtable and Google Spreadsheet.\n\nThis may be temporarily solved by setting `overscroll-behavior` to `contain` of the sheet container, however - if swipe back happens once anywhere outside the sheet container, it then always triggered even in sheet container.\n\nIf this happens, try setting `overscroll-behavior` to `contain` directly on `body` to see if it may solve this issue.\n\nReference:\n\n - https://bugs.chromium.org/p/chromium/issues/detail?id=889846\n - https://bugs.chromium.org/p/chromium/issues/detail?id=862693\n - https://bugs.chromium.org/p/chromium/issues/detail?id=906886\n - https://community.airtable.com/t/3074\n\n\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplotdb%2Fsheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplotdb%2Fsheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplotdb%2Fsheet/lists"}