@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.
Files changed (87) 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 +16 -21
  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/model/meta_columns.d.ts +1 -0
  21. package/dist/esm/perspective-viewer-datagrid.js +3 -3
  22. package/dist/esm/perspective-viewer-datagrid.js.map +4 -4
  23. package/dist/esm/plugin/activate.d.ts +1 -1
  24. package/dist/esm/plugin/column_config_schema.d.ts +31 -0
  25. package/dist/esm/style_handlers/body.d.ts +3 -3
  26. package/dist/esm/style_handlers/column_header.d.ts +4 -3
  27. package/dist/esm/style_handlers/consolidated.d.ts +3 -47
  28. package/dist/esm/style_handlers/editable.d.ts +3 -2
  29. package/dist/esm/style_handlers/focus.d.ts +4 -4
  30. package/dist/esm/style_handlers/group_header.d.ts +1 -1
  31. package/dist/esm/style_handlers/table_cell/boolean.d.ts +1 -1
  32. package/dist/esm/style_handlers/table_cell/cell_flash.d.ts +1 -1
  33. package/dist/esm/style_handlers/table_cell/datetime.d.ts +1 -1
  34. package/dist/esm/style_handlers/table_cell/numeric.d.ts +1 -1
  35. package/dist/esm/style_handlers/table_cell/row_header.d.ts +1 -1
  36. package/dist/esm/style_handlers/table_cell/string.d.ts +1 -1
  37. package/dist/esm/style_handlers/types.d.ts +0 -4
  38. package/dist/esm/types.d.ts +10 -17
  39. package/package.json +2 -4
  40. package/src/css/regular_table.css +87 -31
  41. package/src/css/row-hover.css +20 -7
  42. package/src/css/toolbar.css +11 -0
  43. package/src/ts/color_utils.ts +181 -16
  44. package/src/ts/custom_elements/datagrid.ts +70 -56
  45. package/src/ts/custom_elements/toolbar.ts +4 -5
  46. package/src/ts/data_listener/format_cell.ts +28 -9
  47. package/src/ts/data_listener/format_tree_header.ts +2 -2
  48. package/src/ts/data_listener/formatter_cache.ts +9 -96
  49. package/src/ts/data_listener/index.ts +13 -11
  50. package/src/ts/event_handlers/click/edit_click.ts +10 -6
  51. package/src/ts/event_handlers/click.ts +39 -68
  52. package/src/ts/event_handlers/dispatch_click.ts +27 -25
  53. package/src/ts/event_handlers/expand_collapse.ts +11 -8
  54. package/src/ts/event_handlers/focus.ts +38 -35
  55. package/src/ts/event_handlers/header_click.ts +107 -62
  56. package/src/ts/event_handlers/keydown/edit_keydown.ts +60 -54
  57. package/src/ts/event_handlers/select_region.ts +153 -131
  58. package/src/ts/event_handlers/sort.ts +20 -25
  59. package/src/ts/get_cell_config.ts +10 -3
  60. package/src/ts/model/column_overrides.ts +16 -9
  61. package/src/ts/model/create.ts +68 -55
  62. package/src/ts/{event_handlers/deselect_all.ts → model/meta_columns.ts} +33 -14
  63. package/src/ts/model/toolbar.ts +33 -8
  64. package/src/ts/plugin/activate.ts +122 -92
  65. package/src/ts/plugin/column_config_schema.ts +187 -0
  66. package/src/ts/plugin/draw.ts +1 -0
  67. package/src/ts/plugin/restore.ts +6 -2
  68. package/src/ts/plugin/save.ts +2 -5
  69. package/src/ts/style_handlers/body.ts +48 -51
  70. package/src/ts/style_handlers/column_header.ts +22 -21
  71. package/src/ts/style_handlers/consolidated.ts +23 -123
  72. package/src/ts/style_handlers/editable.ts +16 -10
  73. package/src/ts/style_handlers/focus.ts +7 -5
  74. package/src/ts/style_handlers/group_header.ts +13 -6
  75. package/src/ts/style_handlers/table_cell/boolean.ts +3 -3
  76. package/src/ts/style_handlers/table_cell/cell_flash.ts +11 -11
  77. package/src/ts/style_handlers/table_cell/datetime.ts +3 -3
  78. package/src/ts/style_handlers/table_cell/numeric.ts +24 -25
  79. package/src/ts/style_handlers/table_cell/row_header.ts +2 -2
  80. package/src/ts/style_handlers/table_cell/string.ts +20 -18
  81. package/src/ts/style_handlers/types.ts +0 -10
  82. package/src/ts/types.ts +28 -20
  83. package/dist/esm/event_handlers/deselect_all.d.ts +0 -5
  84. package/dist/esm/event_handlers/row_select_click.d.ts +0 -4
  85. package/dist/esm/plugin/column_style_controls.d.ts +0 -28
  86. package/src/ts/event_handlers/row_select_click.ts +0 -92
  87. package/src/ts/plugin/column_style_controls.ts +0 -76
