@perspective-dev/viewer-datagrid 4.4.0 → 4.4.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/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 +5 -5
- 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/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_style_controls.d.ts +1 -1
- 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 +144 -16
- package/src/ts/custom_elements/datagrid.ts +11 -12
- package/src/ts/custom_elements/toolbar.ts +4 -5
- package/src/ts/data_listener/format_cell.ts +28 -9
- package/src/ts/data_listener/formatter_cache.ts +1 -1
- package/src/ts/data_listener/index.ts +4 -8
- package/src/ts/event_handlers/click/edit_click.ts +7 -6
- package/src/ts/event_handlers/click.ts +39 -68
- package/src/ts/event_handlers/dispatch_click.ts +24 -25
- package/src/ts/event_handlers/expand_collapse.ts +7 -7
- package/src/ts/event_handlers/focus.ts +38 -35
- package/src/ts/event_handlers/header_click.ts +101 -62
- package/src/ts/event_handlers/keydown/edit_keydown.ts +49 -52
- package/src/ts/event_handlers/select_region.ts +144 -133
- package/src/ts/event_handlers/sort.ts +16 -24
- package/src/ts/model/column_overrides.ts +13 -4
- package/src/ts/model/create.ts +51 -55
- package/src/ts/model/toolbar.ts +23 -7
- package/src/ts/plugin/activate.ts +120 -92
- package/src/ts/plugin/column_style_controls.ts +1 -1
- package/src/ts/plugin/save.ts +1 -0
- package/src/ts/style_handlers/body.ts +44 -51
- package/src/ts/style_handlers/column_header.ts +16 -19
- package/src/ts/style_handlers/consolidated.ts +22 -123
- package/src/ts/style_handlers/editable.ts +10 -8
- package/src/ts/style_handlers/focus.ts +5 -5
- package/src/ts/style_handlers/group_header.ts +3 -2
- 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/src/ts/event_handlers/deselect_all.ts +0 -28
- package/src/ts/event_handlers/row_select_click.ts +0 -92
|
@@ -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,9 @@ 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)) return;
|
|
77
89
|
datagrid.model!._selection_state.CURRENT_MOUSEDOWN_COORDINATES = {};
|
|
78
90
|
const meta = table.getMeta(mouseEvent.target as HTMLElement);
|
|
79
91
|
if (
|
|
@@ -122,11 +134,8 @@ const getMouseoverListener =
|
|
|
122
134
|
) =>
|
|
123
135
|
(event: Event): void => {
|
|
124
136
|
const mouseEvent = event as MouseEvent;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
datagrid.model!._edit_mode === "SELECT_ROW" ||
|
|
128
|
-
datagrid.model!._edit_mode === "SELECT_COLUMN"
|
|
129
|
-
) {
|
|
137
|
+
const mode = datagrid.model!._edit_mode;
|
|
138
|
+
if (isSelectionMode(mode) && !isSingleClickMode(mode)) {
|
|
130
139
|
if (
|
|
131
140
|
datagrid.model!._selection_state
|
|
132
141
|
.CURRENT_MOUSEDOWN_COORDINATES &&
|
|
@@ -183,17 +192,63 @@ const getMouseupListener =
|
|
|
183
192
|
datagrid: DatagridPluginElement,
|
|
184
193
|
table: RegularTableElement,
|
|
185
194
|
className: string,
|
|
195
|
+
onSelect?: OnSelectCallback,
|
|
186
196
|
) =>
|
|
187
197
|
(event: Event): void => {
|
|
188
198
|
const mouseEvent = event as MouseEvent;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
datagrid.model!._edit_mode === "SELECT_ROW" ||
|
|
192
|
-
datagrid.model!._edit_mode === "SELECT_COLUMN"
|
|
193
|
-
) {
|
|
199
|
+
const mode = datagrid.model!._edit_mode;
|
|
200
|
+
if (isSelectionMode(mode)) {
|
|
194
201
|
const meta = table.getMeta(mouseEvent.target as HTMLElement);
|
|
195
202
|
if (!meta) return;
|
|
196
203
|
|
|
204
|
+
// For single-click modes (SELECT_ROW_TREE), handle toggle
|
|
205
|
+
if (isSingleClickMode(mode)) {
|
|
206
|
+
if (
|
|
207
|
+
(meta.type === "body" || meta.type === "row_header") &&
|
|
208
|
+
meta.y !== undefined &&
|
|
209
|
+
meta.y >= 0
|
|
210
|
+
) {
|
|
211
|
+
const existing =
|
|
212
|
+
datagrid.model!._selection_state.selected_areas;
|
|
213
|
+
const isSameRow =
|
|
214
|
+
existing.length > 0 && existing[0].y0 === meta.y;
|
|
215
|
+
|
|
216
|
+
if (isSameRow) {
|
|
217
|
+
// Deselect
|
|
218
|
+
datagrid.model!._selection_state.selected_areas = [];
|
|
219
|
+
datagrid.model!._selection_state.dirty = true;
|
|
220
|
+
applyMouseAreaSelections(
|
|
221
|
+
datagrid,
|
|
222
|
+
table,
|
|
223
|
+
className,
|
|
224
|
+
[],
|
|
225
|
+
);
|
|
226
|
+
onSelect?.(existing[0], true);
|
|
227
|
+
} else {
|
|
228
|
+
// Select new row
|
|
229
|
+
const area: SelectionArea = {
|
|
230
|
+
x0: 0,
|
|
231
|
+
x1: 0,
|
|
232
|
+
y0: meta.y,
|
|
233
|
+
y1: meta.y,
|
|
234
|
+
};
|
|
235
|
+
datagrid.model!._selection_state.selected_areas = [
|
|
236
|
+
area,
|
|
237
|
+
];
|
|
238
|
+
datagrid.model!._selection_state.dirty = true;
|
|
239
|
+
applyMouseAreaSelections(datagrid, table, className);
|
|
240
|
+
onSelect?.(area, false);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
datagrid.model!._selection_state.CURRENT_MOUSEDOWN_COORDINATES =
|
|
245
|
+
{};
|
|
246
|
+
datagrid.model!._selection_state.potential_selection =
|
|
247
|
+
undefined;
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Drag-based modes (SELECT_ROW, SELECT_COLUMN, SELECT_REGION)
|
|
197
252
|
if (
|
|
198
253
|
(datagrid.model!._selection_state.old_selected_areas?.length ??
|
|
199
254
|
0) > 0
|
|
@@ -260,80 +315,103 @@ const getMouseupListener =
|
|
|
260
315
|
}
|
|
261
316
|
};
|
|
262
317
|
|
|
318
|
+
function modeIncludesColumns(mode: EditMode): boolean {
|
|
319
|
+
return mode === "SELECT_COLUMN" || mode === "SELECT_REGION";
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function modeIncludesRows(mode: EditMode): boolean {
|
|
323
|
+
return (
|
|
324
|
+
mode === "SELECT_ROW" ||
|
|
325
|
+
mode === "SELECT_REGION" ||
|
|
326
|
+
mode === "SELECT_ROW_TREE"
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
263
330
|
function set_psp_selection(
|
|
264
|
-
viewer:
|
|
331
|
+
viewer: HTMLPerspectiveViewerElement,
|
|
265
332
|
datagrid: DatagridPluginElement,
|
|
266
333
|
{ x0, x1, y0, y1 }: SelectionArea,
|
|
267
334
|
): void {
|
|
268
335
|
const viewport: ViewWindow = {};
|
|
269
336
|
const mode = datagrid.model!._edit_mode;
|
|
270
|
-
if (
|
|
271
|
-
x0 !== undefined &&
|
|
272
|
-
["SELECT_COLUMN", "SELECT_REGION"].indexOf(mode) > -1
|
|
273
|
-
) {
|
|
337
|
+
if (x0 !== undefined && modeIncludesColumns(mode)) {
|
|
274
338
|
viewport.start_col = x0;
|
|
275
339
|
}
|
|
276
340
|
|
|
277
|
-
if (
|
|
278
|
-
x1 !== undefined &&
|
|
279
|
-
["SELECT_COLUMN", "SELECT_REGION"].indexOf(mode) > -1
|
|
280
|
-
) {
|
|
341
|
+
if (x1 !== undefined && modeIncludesColumns(mode)) {
|
|
281
342
|
viewport.end_col = x1 + 1;
|
|
282
343
|
}
|
|
283
344
|
|
|
284
|
-
if (
|
|
285
|
-
y0 !== undefined &&
|
|
286
|
-
["SELECT_ROW", "SELECT_REGION"].indexOf(mode) > -1
|
|
287
|
-
) {
|
|
345
|
+
if (y0 !== undefined && modeIncludesRows(mode)) {
|
|
288
346
|
viewport.start_row = y0;
|
|
289
347
|
}
|
|
290
348
|
|
|
291
|
-
if (
|
|
292
|
-
y1 !== undefined &&
|
|
293
|
-
["SELECT_ROW", "SELECT_REGION"].indexOf(mode) > -1
|
|
294
|
-
) {
|
|
349
|
+
if (y1 !== undefined && modeIncludesRows(mode)) {
|
|
295
350
|
viewport.end_row = y1 + 1;
|
|
296
351
|
}
|
|
297
352
|
|
|
298
353
|
viewer.setSelection(viewport);
|
|
299
354
|
}
|
|
300
355
|
|
|
356
|
+
type CellPredicate = (meta: CellMetadataBody, area: SelectionArea) => boolean;
|
|
357
|
+
|
|
358
|
+
const SELECTION_PREDICATES: Record<string, CellPredicate> = {
|
|
359
|
+
SELECT_REGION: (m, a) =>
|
|
360
|
+
a.x0 <= m.x && m.x <= a.x1 && a.y0 <= m.y && m.y <= a.y1,
|
|
361
|
+
SELECT_ROW: (m, a) => a.y0 <= m.y && m.y <= a.y1,
|
|
362
|
+
SELECT_ROW_TREE: (m, a) => a.y0 <= m.y && m.y <= a.y1,
|
|
363
|
+
SELECT_COLUMN: (m, a) => a.x0 <= m.x && m.x <= a.x1,
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
function isSelectionMode(mode: EditMode): boolean {
|
|
367
|
+
return (
|
|
368
|
+
mode === "SELECT_REGION" ||
|
|
369
|
+
mode === "SELECT_ROW" ||
|
|
370
|
+
mode === "SELECT_COLUMN" ||
|
|
371
|
+
mode === "SELECT_ROW_TREE"
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
|
|
301
375
|
export const applyMouseAreaSelections = (
|
|
302
376
|
datagrid: DatagridPluginElement,
|
|
303
377
|
table: RegularTableElement,
|
|
304
378
|
className: string,
|
|
305
379
|
selected?: SelectionArea[],
|
|
306
380
|
): void => {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
datagrid.model!._edit_mode === "SELECT_ROW" ||
|
|
310
|
-
datagrid.model!._edit_mode === "SELECT_COLUMN"
|
|
311
|
-
) {
|
|
381
|
+
const mode = datagrid.model!._edit_mode;
|
|
382
|
+
if (isSelectionMode(mode)) {
|
|
312
383
|
selected = datagrid.model!._selection_state.selected_areas.slice(0);
|
|
313
384
|
if (datagrid.model!._selection_state.potential_selection) {
|
|
314
385
|
selected.push(datagrid.model!._selection_state.potential_selection);
|
|
315
386
|
}
|
|
316
387
|
|
|
317
|
-
const tds = table.querySelectorAll("tbody td");
|
|
318
|
-
|
|
319
388
|
if (selected.length > 0) {
|
|
320
389
|
set_psp_selection(
|
|
321
|
-
datagrid.parentElement as
|
|
390
|
+
datagrid.parentElement as HTMLPerspectiveViewerElement,
|
|
322
391
|
datagrid,
|
|
323
392
|
selected[0],
|
|
324
393
|
);
|
|
325
|
-
|
|
394
|
+
|
|
395
|
+
// SELECT_ROW_TREE styling is handled entirely by the
|
|
396
|
+
// identity-based system in body.ts, which styles both td
|
|
397
|
+
// and th uniformly in a single draw pass.
|
|
398
|
+
if (!isSingleClickMode(mode)) {
|
|
399
|
+
applyMouseAreaSelection(datagrid, table, selected, className);
|
|
400
|
+
}
|
|
326
401
|
} else {
|
|
327
|
-
(
|
|
402
|
+
(
|
|
403
|
+
datagrid.parentElement as HTMLPerspectiveViewerElement
|
|
404
|
+
).setSelection();
|
|
405
|
+
const tds = table.querySelectorAll("tbody td");
|
|
328
406
|
for (const td of tds) {
|
|
329
407
|
td.classList.remove(className);
|
|
330
408
|
}
|
|
331
409
|
}
|
|
332
410
|
} else if (datagrid.model!._selection_state.dirty) {
|
|
333
411
|
datagrid.model!._selection_state.dirty = false;
|
|
334
|
-
const
|
|
335
|
-
for (const
|
|
336
|
-
|
|
412
|
+
const cells = table.querySelectorAll("tbody td, tbody th");
|
|
413
|
+
for (const cell of cells) {
|
|
414
|
+
cell.classList.remove(className);
|
|
337
415
|
}
|
|
338
416
|
}
|
|
339
417
|
};
|
|
@@ -344,96 +422,29 @@ const applyMouseAreaSelection = (
|
|
|
344
422
|
selected: SelectionArea[],
|
|
345
423
|
className: string,
|
|
346
424
|
): void => {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
)
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
meta.y <= y1
|
|
366
|
-
) {
|
|
367
|
-
rendered = true;
|
|
368
|
-
datagrid.model!._selection_state.dirty = true;
|
|
369
|
-
td.classList.add(className);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
if (!rendered) {
|
|
375
|
-
td.classList.remove(className);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
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
|
-
|
|
404
|
-
if (!rendered) {
|
|
405
|
-
td.classList.remove(className);
|
|
425
|
+
const predicate = SELECTION_PREDICATES[datagrid.model!._edit_mode];
|
|
426
|
+
if (!predicate || selected.length === 0) return;
|
|
427
|
+
const tds = table.querySelectorAll("tbody td");
|
|
428
|
+
for (const td of tds) {
|
|
429
|
+
const meta = table.getMeta(td as HTMLElement);
|
|
430
|
+
if (!meta || meta.type !== "body") continue;
|
|
431
|
+
let rendered = false;
|
|
432
|
+
for (const area of selected) {
|
|
433
|
+
if (
|
|
434
|
+
area.x0 !== undefined &&
|
|
435
|
+
area.y0 !== undefined &&
|
|
436
|
+
area.x1 !== undefined &&
|
|
437
|
+
area.y1 !== undefined &&
|
|
438
|
+
predicate(meta, area)
|
|
439
|
+
) {
|
|
440
|
+
rendered = true;
|
|
441
|
+
datagrid.model!._selection_state.dirty = true;
|
|
442
|
+
td.classList.add(className);
|
|
406
443
|
}
|
|
407
444
|
}
|
|
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
445
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
}
|
|
446
|
+
if (!rendered) {
|
|
447
|
+
td.classList.remove(className);
|
|
437
448
|
}
|
|
438
449
|
}
|
|
439
450
|
};
|
|
@@ -10,14 +10,10 @@
|
|
|
10
10
|
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
|
-
import { RegularTableElement } from "regular-table";
|
|
14
|
-
import type {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
SortRotationOrder,
|
|
18
|
-
SortTerm,
|
|
19
|
-
} from "../types.js";
|
|
20
|
-
import { SortDir } from "@perspective-dev/client";
|
|
13
|
+
import type { RegularTableElement } from "regular-table";
|
|
14
|
+
import type { DatagridModel, SortRotationOrder, SortTerm } from "../types.js";
|
|
15
|
+
import type { SortDir } from "@perspective-dev/client";
|
|
16
|
+
import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
|
|
21
17
|
|
|
22
18
|
const ROW_SORT_ORDER: SortRotationOrder = {
|
|
23
19
|
desc: "asc",
|
|
@@ -31,22 +27,18 @@ const ROW_COL_SORT_ORDER: SortRotationOrder = {
|
|
|
31
27
|
asc: undefined,
|
|
32
28
|
"desc abs": "asc abs",
|
|
33
29
|
"asc abs": undefined,
|
|
34
|
-
// "col desc": "col asc",
|
|
35
|
-
// "col asc": undefined,
|
|
36
|
-
// "col desc abs": "col asc abs",
|
|
37
|
-
// "col asc abs": undefined,
|
|
38
30
|
};
|
|
39
31
|
|
|
40
32
|
export async function sortHandler(
|
|
41
|
-
|
|
33
|
+
model: DatagridModel,
|
|
42
34
|
regularTable: RegularTableElement,
|
|
43
|
-
viewer:
|
|
35
|
+
viewer: HTMLPerspectiveViewerElement,
|
|
44
36
|
event: MouseEvent,
|
|
45
37
|
target: HTMLElement,
|
|
46
38
|
): Promise<void> {
|
|
47
39
|
const meta = regularTable.getMeta(target);
|
|
48
40
|
if (!meta?.column_header) return;
|
|
49
|
-
const column_name = meta.column_header[
|
|
41
|
+
const column_name = meta.column_header[model._config.split_by.length];
|
|
50
42
|
const sort_method =
|
|
51
43
|
event.ctrlKey ||
|
|
52
44
|
(event as MouseEvent & { metaKey?: boolean }).metaKey ||
|
|
@@ -55,22 +47,22 @@ export async function sortHandler(
|
|
|
55
47
|
: override_sort;
|
|
56
48
|
|
|
57
49
|
const abs = event.shiftKey;
|
|
58
|
-
const sort = sort_method
|
|
50
|
+
const sort = sort_method(model, `${column_name}`, abs);
|
|
59
51
|
await viewer.restore({ sort });
|
|
60
52
|
}
|
|
61
53
|
|
|
62
54
|
export function append_sort(
|
|
63
|
-
|
|
55
|
+
model: DatagridModel,
|
|
64
56
|
column_name: string,
|
|
65
57
|
abs: boolean,
|
|
66
58
|
): SortTerm[] {
|
|
67
59
|
const sort: SortTerm[] = [];
|
|
68
60
|
let found = false;
|
|
69
|
-
for (const sort_term of
|
|
61
|
+
for (const sort_term of model._config.sort) {
|
|
70
62
|
const [_column_name, _sort_dir] = sort_term;
|
|
71
63
|
if (_column_name === column_name) {
|
|
72
64
|
found = true;
|
|
73
|
-
const term = create_sort
|
|
65
|
+
const term = create_sort(model, column_name, _sort_dir, abs);
|
|
74
66
|
if (term) {
|
|
75
67
|
sort.push(term);
|
|
76
68
|
}
|
|
@@ -87,13 +79,13 @@ export function append_sort(
|
|
|
87
79
|
}
|
|
88
80
|
|
|
89
81
|
export function override_sort(
|
|
90
|
-
|
|
82
|
+
model: DatagridModel,
|
|
91
83
|
column_name: string,
|
|
92
84
|
abs: boolean,
|
|
93
85
|
): SortTerm[] {
|
|
94
|
-
for (const [_column_name, _sort_dir] of
|
|
86
|
+
for (const [_column_name, _sort_dir] of model._config.sort) {
|
|
95
87
|
if (_column_name === column_name) {
|
|
96
|
-
const sort = create_sort
|
|
88
|
+
const sort = create_sort(model, column_name, _sort_dir, abs);
|
|
97
89
|
return sort ? [sort] : [];
|
|
98
90
|
}
|
|
99
91
|
}
|
|
@@ -102,12 +94,12 @@ export function override_sort(
|
|
|
102
94
|
}
|
|
103
95
|
|
|
104
96
|
export function create_sort(
|
|
105
|
-
|
|
97
|
+
model: DatagridModel,
|
|
106
98
|
column_name: string,
|
|
107
99
|
sort_dir: SortDir | undefined,
|
|
108
100
|
_abs: boolean,
|
|
109
101
|
): SortTerm | undefined {
|
|
110
|
-
const is_col_sortable =
|
|
102
|
+
const is_col_sortable = model._config.split_by.length > 0;
|
|
111
103
|
const order = is_col_sortable ? ROW_COL_SORT_ORDER : ROW_SORT_ORDER;
|
|
112
104
|
const inc_sort_dir: SortDir | undefined = sort_dir
|
|
113
105
|
? order[sort_dir]
|
|
@@ -46,7 +46,10 @@ export function restore_column_size_overrides(
|
|
|
46
46
|
this._cached_column_sizes = old_sizes;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
const
|
|
49
|
+
const regular_table = this.regular_table as RegularTableWithOverrides;
|
|
50
|
+
const overrides: Record<number, number | undefined> = {
|
|
51
|
+
...regular_table.saveColumnSizes(),
|
|
52
|
+
};
|
|
50
53
|
const { group_by } = this.model!._config;
|
|
51
54
|
const tree_header_offset = group_by?.length > 0 ? group_by.length + 1 : 0;
|
|
52
55
|
|
|
@@ -57,15 +60,21 @@ export function restore_column_size_overrides(
|
|
|
57
60
|
| undefined;
|
|
58
61
|
} else {
|
|
59
62
|
const index = this.model!._column_paths.indexOf(key);
|
|
63
|
+
// Skip keys that don't resolve to a known column — e.g. on the
|
|
64
|
+
// first draw after `activate`, `_column_paths` has not yet been
|
|
65
|
+
// populated by the data listener, so we leave any existing
|
|
66
|
+
// `regular-table` widths untouched rather than clobbering them
|
|
67
|
+
// with garbage indices.
|
|
68
|
+
if (index === -1) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
60
71
|
overrides[index + tree_header_offset] = old_sizes[key] as
|
|
61
72
|
| number
|
|
62
73
|
| undefined;
|
|
63
74
|
}
|
|
64
75
|
}
|
|
65
76
|
|
|
66
|
-
|
|
67
|
-
overrides,
|
|
68
|
-
);
|
|
77
|
+
regular_table.restoreColumnSizes(overrides);
|
|
69
78
|
}
|
|
70
79
|
|
|
71
80
|
/**
|