@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.
Files changed (80) hide show
  1. package/dist/cdn/perspective-viewer-datagrid.js +4 -22
  2. package/dist/cdn/perspective-viewer-datagrid.js.map +4 -4
  3. package/dist/css/perspective-viewer-datagrid-toolbar.css +1 -1
  4. package/dist/css/perspective-viewer-datagrid.css +1 -1
  5. package/dist/esm/color_utils.d.ts +22 -0
  6. package/dist/esm/custom_elements/datagrid.d.ts +5 -5
  7. package/dist/esm/data_listener/format_cell.d.ts +1 -1
  8. package/dist/esm/data_listener/formatter_cache.d.ts +1 -1
  9. package/dist/esm/data_listener/index.d.ts +3 -2
  10. package/dist/esm/event_handlers/click/edit_click.d.ts +3 -2
  11. package/dist/esm/event_handlers/click.d.ts +4 -6
  12. package/dist/esm/event_handlers/dispatch_click.d.ts +3 -2
  13. package/dist/esm/event_handlers/expand_collapse.d.ts +1 -1
  14. package/dist/esm/event_handlers/focus.d.ts +4 -5
  15. package/dist/esm/event_handlers/header_click.d.ts +5 -3
  16. package/dist/esm/event_handlers/keydown/edit_keydown.d.ts +3 -4
  17. package/dist/esm/event_handlers/select_region.d.ts +3 -1
  18. package/dist/esm/event_handlers/sort.d.ts +8 -7
  19. package/dist/esm/model/create.d.ts +1 -1
  20. package/dist/esm/perspective-viewer-datagrid.js +3 -3
  21. package/dist/esm/perspective-viewer-datagrid.js.map +4 -4
  22. package/dist/esm/plugin/activate.d.ts +1 -1
  23. package/dist/esm/plugin/column_style_controls.d.ts +1 -1
  24. package/dist/esm/style_handlers/body.d.ts +3 -3
  25. package/dist/esm/style_handlers/column_header.d.ts +4 -3
  26. package/dist/esm/style_handlers/consolidated.d.ts +3 -47
  27. package/dist/esm/style_handlers/editable.d.ts +3 -2
  28. package/dist/esm/style_handlers/focus.d.ts +4 -4
  29. package/dist/esm/style_handlers/group_header.d.ts +1 -1
  30. package/dist/esm/style_handlers/table_cell/boolean.d.ts +1 -1
  31. package/dist/esm/style_handlers/table_cell/cell_flash.d.ts +1 -1
  32. package/dist/esm/style_handlers/table_cell/datetime.d.ts +1 -1
  33. package/dist/esm/style_handlers/table_cell/numeric.d.ts +1 -1
  34. package/dist/esm/style_handlers/table_cell/row_header.d.ts +1 -1
  35. package/dist/esm/style_handlers/table_cell/string.d.ts +1 -1
  36. package/dist/esm/style_handlers/types.d.ts +0 -4
  37. package/dist/esm/types.d.ts +10 -17
  38. package/package.json +2 -4
  39. package/src/css/regular_table.css +87 -31
  40. package/src/css/row-hover.css +20 -7
  41. package/src/css/toolbar.css +11 -0
  42. package/src/ts/color_utils.ts +144 -16
  43. package/src/ts/custom_elements/datagrid.ts +11 -12
  44. package/src/ts/custom_elements/toolbar.ts +4 -5
  45. package/src/ts/data_listener/format_cell.ts +28 -9
  46. package/src/ts/data_listener/formatter_cache.ts +1 -1
  47. package/src/ts/data_listener/index.ts +4 -8
  48. package/src/ts/event_handlers/click/edit_click.ts +7 -6
  49. package/src/ts/event_handlers/click.ts +39 -68
  50. package/src/ts/event_handlers/dispatch_click.ts +24 -25
  51. package/src/ts/event_handlers/expand_collapse.ts +7 -7
  52. package/src/ts/event_handlers/focus.ts +38 -35
  53. package/src/ts/event_handlers/header_click.ts +101 -62
  54. package/src/ts/event_handlers/keydown/edit_keydown.ts +49 -52
  55. package/src/ts/event_handlers/select_region.ts +144 -133
  56. package/src/ts/event_handlers/sort.ts +16 -24
  57. package/src/ts/model/column_overrides.ts +13 -4
  58. package/src/ts/model/create.ts +51 -55
  59. package/src/ts/model/toolbar.ts +23 -7
  60. package/src/ts/plugin/activate.ts +120 -92
  61. package/src/ts/plugin/column_style_controls.ts +1 -1
  62. package/src/ts/plugin/save.ts +1 -0
  63. package/src/ts/style_handlers/body.ts +44 -51
  64. package/src/ts/style_handlers/column_header.ts +16 -19
  65. package/src/ts/style_handlers/consolidated.ts +22 -123
  66. package/src/ts/style_handlers/editable.ts +10 -8
  67. package/src/ts/style_handlers/focus.ts +5 -5
  68. package/src/ts/style_handlers/group_header.ts +3 -2
  69. package/src/ts/style_handlers/table_cell/boolean.ts +3 -3
  70. package/src/ts/style_handlers/table_cell/cell_flash.ts +11 -11
  71. package/src/ts/style_handlers/table_cell/datetime.ts +3 -3
  72. package/src/ts/style_handlers/table_cell/numeric.ts +24 -25
  73. package/src/ts/style_handlers/table_cell/row_header.ts +2 -2
  74. package/src/ts/style_handlers/table_cell/string.ts +20 -18
  75. package/src/ts/style_handlers/types.ts +0 -10
  76. package/src/ts/types.ts +28 -20
  77. package/dist/esm/event_handlers/deselect_all.d.ts +0 -5
  78. package/dist/esm/event_handlers/row_select_click.d.ts +0 -4
  79. package/src/ts/event_handlers/deselect_all.ts +0 -28
  80. package/src/ts/event_handlers/row_select_click.ts +0 -92
