├── .babelrc.json
├── .github
└── workflows
│ └── npm-publish-github-packages.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.json
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── babel-register.js
├── build
├── webpack.config.js
├── webpack.dev.js
└── webpack.prod.js
├── dist
├── config.d.ts
├── data
│ ├── border.d.ts
│ ├── cells.d.ts
│ ├── col.d.ts
│ ├── copy.d.ts
│ ├── index.d.ts
│ ├── merge.d.ts
│ ├── row.d.ts
│ ├── scroll.d.ts
│ └── style.d.ts
├── editor
│ ├── index.d.ts
│ ├── select
│ │ └── index.d.ts
│ └── text
│ │ └── index.d.ts
├── element.d.ts
├── event.d.ts
├── helper.d.ts
├── index.d.ts
├── index.editor.d.ts
├── index.event.d.ts
├── index.html.d.ts
├── index.resizer.d.ts
├── index.scrollbar.d.ts
├── index.selector.d.ts
├── overlayer
│ └── index.d.ts
├── resizer
│ └── index.d.ts
├── scrollbar
│ └── index.d.ts
├── selector
│ └── index.d.ts
├── table.min.css
└── table.min.js
├── index-dev.ts
├── index.html
├── logo.svg
├── package-lock.json
├── package.json
├── src
├── config.ts
├── data
│ ├── border.ts
│ ├── cells.ts
│ ├── col.ts
│ ├── copy.ts
│ ├── index.ts
│ ├── merge.ts
│ ├── row.ts
│ ├── scroll.ts
│ └── style.ts
├── editor
│ ├── index.ts
│ ├── select
│ │ ├── index.ts
│ │ └── style.less
│ ├── style.less
│ └── text
│ │ └── index.ts
├── element.ts
├── event.ts
├── helper.ts
├── index.editor.ts
├── index.event.ts
├── index.html.ts
├── index.resizer.ts
├── index.scrollbar.ts
├── index.selector.ts
├── index.ts
├── overlayer
│ ├── index.ts
│ └── style.less
├── resizer
│ ├── index.ts
│ └── style.less
├── scrollbar
│ ├── index.ts
│ └── style.less
├── selector
│ ├── index.ts
│ └── style.less
├── style.base.less
└── style.index.less
├── test
├── index.html.test.ts
└── test.ts
└── tsconfig.json
/.babelrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-typescript"
5 | ],
6 | "plugins": [
7 | [
8 | "@babel/plugin-transform-runtime",
9 | {
10 | "absoluteRuntime": false,
11 | "corejs": false,
12 | "helpers": true,
13 | "regenerator": true
14 | }
15 | ]
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/.github/workflows/npm-publish-github-packages.yml:
--------------------------------------------------------------------------------
1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2 | # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3 |
4 | name: Publish package to npmjs
5 |
6 | on:
7 | push:
8 | tags:
9 | - "v*"
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: actions/checkout@v3
16 | - uses: actions/setup-node@v3
17 | with:
18 | node-version: 16
19 | - run: npm install
20 | - run: npm test
21 | - run: npm run build
22 |
23 | publish-gpr:
24 | needs: build
25 | runs-on: ubuntu-latest
26 | permissions:
27 | contents: read
28 | packages: write
29 | steps:
30 | - uses: actions/checkout@v3
31 | - uses: actions/setup-node@v3
32 | with:
33 | node-version: 16
34 | registry-url: https://registry.npmjs.org
35 | - run: npm publish --access public
36 | env:
37 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | # don't ever lint node_modules
2 | node_modules
3 | # don't lint build output (make sure it's set to your correct build folder name)
4 | dist
5 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 80,
3 | "tabWidth": 2,
4 | "singleQuote": true,
5 | "semi": true,
6 | "trailingComma": "es5",
7 | "bracketSpacing": true,
8 | "jsxBracketSameLine": true,
9 | "arrowParens": "always",
10 | "parser": "typescript",
11 | "overrides": [
12 | {
13 | "files": "*.less",
14 | "options": {"parser": "less"}
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.defaultFormatter": "esbenp.prettier-vscode",
3 | "eslint.alwaysShowStatus": true,
4 | "editor.tabSize": 2,
5 | "editor.detectIndentation": false,
6 | "prettier.embeddedLanguageFormatting": "off",
7 | "extensions.ignoreRecommendations": true,
8 | "workbench.editorAssociations": {
9 | "*.dbf": "dbf-table",
10 | "*.hda": "default"
11 | },
12 | "editor.codeActionsOnSave": {},
13 | "editor.formatOnSave": true
14 | }
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 wolf-table
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | ## wolf-table
15 | > A web-based(canvas) JavaScript Table
16 |
17 | ## Demo
18 | Open in Stackblitz
19 | Preview in browser
20 |
21 | ## NPM
22 | npm install
23 | ```shell
24 | npm install @wolf-table/table@0.0.1
25 | ```
26 | ## Usage
27 | ```javascript
28 | import '@wolf-table/table/dist/table.min.css';
29 | import Table from "@wolf-table/table";
30 |
31 | const t = Table.create(
32 | '#table',
33 | () => 1400,
34 | () => 600,
35 | {
36 | scrollable: true,
37 | resizable: true,
38 | selectable: true,
39 | editable: true,
40 | copyable: true,
41 | }
42 | )
43 | .freeze('D5')
44 | .merge('F10:G11')
45 | .merge('I10:K11')
46 | .addBorder('E8:L12', 'all', 'medium', '#21ba45')
47 | .formulaParser((v) => `${v}-formula`)
48 | .data({
49 | styles: [
50 | { bold: true, strikethrough: true, color: '#21ba45', italic: true, align: 'center', fontSize: 12 },
51 | ],
52 | cells: [
53 | [0, 0, 'abc'],
54 | [1, 1, 100],
55 | [2, 6, { value: 'formua', style: 0 }],
56 | [9, 5, { value: '', formula: '=sum(A1:A10)' }],
57 | ],
58 | })
59 | .render();
60 |
61 | // add style
62 | const si = t.addStyle({
63 | bold: true,
64 | italic: true,
65 | underline: true,
66 | color: '#1b1c1d',
67 | });
68 | // set cell
69 | t.cell(2, 2, { value: 'set-value', style: si }).render();
70 |
71 | // get cell
72 | console.log('cell[2,2]:', t.cell(2, 2));
73 | ```
74 |
75 | ## Development
76 |
77 | ```shell
78 | git clone https://github.com/wolf-table/table.git
79 | cd table
80 | npm install
81 | npm run dev
82 | ```
83 |
84 | Open your browser and visit http://127.0.0.1:8080.
85 |
86 | ## Browser Support
87 |
88 | Modern browsers(chrome, firefox, Safari).
89 |
90 | ## LICENSE
91 |
92 | MIT
93 |
94 | Copyright (c) 2022-present, myliang
--------------------------------------------------------------------------------
/babel-register.js:
--------------------------------------------------------------------------------
1 | require("@babel/register")({ extensions: ['.js', '.ts'] });
2 |
--------------------------------------------------------------------------------
/build/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3 | const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
4 |
5 | module.exports = {
6 | entry: {
7 | table: './src/index.ts',
8 | },
9 | plugins: [
10 | new MiniCssExtractPlugin({
11 | filename: '[name].min.css',
12 | }),
13 | ],
14 | optimization: {
15 | minimizer: [`...`, new CssMinimizerPlugin()],
16 | },
17 | module: {
18 | rules: [
19 | {
20 | test: /\.ts$/,
21 | use: 'babel-loader',
22 | exclude: /node_modules/,
23 | },
24 | {
25 | test: /\.less$/,
26 | use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
27 | },
28 | ],
29 | },
30 | resolve: {
31 | extensions: ['.ts', '.js'],
32 | },
33 | output: {
34 | filename: '[name].min.js',
35 | path: path.resolve(__dirname, '../dist'),
36 | clean: true,
37 | },
38 | };
39 |
--------------------------------------------------------------------------------
/build/webpack.dev.js:
--------------------------------------------------------------------------------
1 | const { merge } = require('webpack-merge');
2 | const common = require('./webpack.config.js');
3 | const HtmlWebpackPlugin = require('html-webpack-plugin');
4 |
5 | module.exports = merge(common, {
6 | entry: {
7 | table: './index-dev.ts',
8 | },
9 | mode: 'development',
10 | devtool: 'inline-source-map',
11 | plugins: [
12 | new HtmlWebpackPlugin({
13 | template: './index.html',
14 | title: 'Table',
15 | }),
16 | ],
17 | devServer: {
18 | host: '0.0.0.0',
19 | static: '../dist',
20 | },
21 | });
22 |
--------------------------------------------------------------------------------
/build/webpack.prod.js:
--------------------------------------------------------------------------------
1 | const { merge } = require('webpack-merge');
2 | const common = require('./webpack.config.js');
3 |
4 | module.exports = merge(common, {
5 | mode: 'production',
6 | output: {
7 | libraryTarget: 'commonjs2',
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/dist/config.d.ts:
--------------------------------------------------------------------------------
1 | export declare const stylePrefix = "wolf-table";
2 | export declare const borderWidth = 2;
3 |
--------------------------------------------------------------------------------
/dist/data/border.d.ts:
--------------------------------------------------------------------------------
1 | import { TableData } from '.';
2 | import { Border } from '@wolf-table/table-renderer';
3 | export declare function addBorder(t: TableData, value: Border): void;
4 | export declare function clearBorder(t: TableData, ref: string): void;
5 | export declare function clearBorders(t: TableData): void;
6 |
--------------------------------------------------------------------------------
/dist/data/cells.d.ts:
--------------------------------------------------------------------------------
1 | import { Formatter } from '@wolf-table/table-renderer';
2 | import { IndexDataCell, DataCell, TableData, FormulaParser, DataCellValue } from '.';
3 | export default class Cells {
4 | _: IndexDataCell[];
5 | _indexes: Map;
6 | _formulas: number[];
7 | _formulaParser: FormulaParser;
8 | _formatter: Formatter;
9 | constructor();
10 | formulaParser(v: FormulaParser): this;
11 | formatter(v: Formatter): this;
12 | load({ cells }: TableData): void;
13 | get(row: number, col: number): IndexDataCell | null;
14 | remove(row: number, col: number): this;
15 | set(row: number, col: number, cell: DataCell): void;
16 | private resetIndexes;
17 | private updateIndex;
18 | private addFormula;
19 | private resetFormulas;
20 | }
21 | export declare function cellValue(cell: DataCell): DataCellValue;
22 | export declare function cellValueString(cell: DataCell): string;
23 |
--------------------------------------------------------------------------------
/dist/data/col.d.ts:
--------------------------------------------------------------------------------
1 | import { DataCol, TableData } from '.';
2 | export declare function col(data: TableData, index: number): DataCol;
3 | export declare function col(data: TableData, index: number, value: Partial): DataCol;
4 | export declare function colWidth(data: TableData, index: number): number;
5 | export declare function colWidth(data: TableData, index: number, value: number): void;
6 | export declare function colsWidth(data: TableData): number;
7 | export declare function colsWidth(data: TableData, min: number, max: number): number;
8 | export declare function isLastCol(data: TableData, index: number): boolean;
9 | export declare function stepColIndex(data: TableData, index: number, step: number): number;
10 |
--------------------------------------------------------------------------------
/dist/data/copy.d.ts:
--------------------------------------------------------------------------------
1 | import { Range } from '@wolf-table/table-renderer';
2 | import { Cells, TableData } from '.';
3 | export declare type CopyData = {
4 | range: Range;
5 | cells: Cells;
6 | data: TableData;
7 | };
8 | export declare type CopyCells = {
9 | range: Range;
10 | cells: Cells;
11 | data: TableData;
12 | };
13 | export declare function copy(from: CopyCells | null, to: CopyCells | null, autofill?: boolean): void;
14 |
--------------------------------------------------------------------------------
/dist/data/index.d.ts:
--------------------------------------------------------------------------------
1 | import { Cell, Style, Border, Row, Col } from '@wolf-table/table-renderer';
2 | import Cells, { cellValue, cellValueString } from './cells';
3 | import { scrollx, scrolly, scrollResetRows, scrollResetCols } from './scroll';
4 | import { isMerged, merge, unmerge, rangeUnoinMerges } from './merge';
5 | import { addStyle, clearStyles } from './style';
6 | import { addBorder, clearBorder, clearBorders } from './border';
7 | import { col, colWidth, colsWidth, isLastCol, stepColIndex } from './col';
8 | import { row, rowHeight, rowsHeight, isLastRow, stepRowIndex } from './row';
9 | import { copy } from './copy';
10 | export declare type DataRow = Row;
11 | export declare type DataRows = {
12 | len: number;
13 | [key: number]: DataRow;
14 | };
15 | export declare type DataCol = Col;
16 | export declare type DataCols = {
17 | len: number;
18 | [key: number]: DataCol;
19 | };
20 | export declare type DataCell = Cell;
21 | export declare type IndexDataCell = [number, number, DataCell];
22 | export declare type DataCellValue = string | number | null | undefined;
23 | export declare type TableData = {
24 | rows: DataRows;
25 | cols: DataCols;
26 | rowHeight: number;
27 | colWidth: number;
28 | scroll: [number, number, number, number];
29 | style: Style;
30 | styles: Partial