@perspective-dev/viewer-datagrid 4.4.0 → 4.5.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.
- package/dist/cdn/perspective-viewer-datagrid.js +4 -22
- package/dist/cdn/perspective-viewer-datagrid.js.map +4 -4
- package/dist/css/perspective-viewer-datagrid-toolbar.css +1 -1
- package/dist/css/perspective-viewer-datagrid.css +1 -1
- package/dist/esm/color_utils.d.ts +22 -0
- package/dist/esm/custom_elements/datagrid.d.ts +16 -21
- package/dist/esm/data_listener/format_cell.d.ts +1 -1
- package/dist/esm/data_listener/formatter_cache.d.ts +1 -1
- package/dist/esm/data_listener/index.d.ts +3 -2
- package/dist/esm/event_handlers/click/edit_click.d.ts +3 -2
- package/dist/esm/event_handlers/click.d.ts +4 -6
- package/dist/esm/event_handlers/dispatch_click.d.ts +3 -2
- package/dist/esm/event_handlers/expand_collapse.d.ts +1 -1
- package/dist/esm/event_handlers/focus.d.ts +4 -5
- package/dist/esm/event_handlers/header_click.d.ts +5 -3
- package/dist/esm/event_handlers/keydown/edit_keydown.d.ts +3 -4
- package/dist/esm/event_handlers/select_region.d.ts +3 -1
- package/dist/esm/event_handlers/sort.d.ts +8 -7
- package/dist/esm/model/create.d.ts +1 -1
- package/dist/esm/model/meta_columns.d.ts +1 -0
- package/dist/esm/perspective-viewer-datagrid.js +3 -3
- package/dist/esm/perspective-viewer-datagrid.js.map +4 -4
- package/dist/esm/plugin/activate.d.ts +1 -1
- package/dist/esm/plugin/column_config_schema.d.ts +31 -0
- package/dist/esm/style_handlers/body.d.ts +3 -3
- package/dist/esm/style_handlers/column_header.d.ts +4 -3
- package/dist/esm/style_handlers/consolidated.d.ts +3 -47
- package/dist/esm/style_handlers/editable.d.ts +3 -2
- package/dist/esm/style_handlers/focus.d.ts +4 -4
- package/dist/esm/style_handlers/group_header.d.ts +1 -1
- package/dist/esm/style_handlers/table_cell/boolean.d.ts +1 -1
- package/dist/esm/style_handlers/table_cell/cell_flash.d.ts +1 -1
- package/dist/esm/style_handlers/table_cell/datetime.d.ts +1 -1
- package/dist/esm/style_handlers/table_cell/numeric.d.ts +1 -1
- package/dist/esm/style_handlers/table_cell/row_header.d.ts +1 -1
- package/dist/esm/style_handlers/table_cell/string.d.ts +1 -1
- package/dist/esm/style_handlers/types.d.ts +0 -4
- package/dist/esm/types.d.ts +10 -17
- package/package.json +2 -4
- package/src/css/regular_table.css +87 -31
- package/src/css/row-hover.css +20 -7
- package/src/css/toolbar.css +11 -0
- package/src/ts/color_utils.ts +181 -16
- package/src/ts/custom_elements/datagrid.ts +70 -56
- package/src/ts/custom_elements/toolbar.ts +4 -5
- package/src/ts/data_listener/format_cell.ts +28 -9
- package/src/ts/data_listener/format_tree_header.ts +2 -2
- package/src/ts/data_listener/formatter_cache.ts +9 -96
- package/src/ts/data_listener/index.ts +13 -11
- package/src/ts/event_handlers/click/edit_click.ts +10 -6
- package/src/ts/event_handlers/click.ts +39 -68
- package/src/ts/event_handlers/dispatch_click.ts +27 -25
- package/src/ts/event_handlers/expand_collapse.ts +11 -8
- package/src/ts/event_handlers/focus.ts +38 -35
- package/src/ts/event_handlers/header_click.ts +107 -62
- package/src/ts/event_handlers/keydown/edit_keydown.ts +60 -54
- package/src/ts/event_handlers/select_region.ts +153 -131
- package/src/ts/event_handlers/sort.ts +20 -25
- package/src/ts/get_cell_config.ts +10 -3
- package/src/ts/model/column_overrides.ts +16 -9
- package/src/ts/model/create.ts +68 -55
- package/src/ts/{event_handlers/deselect_all.ts → model/meta_columns.ts} +33 -14
- package/src/ts/model/toolbar.ts +33 -8
- package/src/ts/plugin/activate.ts +122 -92
- package/src/ts/plugin/column_config_schema.ts +187 -0
- package/src/ts/plugin/draw.ts +1 -0
- package/src/ts/plugin/restore.ts +6 -2
- package/src/ts/plugin/save.ts +2 -5
- package/src/ts/style_handlers/body.ts +48 -51
- package/src/ts/style_handlers/column_header.ts +22 -21
- package/src/ts/style_handlers/consolidated.ts +23 -123
- package/src/ts/style_handlers/editable.ts +16 -10
- package/src/ts/style_handlers/focus.ts +7 -5
- package/src/ts/style_handlers/group_header.ts +13 -6
- package/src/ts/style_handlers/table_cell/boolean.ts +3 -3
- package/src/ts/style_handlers/table_cell/cell_flash.ts +11 -11
- package/src/ts/style_handlers/table_cell/datetime.ts +3 -3
- package/src/ts/style_handlers/table_cell/numeric.ts +24 -25
- package/src/ts/style_handlers/table_cell/row_header.ts +2 -2
- package/src/ts/style_handlers/table_cell/string.ts +20 -18
- package/src/ts/style_handlers/types.ts +0 -10
- package/src/ts/types.ts +28 -20
- package/dist/esm/event_handlers/deselect_all.d.ts +0 -5
- package/dist/esm/event_handlers/row_select_click.d.ts +0 -4
- package/dist/esm/plugin/column_style_controls.d.ts +0 -28
- package/src/ts/event_handlers/row_select_click.ts +0 -92
- package/src/ts/plugin/column_style_controls.ts +0 -76
|
@@ -14,25 +14,29 @@ import { focusSelectedCell } from "../../style_handlers/focus.js";
|
|
|
14
14
|
import type {
|
|
15
15
|
RegularTable,
|
|
16
16
|
DatagridModel,
|
|
17
|
-
|
|
18
|
-
SelectedPosition,
|
|
17
|
+
SelectedPositionMap,
|
|
19
18
|
} from "../../types.js";
|
|
19
|
+
import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
|
|
20
20
|
|
|
21
|
-
type
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
type AsyncMoveFunction = (
|
|
22
|
+
model: DatagridModel,
|
|
23
|
+
table: RegularTable,
|
|
24
|
+
selected_position_map: SelectedPositionMap,
|
|
25
|
+
active_cell: HTMLElement,
|
|
26
|
+
dx: number,
|
|
27
|
+
dy: number,
|
|
28
|
+
) => Promise<void | undefined>;
|
|
27
29
|
|
|
28
|
-
function lock
|
|
29
|
-
body: AsyncFunction<T, R>,
|
|
30
|
-
): AsyncFunction<T, R | undefined> {
|
|
30
|
+
function lock(body: AsyncMoveFunction): AsyncMoveFunction {
|
|
31
31
|
let lockPromise: Promise<void> | undefined;
|
|
32
32
|
return async function (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
model: DatagridModel,
|
|
34
|
+
table: RegularTable,
|
|
35
|
+
selected_position_map: SelectedPositionMap,
|
|
36
|
+
active_cell: HTMLElement,
|
|
37
|
+
dx: number,
|
|
38
|
+
dy: number,
|
|
39
|
+
): Promise<void | undefined> {
|
|
36
40
|
if (lockPromise) {
|
|
37
41
|
await lockPromise;
|
|
38
42
|
return;
|
|
@@ -40,7 +44,14 @@ function lock<T extends unknown[], R>(
|
|
|
40
44
|
|
|
41
45
|
let resolve: () => void;
|
|
42
46
|
lockPromise = new Promise((x) => (resolve = x));
|
|
43
|
-
const result = await body
|
|
47
|
+
const result = await body(
|
|
48
|
+
model,
|
|
49
|
+
table,
|
|
50
|
+
selected_position_map,
|
|
51
|
+
active_cell,
|
|
52
|
+
dx,
|
|
53
|
+
dy,
|
|
54
|
+
);
|
|
44
55
|
lockPromise = undefined;
|
|
45
56
|
resolve!();
|
|
46
57
|
return result;
|
|
@@ -52,23 +63,26 @@ interface ContentEditableElement extends HTMLElement {
|
|
|
52
63
|
selectionStart?: number;
|
|
53
64
|
}
|
|
54
65
|
|
|
55
|
-
function getPos(
|
|
56
|
-
if (
|
|
57
|
-
const _range = (
|
|
66
|
+
function getPos(elem: ContentEditableElement): number {
|
|
67
|
+
if (elem.isContentEditable) {
|
|
68
|
+
const _range = (elem.getRootNode() as Document)
|
|
58
69
|
.getSelection()
|
|
59
70
|
?.getRangeAt(0);
|
|
60
|
-
if (!_range)
|
|
71
|
+
if (!_range) {
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
|
|
61
75
|
const range = _range.cloneRange();
|
|
62
|
-
range.selectNodeContents(
|
|
76
|
+
range.selectNodeContents(elem);
|
|
63
77
|
range.setEnd(_range.endContainer, _range.endOffset);
|
|
64
78
|
return range.toString().length;
|
|
65
79
|
} else {
|
|
66
|
-
return
|
|
80
|
+
return elem.selectionStart || 0;
|
|
67
81
|
}
|
|
68
82
|
}
|
|
69
83
|
|
|
70
84
|
const moveSelection = lock(async function (
|
|
71
|
-
|
|
85
|
+
model: DatagridModel,
|
|
72
86
|
table: RegularTable,
|
|
73
87
|
selected_position_map: SelectedPositionMap,
|
|
74
88
|
active_cell: HTMLElement,
|
|
@@ -76,9 +90,12 @@ const moveSelection = lock(async function (
|
|
|
76
90
|
dy: number,
|
|
77
91
|
): Promise<void> {
|
|
78
92
|
const meta = table.getMeta(active_cell);
|
|
79
|
-
if (!meta || meta.type !== "body")
|
|
80
|
-
|
|
81
|
-
|
|
93
|
+
if (!meta || meta.type !== "body") {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const num_columns = model._column_paths.length;
|
|
98
|
+
const num_rows = model._num_rows;
|
|
82
99
|
const selected_position = selected_position_map.get(table);
|
|
83
100
|
if (!selected_position) {
|
|
84
101
|
return;
|
|
@@ -122,9 +139,9 @@ function isLastCell(
|
|
|
122
139
|
}
|
|
123
140
|
|
|
124
141
|
export function keydownListener(
|
|
125
|
-
|
|
142
|
+
model: DatagridModel,
|
|
126
143
|
table: RegularTable,
|
|
127
|
-
_viewer:
|
|
144
|
+
_viewer: HTMLPerspectiveViewerElement,
|
|
128
145
|
selected_position_map: SelectedPositionMap,
|
|
129
146
|
event: KeyboardEvent,
|
|
130
147
|
): void {
|
|
@@ -134,12 +151,12 @@ export function keydownListener(
|
|
|
134
151
|
switch (event.key) {
|
|
135
152
|
case "Enter":
|
|
136
153
|
event.preventDefault();
|
|
137
|
-
if (isLastCell(
|
|
154
|
+
if (isLastCell(model, table, target)) {
|
|
138
155
|
target.blur();
|
|
139
156
|
selected_position_map.delete(table);
|
|
140
157
|
} else if (event.shiftKey) {
|
|
141
|
-
moveSelection
|
|
142
|
-
|
|
158
|
+
moveSelection(
|
|
159
|
+
model,
|
|
143
160
|
table,
|
|
144
161
|
selected_position_map,
|
|
145
162
|
target,
|
|
@@ -147,8 +164,8 @@ export function keydownListener(
|
|
|
147
164
|
-1,
|
|
148
165
|
);
|
|
149
166
|
} else {
|
|
150
|
-
moveSelection
|
|
151
|
-
|
|
167
|
+
moveSelection(
|
|
168
|
+
model,
|
|
152
169
|
table,
|
|
153
170
|
selected_position_map,
|
|
154
171
|
target,
|
|
@@ -156,12 +173,13 @@ export function keydownListener(
|
|
|
156
173
|
1,
|
|
157
174
|
);
|
|
158
175
|
}
|
|
176
|
+
|
|
159
177
|
break;
|
|
160
178
|
case "ArrowLeft":
|
|
161
|
-
if (getPos
|
|
179
|
+
if (getPos(target as ContentEditableElement) === 0) {
|
|
162
180
|
event.preventDefault();
|
|
163
|
-
moveSelection
|
|
164
|
-
|
|
181
|
+
moveSelection(
|
|
182
|
+
model,
|
|
165
183
|
table,
|
|
166
184
|
selected_position_map,
|
|
167
185
|
target,
|
|
@@ -169,26 +187,20 @@ export function keydownListener(
|
|
|
169
187
|
0,
|
|
170
188
|
);
|
|
171
189
|
}
|
|
190
|
+
|
|
172
191
|
break;
|
|
173
192
|
case "ArrowUp":
|
|
174
193
|
event.preventDefault();
|
|
175
|
-
moveSelection
|
|
176
|
-
this,
|
|
177
|
-
table,
|
|
178
|
-
selected_position_map,
|
|
179
|
-
target,
|
|
180
|
-
0,
|
|
181
|
-
-1,
|
|
182
|
-
);
|
|
194
|
+
moveSelection(model, table, selected_position_map, target, 0, -1);
|
|
183
195
|
break;
|
|
184
196
|
case "ArrowRight":
|
|
185
197
|
if (
|
|
186
|
-
getPos
|
|
198
|
+
getPos(target as ContentEditableElement) ===
|
|
187
199
|
(target.textContent?.length || 0)
|
|
188
200
|
) {
|
|
189
201
|
event.preventDefault();
|
|
190
|
-
moveSelection
|
|
191
|
-
|
|
202
|
+
moveSelection(
|
|
203
|
+
model,
|
|
192
204
|
table,
|
|
193
205
|
selected_position_map,
|
|
194
206
|
target,
|
|
@@ -196,17 +208,11 @@ export function keydownListener(
|
|
|
196
208
|
0,
|
|
197
209
|
);
|
|
198
210
|
}
|
|
211
|
+
|
|
199
212
|
break;
|
|
200
213
|
case "ArrowDown":
|
|
201
214
|
event.preventDefault();
|
|
202
|
-
moveSelection
|
|
203
|
-
this,
|
|
204
|
-
table,
|
|
205
|
-
selected_position_map,
|
|
206
|
-
target,
|
|
207
|
-
0,
|
|
208
|
-
1,
|
|
209
|
-
);
|
|
215
|
+
moveSelection(model, table, selected_position_map, target, 0, 1);
|
|
210
216
|
break;
|
|
211
217
|
default:
|
|
212
218
|
}
|
|
@@ -13,16 +13,24 @@
|
|
|
13
13
|
import { RegularTableElement } from "regular-table";
|
|
14
14
|
import type {
|
|
15
15
|
DatagridPluginElement,
|
|
16
|
-
|
|
16
|
+
EditMode,
|
|
17
17
|
SelectionArea,
|
|
18
18
|
} from "../types.js";
|
|
19
|
-
import {
|
|
19
|
+
import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
|
|
20
|
+
import type { ViewWindow } from "@perspective-dev/client";
|
|
21
|
+
import type { CellMetadataBody } from "regular-table/dist/esm/types.js";
|
|
20
22
|
|
|
21
23
|
const MOUSE_SELECTED_AREA_CLASS = "mouse-selected-area";
|
|
22
24
|
|
|
25
|
+
export type OnSelectCallback = (
|
|
26
|
+
area: SelectionArea,
|
|
27
|
+
isDeselect: boolean,
|
|
28
|
+
) => void;
|
|
29
|
+
|
|
23
30
|
interface AddAreaMouseSelectionOptions {
|
|
24
31
|
className?: string;
|
|
25
32
|
selected?: SelectionArea[];
|
|
33
|
+
onSelect?: OnSelectCallback;
|
|
26
34
|
}
|
|
27
35
|
|
|
28
36
|
export const addAreaMouseSelection = (
|
|
@@ -31,6 +39,7 @@ export const addAreaMouseSelection = (
|
|
|
31
39
|
{
|
|
32
40
|
className = MOUSE_SELECTED_AREA_CLASS,
|
|
33
41
|
selected = [],
|
|
42
|
+
onSelect,
|
|
34
43
|
}: AddAreaMouseSelectionOptions = {},
|
|
35
44
|
): RegularTableElement => {
|
|
36
45
|
datagrid.model!._selection_state = {
|
|
@@ -50,7 +59,7 @@ export const addAreaMouseSelection = (
|
|
|
50
59
|
|
|
51
60
|
table.addEventListener(
|
|
52
61
|
"mouseup",
|
|
53
|
-
getMouseupListener(datagrid, table, className),
|
|
62
|
+
getMouseupListener(datagrid, table, className, onSelect),
|
|
54
63
|
);
|
|
55
64
|
|
|
56
65
|
table.addStyleListener(() =>
|
|
@@ -60,6 +69,10 @@ export const addAreaMouseSelection = (
|
|
|
60
69
|
return table;
|
|
61
70
|
};
|
|
62
71
|
|
|
72
|
+
function isSingleClickMode(mode: EditMode): boolean {
|
|
73
|
+
return mode === "SELECT_ROW_TREE";
|
|
74
|
+
}
|
|
75
|
+
|
|
63
76
|
const getMousedownListener =
|
|
64
77
|
(
|
|
65
78
|
datagrid: DatagridPluginElement,
|
|
@@ -70,10 +83,12 @@ const getMousedownListener =
|
|
|
70
83
|
const mouseEvent = event as MouseEvent;
|
|
71
84
|
if (
|
|
72
85
|
mouseEvent.button === 0 &&
|
|
73
|
-
(datagrid.model!._edit_mode
|
|
74
|
-
datagrid.model!._edit_mode === "SELECT_ROW" ||
|
|
75
|
-
datagrid.model!._edit_mode === "SELECT_COLUMN")
|
|
86
|
+
isSelectionMode(datagrid.model!._edit_mode)
|
|
76
87
|
) {
|
|
88
|
+
if (isSingleClickMode(datagrid.model!._edit_mode)) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
77
92
|
datagrid.model!._selection_state.CURRENT_MOUSEDOWN_COORDINATES = {};
|
|
78
93
|
const meta = table.getMeta(mouseEvent.target as HTMLElement);
|
|
79
94
|
if (
|
|
@@ -122,11 +137,8 @@ const getMouseoverListener =
|
|
|
122
137
|
) =>
|
|
123
138
|
(event: Event): void => {
|
|
124
139
|
const mouseEvent = event as MouseEvent;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
datagrid.model!._edit_mode === "SELECT_ROW" ||
|
|
128
|
-
datagrid.model!._edit_mode === "SELECT_COLUMN"
|
|
129
|
-
) {
|
|
140
|
+
const mode = datagrid.model!._edit_mode;
|
|
141
|
+
if (isSelectionMode(mode) && !isSingleClickMode(mode)) {
|
|
130
142
|
if (
|
|
131
143
|
datagrid.model!._selection_state
|
|
132
144
|
.CURRENT_MOUSEDOWN_COORDINATES &&
|
|
@@ -183,17 +195,65 @@ const getMouseupListener =
|
|
|
183
195
|
datagrid: DatagridPluginElement,
|
|
184
196
|
table: RegularTableElement,
|
|
185
197
|
className: string,
|
|
198
|
+
onSelect?: OnSelectCallback,
|
|
186
199
|
) =>
|
|
187
200
|
(event: Event): void => {
|
|
188
201
|
const mouseEvent = event as MouseEvent;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
datagrid.model!._edit_mode === "SELECT_ROW" ||
|
|
192
|
-
datagrid.model!._edit_mode === "SELECT_COLUMN"
|
|
193
|
-
) {
|
|
202
|
+
const mode = datagrid.model!._edit_mode;
|
|
203
|
+
if (isSelectionMode(mode)) {
|
|
194
204
|
const meta = table.getMeta(mouseEvent.target as HTMLElement);
|
|
195
|
-
if (!meta)
|
|
205
|
+
if (!meta) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
196
208
|
|
|
209
|
+
// For single-click modes (SELECT_ROW_TREE), handle toggle
|
|
210
|
+
if (isSingleClickMode(mode)) {
|
|
211
|
+
if (
|
|
212
|
+
(meta.type === "body" || meta.type === "row_header") &&
|
|
213
|
+
meta.y !== undefined &&
|
|
214
|
+
meta.y >= 0
|
|
215
|
+
) {
|
|
216
|
+
const existing =
|
|
217
|
+
datagrid.model!._selection_state.selected_areas;
|
|
218
|
+
const isSameRow =
|
|
219
|
+
existing.length > 0 && existing[0].y0 === meta.y;
|
|
220
|
+
|
|
221
|
+
if (isSameRow) {
|
|
222
|
+
// Deselect
|
|
223
|
+
datagrid.model!._selection_state.selected_areas = [];
|
|
224
|
+
datagrid.model!._selection_state.dirty = true;
|
|
225
|
+
applyMouseAreaSelections(
|
|
226
|
+
datagrid,
|
|
227
|
+
table,
|
|
228
|
+
className,
|
|
229
|
+
[],
|
|
230
|
+
);
|
|
231
|
+
onSelect?.(existing[0], true);
|
|
232
|
+
} else {
|
|
233
|
+
// Select new row
|
|
234
|
+
const area: SelectionArea = {
|
|
235
|
+
x0: 0,
|
|
236
|
+
x1: 0,
|
|
237
|
+
y0: meta.y,
|
|
238
|
+
y1: meta.y,
|
|
239
|
+
};
|
|
240
|
+
datagrid.model!._selection_state.selected_areas = [
|
|
241
|
+
area,
|
|
242
|
+
];
|
|
243
|
+
datagrid.model!._selection_state.dirty = true;
|
|
244
|
+
applyMouseAreaSelections(datagrid, table, className);
|
|
245
|
+
onSelect?.(area, false);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
datagrid.model!._selection_state.CURRENT_MOUSEDOWN_COORDINATES =
|
|
250
|
+
{};
|
|
251
|
+
datagrid.model!._selection_state.potential_selection =
|
|
252
|
+
undefined;
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Drag-based modes (SELECT_ROW, SELECT_COLUMN, SELECT_REGION)
|
|
197
257
|
if (
|
|
198
258
|
(datagrid.model!._selection_state.old_selected_areas?.length ??
|
|
199
259
|
0) > 0
|
|
@@ -260,80 +320,103 @@ const getMouseupListener =
|
|
|
260
320
|
}
|
|
261
321
|
};
|
|
262
322
|
|
|
323
|
+
function modeIncludesColumns(mode: EditMode): boolean {
|
|
324
|
+
return mode === "SELECT_COLUMN" || mode === "SELECT_REGION";
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function modeIncludesRows(mode: EditMode): boolean {
|
|
328
|
+
return (
|
|
329
|
+
mode === "SELECT_ROW" ||
|
|
330
|
+
mode === "SELECT_REGION" ||
|
|
331
|
+
mode === "SELECT_ROW_TREE"
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
263
335
|
function set_psp_selection(
|
|
264
|
-
viewer:
|
|
336
|
+
viewer: HTMLPerspectiveViewerElement,
|
|
265
337
|
datagrid: DatagridPluginElement,
|
|
266
338
|
{ x0, x1, y0, y1 }: SelectionArea,
|
|
267
339
|
): void {
|
|
268
340
|
const viewport: ViewWindow = {};
|
|
269
341
|
const mode = datagrid.model!._edit_mode;
|
|
270
|
-
if (
|
|
271
|
-
x0 !== undefined &&
|
|
272
|
-
["SELECT_COLUMN", "SELECT_REGION"].indexOf(mode) > -1
|
|
273
|
-
) {
|
|
342
|
+
if (x0 !== undefined && modeIncludesColumns(mode)) {
|
|
274
343
|
viewport.start_col = x0;
|
|
275
344
|
}
|
|
276
345
|
|
|
277
|
-
if (
|
|
278
|
-
x1 !== undefined &&
|
|
279
|
-
["SELECT_COLUMN", "SELECT_REGION"].indexOf(mode) > -1
|
|
280
|
-
) {
|
|
346
|
+
if (x1 !== undefined && modeIncludesColumns(mode)) {
|
|
281
347
|
viewport.end_col = x1 + 1;
|
|
282
348
|
}
|
|
283
349
|
|
|
284
|
-
if (
|
|
285
|
-
y0 !== undefined &&
|
|
286
|
-
["SELECT_ROW", "SELECT_REGION"].indexOf(mode) > -1
|
|
287
|
-
) {
|
|
350
|
+
if (y0 !== undefined && modeIncludesRows(mode)) {
|
|
288
351
|
viewport.start_row = y0;
|
|
289
352
|
}
|
|
290
353
|
|
|
291
|
-
if (
|
|
292
|
-
y1 !== undefined &&
|
|
293
|
-
["SELECT_ROW", "SELECT_REGION"].indexOf(mode) > -1
|
|
294
|
-
) {
|
|
354
|
+
if (y1 !== undefined && modeIncludesRows(mode)) {
|
|
295
355
|
viewport.end_row = y1 + 1;
|
|
296
356
|
}
|
|
297
357
|
|
|
298
358
|
viewer.setSelection(viewport);
|
|
299
359
|
}
|
|
300
360
|
|
|
361
|
+
type CellPredicate = (meta: CellMetadataBody, area: SelectionArea) => boolean;
|
|
362
|
+
|
|
363
|
+
const SELECTION_PREDICATES: Record<string, CellPredicate> = {
|
|
364
|
+
SELECT_REGION: (m, a) =>
|
|
365
|
+
a.x0 <= m.x && m.x <= a.x1 && a.y0 <= m.y && m.y <= a.y1,
|
|
366
|
+
SELECT_ROW: (m, a) => a.y0 <= m.y && m.y <= a.y1,
|
|
367
|
+
SELECT_ROW_TREE: (m, a) => a.y0 <= m.y && m.y <= a.y1,
|
|
368
|
+
SELECT_COLUMN: (m, a) => a.x0 <= m.x && m.x <= a.x1,
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
function isSelectionMode(mode: EditMode): boolean {
|
|
372
|
+
return (
|
|
373
|
+
mode === "SELECT_REGION" ||
|
|
374
|
+
mode === "SELECT_ROW" ||
|
|
375
|
+
mode === "SELECT_COLUMN" ||
|
|
376
|
+
mode === "SELECT_ROW_TREE"
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
|
|
301
380
|
export const applyMouseAreaSelections = (
|
|
302
381
|
datagrid: DatagridPluginElement,
|
|
303
382
|
table: RegularTableElement,
|
|
304
383
|
className: string,
|
|
305
384
|
selected?: SelectionArea[],
|
|
306
385
|
): void => {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
datagrid.model!._edit_mode === "SELECT_ROW" ||
|
|
310
|
-
datagrid.model!._edit_mode === "SELECT_COLUMN"
|
|
311
|
-
) {
|
|
386
|
+
const mode = datagrid.model!._edit_mode;
|
|
387
|
+
if (isSelectionMode(mode)) {
|
|
312
388
|
selected = datagrid.model!._selection_state.selected_areas.slice(0);
|
|
313
389
|
if (datagrid.model!._selection_state.potential_selection) {
|
|
314
390
|
selected.push(datagrid.model!._selection_state.potential_selection);
|
|
315
391
|
}
|
|
316
392
|
|
|
317
|
-
const tds = table.querySelectorAll("tbody td");
|
|
318
|
-
|
|
319
393
|
if (selected.length > 0) {
|
|
320
394
|
set_psp_selection(
|
|
321
|
-
datagrid.parentElement as
|
|
395
|
+
datagrid.parentElement as HTMLPerspectiveViewerElement,
|
|
322
396
|
datagrid,
|
|
323
397
|
selected[0],
|
|
324
398
|
);
|
|
325
|
-
|
|
399
|
+
|
|
400
|
+
// SELECT_ROW_TREE styling is handled entirely by the
|
|
401
|
+
// identity-based system in body.ts, which styles both td
|
|
402
|
+
// and th uniformly in a single draw pass.
|
|
403
|
+
if (!isSingleClickMode(mode)) {
|
|
404
|
+
applyMouseAreaSelection(datagrid, table, selected, className);
|
|
405
|
+
}
|
|
326
406
|
} else {
|
|
327
|
-
(
|
|
407
|
+
(
|
|
408
|
+
datagrid.parentElement as HTMLPerspectiveViewerElement
|
|
409
|
+
).setSelection();
|
|
410
|
+
const tds = table.querySelectorAll("tbody td");
|
|
328
411
|
for (const td of tds) {
|
|
329
412
|
td.classList.remove(className);
|
|
330
413
|
}
|
|
331
414
|
}
|
|
332
415
|
} else if (datagrid.model!._selection_state.dirty) {
|
|
333
416
|
datagrid.model!._selection_state.dirty = false;
|
|
334
|
-
const
|
|
335
|
-
for (const
|
|
336
|
-
|
|
417
|
+
const cells = table.querySelectorAll("tbody td, tbody th");
|
|
418
|
+
for (const cell of cells) {
|
|
419
|
+
cell.classList.remove(className);
|
|
337
420
|
}
|
|
338
421
|
}
|
|
339
422
|
};
|
|
@@ -344,96 +427,35 @@ const applyMouseAreaSelection = (
|
|
|
344
427
|
selected: SelectionArea[],
|
|
345
428
|
className: string,
|
|
346
429
|
): void => {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
const meta = table.getMeta(td as HTMLElement);
|
|
352
|
-
if (!meta || meta.type !== "body") continue;
|
|
353
|
-
let rendered = false;
|
|
354
|
-
for (const { x0, x1, y0, y1 } of selected) {
|
|
355
|
-
if (
|
|
356
|
-
x0 !== undefined &&
|
|
357
|
-
y0 !== undefined &&
|
|
358
|
-
x1 !== undefined &&
|
|
359
|
-
y1 !== undefined
|
|
360
|
-
) {
|
|
361
|
-
if (
|
|
362
|
-
x0 <= meta.x &&
|
|
363
|
-
meta.x <= x1 &&
|
|
364
|
-
y0 <= meta.y &&
|
|
365
|
-
meta.y <= y1
|
|
366
|
-
) {
|
|
367
|
-
rendered = true;
|
|
368
|
-
datagrid.model!._selection_state.dirty = true;
|
|
369
|
-
td.classList.add(className);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
430
|
+
const predicate = SELECTION_PREDICATES[datagrid.model!._edit_mode];
|
|
431
|
+
if (!predicate || selected.length === 0) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
373
434
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
435
|
+
const tds = table.querySelectorAll("tbody td");
|
|
436
|
+
for (const td of tds) {
|
|
437
|
+
const meta = table.getMeta(td as HTMLElement);
|
|
438
|
+
if (!meta || meta.type !== "body") {
|
|
439
|
+
continue;
|
|
377
440
|
}
|
|
378
|
-
} else if (
|
|
379
|
-
datagrid.model!._edit_mode === "SELECT_ROW" &&
|
|
380
|
-
selected.length > 0
|
|
381
|
-
) {
|
|
382
|
-
const tds = table.querySelectorAll("tbody td");
|
|
383
|
-
|
|
384
|
-
for (const td of tds) {
|
|
385
|
-
const meta = table.getMeta(td as HTMLElement);
|
|
386
|
-
if (!meta) continue;
|
|
387
|
-
let rendered = false;
|
|
388
|
-
for (const { x0, x1, y0, y1 } of selected) {
|
|
389
|
-
if (
|
|
390
|
-
x0 !== undefined &&
|
|
391
|
-
y0 !== undefined &&
|
|
392
|
-
x1 !== undefined &&
|
|
393
|
-
y1 !== undefined &&
|
|
394
|
-
meta?.type === "body"
|
|
395
|
-
) {
|
|
396
|
-
if (y0 <= meta.y && meta.y <= y1) {
|
|
397
|
-
datagrid.model!._selection_state.dirty = true;
|
|
398
|
-
rendered = true;
|
|
399
|
-
td.classList.add(className);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
441
|
|
|
404
|
-
|
|
405
|
-
|
|
442
|
+
let rendered = false;
|
|
443
|
+
for (const area of selected) {
|
|
444
|
+
if (
|
|
445
|
+
area.x0 !== undefined &&
|
|
446
|
+
area.y0 !== undefined &&
|
|
447
|
+
area.x1 !== undefined &&
|
|
448
|
+
area.y1 !== undefined &&
|
|
449
|
+
predicate(meta, area)
|
|
450
|
+
) {
|
|
451
|
+
rendered = true;
|
|
452
|
+
datagrid.model!._selection_state.dirty = true;
|
|
453
|
+
td.classList.add(className);
|
|
406
454
|
}
|
|
407
455
|
}
|
|
408
|
-
} else if (
|
|
409
|
-
datagrid.model!._edit_mode === "SELECT_COLUMN" &&
|
|
410
|
-
selected.length > 0
|
|
411
|
-
) {
|
|
412
|
-
const tds = table.querySelectorAll("tbody td");
|
|
413
|
-
|
|
414
|
-
for (const td of tds) {
|
|
415
|
-
const meta = table.getMeta(td as HTMLElement);
|
|
416
|
-
if (!meta) continue;
|
|
417
|
-
let rendered = false;
|
|
418
|
-
for (const { x0, x1, y0, y1 } of selected) {
|
|
419
|
-
if (
|
|
420
|
-
x0 !== undefined &&
|
|
421
|
-
y0 !== undefined &&
|
|
422
|
-
x1 !== undefined &&
|
|
423
|
-
y1 !== undefined &&
|
|
424
|
-
meta?.type === "body"
|
|
425
|
-
) {
|
|
426
|
-
if (x0 <= meta.x && meta.x <= x1) {
|
|
427
|
-
datagrid.model!._selection_state.dirty = true;
|
|
428
|
-
rendered = true;
|
|
429
|
-
td.classList.add(className);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
456
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
}
|
|
457
|
+
if (!rendered) {
|
|
458
|
+
td.classList.remove(className);
|
|
437
459
|
}
|
|
438
460
|
}
|
|
439
461
|
};
|