@@ -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
- this: DatagridModel,
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 hasSelected = selectedRowsMap.has(regularTable);
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
- this._config.group_rollup_mode === "flat",
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?.[this._config.split_by.length];
60
- const type = get_psp_type(this, metadata);
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
- this._config.group_rollup_mode === "rollup" &&
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
- this._config.group_by.length,
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.call(
86
- this,
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.call(this, plugin, td, metadata as any);
83
+ cell_style_boolean(model, plugin, td, metadata as any);
94
84
  } else if (type === "string") {
95
- cell_style_string.call(this, plugin as any, td, metadata as any);
85
+ cell_style_string(model, plugin as any, td, metadata as any);
96
86
  } else if (type === "date" || type === "datetime") {
97
- cell_style_datetime.call(this, plugin as any, td, metadata);
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 (this._column_settings_selected_column) {
102
+ if (model._column_settings_selected_column) {
113
103
  td.classList.toggle(
114
104
  "psp-menu-open",
115
- column_name === this._column_settings_selected_column,
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.call(this, regularTable, td, metadata as any);
123
+ cell_style_row_header(model, regularTable, td, metadata as any);
129
124
  }
130
125
 
131
126
  // Set data attributes
@@ -152,55 +147,53 @@ export function applyBodyCellStyles(
152
147
  delete td.dataset.x;
153
148
  }
154
149
 
155
- // Apply selection styling (if selectable)
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 (!hasSelected) {
158
- td.classList.toggle("psp-row-selected", false);
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 = this._ids[(metadata.y ?? 0) - (metadata.y0 ?? 0)];
162
- const key_match = (selected as unknown[]).reduce<boolean>(
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 selectedArr = selected as unknown[];
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-row-selected", false);
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-row-selected",
179
- id.length === selectedArr.length && key_match,
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
- "psp-row-selected",
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 {
189
+ td.classList.toggle("psp-select-region", false);
197
190
  }
198
191
 
199
192
  // Apply editable styling (if editable)
200
193
  if (!isHeader && metadata.type === "body") {
201
- if (isEditable && this._is_editable[metadata.x]) {
194
+ if (isEditable && model._is_editable[metadata.x]) {
202
195
  const col_name =
203
- metadata.column_header?.[this._config.split_by.length];
196
+ metadata.column_header?.[model._config.split_by.length];
204
197
  const col_name_str = col_name?.toString();
205
198
  if (
206
199
  col_name_str &&
@@ -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
- this: DatagridModel,
24
+ model: DatagridModel,
28
25
  regularTable: RegularTableElement,
29
- viewer: PerspectiveViewerElement,
26
+ viewer: HTMLPerspectiveViewerElement,
30
27
  selectedColumn: string | undefined,
31
28
  ): void {
32
29
  const group_header_trs = Array.from(
@@ -72,7 +69,7 @@ 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 (this._config.columns.length > 1) {
72
+ if (model._config.columns.length > 1) {
76
73
  for (const r of regularTable.querySelectorAll("td")) {
77
74
  const meta = regularTable.getMeta(r);
78
75
  if (!meta?.column_header) continue;
@@ -92,16 +89,16 @@ export function style_selected_column(
92
89
  * Style a single column header row.
93
90
  */
94
91
  export function styleColumnHeaderRow(
95
- this: DatagridModel,
92
+ model: DatagridModel,
96
93
  headerRow: CollectedHeaderRow,
97
94
  regularTable: RegularTableElement,
98
95
  is_menu_row: boolean,
99
96
  ): void {
100
97
  const header_depth =
101
- this._config.group_by.length -
102
- (this._config.group_rollup_mode === "flat" ? 1 : 0);
98
+ model._config.group_by.length -
99
+ (model._config.group_rollup_mode === "flat" ? 1 : 0);
103
100
 
104
- const selectedColumn = this._column_settings_selected_column;
101
+ const selectedColumn = model._column_settings_selected_column;
105
102
  for (const { element: td, metadata } of headerRow.cells) {
106
103
  if (
107
104
  !metadata ||
@@ -111,15 +108,15 @@ export function styleColumnHeaderRow(
111
108
  continue;
112
109
 
113
110
  const column_name =
114
- metadata.column_header?.[this._config.split_by.length];
111
+ metadata.column_header?.[model._config.split_by.length];
115
112
 
116
- const sort = this._config.sort.find((x) => x[0] === column_name);
113
+ const sort = model._config.sort.find((x) => x[0] === column_name);
117
114
  const is_corner = typeof metadata.x === "undefined";
118
115
  const needs_border =
119
116
  (metadata.type === "corner" &&
120
117
  metadata.row_header_x === header_depth) ||
121
118
  (!is_corner &&
122
- (metadata.x + 1) % this._config.columns.length === 0);
119
+ (metadata.x + 1) % model._config.columns.length === 0);
123
120
 
124
121
  td.classList.toggle("psp-header-border", needs_border);
125
122
  td.classList.toggle("psp-header-group", false);
@@ -159,7 +156,7 @@ export function styleColumnHeaderRow(
159
156
  !is_menu_row && !!sort && sort[1] === "col desc abs",
160
157
  );
161
158
 
162
- const type = get_psp_type(this, metadata);
159
+ const type = get_psp_type(model, metadata);
163
160
  const is_numeric = type === "integer" || type === "float";
164
161
  const is_string = type === "string";
165
162
  const is_date = type === "date";
@@ -171,13 +168,13 @@ export function styleColumnHeaderRow(
171
168
  "psp-menu-enabled",
172
169
  (is_string || is_numeric || is_date || is_datetime) &&
173
170
  !is_corner &&
174
- metadata.column_header_y === this._config.split_by.length + 1,
171
+ metadata.column_header_y === model._config.split_by.length + 1,
175
172
  );
176
173
  td.classList.toggle(
177
174
  "psp-sort-enabled",
178
175
  (is_string || is_numeric || is_date || is_datetime) &&
179
176
  !is_corner &&
180
- metadata.column_header_y === this._config.split_by.length,
177
+ metadata.column_header_y === model._config.split_by.length,
181
178
  );
182
179
  td.classList.toggle(
183
180
  "psp-is-width-override",
@@ -185,7 +182,7 @@ export function styleColumnHeaderRow(
185
182
  );
186
183
 
187
184
  // Apply menu-open for selected column
188
- if (this._config.columns.length > 1 && selectedColumn) {
185
+ if (model._config.columns.length > 1 && selectedColumn) {
189
186
  const isOpen =
190
187
  metadata.column_header?.[metadata.column_header.length - 2] ===
191
188
  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
- SelectedPosition,
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
- selectedRowsMap: LocalSelectedRowsMap,
90
- selectedPositionMap: LocalSelectedPositionMap,
91
- ): (
92
- this: DatagridModel,
39
+ model: DatagridModel,
93
40
  regularTable: RegularTableElement,
94
- viewer: PerspectiveViewerElement,
95
- ) => void {
96
- return function consolidatedStyleListener(
97
- this: DatagridModel,
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 = viewer.hasAttribute("selectable");
105
- const isEditable = isEditableMode(this, viewer);
106
- const isEditableAllowed = isEditableMode(this, viewer, true);
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 (metadata) {
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,
@@ -152,67 +100,18 @@ export function createConsolidatedStyleListener(
152
100
  }
153
101
  }
154
102
 
155
- this._applyBodyCellStyles(
103
+ applyBodyCellStyles(
104
+ model,
156
105
  bodyCells,
157
106
  plugins,
158
107
  isSettingsOpen,
159
108
  isSelectable,
160
109
  isEditable,
161
110
  regularTable,
162
- selectedRowsMap,
163
- selectedPositionMap,
164
- viewer,
165
111
  );
166
112
 
167
- this._applyGroupHeaderStyles(groupHeaderRows, regularTable);
168
- this._applyColumnHeaderStyles(groupHeaderRows, regularTable, viewer);
169
- this._applyFocusStyle(bodyCells, regularTable, selectedPositionMap);
113
+ applyGroupHeaderStyles(model, groupHeaderRows, regularTable);
114
+ applyColumnHeaderStyles(model, groupHeaderRows, regularTable, viewer);
115
+ applyFocusStyle(model, bodyCells, regularTable, selectedPositionMap);
170
116
  };
171
117
  }
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, PerspectiveViewerElement } from "../types.js";
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,15 @@ import { CollectedHeaderRow } from "./types.js";
20
22
  * Apply styles to column header rows.
21
23
  */
22
24
  export function applyColumnHeaderStyles(
23
- this: DatagridModel,
25
+ model: DatagridModel,
24
26
  headerRows: CollectedHeaderRow[],
25
27
  regularTable: RegularTableElement,
26
- viewer: PerspectiveViewerElement,
28
+ viewer: HTMLPerspectiveViewerElement,
27
29
  ): void {
28
30
  if (headerRows.length === 0) return;
29
31
 
30
32
  // Style selected column for settings panel
31
- const selectedColumn = this._column_settings_selected_column;
33
+ const selectedColumn = model._column_settings_selected_column;
32
34
  const len = headerRows.length;
33
35
  const settings_open = viewer.hasAttribute("settings");
34
36
 
@@ -76,19 +78,19 @@ export function applyColumnHeaderStyles(
76
78
  }
77
79
 
78
80
  // Style the actual column header rows
79
- const colHeadersIndex = this._config.split_by.length;
81
+ const colHeadersIndex = model._config.split_by.length;
80
82
  if (colHeadersIndex < headerRows.length) {
81
83
  const colHeaders = headerRows[colHeadersIndex];
82
84
  if (colHeaders) {
83
- this._styleColumnHeaderRow(colHeaders, regularTable, false);
85
+ styleColumnHeaderRow(model, colHeaders, regularTable, false);
84
86
  }
85
87
  }
86
88
 
87
- const menuHeadersIndex = this._config.split_by.length + 1;
89
+ const menuHeadersIndex = model._config.split_by.length + 1;
88
90
  if (menuHeadersIndex < headerRows.length) {
89
91
  const menuHeaders = headerRows[menuHeadersIndex];
90
92
  if (menuHeaders) {
91
- this._styleColumnHeaderRow(menuHeaders, regularTable, true);
93
+ styleColumnHeaderRow(model, menuHeaders, regularTable, true);
92
94
  }
93
95
  }
94
96
  }
@@ -11,18 +11,18 @@
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
13
  import { RegularTableElement } from "regular-table";
14
- import type { DatagridModel, SelectedPosition } from "../types.js";
15
- import { CollectedCell, LocalSelectedPositionMap } from "./types.js";
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
- this: DatagridModel,
22
+ _model: DatagridModel,
23
23
  cells: CollectedCell[],
24
24
  regularTable: RegularTableElement,
25
- selectedPositionMap: LocalSelectedPositionMap,
25
+ selectedPositionMap: SelectedPositionMap,
26
26
  ): void {
27
27
  const selected_position = selectedPositionMap.get(regularTable);
28
28
  const host = regularTable.getRootNode() as Document;
@@ -60,7 +60,7 @@ export function applyFocusStyle(
60
60
  */
61
61
  export function focusSelectedCell(
62
62
  regularTable: RegularTableElement,
63
- selectedPositionMap: Map<RegularTableElement, SelectedPosition>,
63
+ selectedPositionMap: SelectedPositionMap,
64
64
  ): boolean {
65
65
  const selected_position = selectedPositionMap.get(regularTable);
66
66
  if (!selected_position) {
@@ -19,11 +19,11 @@ import { CollectedHeaderRow } from "./types.js";
19
19
  * Apply styles to group header rows.
20
20
  */
21
21
  export function applyGroupHeaderStyles(
22
- this: DatagridModel,
22
+ model: DatagridModel,
23
23
  headerRows: CollectedHeaderRow[],
24
24
  regularTable: RegularTableElement,
25
25
  ): void {
26
- const header_depth = this._config.group_by.length;
26
+ const header_depth = model._config.group_by.length;
27
27
  const m: boolean[][] = [];
28
28
  let marked = new Set<number>();
29
29
 
@@ -54,6 +54,7 @@ export function applyGroupHeaderStyles(
54
54
  );
55
55
 
56
56
  td.classList.toggle("psp-color-mode-bar", false);
57
+ td.classList.toggle("psp-color-mode-label-bar", false);
57
58
  td.classList.toggle("psp-header-sort-asc", false);
58
59
  td.classList.toggle("psp-header-sort-desc", false);
59
60
  td.classList.toggle("psp-header-sort-col-asc", false);
@@ -14,7 +14,7 @@ import { CellMetadata } from "regular-table/dist/esm/types.js";
14
14
  import type { DatagridModel, ColumnConfig, ColorRecord } from "../../types.js";
15
15
 
16
16
  export function cell_style_boolean(
17
- this: DatagridModel,
17
+ model: DatagridModel,
18
18
  _plugin: ColumnConfig | undefined,
19
19
  td: HTMLElement,
20
20
  metadata: CellMetadata,
@@ -26,9 +26,9 @@ export function cell_style_boolean(
26
26
  } else {
27
27
  const [hex]: ColorRecord | [string, number, number, number, string] =
28
28
  metadata.user === true
29
- ? this._pos_fg_color
29
+ ? model._pos_fg_color
30
30
  : metadata.user === false
31
- ? this._neg_fg_color
31
+ ? model._neg_fg_color
32
32
  : ["", 0, 0, 0, ""];
33
33
  td.style.backgroundColor = "";
34
34
  td.style.color = hex;