vastgrid 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +175 -13
- package/dist/canvas/geometry.d.ts +92 -0
- package/dist/canvas/geometry.d.ts.map +1 -0
- package/dist/canvas/geometry.js +197 -0
- package/dist/canvas/geometry.js.map +1 -0
- package/dist/canvas/grid-canvas.d.ts +161 -0
- package/dist/canvas/grid-canvas.d.ts.map +1 -0
- package/dist/canvas/grid-canvas.js +1146 -0
- package/dist/canvas/grid-canvas.js.map +1 -0
- package/dist/canvas/hooks.d.ts +61 -0
- package/dist/canvas/hooks.d.ts.map +1 -0
- package/dist/canvas/hooks.js +2 -0
- package/dist/canvas/hooks.js.map +1 -0
- package/dist/canvas/keys.d.ts +26 -0
- package/dist/canvas/keys.d.ts.map +1 -0
- package/dist/canvas/keys.js +133 -0
- package/dist/canvas/keys.js.map +1 -0
- package/dist/canvas/layout.d.ts +26 -0
- package/dist/canvas/layout.d.ts.map +1 -0
- package/dist/canvas/layout.js +73 -0
- package/dist/canvas/layout.js.map +1 -0
- package/dist/canvas/scroll.d.ts +31 -0
- package/dist/canvas/scroll.d.ts.map +1 -0
- package/dist/canvas/scroll.js +111 -0
- package/dist/canvas/scroll.js.map +1 -0
- package/dist/canvas/text.d.ts +23 -0
- package/dist/canvas/text.d.ts.map +1 -0
- package/dist/canvas/text.js +142 -0
- package/dist/canvas/text.js.map +1 -0
- package/dist/{theme.d.ts → canvas/theme.d.ts} +8 -0
- package/dist/canvas/theme.d.ts.map +1 -0
- package/dist/canvas/theme.js +62 -0
- package/dist/canvas/theme.js.map +1 -0
- package/dist/core/cache.d.ts +48 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +222 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/checked.d.ts +20 -0
- package/dist/core/checked.d.ts.map +1 -0
- package/dist/core/checked.js +61 -0
- package/dist/core/checked.js.map +1 -0
- package/dist/core/client.d.ts +33 -0
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js +103 -0
- package/dist/core/client.js.map +1 -0
- package/dist/core/conditions.d.ts +48 -0
- package/dist/core/conditions.d.ts.map +1 -0
- package/dist/core/conditions.js +105 -0
- package/dist/core/conditions.js.map +1 -0
- package/dist/core/evaluate.d.ts +20 -0
- package/dist/core/evaluate.d.ts.map +1 -0
- package/dist/core/evaluate.js +210 -0
- package/dist/core/evaluate.js.map +1 -0
- package/dist/core/filters.d.ts +51 -0
- package/dist/core/filters.d.ts.map +1 -0
- package/dist/core/filters.js +303 -0
- package/dist/core/filters.js.map +1 -0
- package/dist/core/format.d.ts +14 -0
- package/dist/core/format.d.ts.map +1 -0
- package/dist/core/format.js +303 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/measures.d.ts +26 -0
- package/dist/core/measures.d.ts.map +1 -0
- package/dist/core/measures.js +105 -0
- package/dist/core/measures.js.map +1 -0
- package/dist/core/request-ids.d.ts +20 -0
- package/dist/core/request-ids.d.ts.map +1 -0
- package/dist/core/request-ids.js +55 -0
- package/dist/core/request-ids.js.map +1 -0
- package/dist/core/rows.d.ts +79 -0
- package/dist/core/rows.d.ts.map +1 -0
- package/dist/core/rows.js +173 -0
- package/dist/core/rows.js.map +1 -0
- package/dist/core/store.d.ts +233 -0
- package/dist/core/store.d.ts.map +1 -0
- package/dist/core/store.js +1162 -0
- package/dist/core/store.js.map +1 -0
- package/dist/core/totals.d.ts +24 -0
- package/dist/core/totals.d.ts.map +1 -0
- package/dist/core/totals.js +49 -0
- package/dist/core/totals.js.map +1 -0
- package/dist/core/trace.d.ts +7 -0
- package/dist/core/trace.d.ts.map +1 -0
- package/dist/core/trace.js +26 -0
- package/dist/core/trace.js.map +1 -0
- package/dist/core/transports.d.ts +50 -0
- package/dist/core/transports.d.ts.map +1 -0
- package/dist/core/transports.js +160 -0
- package/dist/core/transports.js.map +1 -0
- package/dist/core/types.d.ts +151 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +45 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core.d.ts +12 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +11 -0
- package/dist/core.js.map +1 -0
- package/dist/index.d.ts +15 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -7
- package/dist/index.js.map +1 -1
- package/dist/react/accessible-rows.d.ts +13 -0
- package/dist/react/accessible-rows.d.ts.map +1 -0
- package/dist/react/accessible-rows.js +320 -0
- package/dist/react/accessible-rows.js.map +1 -0
- package/dist/react/cell-editor.d.ts +22 -0
- package/dist/react/cell-editor.d.ts.map +1 -0
- package/dist/react/cell-editor.js +431 -0
- package/dist/react/cell-editor.js.map +1 -0
- package/dist/react/cell-menu.d.ts +18 -0
- package/dist/react/cell-menu.d.ts.map +1 -0
- package/dist/react/cell-menu.js +299 -0
- package/dist/react/cell-menu.js.map +1 -0
- package/dist/react/column-menu.d.ts +16 -0
- package/dist/react/column-menu.d.ts.map +1 -0
- package/dist/react/column-menu.js +1311 -0
- package/dist/react/column-menu.js.map +1 -0
- package/dist/react/columns-menu.d.ts +7 -0
- package/dist/react/columns-menu.d.ts.map +1 -0
- package/dist/react/columns-menu.js +249 -0
- package/dist/react/columns-menu.js.map +1 -0
- package/dist/react/conditions-menu.d.ts +10 -0
- package/dist/react/conditions-menu.d.ts.map +1 -0
- package/dist/react/conditions-menu.js +795 -0
- package/dist/react/conditions-menu.js.map +1 -0
- package/dist/react/context.d.ts +29 -0
- package/dist/react/context.d.ts.map +1 -0
- package/dist/react/context.js +18 -0
- package/dist/react/context.js.map +1 -0
- package/dist/react/data-grid.d.ts +79 -0
- package/dist/react/data-grid.d.ts.map +1 -0
- package/dist/react/data-grid.js +653 -0
- package/dist/react/data-grid.js.map +1 -0
- package/dist/react/detail-panel.d.ts +22 -0
- package/dist/react/detail-panel.d.ts.map +1 -0
- package/dist/react/detail-panel.js +242 -0
- package/dist/react/detail-panel.js.map +1 -0
- package/dist/react/export-menu.d.ts +11 -0
- package/dist/react/export-menu.d.ts.map +1 -0
- package/dist/react/export-menu.js +304 -0
- package/dist/react/export-menu.js.map +1 -0
- package/dist/react/find-bar.d.ts +11 -0
- package/dist/react/find-bar.d.ts.map +1 -0
- package/dist/react/find-bar.js +303 -0
- package/dist/react/find-bar.js.map +1 -0
- package/dist/react/format-form.d.ts +12 -0
- package/dist/react/format-form.d.ts.map +1 -0
- package/dist/react/format-form.js +863 -0
- package/dist/react/format-form.js.map +1 -0
- package/dist/react/formula-menu.d.ts +6 -0
- package/dist/react/formula-menu.d.ts.map +1 -0
- package/dist/react/formula-menu.js +343 -0
- package/dist/react/formula-menu.js.map +1 -0
- package/dist/react/grid-body.d.ts +33 -0
- package/dist/react/grid-body.d.ts.map +1 -0
- package/dist/react/grid-body.js +1389 -0
- package/dist/react/grid-body.js.map +1 -0
- package/dist/react/group-menu.d.ts +7 -0
- package/dist/react/group-menu.d.ts.map +1 -0
- package/dist/react/group-menu.js +508 -0
- package/dist/react/group-menu.js.map +1 -0
- package/dist/react/hooks.d.ts +33 -0
- package/dist/react/hooks.d.ts.map +1 -0
- package/dist/react/hooks.js +161 -0
- package/dist/react/hooks.js.map +1 -0
- package/dist/react/messages.d.ts +180 -0
- package/dist/react/messages.d.ts.map +1 -0
- package/dist/react/messages.js +414 -0
- package/dist/react/messages.js.map +1 -0
- package/dist/react/save.d.ts +9 -0
- package/dist/react/save.d.ts.map +1 -0
- package/dist/react/save.js +102 -0
- package/dist/react/save.js.map +1 -0
- package/dist/react/static-rows.d.ts +9 -0
- package/dist/react/static-rows.d.ts.map +1 -0
- package/dist/react/static-rows.js +176 -0
- package/dist/react/static-rows.js.map +1 -0
- package/dist/react/status-bar.d.ts +12 -0
- package/dist/react/status-bar.d.ts.map +1 -0
- package/dist/react/status-bar.js +413 -0
- package/dist/react/status-bar.js.map +1 -0
- package/dist/react/toolbar-popover.d.ts +14 -0
- package/dist/react/toolbar-popover.d.ts.map +1 -0
- package/dist/react/toolbar-popover.js +143 -0
- package/dist/react/toolbar-popover.js.map +1 -0
- package/dist/react/toolbar.d.ts +13 -0
- package/dist/react/toolbar.d.ts.map +1 -0
- package/dist/react/toolbar.js +344 -0
- package/dist/react/toolbar.js.map +1 -0
- package/dist/server.d.ts +22 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +45 -0
- package/dist/server.js.map +1 -0
- package/dist/styles.css +496 -316
- package/package.json +42 -17
- package/src/canvas/geometry.ts +197 -0
- package/src/canvas/grid-canvas.ts +1222 -0
- package/src/canvas/hooks.ts +61 -0
- package/src/canvas/keys.ts +96 -0
- package/src/canvas/layout.ts +77 -0
- package/src/canvas/scroll.ts +120 -0
- package/src/canvas/text.ts +155 -0
- package/src/{theme.ts → canvas/theme.ts} +14 -1
- package/src/core/cache.ts +247 -0
- package/src/core/checked.ts +64 -0
- package/src/core/client.ts +103 -0
- package/src/core/conditions.ts +89 -0
- package/src/core/evaluate.ts +221 -0
- package/src/core/filters.ts +268 -0
- package/src/core/format.ts +309 -0
- package/src/core/measures.ts +99 -0
- package/src/core/request-ids.ts +54 -0
- package/src/core/rows.ts +213 -0
- package/src/core/store.ts +1122 -0
- package/src/core/totals.ts +59 -0
- package/src/core/trace.ts +44 -0
- package/src/core/transports.ts +177 -0
- package/src/core/types.ts +169 -0
- package/src/core.ts +39 -0
- package/src/index.ts +24 -12
- package/src/react/accessible-rows.tsx +242 -0
- package/src/react/cell-editor.tsx +216 -0
- package/src/react/cell-menu.tsx +166 -0
- package/src/react/column-menu.tsx +619 -0
- package/src/react/columns-menu.tsx +116 -0
- package/src/react/conditions-menu.tsx +289 -0
- package/src/react/context.ts +33 -0
- package/src/react/data-grid.tsx +286 -0
- package/src/react/detail-panel.tsx +92 -0
- package/src/react/export-menu.tsx +112 -0
- package/src/react/find-bar.tsx +112 -0
- package/src/react/format-form.tsx +421 -0
- package/src/react/formula-menu.tsx +163 -0
- package/src/react/grid-body.tsx +744 -0
- package/src/react/group-menu.tsx +214 -0
- package/src/react/hooks.ts +104 -0
- package/src/react/messages.ts +556 -0
- package/src/react/save.ts +42 -0
- package/src/react/static-rows.tsx +59 -0
- package/src/react/status-bar.tsx +175 -0
- package/src/react/toolbar-popover.tsx +69 -0
- package/src/react/toolbar.tsx +152 -0
- package/src/server.ts +58 -0
- package/src/styles.css +496 -316
- package/dist/components/bars.d.ts +0 -14
- package/dist/components/bars.d.ts.map +0 -1
- package/dist/components/bars.js +0 -68
- package/dist/components/bars.js.map +0 -1
- package/dist/components/cell-inspector.d.ts +0 -11
- package/dist/components/cell-inspector.d.ts.map +0 -1
- package/dist/components/cell-inspector.js +0 -37
- package/dist/components/cell-inspector.js.map +0 -1
- package/dist/components/columns-panel.d.ts +0 -12
- package/dist/components/columns-panel.d.ts.map +0 -1
- package/dist/components/columns-panel.js +0 -11
- package/dist/components/columns-panel.js.map +0 -1
- package/dist/components/filter-panel.d.ts +0 -22
- package/dist/components/filter-panel.d.ts.map +0 -1
- package/dist/components/filter-panel.js +0 -169
- package/dist/components/filter-panel.js.map +0 -1
- package/dist/components/find-bar.d.ts +0 -9
- package/dist/components/find-bar.d.ts.map +0 -1
- package/dist/components/find-bar.js +0 -46
- package/dist/components/find-bar.js.map +0 -1
- package/dist/components/popover.d.ts +0 -38
- package/dist/components/popover.d.ts.map +0 -1
- package/dist/components/popover.js +0 -104
- package/dist/components/popover.js.map +0 -1
- package/dist/components/stats-panel.d.ts +0 -12
- package/dist/components/stats-panel.d.ts.map +0 -1
- package/dist/components/stats-panel.js +0 -40
- package/dist/components/stats-panel.js.map +0 -1
- package/dist/controller.d.ts +0 -227
- package/dist/controller.d.ts.map +0 -1
- package/dist/controller.js +0 -845
- package/dist/controller.js.map +0 -1
- package/dist/data-grid.d.ts +0 -51
- package/dist/data-grid.d.ts.map +0 -1
- package/dist/data-grid.js +0 -704
- package/dist/data-grid.js.map +0 -1
- package/dist/labels.d.ts +0 -9
- package/dist/labels.d.ts.map +0 -1
- package/dist/labels.js +0 -38
- package/dist/labels.js.map +0 -1
- package/dist/messages.d.ts +0 -99
- package/dist/messages.d.ts.map +0 -1
- package/dist/messages.js +0 -276
- package/dist/messages.js.map +0 -1
- package/dist/renderer.d.ts +0 -52
- package/dist/renderer.d.ts.map +0 -1
- package/dist/renderer.js +0 -522
- package/dist/renderer.js.map +0 -1
- package/dist/text.d.ts +0 -14
- package/dist/text.d.ts.map +0 -1
- package/dist/text.js +0 -63
- package/dist/text.js.map +0 -1
- package/dist/theme.d.ts.map +0 -1
- package/dist/theme.js +0 -54
- package/dist/theme.js.map +0 -1
- package/src/components/bars.tsx +0 -180
- package/src/components/cell-inspector.tsx +0 -70
- package/src/components/columns-panel.tsx +0 -59
- package/src/components/filter-panel.tsx +0 -293
- package/src/components/find-bar.tsx +0 -104
- package/src/components/popover.tsx +0 -194
- package/src/components/stats-panel.tsx +0 -153
- package/src/controller.ts +0 -945
- package/src/data-grid.tsx +0 -1035
- package/src/labels.ts +0 -46
- package/src/messages.ts +0 -390
- package/src/renderer.ts +0 -535
- package/src/text.ts +0 -55
package/package.json
CHANGED
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vastgrid",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A canvas data grid for React that opens
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "A canvas data grid for React that opens tables of any size like a spreadsheet: sort, filter, group, pivot, edit, undo and export, driven by a typed document, session and commands.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react",
|
|
7
|
+
"data grid",
|
|
8
|
+
"datagrid",
|
|
9
|
+
"table",
|
|
10
|
+
"spreadsheet",
|
|
11
|
+
"canvas",
|
|
12
|
+
"virtual scroll",
|
|
13
|
+
"csv",
|
|
14
|
+
"parquet",
|
|
15
|
+
"excel"
|
|
16
|
+
],
|
|
5
17
|
"license": "MIT",
|
|
6
18
|
"author": "yhay81",
|
|
7
19
|
"repository": {
|
|
8
20
|
"type": "git",
|
|
9
21
|
"url": "git+https://github.com/yhay81/vastgrid.git",
|
|
10
|
-
"directory": "packages/
|
|
22
|
+
"directory": "packages/grid"
|
|
11
23
|
},
|
|
12
24
|
"homepage": "https://vastgrid.yhay81.com",
|
|
13
25
|
"bugs": "https://github.com/yhay81/vastgrid/issues",
|
|
@@ -21,6 +33,16 @@
|
|
|
21
33
|
"types": "./dist/index.d.ts",
|
|
22
34
|
"default": "./dist/index.js"
|
|
23
35
|
},
|
|
36
|
+
"./core": {
|
|
37
|
+
"vastgrid-source": "./src/core.ts",
|
|
38
|
+
"types": "./dist/core.d.ts",
|
|
39
|
+
"default": "./dist/core.js"
|
|
40
|
+
},
|
|
41
|
+
"./server": {
|
|
42
|
+
"vastgrid-source": "./src/server.ts",
|
|
43
|
+
"types": "./dist/server.d.ts",
|
|
44
|
+
"default": "./dist/server.js"
|
|
45
|
+
},
|
|
24
46
|
"./styles.css": {
|
|
25
47
|
"vastgrid-source": "./src/styles.css",
|
|
26
48
|
"default": "./dist/styles.css"
|
|
@@ -30,25 +52,28 @@
|
|
|
30
52
|
"dist",
|
|
31
53
|
"src"
|
|
32
54
|
],
|
|
33
|
-
"keywords": [
|
|
34
|
-
"react",
|
|
35
|
-
"datagrid",
|
|
36
|
-
"data-grid",
|
|
37
|
-
"canvas",
|
|
38
|
-
"spreadsheet",
|
|
39
|
-
"csv",
|
|
40
|
-
"parquet",
|
|
41
|
-
"virtual-scroll",
|
|
42
|
-
"big-data"
|
|
43
|
-
],
|
|
44
55
|
"scripts": {
|
|
45
56
|
"build": "tsc -b"
|
|
46
57
|
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">=20"
|
|
60
|
+
},
|
|
47
61
|
"dependencies": {
|
|
48
|
-
"vastgrid-
|
|
62
|
+
"vastgrid-spec": "0.2.1"
|
|
49
63
|
},
|
|
50
64
|
"peerDependencies": {
|
|
51
|
-
"react": "
|
|
52
|
-
"react-dom": "
|
|
65
|
+
"react": "^19.3.0",
|
|
66
|
+
"react-dom": "^19.3.0"
|
|
67
|
+
},
|
|
68
|
+
"peerDependenciesMeta": {
|
|
69
|
+
"react": {
|
|
70
|
+
"optional": true
|
|
71
|
+
},
|
|
72
|
+
"react-dom": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"devDependencies": {
|
|
77
|
+
"vastgrid-js": "0.2.1"
|
|
53
78
|
}
|
|
54
79
|
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { ColumnLayout } from "./layout.js";
|
|
2
|
+
import { ScrollAxis } from "./scroll.js";
|
|
3
|
+
|
|
4
|
+
/** The width of the check boxes at the left of the gutter (§5.2.1 of the specification). */
|
|
5
|
+
export const CHECK_WIDTH = 24;
|
|
6
|
+
/** The width of the button at the right of a header that opens the column menu. */
|
|
7
|
+
export const MENU_WIDTH = 16;
|
|
8
|
+
|
|
9
|
+
/** What is under a point of the grid. */
|
|
10
|
+
export interface Hit {
|
|
11
|
+
area: "cell" | "header" | "group" | "gutter" | "corner" | "none";
|
|
12
|
+
/** A view position, for cells and the gutter; clamped to the rows. */
|
|
13
|
+
row: number;
|
|
14
|
+
/** A display position, for cells and headers. */
|
|
15
|
+
column: number;
|
|
16
|
+
/** Within a few pixels of the right edge of a header, where dragging resizes the column. */
|
|
17
|
+
edge: boolean;
|
|
18
|
+
/** On the button of a header that opens the column menu. */
|
|
19
|
+
menu: boolean;
|
|
20
|
+
/** On the check box of a row (the gutter) or of every row (the corner). */
|
|
21
|
+
check?: boolean;
|
|
22
|
+
/** For a group header: its row of groups, from the top. */
|
|
23
|
+
level?: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Where the parts of the grid are on the canvas (§6 of react.md): the rows of groups and the column names at the
|
|
28
|
+
* top, the gutter at the left, the rows, the totals row at the bottom, and the columns pinned at each side with those
|
|
29
|
+
* that scroll between them. The canvas lays it out and draws with it; React places what it puts over the canvas
|
|
30
|
+
* with it.
|
|
31
|
+
*/
|
|
32
|
+
export class Geometry {
|
|
33
|
+
readonly scrollX = new ScrollAxis();
|
|
34
|
+
readonly scrollY = new ScrollAxis();
|
|
35
|
+
width = 0;
|
|
36
|
+
height = 0;
|
|
37
|
+
rowHeight = 24;
|
|
38
|
+
headerHeight = 32;
|
|
39
|
+
/** The height of the row of column names; `headerHeight` adds the rows of groups above it. */
|
|
40
|
+
nameHeight = 32;
|
|
41
|
+
groupHeight = 24;
|
|
42
|
+
/** Rows of groups above the column names. */
|
|
43
|
+
groupRows = 0;
|
|
44
|
+
/** By display position: its group in each row of groups (an id and a name), or null. */
|
|
45
|
+
groupPaths: ({ id: number; name: string } | null)[][] = [];
|
|
46
|
+
gutterWidth = 48;
|
|
47
|
+
/** Whether the gutter has a check box for each row. */
|
|
48
|
+
checkboxes = false;
|
|
49
|
+
/** The height of the totals row at the bottom (§5.1 of the specification), 0 without totals. */
|
|
50
|
+
footer = 0;
|
|
51
|
+
/** The rows of the view on screen. */
|
|
52
|
+
rowCount = 0;
|
|
53
|
+
/** The widths of the displayed columns, by display position. */
|
|
54
|
+
layout = new ColumnLayout([]);
|
|
55
|
+
/** How many displayed columns are pinned at the left and at the right. */
|
|
56
|
+
frozenLeft = 0;
|
|
57
|
+
frozenRight = 0;
|
|
58
|
+
|
|
59
|
+
/** The top of the row of column names: the rows of groups are above it. */
|
|
60
|
+
get groupTop() {
|
|
61
|
+
return this.groupRows * this.groupHeight;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** The first row on screen. */
|
|
65
|
+
topRow() {
|
|
66
|
+
return Math.max(0, Math.floor(this.scrollY.position / this.rowHeight));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Rows on screen `[first, last)`. */
|
|
70
|
+
visibleRows(): [number, number] {
|
|
71
|
+
const rowCount = this.rowCount;
|
|
72
|
+
const body = Math.max(0, this.bottom - this.headerHeight);
|
|
73
|
+
const first = Math.min(rowCount, this.topRow());
|
|
74
|
+
const last = Math.min(rowCount, Math.ceil((this.scrollY.position + body) / this.rowHeight));
|
|
75
|
+
return [first, Math.max(first, last)];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** The bottom of the rows: the top of the totals row. */
|
|
79
|
+
get bottom() {
|
|
80
|
+
return this.height - this.footer;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get frozenWidth() {
|
|
84
|
+
return this.layout.left(this.frozenLeft);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get rightStart() {
|
|
88
|
+
return this.layout.count - this.frozenRight;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get frozenRightWidth() {
|
|
92
|
+
return this.layout.total - this.layout.left(this.rightStart);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Display positions `[first, last]` of the scrolling columns on screen, or `[0, -1]`. */
|
|
96
|
+
visibleScrollColumns(): [number, number] {
|
|
97
|
+
const rightStart = this.rightStart;
|
|
98
|
+
if (rightStart <= this.frozenLeft) return [0, -1];
|
|
99
|
+
const start = this.frozenWidth + this.scrollX.position;
|
|
100
|
+
const end = Math.min(
|
|
101
|
+
this.scrollX.position + this.width - this.gutterWidth - this.frozenRightWidth,
|
|
102
|
+
this.layout.left(rightStart),
|
|
103
|
+
);
|
|
104
|
+
if (start >= this.layout.left(rightStart) || end <= start) return [0, -1];
|
|
105
|
+
const first = Math.max(this.frozenLeft, this.layout.indexAt(start));
|
|
106
|
+
const last = Math.min(rightStart - 1, this.layout.indexAt(Math.max(start, end - 0.001)));
|
|
107
|
+
return [first, last];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** The x of a displayed column's left edge on the canvas. */
|
|
111
|
+
columnX(column: number) {
|
|
112
|
+
if (column < this.frozenLeft) return this.gutterWidth + this.layout.left(column);
|
|
113
|
+
if (column >= this.rightStart) {
|
|
114
|
+
return this.width - this.frozenRightWidth + this.layout.left(column) - this.layout.left(this.rightStart);
|
|
115
|
+
}
|
|
116
|
+
return this.gutterWidth + this.layout.left(column) - this.scrollX.position;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
rowY(row: number) {
|
|
120
|
+
return this.headerHeight + row * this.rowHeight - this.scrollY.position;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** The width of a displayed column. */
|
|
124
|
+
columnWidth(column: number) {
|
|
125
|
+
return this.layout.width(column);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Where a cell is, in the body's coordinates, and whether it is on screen: outside the header and the gutter,
|
|
130
|
+
* and for a scrolling column, between the columns pinned at each side.
|
|
131
|
+
*/
|
|
132
|
+
cellBox(row: number, column: number): { left: number; top: number; width: number; height: number; shown: boolean } {
|
|
133
|
+
const left = this.columnX(column);
|
|
134
|
+
const top = this.rowY(row);
|
|
135
|
+
const width = this.layout.width(column);
|
|
136
|
+
const height = this.rowHeight;
|
|
137
|
+
const scrolls = column >= this.frozenLeft && column < this.rightStart;
|
|
138
|
+
const from = scrolls ? this.gutterWidth + this.frozenWidth : this.gutterWidth;
|
|
139
|
+
const to = scrolls ? this.width - this.frozenRightWidth : this.width;
|
|
140
|
+
const shown = top + height > this.headerHeight && top < this.bottom && left + width > from && left < to;
|
|
141
|
+
return { left, top, width, height, shown };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** What is at a point given in the scroller's client coordinates. */
|
|
145
|
+
hit(x: number, y: number): Hit {
|
|
146
|
+
const rowCount = this.rowCount;
|
|
147
|
+
const none: Hit = { area: "none", row: 0, column: 0, edge: false, menu: false };
|
|
148
|
+
if (x < 0 || y < 0 || x > this.width || y > this.height || y >= this.bottom) return none;
|
|
149
|
+
const row = Math.max(
|
|
150
|
+
0,
|
|
151
|
+
Math.min(rowCount - 1, Math.floor((y - this.headerHeight + this.scrollY.position) / this.rowHeight)),
|
|
152
|
+
);
|
|
153
|
+
if (x < this.gutterWidth) {
|
|
154
|
+
return {
|
|
155
|
+
area: y < this.headerHeight ? "corner" : "gutter",
|
|
156
|
+
row,
|
|
157
|
+
column: 0,
|
|
158
|
+
edge: false,
|
|
159
|
+
menu: false,
|
|
160
|
+
check: this.checkboxes && x < CHECK_WIDTH,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const column = this.columnAt(x);
|
|
164
|
+
if (column < 0) return none;
|
|
165
|
+
const right = this.columnX(column) + this.layout.width(column);
|
|
166
|
+
const edge = Math.abs(x - right) <= 4;
|
|
167
|
+
if (y < this.groupTop) {
|
|
168
|
+
const level = Math.floor(y / this.groupHeight);
|
|
169
|
+
return {
|
|
170
|
+
area: this.groupPaths[column]?.[level] ? "group" : "none",
|
|
171
|
+
row: 0,
|
|
172
|
+
column,
|
|
173
|
+
edge: false,
|
|
174
|
+
menu: false,
|
|
175
|
+
level,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
if (y < this.headerHeight) {
|
|
179
|
+
return { area: "header", row: 0, column, edge, menu: !edge && x >= right - MENU_WIDTH - 4 };
|
|
180
|
+
}
|
|
181
|
+
if (rowCount === 0 || y - this.headerHeight + this.scrollY.position >= rowCount * this.rowHeight) return none;
|
|
182
|
+
return { area: "cell", row, column, edge: false, menu: false };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** The display position of the column at an x of the canvas; -1 when there is none. */
|
|
186
|
+
columnAt(x: number) {
|
|
187
|
+
if (this.layout.count === 0) return -1;
|
|
188
|
+
const rightX = this.width - this.frozenRightWidth;
|
|
189
|
+
if (this.frozenRight > 0 && x >= rightX) {
|
|
190
|
+
return Math.max(this.rightStart, this.layout.indexAt(this.layout.left(this.rightStart) + x - rightX));
|
|
191
|
+
}
|
|
192
|
+
const local = x - this.gutterWidth;
|
|
193
|
+
if (this.frozenLeft > 0 && local < this.frozenWidth) return this.layout.indexAt(local);
|
|
194
|
+
const column = this.layout.indexAt(local + this.scrollX.position);
|
|
195
|
+
return Math.min(column, this.rightStart - 1);
|
|
196
|
+
}
|
|
197
|
+
}
|