@perspective-dev/viewer-datagrid 4.0.0 → 4.1.0

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.
Files changed (99) hide show
  1. package/dist/cdn/perspective-viewer-datagrid.js +4 -17
  2. package/dist/cdn/perspective-viewer-datagrid.js.map +4 -4
  3. package/dist/css/perspective-viewer-datagrid.css +1 -1
  4. package/dist/esm/color_utils.d.ts +9 -0
  5. package/dist/esm/custom_elements/datagrid.d.ts +52 -0
  6. package/dist/esm/custom_elements/toolbar.d.ts +10 -0
  7. package/dist/esm/data_listener/format_cell.d.ts +8 -0
  8. package/dist/esm/data_listener/format_tree_header.d.ts +13 -0
  9. package/dist/esm/data_listener/formatter_cache.d.ts +16 -0
  10. package/dist/esm/data_listener/index.d.ts +10 -0
  11. package/dist/esm/event_handlers/click/edit_click.d.ts +3 -0
  12. package/dist/esm/event_handlers/click.d.ts +7 -0
  13. package/dist/esm/event_handlers/deselect_all.d.ts +5 -0
  14. package/dist/esm/event_handlers/dispatch_click.d.ts +3 -0
  15. package/dist/esm/event_handlers/expand_collapse.d.ts +2 -0
  16. package/dist/esm/event_handlers/focus.d.ts +5 -0
  17. package/dist/esm/event_handlers/header_click.d.ts +3 -0
  18. package/dist/esm/event_handlers/keydown/edit_keydown.d.ts +4 -0
  19. package/dist/esm/event_handlers/row_select_click.d.ts +4 -0
  20. package/dist/esm/event_handlers/select_region.d.ts +9 -0
  21. package/dist/esm/event_handlers/sort.d.ts +7 -0
  22. package/dist/esm/get_cell_config.d.ts +8 -0
  23. package/dist/esm/index.d.ts +6 -0
  24. package/dist/esm/model/column_overrides.d.ts +23 -0
  25. package/dist/esm/model/create.d.ts +3 -0
  26. package/dist/esm/model/index.d.ts +4 -0
  27. package/dist/esm/model/toolbar.d.ts +4 -0
  28. package/dist/esm/perspective-viewer-datagrid.js +3 -3
  29. package/dist/esm/perspective-viewer-datagrid.js.map +4 -4
  30. package/dist/esm/plugin/activate.d.ts +6 -0
  31. package/dist/esm/plugin/column_style_controls.d.ts +28 -0
  32. package/dist/esm/plugin/draw.d.ts +7 -0
  33. package/dist/esm/plugin/restore.d.ts +10 -0
  34. package/dist/esm/plugin/save.d.ts +2 -0
  35. package/dist/esm/style_handlers/body.d.ts +7 -0
  36. package/dist/esm/style_handlers/column_header.d.ts +13 -0
  37. package/dist/esm/style_handlers/consolidated.d.ts +57 -0
  38. package/dist/esm/style_handlers/editable.d.ts +7 -0
  39. package/dist/esm/style_handlers/focus.d.ts +16 -0
  40. package/dist/esm/style_handlers/group_header.d.ts +7 -0
  41. package/dist/esm/style_handlers/table_cell/boolean.d.ts +7 -0
  42. package/dist/esm/style_handlers/table_cell/cell_flash.d.ts +3 -0
  43. package/dist/esm/style_handlers/table_cell/datetime.d.ts +7 -0
  44. package/dist/esm/style_handlers/table_cell/numeric.d.ts +15 -0
  45. package/dist/esm/style_handlers/table_cell/row_header.d.ts +4 -0
  46. package/dist/esm/style_handlers/table_cell/string.d.ts +11 -0
  47. package/dist/esm/style_handlers/types.d.ts +20 -0
  48. package/dist/esm/types.d.ts +193 -0
  49. package/package.json +10 -5
  50. package/src/less/mitered-headers.less +65 -0
  51. package/src/less/pro.less +196 -0
  52. package/src/less/regular_table.less +509 -0
  53. package/src/less/row-hover.less +88 -0
  54. package/{index.d.ts → src/less/scrollbar.less} +18 -19
  55. package/src/less/sub-cell-scroll.less +82 -0
  56. package/src/less/toolbar.less +201 -0
  57. package/src/ts/color_utils.ts +70 -0
  58. package/src/ts/custom_elements/datagrid.ts +250 -0
  59. package/src/ts/custom_elements/toolbar.ts +75 -0
  60. package/src/ts/data_listener/format_cell.ts +84 -0
  61. package/src/ts/data_listener/format_tree_header.ts +82 -0
  62. package/src/ts/data_listener/formatter_cache.ts +191 -0
  63. package/src/ts/data_listener/index.ts +242 -0
  64. package/src/ts/event_handlers/click/edit_click.ts +73 -0
  65. package/src/ts/event_handlers/click.ts +92 -0
  66. package/src/ts/event_handlers/deselect_all.ts +28 -0
  67. package/src/ts/event_handlers/dispatch_click.ts +44 -0
  68. package/src/ts/event_handlers/expand_collapse.ts +44 -0
  69. package/src/ts/event_handlers/focus.ts +63 -0
  70. package/src/ts/event_handlers/header_click.ts +85 -0
  71. package/src/ts/event_handlers/keydown/edit_keydown.ts +213 -0
  72. package/src/ts/event_handlers/row_select_click.ts +87 -0
  73. package/src/ts/event_handlers/select_region.ts +427 -0
  74. package/src/ts/event_handlers/sort.ts +118 -0
  75. package/src/ts/get_cell_config.ts +68 -0
  76. package/src/ts/index.ts +49 -0
  77. package/src/ts/model/column_overrides.ts +112 -0
  78. package/src/ts/model/create.ts +247 -0
  79. package/src/ts/model/index.ts +19 -0
  80. package/src/ts/model/toolbar.ts +64 -0
  81. package/src/ts/plugin/activate.ts +235 -0
  82. package/src/ts/plugin/column_style_controls.ts +76 -0
  83. package/src/ts/plugin/draw.ts +69 -0
  84. package/src/ts/plugin/restore.ts +110 -0
  85. package/src/ts/plugin/save.ts +45 -0
  86. package/src/ts/style_handlers/body.ts +228 -0
  87. package/src/ts/style_handlers/column_header.ts +183 -0
  88. package/src/ts/style_handlers/consolidated.ts +223 -0
  89. package/src/ts/style_handlers/editable.ts +94 -0
  90. package/src/ts/style_handlers/focus.ts +106 -0
  91. package/src/ts/style_handlers/group_header.ts +78 -0
  92. package/src/ts/style_handlers/table_cell/boolean.ts +39 -0
  93. package/src/ts/style_handlers/table_cell/cell_flash.ts +75 -0
  94. package/src/ts/style_handlers/table_cell/datetime.ts +64 -0
  95. package/src/ts/style_handlers/table_cell/numeric.ts +186 -0
  96. package/src/ts/style_handlers/table_cell/row_header.ts +53 -0
  97. package/src/ts/style_handlers/table_cell/string.ts +102 -0
  98. package/src/ts/style_handlers/types.ts +41 -0
  99. package/src/ts/types.ts +279 -0