@@ -11,20 +11,17 @@
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
13
  import { PRIVATE_PLUGIN_SYMBOL } from "../types.js";
14
+ import { isMetaColumn } from "../model/meta_columns.js";
14
15
  import { format_cell } from "./format_cell.js";
15
16
  import {
16
17
  format_flat_header_row_path,
17
18
  format_tree_header,
18
19
  format_tree_header_row_path,
19
20
  } from "./format_tree_header.js";
20
- import type {
21
- DatagridModel,
22
- PerspectiveViewerElement,
23
- RegularTable,
24
- Schema,
25
- } from "../types.js";
21
+ import type { DatagridModel, RegularTable, Schema } from "../types.js";
26
22
  import type { CellScalar, DataResponse } from "regular-table/dist/esm/types.js";
27
- import { ViewConfig, ViewWindow } from "@perspective-dev/client";
23
+ import type { ViewConfig, ViewWindow } from "@perspective-dev/client";
24
+ import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
28
25
 
29
26
  interface ColumnData {
30
27
  __ROW_PATH__?: unknown[][];
@@ -40,7 +37,7 @@ interface ColumnData {
40
37
  * @returns A data listener for the plugin.
41
38
  */
42
39
  export function createDataListener(
43
- viewer: PerspectiveViewerElement,
40
+ viewer: HTMLPerspectiveViewerElement,
44
41
  ): (
45
42
  regularTable: RegularTable,
46
43
  x0: number,
@@ -88,9 +85,14 @@ export function createDataListener(
88
85
  num_columns = z;
89
86
  columns = JSON.parse(x as string) as ColumnData;
90
87
  const y = Object.keys(columns);
91
- const new_col_paths = y.filter(
92
- (x) => x !== "__ROW_PATH__" && x !== "__ID__",
93
- );
88
+ // `isMetaColumn` covers `__ROW_PATH__`, `__ID__`,
89
+ // `__GROUPING_ID__`, and the per-level `__ROW_PATH_<n>__`
90
+ // columns the DuckDB virtual server emits inline alongside
91
+ // the JSON sidecar. Exact-match against `__ROW_PATH__` /
92
+ // `__ID__` (the previous filter) misses the per-level
93
+ // form and the virtual server's columns leak into the
94
+ // visible grid.
95
+ const new_col_paths = y.filter((x) => !isMetaColumn(x));
94
96
 
95
97
  let changed_cols = false;
96
98
  for (let i = 0; i < new_col_paths.length; i++) {
@@ -14,10 +14,11 @@ import { CellMetadataBody } from "regular-table/dist/esm/types.js";
14
14
  import {
15
15
  type RegularTable,
16
16
  type DatagridModel,
17
- type PerspectiveViewerElement,
18
17
  get_psp_type,
19
18
  } from "../../types.js";
20
19
 
20
+ import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
21
+
21
22
  export function write_cell(
22
23
  table: RegularTable,
23
24
  model: DatagridModel,
@@ -27,6 +28,7 @@ export function write_cell(
27
28
  if (!meta) {
28
29
  return false;
29
30
  }
31
+
30
32
  const type = model._schema[model._column_paths[meta.x!]];
31
33
  let text: string | number | boolean | null = active_cell.textContent || "";
32
34
  const id = model._ids[meta.y! - meta.y0][0];
@@ -35,12 +37,14 @@ export function write_cell(
35
37
  if (isNaN(parsed)) {
36
38
  return false;
37
39
  }
40
+
38
41
  text = parsed;
39
42
  } else if (type === "date" || type === "datetime") {
40
43
  const parsed = Date.parse(text);
41
44
  if (isNaN(parsed)) {
42
45
  return false;
43
46
  }
47
+
44
48
  text = parsed;
45
49
  } else if (type === "boolean") {
46
50
  text = text === "true" ? false : text === "false" ? true : null;
@@ -56,21 +60,21 @@ export function write_cell(
56
60
  }
57
61
 
58
62
  export function clickListener(
59
- this: DatagridModel,
63
+ model: DatagridModel,
60
64
  table: RegularTable,
61
- _viewer: PerspectiveViewerElement,
65
+ _viewer: HTMLPerspectiveViewerElement,
62
66
  event: MouseEvent,
63
67
  ): void {
64
68
  const meta = table.getMeta(event.target as HTMLElement);
65
69
  if (meta?.type === "body" || meta?.type === "column_header") {
66
- const is_editable2 = this._is_editable[meta.x];
67
- const is_bool = get_psp_type(this, meta) === "boolean";
70
+ const is_editable2 = model._is_editable[meta.x];
71
+ const is_bool = get_psp_type(model, meta) === "boolean";
68
72
  const is_null = (event.target as Element).classList.contains(
69
73
  "psp-null",
70
74
  );
71
75
 
72
76
  if (is_editable2 && is_bool && !is_null) {
73
- write_cell(table, this, event.target as HTMLElement);
77
+ write_cell(table, model, event.target as HTMLElement);
74
78
  }
75
79
  }
76
80
  }
@@ -12,81 +12,52 @@
12
12
 
13
13
  import * as edit_click from "./click/edit_click.js";
14
14
  import * as edit_keydown from "./keydown/edit_keydown.js";
15
- import type {
16
- DatagridModel,
17
- PerspectiveViewerElement,
18
- SelectedPosition,
19
- } from "../types.js";
15
+ import type { DatagridModel, SelectedPositionMap } from "../types.js";
16
+ import { isEditableMode } from "../types.js";
20
17
  import { RegularTableElement } from "regular-table";
21
- import { HTMLPerspectiveViewerDatagridPluginElement } from "../custom_elements/datagrid.js";
18
+ import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
22
19
 
23
- type SelectedPositionMap = Map<RegularTableElement, SelectedPosition>;
24
-
25
- export function is_editable(
26
- this: DatagridModel,
27
- viewer: PerspectiveViewerElement,
28
- allowed: boolean = false,
29
- ): boolean {
30
- const has_pivots =
31
- this._config.group_by.length === 0 &&
32
- this._config.split_by.length === 0;
33
- const selectable = viewer.hasAttribute("selectable");
34
- const plugin = viewer.children[0] as
35
- | HTMLPerspectiveViewerDatagridPluginElement
36
- | undefined;
37
- const editable = allowed || !!(plugin?._edit_mode === "EDIT");
38
- return has_pivots && !selectable && editable;
39
- }
40
-
41
- export function keydownListener(
42
- this: DatagridModel,
20
+ export function createKeydownListener(
21
+ model: DatagridModel,
43
22
  table: RegularTableElement,
44
- viewer: PerspectiveViewerElement,
23
+ viewer: HTMLPerspectiveViewerElement,
45
24
  selected_position_map: SelectedPositionMap,
46
- event: KeyboardEvent,
47
- ): void {
48
- if (this._edit_mode === "EDIT") {
49
- if (!is_editable.call(this, viewer)) {
50
- return;
51
- }
25
+ ): EventListener {
26
+ return (event: Event): void => {
27
+ const keyEvent = event as KeyboardEvent;
28
+ if (model._edit_mode === "EDIT") {
29
+ if (!isEditableMode(model, viewer)) {
30
+ return;
31
+ }
52
32
 
53
- edit_keydown.keydownListener.call(
54
- this,
55
- table,
56
- viewer,
57
- selected_position_map,
58
- event,
59
- );
60
- } else {
61
- console.debug(
62
- `Mode ${this._edit_mode} for "keydown" event not yet implemented`,
63
- );
64
- }
33
+ edit_keydown.keydownListener(
34
+ model,
35
+ table,
36
+ viewer,
37
+ selected_position_map,
38
+ keyEvent,
39
+ );
40
+ } else {
41
+ console.debug(
42
+ `Mode ${model._edit_mode} for "keydown" event not yet implemented`,
43
+ );
44
+ }
45
+ };
65
46
  }
66
47
 
67
- export function clickListener(
68
- this: DatagridModel,
48
+ export function createEditClickListener(
49
+ model: DatagridModel,
69
50
  table: RegularTableElement,
70
- viewer: PerspectiveViewerElement,
71
- event: MouseEvent,
72
- ): void {
73
- if (this._edit_mode === "EDIT") {
74
- if (!is_editable.call(this, viewer)) {
75
- return;
76
- }
51
+ viewer: HTMLPerspectiveViewerElement,
52
+ ): EventListener {
53
+ return (event: Event): void => {
54
+ const mouseEvent = event as MouseEvent;
55
+ if (model._edit_mode === "EDIT") {
56
+ if (!isEditableMode(model, viewer)) {
57
+ return;
58
+ }
77
59
 
78
- edit_click.clickListener.call(this, table, viewer, event);
79
- } else if (this._edit_mode === "READ_ONLY") {
80
- // No-op for read-only mode
81
- } else if (this._edit_mode === "SELECT_COLUMN") {
82
- // Not yet implemented
83
- } else if (this._edit_mode === "SELECT_ROW") {
84
- // Not yet implemented
85
- } else if (this._edit_mode === "SELECT_REGION") {
86
- // Not yet implemented
87
- } else {
88
- console.debug(
89
- `Mode ${this._edit_mode} for "click" event not yet implemented`,
90
- );
91
- }
60
+ edit_click.clickListener(model, table, viewer, mouseEvent);
61
+ }
62
+ };
92
63
  }
@@ -12,31 +12,33 @@
12
12
 
13
13
  import { RegularTableElement } from "regular-table";
14
14
  import getCellConfig from "../get_cell_config.js";
15
- import type {
16
- DatagridModel,
17
- PerspectiveViewerElement,
18
- PerspectiveClickDetail,
19
- } from "../types.js";
15
+ import type { DatagridModel, PerspectiveClickDetail } from "../types.js";
16
+ import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
20
17
 
21
- export async function dispatch_click_listener(
22
- this: DatagridModel,
18
+ export function createDispatchClickListener(
19
+ model: DatagridModel,
23
20
  table: RegularTableElement,
24
- viewer: PerspectiveViewerElement,
25
- event: MouseEvent,
26
- ): Promise<void> {
27
- const meta = table.getMeta(event.target as HTMLElement);
28
- if (!meta || meta.type !== "body") return;
29
- const { x, y } = meta;
30
- const { row, column_names, config } = await getCellConfig(this, y, x);
31
- viewer.dispatchEvent(
32
- new CustomEvent<PerspectiveClickDetail>("perspective-click", {
33
- bubbles: true,
34
- composed: true,
35
- detail: {
36
- row,
37
- column_names,
38
- config,
39
- },
40
- }),
41
- );
21
+ viewer: HTMLPerspectiveViewerElement,
22
+ ): EventListener {
23
+ return async (event: Event): Promise<void> => {
24
+ const mouseEvent = event as MouseEvent;
25
+ const meta = table.getMeta(mouseEvent.target as HTMLElement);
26
+ if (!meta || meta.type !== "body") {
27
+ return;
28
+ }
29
+
30
+ const { x, y } = meta;
31
+ const { row, column_names, config } = await getCellConfig(model, y, x);
32
+ viewer.dispatchEvent(
33
+ new CustomEvent<PerspectiveClickDetail>("perspective-click", {
34
+ bubbles: true,
35
+ composed: true,
36
+ detail: {
37
+ row,
38
+ column_names,
39
+ config,
40
+ },
41
+ }),
42
+ );
43
+ };
42
44
  }
@@ -13,33 +13,36 @@
13
13
  import type { RegularTable, DatagridModel } from "../types.js";
14
14
 
15
15
  export async function expandCollapseHandler(
16
- this: DatagridModel,
16
+ model: DatagridModel,
17
17
  regularTable: RegularTable,
18
18
  event: MouseEvent,
19
19
  ): Promise<void> {
20
20
  const meta = regularTable.getMeta(event.target as HTMLElement);
21
- if (!meta || meta.type !== "row_header") return;
21
+ if (!meta || meta.type !== "row_header") {
22
+ return;
23
+ }
24
+
22
25
  const is_collapse = (event.target as Element).classList.contains(
23
26
  "psp-tree-label-collapse",
24
27
  );
25
28
 
26
29
  if (event.shiftKey && is_collapse) {
27
- this._view.set_depth(
30
+ model._view.set_depth(
28
31
  (meta.row_header as unknown[]).filter((x) => x !== undefined)
29
32
  .length - 2,
30
33
  );
31
34
  } else if (event.shiftKey) {
32
- this._view.set_depth(
35
+ model._view.set_depth(
33
36
  (meta.row_header as unknown[]).filter((x) => x !== undefined)
34
37
  .length - 1,
35
38
  );
36
39
  } else if (is_collapse) {
37
- this._view.collapse(meta.y);
40
+ model._view.collapse(meta.y);
38
41
  } else {
39
- this._view.expand(meta.y);
42
+ model._view.expand(meta.y);
40
43
  }
41
44
 
42
- this._num_rows = await this._view.num_rows();
43
- this._num_columns = await this._view.num_columns();
45
+ model._num_rows = await model._view.num_rows();
46
+ model._num_columns = await model._view.num_columns();
44
47
  regularTable.draw();
45
48
  }
@@ -10,54 +10,57 @@
10
10
  // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
- import { is_editable } from "./click.js";
14
13
  import { write_cell } from "./click/edit_click.js";
15
14
  import type {
16
15
  RegularTable,
17
16
  DatagridModel,
18
- PerspectiveViewerElement,
19
17
  SelectedPosition,
18
+ SelectedPositionMap,
20
19
  } from "../types.js";
20
+ import { isEditableMode } from "../types.js";
21
+ import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
21
22
 
22
- type SelectedPositionMap = Map<RegularTable, SelectedPosition>;
23
-
24
- export function focusoutListener(
25
- this: DatagridModel,
23
+ export function createFocusoutListener(
24
+ model: DatagridModel,
26
25
  table: RegularTable,
27
- viewer: PerspectiveViewerElement,
26
+ viewer: HTMLPerspectiveViewerElement,
28
27
  selected_position_map: SelectedPositionMap,
29
- event: FocusEvent,
30
- ): void {
31
- if (is_editable.call(this, viewer) && selected_position_map.has(table)) {
32
- const target = event.target as HTMLElement;
33
- target.classList.remove("psp-error");
34
- const selectedPosition = selected_position_map.get(table)!;
35
- selected_position_map.delete(table);
36
- if (selectedPosition.content !== target.textContent) {
37
- if (!write_cell(table, this, target)) {
38
- target.textContent = selectedPosition.content || "";
39
- target.classList.add("psp-error");
40
- target.focus();
28
+ ): EventListener {
29
+ return (event: Event): void => {
30
+ const focusEvent = event as FocusEvent;
31
+ if (isEditableMode(model, viewer) && selected_position_map.has(table)) {
32
+ const target = focusEvent.target as HTMLElement;
33
+ target.classList.remove("psp-error");
34
+ const selectedPosition = selected_position_map.get(table)!;
35
+ selected_position_map.delete(table);
36
+ if (selectedPosition.content !== target.textContent) {
37
+ if (!write_cell(table, model, target)) {
38
+ target.textContent = selectedPosition.content || "";
39
+ target.classList.add("psp-error");
40
+ target.focus();
41
+ }
41
42
  }
42
43
  }
43
- }
44
+ };
44
45
  }
45
46
 
46
- export function focusinListener(
47
- this: DatagridModel,
47
+ export function createFocusinListener(
48
+ _model: DatagridModel,
48
49
  table: RegularTable,
49
- _viewer: PerspectiveViewerElement,
50
+ _viewer: HTMLPerspectiveViewerElement,
50
51
  selected_position_map: SelectedPositionMap,
51
- event: FocusEvent,
52
- ): void {
53
- const target = event.target as HTMLElement;
54
- const meta = table.getMeta(target);
55
- if (meta?.type === "body") {
56
- const new_state: SelectedPosition = {
57
- x: meta.x,
58
- y: meta.y,
59
- content: target.textContent || undefined,
60
- };
61
- selected_position_map.set(table, new_state);
62
- }
52
+ ): EventListener {
53
+ return (event: Event): void => {
54
+ const focusEvent = event as FocusEvent;
55
+ const target = focusEvent.target as HTMLElement;
56
+ const meta = table.getMeta(target);
57
+ if (meta?.type === "body") {
58
+ const new_state: SelectedPosition = {
59
+ x: meta.x,
60
+ y: meta.y,
61
+ content: target.textContent || undefined,
62
+ };
63
+ selected_position_map.set(table, new_state);
64
+ }
65
+ };
63
66
  }
@@ -12,74 +12,119 @@
12
12
 
13
13
  import { sortHandler } from "./sort.js";
14
14
  import { expandCollapseHandler } from "./expand_collapse.js";
15
- import type {
16
- RegularTable,
17
- DatagridModel,
18
- PerspectiveViewerElement,
19
- } from "../types.js";
20
-
21
- export async function mousedown_listener(
22
- this: DatagridModel,
15
+ import type { RegularTable, DatagridModel } from "../types.js";
16
+ import type { HTMLPerspectiveViewerElement } from "@perspective-dev/viewer";
17
+
18
+ export function createMousedownListener(
19
+ model: DatagridModel,
23
20
  regularTable: RegularTable,
24
- viewer: PerspectiveViewerElement,
25
- event: MouseEvent,
26
- ): Promise<void> {
27
- if (event.which !== 1) {
28
- return;
29
- }
30
-
31
- let target = event.target as HTMLElement | null;
32
- if (target?.tagName === "A") {
33
- return;
34
- }
35
-
36
- while (target && target.tagName !== "TD" && target.tagName !== "TH") {
37
- target = target.parentElement;
38
- if (!target || !regularTable.contains(target)) {
21
+ viewer: HTMLPerspectiveViewerElement,
22
+ ): EventListener {
23
+ return async (event: Event): Promise<void> => {
24
+ const mouseEvent = event as MouseEvent;
25
+ if (mouseEvent.which !== 1) {
26
+ return;
27
+ }
28
+
29
+ let target = mouseEvent.target as HTMLElement | null;
30
+ if (target?.tagName === "A") {
31
+ return;
32
+ }
33
+
34
+ while (target && target.tagName !== "TD" && target.tagName !== "TH") {
35
+ target = target.parentElement;
36
+ if (!target || !regularTable.contains(target)) {
37
+ return;
38
+ }
39
+ }
40
+
41
+ if (!target) {
39
42
  return;
40
43
  }
41
- }
42
-
43
- if (!target) return;
44
-
45
- if (target.classList.contains("psp-tree-label")) {
46
- expandCollapseHandler.call(this, regularTable, event);
47
- return;
48
- }
49
-
50
- if (target.classList.contains("psp-menu-enabled")) {
51
- const meta = regularTable.getMeta(target);
52
- const column_name = meta?.column_header?.[this._config.split_by.length];
53
- await viewer.toggleColumnSettings(`${column_name}`);
54
- } else if (target.classList.contains("psp-sort-enabled")) {
55
- sortHandler.call(this, regularTable, viewer, event, target);
56
- }
44
+
45
+ if (target.classList.contains("psp-tree-label")) {
46
+ if (model._edit_mode !== "SELECT_ROW_TREE") {
47
+ expandCollapseHandler(model, regularTable, mouseEvent);
48
+ }
49
+
50
+ return;
51
+ }
52
+
53
+ if (target.classList.contains("psp-menu-enabled")) {
54
+ const meta = regularTable.getMeta(target);
55
+ const column_name =
56
+ meta?.column_header?.[model._config.split_by.length];
57
+ await viewer.toggleColumnSettings(`${column_name}`);
58
+ } else if (target.classList.contains("psp-sort-enabled")) {
59
+ sortHandler(model, regularTable, viewer, mouseEvent, target);
60
+ }
61
+ };
57
62
  }
58
63
 
59
- export function click_listener(
64
+ export function createDblclickListener(
65
+ model: DatagridModel,
60
66
  regularTable: RegularTable,
61
- event: MouseEvent,
62
- ): void {
63
- if (event.which !== 1) {
64
- return;
65
- }
66
-
67
- let target = event.target as HTMLElement | null;
68
- while (target && target.tagName !== "TD" && target.tagName !== "TH") {
69
- target = target.parentElement;
70
- if (!target || !regularTable.contains(target)) {
67
+ viewer: HTMLPerspectiveViewerElement,
68
+ ): EventListener {
69
+ return async (event: Event): Promise<void> => {
70
+ const mouseEvent = event as MouseEvent;
71
+ if (mouseEvent.which !== 1) {
72
+ return;
73
+ }
74
+
75
+ let target = mouseEvent.target as HTMLElement | null;
76
+ if (target?.tagName === "A") {
71
77
  return;
72
78
  }
73
- }
74
-
75
- if (!target) return;
76
-
77
- if (target.classList.contains("psp-tree-label") && event.offsetX < 26) {
78
- event.stopImmediatePropagation();
79
- } else if (
80
- target.classList.contains("psp-header-leaf") &&
81
- !target.classList.contains("psp-header-corner")
82
- ) {
83
- event.stopImmediatePropagation();
84
- }
79
+
80
+ while (target && target.tagName !== "TD" && target.tagName !== "TH") {
81
+ target = target.parentElement;
82
+ if (!target || !regularTable.contains(target)) {
83
+ return;
84
+ }
85
+ }
86
+
87
+ if (!target) {
88
+ return;
89
+ }
90
+
91
+ if (target.classList.contains("psp-tree-label")) {
92
+ if (model._edit_mode === "SELECT_ROW_TREE") {
93
+ expandCollapseHandler(model, regularTable, mouseEvent);
94
+ }
95
+ }
96
+ };
97
+ }
98
+
99
+ export function createClickListener(regularTable: RegularTable): EventListener {
100
+ return (event: Event): void => {
101
+ const mouseEvent = event as MouseEvent;
102
+ if (mouseEvent.which !== 1) {
103
+ return;
104
+ }
105
+
106
+ let target = mouseEvent.target as HTMLElement | null;
107
+ while (target && target.tagName !== "TD" && target.tagName !== "TH") {
108
+ target = target.parentElement;
109
+ if (!target || !regularTable.contains(target)) {
110
+ return;
111
+ }
112
+ }
113
+
114
+ if (!target) {
115
+ return;
116
+ }
117
+
118
+ if (
119
+ target.classList.contains("psp-tree-label") &&
120
+ mouseEvent.offsetX < 26
121
+ ) {
122
+ mouseEvent.stopImmediatePropagation();
123
+ } else if (
124
+ target.classList.contains("psp-header-leaf") &&
125
+ !target.classList.contains("psp-header-corner")
126
+ ) {
127
+ mouseEvent.stopImmediatePropagation();
128
+ }
129
+ };
85
130
  }