@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,9 +14,7 @@ import { RegularTableElement } from "regular-table";
|
|
|
14
14
|
|
|
15
15
|
import {
|
|
16
16
|
type DatagridModel,
|
|
17
|
-
type PerspectiveViewerElement,
|
|
18
17
|
type ColumnsConfig,
|
|
19
|
-
type DatagridPluginElement,
|
|
20
18
|
get_psp_type,
|
|
21
19
|
} from "../types.js";
|
|
22
20
|
|
|
@@ -25,39 +23,31 @@ import { cell_style_string } from "./table_cell/string.js";
|
|
|
25
23
|
import { cell_style_datetime } from "./table_cell/datetime.js";
|
|
26
24
|
import { cell_style_boolean } from "./table_cell/boolean.js";
|
|
27
25
|
import { cell_style_row_header } from "./table_cell/row_header.js";
|
|
28
|
-
import {
|
|
29
|
-
CollectedCell,
|
|
30
|
-
LocalSelectedPositionMap,
|
|
31
|
-
LocalSelectedRowsMap,
|
|
32
|
-
} from "./types.js";
|
|
26
|
+
import { CollectedCell } from "./types.js";
|
|
33
27
|
|
|
34
28
|
/**
|
|
35
29
|
* Apply styles to all body cells in a single pass.
|
|
36
30
|
*/
|
|
37
31
|
export function applyBodyCellStyles(
|
|
38
|
-
|
|
32
|
+
model: DatagridModel,
|
|
39
33
|
cells: CollectedCell[],
|
|
40
34
|
plugins: ColumnsConfig,
|
|
41
35
|
isSettingsOpen: boolean,
|
|
42
36
|
isSelectable: boolean,
|
|
43
37
|
isEditable: boolean,
|
|
44
38
|
regularTable: RegularTableElement,
|
|
45
|
-
selectedRowsMap: LocalSelectedRowsMap,
|
|
46
|
-
selectedPositionMap: LocalSelectedPositionMap,
|
|
47
|
-
viewer: PerspectiveViewerElement,
|
|
48
39
|
): void {
|
|
49
|
-
const
|
|
50
|
-
const selected = selectedRowsMap.get(regularTable);
|
|
40
|
+
const selectedId = isSelectable ? model._tree_selection_id : undefined;
|
|
51
41
|
|
|
52
42
|
regularTable.classList.toggle(
|
|
53
43
|
"flat-group-rollup-mode",
|
|
54
|
-
|
|
44
|
+
model._config.group_rollup_mode === "flat",
|
|
55
45
|
);
|
|
56
46
|
|
|
57
47
|
for (const { element: td, metadata, isHeader } of cells) {
|
|
58
48
|
const column_name =
|
|
59
|
-
metadata.column_header?.[
|
|
60
|
-
const type = get_psp_type(
|
|
49
|
+
metadata.column_header?.[model._config.split_by.length];
|
|
50
|
+
const type = get_psp_type(model, metadata);
|
|
61
51
|
const plugin = column_name
|
|
62
52
|
? plugins[column_name.toString()]
|
|
63
53
|
: undefined;
|
|
@@ -66,13 +56,13 @@ export function applyBodyCellStyles(
|
|
|
66
56
|
// Calculate aggregate depth visibility
|
|
67
57
|
// @ts-ignore
|
|
68
58
|
metadata._is_hidden_by_aggregate_depth =
|
|
69
|
-
|
|
59
|
+
model._config.group_rollup_mode === "rollup" &&
|
|
70
60
|
((x?: number) =>
|
|
71
61
|
x === 0 || x === undefined
|
|
72
62
|
? false
|
|
73
63
|
: x - 1 <
|
|
74
64
|
Math.min(
|
|
75
|
-
|
|
65
|
+
model._config.group_by.length,
|
|
76
66
|
plugin?.aggregate_depth || 0,
|
|
77
67
|
))(
|
|
78
68
|
(metadata.row_header as unknown[] | undefined)?.filter(
|
|
@@ -82,19 +72,19 @@ export function applyBodyCellStyles(
|
|
|
82
72
|
|
|
83
73
|
// Apply type-specific cell styling
|
|
84
74
|
if (is_numeric) {
|
|
85
|
-
cell_style_numeric
|
|
86
|
-
|
|
75
|
+
cell_style_numeric(
|
|
76
|
+
model,
|
|
87
77
|
plugin as any,
|
|
88
78
|
td,
|
|
89
79
|
metadata as any,
|
|
90
80
|
isSettingsOpen,
|
|
91
81
|
);
|
|
92
82
|
} else if (type === "boolean") {
|
|
93
|
-
cell_style_boolean
|
|
83
|
+
cell_style_boolean(model, plugin, td, metadata as any);
|
|
94
84
|
} else if (type === "string") {
|
|
95
|
-
cell_style_string
|
|
85
|
+
cell_style_string(model, plugin as any, td, metadata as any);
|
|
96
86
|
} else if (type === "date" || type === "datetime") {
|
|
97
|
-
cell_style_datetime
|
|
87
|
+
cell_style_datetime(model, plugin as any, td, metadata);
|
|
98
88
|
} else {
|
|
99
89
|
td.style.backgroundColor = "";
|
|
100
90
|
td.style.color = "";
|
|
@@ -109,10 +99,10 @@ export function applyBodyCellStyles(
|
|
|
109
99
|
td.classList.toggle("psp-null", metadata.value === null);
|
|
110
100
|
td.classList.toggle("psp-align-right", !isHeader && is_numeric);
|
|
111
101
|
td.classList.toggle("psp-align-left", isHeader || !is_numeric);
|
|
112
|
-
if (
|
|
102
|
+
if (model._column_settings_selected_column) {
|
|
113
103
|
td.classList.toggle(
|
|
114
104
|
"psp-menu-open",
|
|
115
|
-
column_name ===
|
|
105
|
+
column_name === model._column_settings_selected_column,
|
|
116
106
|
);
|
|
117
107
|
} else {
|
|
118
108
|
td.classList.toggle("psp-menu-open", false);
|
|
@@ -123,9 +113,14 @@ export function applyBodyCellStyles(
|
|
|
123
113
|
plugin?.number_fg_mode === "bar" && is_numeric,
|
|
124
114
|
);
|
|
125
115
|
|
|
116
|
+
td.classList.toggle(
|
|
117
|
+
"psp-color-mode-label-bar",
|
|
118
|
+
plugin?.number_fg_mode === "label-bar" && is_numeric,
|
|
119
|
+
);
|
|
120
|
+
|
|
126
121
|
// Apply row header styling
|
|
127
122
|
if (isHeader) {
|
|
128
|
-
cell_style_row_header
|
|
123
|
+
cell_style_row_header(model, regularTable, td, metadata as any);
|
|
129
124
|
}
|
|
130
125
|
|
|
131
126
|
// Set data attributes
|
|
@@ -152,55 +147,56 @@ export function applyBodyCellStyles(
|
|
|
152
147
|
delete td.dataset.x;
|
|
153
148
|
}
|
|
154
149
|
|
|
155
|
-
// Apply selection styling (
|
|
150
|
+
// Apply tree selection styling (SELECT_ROW_TREE).
|
|
151
|
+
// psp-select-region-inactive is exclusively a tree-selection class,
|
|
152
|
+
// so always clean it up. psp-select-region is shared with the
|
|
153
|
+
// coordinate-based selection modes, so only touch it when in
|
|
154
|
+
// SELECT_ROW_TREE mode (isSelectable).
|
|
155
|
+
td.classList.toggle("psp-select-region-inactive", false);
|
|
156
156
|
if (isSelectable) {
|
|
157
|
-
if (!
|
|
158
|
-
td.classList.toggle("psp-
|
|
159
|
-
td.classList.toggle("psp-row-subselected", false);
|
|
157
|
+
if (!selectedId) {
|
|
158
|
+
td.classList.toggle("psp-select-region", false);
|
|
160
159
|
} else {
|
|
161
|
-
const id =
|
|
162
|
-
const key_match =
|
|
160
|
+
const id = model._ids[(metadata.y ?? 0) - (metadata.y0 ?? 0)];
|
|
161
|
+
const key_match = selectedId.reduce<boolean>(
|
|
163
162
|
(agg, x, i) => agg && x === id[i],
|
|
164
163
|
true,
|
|
165
164
|
);
|
|
166
165
|
|
|
167
|
-
const
|
|
166
|
+
const isExact = id.length === selectedId.length && key_match;
|
|
167
|
+
const isSub = id.length !== selectedId.length && key_match;
|
|
168
|
+
|
|
168
169
|
if (isHeader) {
|
|
169
170
|
if (
|
|
170
171
|
metadata.type === "row_header" &&
|
|
171
172
|
metadata.row_header_x !== undefined &&
|
|
172
173
|
!!id[metadata.row_header_x]
|
|
173
174
|
) {
|
|
174
|
-
td.classList.toggle("psp-
|
|
175
|
-
td.classList.toggle("psp-row-subselected", false);
|
|
175
|
+
td.classList.toggle("psp-select-region", false);
|
|
176
176
|
} else {
|
|
177
|
+
td.classList.toggle("psp-select-region", isExact);
|
|
177
178
|
td.classList.toggle(
|
|
178
|
-
"psp-
|
|
179
|
-
|
|
180
|
-
);
|
|
181
|
-
td.classList.toggle(
|
|
182
|
-
"psp-row-subselected",
|
|
183
|
-
id.length !== selectedArr.length && key_match,
|
|
179
|
+
"psp-select-region-inactive",
|
|
180
|
+
isSub,
|
|
184
181
|
);
|
|
185
182
|
}
|
|
186
183
|
} else {
|
|
187
|
-
td.classList.toggle(
|
|
188
|
-
|
|
189
|
-
id.length === selectedArr.length && key_match,
|
|
190
|
-
);
|
|
191
|
-
td.classList.toggle(
|
|
192
|
-
"psp-row-subselected",
|
|
193
|
-
id.length !== selectedArr.length && key_match,
|
|
194
|
-
);
|
|
184
|
+
td.classList.toggle("psp-select-region", isExact);
|
|
185
|
+
td.classList.toggle("psp-select-region-inactive", isSub);
|
|
195
186
|
}
|
|
196
187
|
}
|
|
188
|
+
// } else if (
|
|
189
|
+
// model._edit_mode === "READ_ONLY" ||
|
|
190
|
+
// model._edit_mode === "EDIT"
|
|
191
|
+
// ) {
|
|
192
|
+
// td.classList.toggle("psp-select-region", false);
|
|
197
193
|
}
|
|
198
194
|
|
|
199
195
|
// Apply editable styling (if editable)
|
|
200
196
|
if (!isHeader && metadata.type === "body") {
|
|
201
|
-
if (isEditable &&
|
|
197
|
+
if (isEditable && model._is_editable[metadata.x]) {
|
|
202
198
|
const col_name =
|
|
203
|
-
metadata.column_header?.[
|
|
199
|
+
metadata.column_header?.[model._config.split_by.length];
|
|
204
200
|
const col_name_str = col_name?.toString();
|
|
205
201
|
if (
|
|
206
202
|
col_name_str &&
|
|
@@ -219,6 +215,7 @@ export function applyBodyCellStyles(
|
|
|
219
215
|
if (isEditable !== td.hasAttribute("contenteditable")) {
|
|
220
216
|
td.toggleAttribute("contenteditable", isEditable);
|
|
221
217
|
}
|
|
218
|
+
|
|
222
219
|
td.classList.toggle("boolean-editable", false);
|
|
223
220
|
}
|
|
224
221
|
} else {
|
|
@@ -11,12 +11,9 @@
|
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
13
|
import { RegularTableElement } from "regular-table";
|
|
14
|
-
import {
|
|
15
|
-
get_psp_type,
|
|
16
|
-
type DatagridModel,
|
|
17
|
-
type PerspectiveViewerElement,
|
|
18
|
-
} from "../types.js";
|
|
14
|
+
import { get_psp_type, type DatagridModel } from "../types.js";
|
|
19
15
|
import { CollectedHeaderRow } from "./types.js";
|
|
16
|
+
import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
|
|
20
17
|
|
|
21
18
|
/**
|
|
22
19
|
* Apply selected column styling in response to column settings toggle events.
|
|
@@ -24,9 +21,9 @@ import { CollectedHeaderRow } from "./types.js";
|
|
|
24
21
|
* the column settings panel.
|
|
25
22
|
*/
|
|
26
23
|
export function style_selected_column(
|
|
27
|
-
|
|
24
|
+
model: DatagridModel,
|
|
28
25
|
regularTable: RegularTableElement,
|
|
29
|
-
viewer:
|
|
26
|
+
viewer: HTMLPerspectiveViewerElement,
|
|
30
27
|
selectedColumn: string | undefined,
|
|
31
28
|
): void {
|
|
32
29
|
const group_header_trs = Array.from(
|
|
@@ -72,10 +69,13 @@ export function style_selected_column(
|
|
|
72
69
|
const open = title.textContent === selectedColumn;
|
|
73
70
|
title.classList.toggle("psp-menu-open", open);
|
|
74
71
|
editBtn.classList.toggle("psp-menu-open", open);
|
|
75
|
-
if (
|
|
72
|
+
if (model._config.columns.length > 1) {
|
|
76
73
|
for (const r of regularTable.querySelectorAll("td")) {
|
|
77
74
|
const meta = regularTable.getMeta(r);
|
|
78
|
-
if (!meta?.column_header)
|
|
75
|
+
if (!meta?.column_header) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
79
|
const isOpen =
|
|
80
80
|
meta.column_header[
|
|
81
81
|
meta.column_header.length - 2
|
|
@@ -92,34 +92,35 @@ export function style_selected_column(
|
|
|
92
92
|
* Style a single column header row.
|
|
93
93
|
*/
|
|
94
94
|
export function styleColumnHeaderRow(
|
|
95
|
-
|
|
95
|
+
model: DatagridModel,
|
|
96
96
|
headerRow: CollectedHeaderRow,
|
|
97
97
|
regularTable: RegularTableElement,
|
|
98
98
|
is_menu_row: boolean,
|
|
99
99
|
): void {
|
|
100
100
|
const header_depth =
|
|
101
|
-
|
|
102
|
-
(
|
|
101
|
+
model._config.group_by.length -
|
|
102
|
+
(model._config.group_rollup_mode === "flat" ? 1 : 0);
|
|
103
103
|
|
|
104
|
-
const selectedColumn =
|
|
104
|
+
const selectedColumn = model._column_settings_selected_column;
|
|
105
105
|
for (const { element: td, metadata } of headerRow.cells) {
|
|
106
106
|
if (
|
|
107
107
|
!metadata ||
|
|
108
108
|
metadata.type === "body" ||
|
|
109
109
|
metadata.type === "row_header"
|
|
110
|
-
)
|
|
110
|
+
) {
|
|
111
111
|
continue;
|
|
112
|
+
}
|
|
112
113
|
|
|
113
114
|
const column_name =
|
|
114
|
-
metadata.column_header?.[
|
|
115
|
+
metadata.column_header?.[model._config.split_by.length];
|
|
115
116
|
|
|
116
|
-
const sort =
|
|
117
|
+
const sort = model._config.sort.find((x) => x[0] === column_name);
|
|
117
118
|
const is_corner = typeof metadata.x === "undefined";
|
|
118
119
|
const needs_border =
|
|
119
120
|
(metadata.type === "corner" &&
|
|
120
121
|
metadata.row_header_x === header_depth) ||
|
|
121
122
|
(!is_corner &&
|
|
122
|
-
(metadata.x + 1) %
|
|
123
|
+
(metadata.x + 1) % model._config.columns.length === 0);
|
|
123
124
|
|
|
124
125
|
td.classList.toggle("psp-header-border", needs_border);
|
|
125
126
|
td.classList.toggle("psp-header-group", false);
|
|
@@ -159,7 +160,7 @@ export function styleColumnHeaderRow(
|
|
|
159
160
|
!is_menu_row && !!sort && sort[1] === "col desc abs",
|
|
160
161
|
);
|
|
161
162
|
|
|
162
|
-
const type = get_psp_type(
|
|
163
|
+
const type = get_psp_type(model, metadata);
|
|
163
164
|
const is_numeric = type === "integer" || type === "float";
|
|
164
165
|
const is_string = type === "string";
|
|
165
166
|
const is_date = type === "date";
|
|
@@ -171,13 +172,13 @@ export function styleColumnHeaderRow(
|
|
|
171
172
|
"psp-menu-enabled",
|
|
172
173
|
(is_string || is_numeric || is_date || is_datetime) &&
|
|
173
174
|
!is_corner &&
|
|
174
|
-
metadata.column_header_y ===
|
|
175
|
+
metadata.column_header_y === model._config.split_by.length + 1,
|
|
175
176
|
);
|
|
176
177
|
td.classList.toggle(
|
|
177
178
|
"psp-sort-enabled",
|
|
178
179
|
(is_string || is_numeric || is_date || is_datetime) &&
|
|
179
180
|
!is_corner &&
|
|
180
|
-
metadata.column_header_y ===
|
|
181
|
+
metadata.column_header_y === model._config.split_by.length,
|
|
181
182
|
);
|
|
182
183
|
td.classList.toggle(
|
|
183
184
|
"psp-is-width-override",
|
|
@@ -185,7 +186,7 @@ export function styleColumnHeaderRow(
|
|
|
185
186
|
);
|
|
186
187
|
|
|
187
188
|
// Apply menu-open for selected column
|
|
188
|
-
if (
|
|
189
|
+
if (model._config.columns.length > 1 && selectedColumn) {
|
|
189
190
|
const isOpen =
|
|
190
191
|
metadata.column_header?.[metadata.column_header.length - 2] ===
|
|
191
192
|
selectedColumn;
|
|
@@ -14,69 +14,19 @@ import { RegularTableElement } from "regular-table";
|
|
|
14
14
|
import { PRIVATE_PLUGIN_SYMBOL } from "../model/index.js";
|
|
15
15
|
import type {
|
|
16
16
|
DatagridModel,
|
|
17
|
-
PerspectiveViewerElement,
|
|
18
17
|
ColumnsConfig,
|
|
19
18
|
DatagridPluginElement,
|
|
20
|
-
|
|
19
|
+
SelectedPositionMap,
|
|
21
20
|
} from "../types.js";
|
|
21
|
+
import { isEditableMode } from "../types.js";
|
|
22
|
+
import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
|
|
22
23
|
|
|
23
24
|
import { applyFocusStyle } from "./focus.js";
|
|
24
|
-
import { styleColumnHeaderRow } from "./column_header.js";
|
|
25
25
|
import { applyColumnHeaderStyles } from "./editable.js";
|
|
26
26
|
import { applyGroupHeaderStyles } from "./group_header.js";
|
|
27
27
|
import { applyBodyCellStyles } from "./body.js";
|
|
28
28
|
import { CellMetadata } from "regular-table/dist/esm/types.js";
|
|
29
|
-
|
|
30
|
-
interface CollectedCell {
|
|
31
|
-
element: HTMLElement;
|
|
32
|
-
metadata: CellMetadata;
|
|
33
|
-
isHeader: boolean;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
interface CollectedHeaderRow {
|
|
37
|
-
row: HTMLTableRowElement;
|
|
38
|
-
cells: Array<{
|
|
39
|
-
element: HTMLTableCellElement;
|
|
40
|
-
metadata: CellMetadata | undefined;
|
|
41
|
-
}>;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Context object passed through consolidated styling
|
|
46
|
-
*/
|
|
47
|
-
export interface StyleContext {
|
|
48
|
-
model: DatagridModel;
|
|
49
|
-
regularTable: RegularTableElement;
|
|
50
|
-
viewer: PerspectiveViewerElement;
|
|
51
|
-
datagrid: DatagridPluginElement;
|
|
52
|
-
plugins: ColumnsConfig;
|
|
53
|
-
isSettingsOpen: boolean;
|
|
54
|
-
isSelectable: boolean;
|
|
55
|
-
isEditable: boolean;
|
|
56
|
-
selectedRowsMap: Map<RegularTableElement, unknown[]>;
|
|
57
|
-
selectedPositionMap: Map<RegularTableElement, SelectedPosition>;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Local types for selection maps - match the actual runtime usage
|
|
61
|
-
// (activate.ts uses `as any` casts when passing these)
|
|
62
|
-
type LocalSelectedRowsMap = WeakMap<RegularTableElement, unknown[]>;
|
|
63
|
-
type LocalSelectedPositionMap = WeakMap<RegularTableElement, SelectedPosition>;
|
|
64
|
-
|
|
65
|
-
function isEditableMode(
|
|
66
|
-
model: DatagridModel,
|
|
67
|
-
viewer: PerspectiveViewerElement,
|
|
68
|
-
allowed: boolean = false,
|
|
69
|
-
): boolean {
|
|
70
|
-
const has_pivots =
|
|
71
|
-
model._config.group_by.length === 0 &&
|
|
72
|
-
model._config.split_by.length === 0;
|
|
73
|
-
const selectable = viewer.hasAttribute("selectable");
|
|
74
|
-
const plugin = viewer.children[0] as
|
|
75
|
-
| (DatagridPluginElement & { dataset: DOMStringMap })
|
|
76
|
-
| undefined;
|
|
77
|
-
const editable = allowed || plugin?.dataset?.editMode === "EDIT";
|
|
78
|
-
return has_pivots && !selectable && editable;
|
|
79
|
-
}
|
|
29
|
+
import { CollectedCell, CollectedHeaderRow } from "./types.js";
|
|
80
30
|
|
|
81
31
|
/**
|
|
82
32
|
* Consolidated style listener that handles all cell styling in a single pass.
|
|
@@ -86,24 +36,18 @@ function isEditableMode(
|
|
|
86
36
|
*/
|
|
87
37
|
export function createConsolidatedStyleListener(
|
|
88
38
|
datagrid: DatagridPluginElement,
|
|
89
|
-
|
|
90
|
-
selectedPositionMap: LocalSelectedPositionMap,
|
|
91
|
-
): (
|
|
92
|
-
this: DatagridModel,
|
|
39
|
+
model: DatagridModel,
|
|
93
40
|
regularTable: RegularTableElement,
|
|
94
|
-
viewer:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
regularTable: RegularTableElement,
|
|
99
|
-
viewer: PerspectiveViewerElement,
|
|
100
|
-
): void {
|
|
41
|
+
viewer: HTMLPerspectiveViewerElement,
|
|
42
|
+
selectedPositionMap: SelectedPositionMap,
|
|
43
|
+
): () => void {
|
|
44
|
+
return function consolidatedStyleListener(): void {
|
|
101
45
|
const plugins: ColumnsConfig =
|
|
102
46
|
(regularTable as any)[PRIVATE_PLUGIN_SYMBOL] || {};
|
|
103
47
|
const isSettingsOpen = viewer.hasAttribute("settings");
|
|
104
|
-
const isSelectable =
|
|
105
|
-
const isEditable = isEditableMode(
|
|
106
|
-
const isEditableAllowed = isEditableMode(
|
|
48
|
+
const isSelectable = model._edit_mode === "SELECT_ROW_TREE";
|
|
49
|
+
const isEditable = isEditableMode(model, viewer);
|
|
50
|
+
const isEditableAllowed = isEditableMode(model, viewer, true);
|
|
107
51
|
|
|
108
52
|
// Toggle edit mode class on datagrid
|
|
109
53
|
datagrid.classList.toggle("edit-mode-allowed", isEditableAllowed);
|
|
@@ -117,7 +61,11 @@ export function createConsolidatedStyleListener(
|
|
|
117
61
|
cell as HTMLElement,
|
|
118
62
|
) as CellMetadata | undefined;
|
|
119
63
|
|
|
120
|
-
if (
|
|
64
|
+
if (
|
|
65
|
+
metadata &&
|
|
66
|
+
(metadata.type === "body" ||
|
|
67
|
+
metadata.type === "row_header")
|
|
68
|
+
) {
|
|
121
69
|
const isHeader = cell.tagName === "TH";
|
|
122
70
|
bodyCells.push({
|
|
123
71
|
element: cell as HTMLElement,
|
|
@@ -148,71 +96,23 @@ export function createConsolidatedStyleListener(
|
|
|
148
96
|
metadata,
|
|
149
97
|
});
|
|
150
98
|
}
|
|
99
|
+
|
|
151
100
|
groupHeaderRows.push(rowData);
|
|
152
101
|
}
|
|
153
102
|
}
|
|
154
103
|
|
|
155
|
-
|
|
104
|
+
applyBodyCellStyles(
|
|
105
|
+
model,
|
|
156
106
|
bodyCells,
|
|
157
107
|
plugins,
|
|
158
108
|
isSettingsOpen,
|
|
159
109
|
isSelectable,
|
|
160
110
|
isEditable,
|
|
161
111
|
regularTable,
|
|
162
|
-
selectedRowsMap,
|
|
163
|
-
selectedPositionMap,
|
|
164
|
-
viewer,
|
|
165
112
|
);
|
|
166
113
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
114
|
+
applyGroupHeaderStyles(model, groupHeaderRows, regularTable);
|
|
115
|
+
applyColumnHeaderStyles(model, groupHeaderRows, regularTable, viewer);
|
|
116
|
+
applyFocusStyle(model, bodyCells, regularTable, selectedPositionMap);
|
|
170
117
|
};
|
|
171
118
|
}
|
|
172
|
-
|
|
173
|
-
declare module "../types.js" {
|
|
174
|
-
interface DatagridModel {
|
|
175
|
-
_applyBodyCellStyles(
|
|
176
|
-
cells: CollectedCell[],
|
|
177
|
-
plugins: ColumnsConfig,
|
|
178
|
-
isSettingsOpen: boolean,
|
|
179
|
-
isSelectable: boolean,
|
|
180
|
-
isEditable: boolean,
|
|
181
|
-
regularTable: RegularTableElement,
|
|
182
|
-
selectedRowsMap: LocalSelectedRowsMap,
|
|
183
|
-
selectedPositionMap: LocalSelectedPositionMap,
|
|
184
|
-
viewer: PerspectiveViewerElement,
|
|
185
|
-
): void;
|
|
186
|
-
_applyGroupHeaderStyles(
|
|
187
|
-
headerRows: CollectedHeaderRow[],
|
|
188
|
-
regularTable: RegularTableElement,
|
|
189
|
-
): void;
|
|
190
|
-
_applyColumnHeaderStyles(
|
|
191
|
-
headerRows: CollectedHeaderRow[],
|
|
192
|
-
regularTable: RegularTableElement,
|
|
193
|
-
viewer: PerspectiveViewerElement,
|
|
194
|
-
): void;
|
|
195
|
-
_applyFocusStyle(
|
|
196
|
-
cells: CollectedCell[],
|
|
197
|
-
regularTable: RegularTableElement,
|
|
198
|
-
selectedPositionMap: LocalSelectedPositionMap,
|
|
199
|
-
): void;
|
|
200
|
-
_styleColumnHeaderRow(
|
|
201
|
-
headerRow: CollectedHeaderRow,
|
|
202
|
-
regularTable: RegularTableElement,
|
|
203
|
-
is_menu_row: boolean,
|
|
204
|
-
): void;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Install the styling methods on the DatagridModel prototype.
|
|
210
|
-
* This should be called once during module initialization.
|
|
211
|
-
*/
|
|
212
|
-
export function installConsolidatedStyleMethods(modelPrototype: any): void {
|
|
213
|
-
modelPrototype._applyBodyCellStyles = applyBodyCellStyles;
|
|
214
|
-
modelPrototype._applyGroupHeaderStyles = applyGroupHeaderStyles;
|
|
215
|
-
modelPrototype._applyColumnHeaderStyles = applyColumnHeaderStyles;
|
|
216
|
-
modelPrototype._applyFocusStyle = applyFocusStyle;
|
|
217
|
-
modelPrototype._styleColumnHeaderRow = styleColumnHeaderRow;
|
|
218
|
-
}
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
|
|
13
13
|
import { RegularTableElement } from "regular-table";
|
|
14
14
|
|
|
15
|
-
import type { DatagridModel
|
|
15
|
+
import type { DatagridModel } from "../types.js";
|
|
16
|
+
import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
|
|
17
|
+
import { styleColumnHeaderRow } from "./column_header.js";
|
|
16
18
|
|
|
17
19
|
import { CollectedHeaderRow } from "./types.js";
|
|
18
20
|
|
|
@@ -20,15 +22,17 @@ import { CollectedHeaderRow } from "./types.js";
|
|
|
20
22
|
* Apply styles to column header rows.
|
|
21
23
|
*/
|
|
22
24
|
export function applyColumnHeaderStyles(
|
|
23
|
-
|
|
25
|
+
model: DatagridModel,
|
|
24
26
|
headerRows: CollectedHeaderRow[],
|
|
25
27
|
regularTable: RegularTableElement,
|
|
26
|
-
viewer:
|
|
28
|
+
viewer: HTMLPerspectiveViewerElement,
|
|
27
29
|
): void {
|
|
28
|
-
if (headerRows.length === 0)
|
|
30
|
+
if (headerRows.length === 0) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
29
33
|
|
|
30
34
|
// Style selected column for settings panel
|
|
31
|
-
const selectedColumn =
|
|
35
|
+
const selectedColumn = model._column_settings_selected_column;
|
|
32
36
|
const len = headerRows.length;
|
|
33
37
|
const settings_open = viewer.hasAttribute("settings");
|
|
34
38
|
|
|
@@ -66,7 +70,9 @@ export function applyColumnHeaderStyles(
|
|
|
66
70
|
for (let i = 0; i < titlesRow.cells.length; i++) {
|
|
67
71
|
const title = titlesRow.cells[i]?.element;
|
|
68
72
|
const editBtn = editBtnsRow.cells[i]?.element;
|
|
69
|
-
if (!title || !editBtn)
|
|
73
|
+
if (!title || !editBtn) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
70
76
|
|
|
71
77
|
const open = title.textContent === selectedColumn;
|
|
72
78
|
title.classList.toggle("psp-menu-open", open);
|
|
@@ -76,19 +82,19 @@ export function applyColumnHeaderStyles(
|
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
// Style the actual column header rows
|
|
79
|
-
const colHeadersIndex =
|
|
85
|
+
const colHeadersIndex = model._config.split_by.length;
|
|
80
86
|
if (colHeadersIndex < headerRows.length) {
|
|
81
87
|
const colHeaders = headerRows[colHeadersIndex];
|
|
82
88
|
if (colHeaders) {
|
|
83
|
-
|
|
89
|
+
styleColumnHeaderRow(model, colHeaders, regularTable, false);
|
|
84
90
|
}
|
|
85
91
|
}
|
|
86
92
|
|
|
87
|
-
const menuHeadersIndex =
|
|
93
|
+
const menuHeadersIndex = model._config.split_by.length + 1;
|
|
88
94
|
if (menuHeadersIndex < headerRows.length) {
|
|
89
95
|
const menuHeaders = headerRows[menuHeadersIndex];
|
|
90
96
|
if (menuHeaders) {
|
|
91
|
-
|
|
97
|
+
styleColumnHeaderRow(model, menuHeaders, regularTable, true);
|
|
92
98
|
}
|
|
93
99
|
}
|
|
94
100
|
}
|
|
@@ -11,18 +11,18 @@
|
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
13
|
import { RegularTableElement } from "regular-table";
|
|
14
|
-
import type { DatagridModel,
|
|
15
|
-
import { CollectedCell
|
|
14
|
+
import type { DatagridModel, SelectedPositionMap } from "../types.js";
|
|
15
|
+
import { CollectedCell } from "./types.js";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Apply focus style to the selected cell.
|
|
19
19
|
* Optimized to use collected cells instead of querySelectorAll.
|
|
20
20
|
*/
|
|
21
21
|
export function applyFocusStyle(
|
|
22
|
-
|
|
22
|
+
_model: DatagridModel,
|
|
23
23
|
cells: CollectedCell[],
|
|
24
24
|
regularTable: RegularTableElement,
|
|
25
|
-
selectedPositionMap:
|
|
25
|
+
selectedPositionMap: SelectedPositionMap,
|
|
26
26
|
): void {
|
|
27
27
|
const selected_position = selectedPositionMap.get(regularTable);
|
|
28
28
|
const host = regularTable.getRootNode() as Document;
|
|
@@ -37,6 +37,7 @@ export function applyFocusStyle(
|
|
|
37
37
|
if (host.activeElement !== td) {
|
|
38
38
|
td.focus({ preventScroll: true });
|
|
39
39
|
}
|
|
40
|
+
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
42
43
|
}
|
|
@@ -60,7 +61,7 @@ export function applyFocusStyle(
|
|
|
60
61
|
*/
|
|
61
62
|
export function focusSelectedCell(
|
|
62
63
|
regularTable: RegularTableElement,
|
|
63
|
-
selectedPositionMap:
|
|
64
|
+
selectedPositionMap: SelectedPositionMap,
|
|
64
65
|
): boolean {
|
|
65
66
|
const selected_position = selectedPositionMap.get(regularTable);
|
|
66
67
|
if (!selected_position) {
|
|
@@ -82,6 +83,7 @@ export function focusSelectedCell(
|
|
|
82
83
|
if (host.activeElement !== cell) {
|
|
83
84
|
(cell as HTMLElement).focus({ preventScroll: true });
|
|
84
85
|
}
|
|
86
|
+
|
|
85
87
|
return true;
|
|
86
88
|
}
|
|
87
89
|
}
|