@@ -0,0 +1,85 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import { sortHandler } from "./sort.js";
14
+ import { expandCollapseHandler } from "./expand_collapse.js";
15
+ import type {
16
+ RegularTable,
17
+ DatagridModel,
18
+ PerspectiveViewerElement,
19
+ } from "../types.js";
20
+
21
+ export async function mousedown_listener(
22
+ this: DatagridModel,
23
+ regularTable: RegularTable,
24
+ viewer: PerspectiveViewerElement,
25
+ event: MouseEvent,
26
+ ): Promise<void> {
27
+ if (event.which !== 1) {
28
+ return;
29
+ }
30
+
31
+ let target = event.target as HTMLElement | null;
32
+ if (target?.tagName === "A") {
33
+ return;
34
+ }
35
+
36
+ while (target && target.tagName !== "TD" && target.tagName !== "TH") {
37
+ target = target.parentElement;
38
+ if (!target || !regularTable.contains(target)) {
39
+ return;
40
+ }
41
+ }
42
+
43
+ if (!target) return;
44
+
45
+ if (target.classList.contains("psp-tree-label")) {
46
+ expandCollapseHandler.call(this, regularTable, event);
47
+ return;
48
+ }
49
+
50
+ if (target.classList.contains("psp-menu-enabled")) {
51
+ const meta = regularTable.getMeta(target);
52
+ const column_name = meta?.column_header?.[this._config.split_by.length];
53
+ await viewer.toggleColumnSettings(column_name);
54
+ } else if (target.classList.contains("psp-sort-enabled")) {
55
+ sortHandler.call(this, regularTable, viewer, event, target);
56
+ }
57
+ }
58
+
59
+ export function click_listener(
60
+ regularTable: RegularTable,
61
+ event: MouseEvent,
62
+ ): void {
63
+ if (event.which !== 1) {
64
+ return;
65
+ }
66
+
67
+ let target = event.target as HTMLElement | null;
68
+ while (target && target.tagName !== "TD" && target.tagName !== "TH") {
69
+ target = target.parentElement;
70
+ if (!target || !regularTable.contains(target)) {
71
+ return;
72
+ }
73
+ }
74
+
75
+ if (!target) return;
76
+
77
+ if (target.classList.contains("psp-tree-label") && event.offsetX < 26) {
78
+ event.stopImmediatePropagation();
79
+ } else if (
80
+ target.classList.contains("psp-header-leaf") &&
81
+ !target.classList.contains("psp-header-corner")
82
+ ) {
83
+ event.stopImmediatePropagation();
84
+ }
85
+ }
@@ -0,0 +1,213 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import { focusSelectedCell } from "../../style_handlers/focus.js";
14
+ import type {
15
+ RegularTable,
16
+ DatagridModel,
17
+ PerspectiveViewerElement,
18
+ SelectedPosition,
19
+ } from "../../types.js";
20
+
21
+ type SelectedPositionMap = Map<RegularTable, SelectedPosition>;
22
+
23
+ type AsyncFunction<T extends unknown[], R> = (
24
+ this: DatagridModel,
25
+ ...args: T
26
+ ) => Promise<R>;
27
+
28
+ function lock<T extends unknown[], R>(
29
+ body: AsyncFunction<T, R>,
30
+ ): AsyncFunction<T, R | undefined> {
31
+ let lockPromise: Promise<void> | undefined;
32
+ return async function (
33
+ this: DatagridModel,
34
+ ...args: T
35
+ ): Promise<R | undefined> {
36
+ if (lockPromise) {
37
+ await lockPromise;
38
+ return;
39
+ }
40
+
41
+ let resolve: () => void;
42
+ lockPromise = new Promise((x) => (resolve = x));
43
+ const result = await body.apply(this, args);
44
+ lockPromise = undefined;
45
+ resolve!();
46
+ return result;
47
+ };
48
+ }
49
+
50
+ interface ContentEditableElement extends HTMLElement {
51
+ isContentEditable: boolean;
52
+ selectionStart?: number;
53
+ }
54
+
55
+ function getPos(this: ContentEditableElement): number {
56
+ if (this.isContentEditable) {
57
+ const _range = (this.getRootNode() as Document)
58
+ .getSelection()
59
+ ?.getRangeAt(0);
60
+ if (!_range) return 0;
61
+ const range = _range.cloneRange();
62
+ range.selectNodeContents(this);
63
+ range.setEnd(_range.endContainer, _range.endOffset);
64
+ return range.toString().length;
65
+ } else {
66
+ return this.selectionStart || 0;
67
+ }
68
+ }
69
+
70
+ const moveSelection = lock(async function (
71
+ this: DatagridModel,
72
+ table: RegularTable,
73
+ selected_position_map: SelectedPositionMap,
74
+ active_cell: HTMLElement,
75
+ dx: number,
76
+ dy: number,
77
+ ): Promise<void> {
78
+ const meta = table.getMeta(active_cell);
79
+ if (!meta) return;
80
+ const num_columns = this._column_paths.length;
81
+ const num_rows = this._num_rows;
82
+ const selected_position = selected_position_map.get(table);
83
+ if (!selected_position) {
84
+ return;
85
+ }
86
+
87
+ if (meta.x + dx < num_columns && 0 <= meta.x + dx) {
88
+ selected_position.x = meta.x + dx;
89
+ }
90
+
91
+ if (meta.y + dy < num_rows && 0 <= meta.y + dy) {
92
+ selected_position.y = meta.y + dy;
93
+ }
94
+
95
+ const xmin = Math.max(meta.x0 - 10, 0);
96
+ const xmax = Math.min(meta.x0 + 10, num_columns);
97
+ const ymin = Math.max(meta.y0 - 5, 0);
98
+ const ymax = Math.min(meta.y0 + 10, num_rows);
99
+ let x = meta.x0 + dx,
100
+ y = meta.y0 + dy;
101
+ while (
102
+ !focusSelectedCell(table, selected_position_map) &&
103
+ x >= xmin &&
104
+ x < xmax &&
105
+ y >= ymin &&
106
+ y < ymax
107
+ ) {
108
+ await table.scrollToCell(x, y);
109
+ selected_position_map.set(table, selected_position);
110
+ x += dx;
111
+ y += dy;
112
+ }
113
+ });
114
+
115
+ function isLastCell(
116
+ model: DatagridModel,
117
+ table: RegularTable,
118
+ target: HTMLElement,
119
+ ): boolean {
120
+ const meta = table.getMeta(target);
121
+ return meta !== undefined && meta.y === model._num_rows - 1;
122
+ }
123
+
124
+ export function keydownListener(
125
+ this: DatagridModel,
126
+ table: RegularTable,
127
+ _viewer: PerspectiveViewerElement,
128
+ selected_position_map: SelectedPositionMap,
129
+ event: KeyboardEvent,
130
+ ): void {
131
+ const target = (table.getRootNode() as Document)
132
+ .activeElement as HTMLElement;
133
+ (event.target as HTMLElement).classList.remove("psp-error");
134
+ switch (event.key) {
135
+ case "Enter":
136
+ event.preventDefault();
137
+ if (isLastCell(this, table, target)) {
138
+ target.blur();
139
+ selected_position_map.delete(table);
140
+ } else if (event.shiftKey) {
141
+ moveSelection.call(
142
+ this,
143
+ table,
144
+ selected_position_map,
145
+ target,
146
+ 0,
147
+ -1,
148
+ );
149
+ } else {
150
+ moveSelection.call(
151
+ this,
152
+ table,
153
+ selected_position_map,
154
+ target,
155
+ 0,
156
+ 1,
157
+ );
158
+ }
159
+ break;
160
+ case "ArrowLeft":
161
+ if (getPos.call(target as ContentEditableElement) === 0) {
162
+ event.preventDefault();
163
+ moveSelection.call(
164
+ this,
165
+ table,
166
+ selected_position_map,
167
+ target,
168
+ -1,
169
+ 0,
170
+ );
171
+ }
172
+ break;
173
+ case "ArrowUp":
174
+ event.preventDefault();
175
+ moveSelection.call(
176
+ this,
177
+ table,
178
+ selected_position_map,
179
+ target,
180
+ 0,
181
+ -1,
182
+ );
183
+ break;
184
+ case "ArrowRight":
185
+ if (
186
+ getPos.call(target as ContentEditableElement) ===
187
+ (target.textContent?.length || 0)
188
+ ) {
189
+ event.preventDefault();
190
+ moveSelection.call(
191
+ this,
192
+ table,
193
+ selected_position_map,
194
+ target,
195
+ 1,
196
+ 0,
197
+ );
198
+ }
199
+ break;
200
+ case "ArrowDown":
201
+ event.preventDefault();
202
+ moveSelection.call(
203
+ this,
204
+ table,
205
+ selected_position_map,
206
+ target,
207
+ 0,
208
+ 1,
209
+ );
210
+ break;
211
+ default:
212
+ }
213
+ }
@@ -0,0 +1,87 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import getCellConfig from "../get_cell_config.js";
14
+ import type {
15
+ RegularTable,
16
+ DatagridModel,
17
+ PerspectiveViewerElement,
18
+ HandledMouseEvent,
19
+ PerspectiveSelectDetail,
20
+ } from "../types.js";
21
+
22
+ type SelectedRowsMap = Map<RegularTable, unknown[]>;
23
+
24
+ export async function selectionListener(
25
+ this: DatagridModel,
26
+ regularTable: RegularTable,
27
+ viewer: PerspectiveViewerElement,
28
+ selected_rows_map: SelectedRowsMap,
29
+ event: HandledMouseEvent,
30
+ ): Promise<void> {
31
+ const meta = regularTable.getMeta(event.target as Element);
32
+ if (!viewer.hasAttribute("selectable")) return;
33
+ if (event.handled) return;
34
+ if (event.shiftKey) return;
35
+ if (event.button !== 0) {
36
+ return;
37
+ }
38
+ event.stopImmediatePropagation();
39
+
40
+ if (!meta) {
41
+ return;
42
+ }
43
+
44
+ const id = this._ids?.[meta.y - meta.y0];
45
+ if (meta && meta.y >= 0) {
46
+ const selected = selected_rows_map.get(regularTable);
47
+ const key_match =
48
+ !!selected &&
49
+ selected.reduce<boolean>((agg, x, i) => agg && x === id[i], true);
50
+
51
+ const is_deselect =
52
+ !!selected && id.length === selected.length && key_match;
53
+
54
+ let detail: PerspectiveSelectDetail = {
55
+ selected: !is_deselect,
56
+ row: {},
57
+ config: { filter: [] },
58
+ };
59
+ const { row, column_names, config } = await getCellConfig(
60
+ this,
61
+ meta.y,
62
+ meta.x,
63
+ );
64
+
65
+ if (is_deselect) {
66
+ selected_rows_map.delete(regularTable);
67
+ detail = {
68
+ ...detail,
69
+ row,
70
+ config: { filter: structuredClone(this._config.filter) },
71
+ };
72
+ } else {
73
+ selected_rows_map.set(regularTable, id);
74
+ detail = { ...detail, row, column_names, config };
75
+ }
76
+
77
+ await regularTable.draw({ preserve_width: true });
78
+ event.handled = true;
79
+ viewer.dispatchEvent(
80
+ new CustomEvent<PerspectiveSelectDetail>("perspective-select", {
81
+ bubbles: true,
82
+ composed: true,
83
+ detail,
84
+ }),
85
+ );
86
+ }
87
+ }