@perspective-dev/viewer-datagrid 4.0.1 → 4.1.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 (99) hide show
  1. package/dist/cdn/perspective-viewer-datagrid.js +4 -17
  2. package/dist/cdn/perspective-viewer-datagrid.js.map +4 -4
  3. package/dist/css/perspective-viewer-datagrid.css +1 -1
  4. package/dist/esm/color_utils.d.ts +9 -0
  5. package/dist/esm/custom_elements/datagrid.d.ts +52 -0
  6. package/dist/esm/custom_elements/toolbar.d.ts +10 -0
  7. package/dist/esm/data_listener/format_cell.d.ts +8 -0
  8. package/dist/esm/data_listener/format_tree_header.d.ts +13 -0
  9. package/dist/esm/data_listener/formatter_cache.d.ts +16 -0
  10. package/dist/esm/data_listener/index.d.ts +10 -0
  11. package/dist/esm/event_handlers/click/edit_click.d.ts +3 -0
  12. package/dist/esm/event_handlers/click.d.ts +7 -0
  13. package/dist/esm/event_handlers/deselect_all.d.ts +5 -0
  14. package/dist/esm/event_handlers/dispatch_click.d.ts +3 -0
  15. package/dist/esm/event_handlers/expand_collapse.d.ts +2 -0
  16. package/dist/esm/event_handlers/focus.d.ts +5 -0
  17. package/dist/esm/event_handlers/header_click.d.ts +3 -0
  18. package/dist/esm/event_handlers/keydown/edit_keydown.d.ts +4 -0
  19. package/dist/esm/event_handlers/row_select_click.d.ts +4 -0
  20. package/dist/esm/event_handlers/select_region.d.ts +9 -0
  21. package/dist/esm/event_handlers/sort.d.ts +7 -0
  22. package/dist/esm/get_cell_config.d.ts +8 -0
  23. package/dist/esm/index.d.ts +6 -0
  24. package/dist/esm/model/column_overrides.d.ts +23 -0
  25. package/dist/esm/model/create.d.ts +3 -0
  26. package/dist/esm/model/index.d.ts +4 -0
  27. package/dist/esm/model/toolbar.d.ts +4 -0
  28. package/dist/esm/perspective-viewer-datagrid.js +3 -3
  29. package/dist/esm/perspective-viewer-datagrid.js.map +4 -4
  30. package/dist/esm/plugin/activate.d.ts +6 -0
  31. package/dist/esm/plugin/column_style_controls.d.ts +28 -0
  32. package/dist/esm/plugin/draw.d.ts +7 -0
  33. package/dist/esm/plugin/restore.d.ts +10 -0
  34. package/dist/esm/plugin/save.d.ts +2 -0
  35. package/dist/esm/style_handlers/body.d.ts +7 -0
  36. package/dist/esm/style_handlers/column_header.d.ts +13 -0
  37. package/dist/esm/style_handlers/consolidated.d.ts +57 -0
  38. package/dist/esm/style_handlers/editable.d.ts +7 -0
  39. package/dist/esm/style_handlers/focus.d.ts +16 -0
  40. package/dist/esm/style_handlers/group_header.d.ts +7 -0
  41. package/dist/esm/style_handlers/table_cell/boolean.d.ts +7 -0
  42. package/dist/esm/style_handlers/table_cell/cell_flash.d.ts +3 -0
  43. package/dist/esm/style_handlers/table_cell/datetime.d.ts +7 -0
  44. package/dist/esm/style_handlers/table_cell/numeric.d.ts +15 -0
  45. package/dist/esm/style_handlers/table_cell/row_header.d.ts +4 -0
  46. package/dist/esm/style_handlers/table_cell/string.d.ts +11 -0
  47. package/dist/esm/style_handlers/types.d.ts +20 -0
  48. package/dist/esm/types.d.ts +193 -0
  49. package/package.json +10 -5
  50. package/src/less/mitered-headers.less +65 -0
  51. package/src/less/pro.less +196 -0
  52. package/src/less/regular_table.less +509 -0
  53. package/src/less/row-hover.less +88 -0
  54. package/{index.d.ts → src/less/scrollbar.less} +18 -19
  55. package/src/less/sub-cell-scroll.less +82 -0
  56. package/src/less/toolbar.less +201 -0
  57. package/src/ts/color_utils.ts +70 -0
  58. package/src/ts/custom_elements/datagrid.ts +250 -0
  59. package/src/ts/custom_elements/toolbar.ts +75 -0
  60. package/src/ts/data_listener/format_cell.ts +84 -0
  61. package/src/ts/data_listener/format_tree_header.ts +82 -0
  62. package/src/ts/data_listener/formatter_cache.ts +191 -0
  63. package/src/ts/data_listener/index.ts +242 -0
  64. package/src/ts/event_handlers/click/edit_click.ts +73 -0
  65. package/src/ts/event_handlers/click.ts +92 -0
  66. package/src/ts/event_handlers/deselect_all.ts +28 -0
  67. package/src/ts/event_handlers/dispatch_click.ts +44 -0
  68. package/src/ts/event_handlers/expand_collapse.ts +44 -0
  69. package/src/ts/event_handlers/focus.ts +63 -0
  70. package/src/ts/event_handlers/header_click.ts +85 -0
  71. package/src/ts/event_handlers/keydown/edit_keydown.ts +213 -0
  72. package/src/ts/event_handlers/row_select_click.ts +87 -0
  73. package/src/ts/event_handlers/select_region.ts +427 -0
  74. package/src/ts/event_handlers/sort.ts +118 -0
  75. package/src/ts/get_cell_config.ts +68 -0
  76. package/src/ts/index.ts +49 -0
  77. package/src/ts/model/column_overrides.ts +112 -0
  78. package/src/ts/model/create.ts +247 -0
  79. package/src/ts/model/index.ts +19 -0
  80. package/src/ts/model/toolbar.ts +64 -0
  81. package/src/ts/plugin/activate.ts +235 -0
  82. package/src/ts/plugin/column_style_controls.ts +76 -0
  83. package/src/ts/plugin/draw.ts +69 -0
  84. package/src/ts/plugin/restore.ts +110 -0
  85. package/src/ts/plugin/save.ts +45 -0
  86. package/src/ts/style_handlers/body.ts +228 -0
  87. package/src/ts/style_handlers/column_header.ts +183 -0
  88. package/src/ts/style_handlers/consolidated.ts +223 -0
  89. package/src/ts/style_handlers/editable.ts +94 -0
  90. package/src/ts/style_handlers/focus.ts +106 -0
  91. package/src/ts/style_handlers/group_header.ts +78 -0
  92. package/src/ts/style_handlers/table_cell/boolean.ts +39 -0
  93. package/src/ts/style_handlers/table_cell/cell_flash.ts +75 -0
  94. package/src/ts/style_handlers/table_cell/datetime.ts +64 -0
  95. package/src/ts/style_handlers/table_cell/numeric.ts +186 -0
  96. package/src/ts/style_handlers/table_cell/row_header.ts +53 -0
  97. package/src/ts/style_handlers/table_cell/string.ts +102 -0
  98. package/src/ts/style_handlers/types.ts +41 -0
  99. package/src/ts/types.ts +279 -0
@@ -0,0 +1,76 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import { ColumnType } from "@perspective-dev/client";
14
+ import type { DatagridPluginElement } from "../types.js";
15
+
16
+ interface NumberStyleOpts {
17
+ datagrid_number_style: {
18
+ fg_gradient: number;
19
+ pos_fg_color: string;
20
+ neg_fg_color: string;
21
+ number_fg_mode: string;
22
+ bg_gradient: number;
23
+ pos_bg_color: string;
24
+ neg_bg_color: string;
25
+ number_bg_mode: string;
26
+ };
27
+ number_string_format: boolean;
28
+ }
29
+
30
+ interface DatetimeStyleOpts {
31
+ datagrid_datetime_style?: {
32
+ color: string;
33
+ bg_color: string;
34
+ };
35
+ datagrid_string_style?: {
36
+ color: string;
37
+ bg_color: string;
38
+ };
39
+ }
40
+
41
+ export type ColumnStyleOpts = NumberStyleOpts | DatetimeStyleOpts | null;
42
+
43
+ export default function column_style_opts(
44
+ this: DatagridPluginElement,
45
+ type: ColumnType,
46
+ _group: string,
47
+ ): ColumnStyleOpts {
48
+ if (type === "integer" || type === "float") {
49
+ return {
50
+ datagrid_number_style: {
51
+ fg_gradient: 0,
52
+ pos_fg_color: this.model!._pos_fg_color[0],
53
+ neg_fg_color: this.model!._neg_fg_color[0],
54
+ number_fg_mode: "color",
55
+ bg_gradient: 0,
56
+ pos_bg_color: this.model!._pos_bg_color[0],
57
+ neg_bg_color: this.model!._neg_bg_color[0],
58
+ number_bg_mode: "disabled",
59
+ },
60
+ number_string_format: true,
61
+ };
62
+ } else if (type === "date" || type === "datetime" || type === "string") {
63
+ const control =
64
+ type === "date" || type === "datetime"
65
+ ? "datagrid_datetime_style"
66
+ : `datagrid_string_style`;
67
+ return {
68
+ [control]: {
69
+ color: this.model!._color[0],
70
+ bg_color: this.model!._color[0],
71
+ },
72
+ } as DatetimeStyleOpts;
73
+ } else {
74
+ return null;
75
+ }
76
+ }
@@ -0,0 +1,69 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import {
14
+ restore_column_size_overrides,
15
+ save_column_size_overrides,
16
+ } from "../model/column_overrides.js";
17
+ import type { View } from "@perspective-dev/client";
18
+ import type { DatagridPluginElement } from "../types.js";
19
+
20
+ interface DatagridPluginWithActivate extends DatagridPluginElement {
21
+ activate(view: View): Promise<void>;
22
+ }
23
+
24
+ export async function draw(
25
+ this: DatagridPluginWithActivate,
26
+ view: View,
27
+ ): Promise<void> {
28
+ if (this.parentElement) {
29
+ await this.activate(view);
30
+ }
31
+
32
+ if (!this.isConnected || this.offsetParent == null || !this.model) {
33
+ return;
34
+ }
35
+
36
+ const old_sizes = save_column_size_overrides.call(this);
37
+ const drawPromise = this.regular_table.draw({
38
+ invalid_columns: true,
39
+ } as any);
40
+ if (this._reset_scroll_top) {
41
+ this.regular_table.scrollTop = 0;
42
+ this._reset_scroll_top = false;
43
+ }
44
+
45
+ if (this._reset_scroll_left) {
46
+ this.regular_table.scrollLeft = 0;
47
+ this._reset_scroll_left = false;
48
+ }
49
+ if (this._reset_select) {
50
+ this.regular_table.dispatchEvent(
51
+ new CustomEvent("psp-deselect-all", { bubbles: false }),
52
+ );
53
+ this._reset_select = false;
54
+ }
55
+
56
+ if (this._reset_column_size) {
57
+ this.regular_table.resetAutoSize();
58
+ this._reset_column_size = false;
59
+ }
60
+
61
+ restore_column_size_overrides.call(this, old_sizes);
62
+ await drawPromise;
63
+
64
+ this._toolbar?.classList.toggle(
65
+ "aggregated",
66
+ this.model._config.group_by.length > 0 ||
67
+ this.model._config.split_by.length > 0,
68
+ );
69
+ }
@@ -0,0 +1,110 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import { restore_column_size_overrides } from "../model/column_overrides.js";
14
+ import {
15
+ EDIT_MODES,
16
+ toggle_edit_mode,
17
+ toggle_scroll_lock,
18
+ } from "../model/toolbar.js";
19
+ import { PRIVATE_PLUGIN_SYMBOL } from "../model/index.js";
20
+ import { make_color_record } from "../color_utils.js";
21
+ import type {
22
+ DatagridPluginElement,
23
+ ColumnOverrides,
24
+ EditMode,
25
+ ColumnsConfig,
26
+ ColorRecord,
27
+ } from "../types.js";
28
+
29
+ interface RestoreToken {
30
+ columns?: Record<string, { column_size_override?: number }>;
31
+ edit_mode?: EditMode;
32
+ scroll_lock?: boolean;
33
+ }
34
+
35
+ // interface ColumnConfigWithColors {
36
+ // pos_fg_color?: string;
37
+ // neg_fg_color?: string;
38
+ // pos_bg_color?: string;
39
+ // neg_bg_color?: string;
40
+ // color?: string;
41
+ // [key: string]: unknown;
42
+ // }
43
+
44
+ interface StylesConfig {
45
+ pos_fg_color?: ColorRecord;
46
+ neg_fg_color?: ColorRecord;
47
+ pos_bg_color?: ColorRecord;
48
+ neg_bg_color?: ColorRecord;
49
+ color?: ColorRecord;
50
+ [key: string]: unknown;
51
+ }
52
+
53
+ export function restore(
54
+ this: DatagridPluginElement,
55
+ token: RestoreToken,
56
+ columns: ColumnsConfig,
57
+ ): void {
58
+ token = JSON.parse(JSON.stringify(token));
59
+ columns = JSON.parse(JSON.stringify(columns));
60
+ const overrides: ColumnOverrides = {};
61
+
62
+ if (token.columns) {
63
+ for (const [col, value] of Object.entries(token.columns)) {
64
+ if (value.column_size_override !== undefined) {
65
+ overrides[col] = value.column_size_override;
66
+ delete value["column_size_override"];
67
+ }
68
+ }
69
+ }
70
+
71
+ const styles: Record<string, StylesConfig> = {};
72
+ if (columns) {
73
+ for (const [col_name, controls] of Object.entries(columns)) {
74
+ styles[col_name] = {
75
+ ...controls,
76
+ pos_fg_color: controls.pos_fg_color
77
+ ? make_color_record(controls.pos_fg_color)
78
+ : undefined,
79
+ neg_fg_color: controls.neg_fg_color
80
+ ? make_color_record(controls.neg_fg_color)
81
+ : undefined,
82
+ pos_bg_color: controls.pos_bg_color
83
+ ? make_color_record(controls.pos_bg_color)
84
+ : undefined,
85
+ neg_bg_color: controls.neg_bg_color
86
+ ? make_color_record(controls.neg_bg_color)
87
+ : undefined,
88
+ color: controls.color
89
+ ? make_color_record(controls.color)
90
+ : undefined,
91
+ };
92
+ }
93
+ }
94
+
95
+ if ("edit_mode" in token && token.edit_mode) {
96
+ if (EDIT_MODES.indexOf(token.edit_mode) !== -1) {
97
+ toggle_edit_mode.call(this, token.edit_mode);
98
+ } else {
99
+ console.error("Unknown edit mode " + token.edit_mode);
100
+ }
101
+ }
102
+
103
+ if ("scroll_lock" in token) {
104
+ toggle_scroll_lock.call(this, token.scroll_lock);
105
+ }
106
+
107
+ const datagrid = this.regular_table;
108
+ restore_column_size_overrides.call(this, overrides, true);
109
+ (datagrid as any)[PRIVATE_PLUGIN_SYMBOL] = styles as ColumnsConfig;
110
+ }
@@ -0,0 +1,45 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import { save_column_size_overrides } from "../model/column_overrides.js";
14
+ import type {
15
+ DatagridPluginElement,
16
+ DatagridPluginConfig,
17
+ EditMode,
18
+ } from "../types.js";
19
+
20
+ export function save(
21
+ this: DatagridPluginElement,
22
+ ): DatagridPluginConfig | Record<string, never> {
23
+ if (this.regular_table) {
24
+ const token: DatagridPluginConfig = {
25
+ columns: {},
26
+ scroll_lock: !!this._is_scroll_lock,
27
+ edit_mode: this._edit_mode,
28
+ };
29
+
30
+ const column_size_overrides = save_column_size_overrides.call(this);
31
+
32
+ for (const col of Object.keys(column_size_overrides || {})) {
33
+ if (!token.columns?.[col]) {
34
+ token.columns = token.columns || {};
35
+ token.columns[col] = {};
36
+ }
37
+
38
+ token.columns[col].column_size_override =
39
+ column_size_overrides[col];
40
+ }
41
+
42
+ return JSON.parse(JSON.stringify(token));
43
+ }
44
+ return {};
45
+ }
@@ -0,0 +1,228 @@
1
+ // ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2
+ // ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
3
+ // ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
4
+ // ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
5
+ // ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
6
+ // ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7
+ // ┃ Copyright (c) 2017, the Perspective Authors. ┃
8
+ // ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9
+ // ┃ This file is part of the Perspective library, distributed under the terms ┃
10
+ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
+ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
+
13
+ import { RegularTableElement } from "regular-table";
14
+
15
+ import type {
16
+ DatagridModel,
17
+ PerspectiveViewerElement,
18
+ ColumnsConfig,
19
+ DatagridPluginElement,
20
+ } from "../types.js";
21
+
22
+ import { cell_style_numeric } from "./table_cell/numeric.js";
23
+ import { cell_style_string } from "./table_cell/string.js";
24
+ import { cell_style_datetime } from "./table_cell/datetime.js";
25
+ import { cell_style_boolean } from "./table_cell/boolean.js";
26
+ import { cell_style_row_header } from "./table_cell/row_header.js";
27
+ import {
28
+ CollectedCell,
29
+ LocalSelectedPositionMap,
30
+ LocalSelectedRowsMap,
31
+ CellMetaExtended,
32
+ } from "./types.js";
33
+ import { ColumnType } from "@perspective-dev/client";
34
+
35
+ function get_psp_type(
36
+ model: DatagridModel,
37
+ metadata: CellMetaExtended,
38
+ ): ColumnType {
39
+ if (metadata.x !== undefined && metadata.x >= 0) {
40
+ return model._column_types[metadata.x];
41
+ } else {
42
+ return model._row_header_types[(metadata.row_header_x ?? 0) - 1];
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Apply styles to all body cells in a single pass.
48
+ */
49
+ export function applyBodyCellStyles(
50
+ this: DatagridModel,
51
+ cells: CollectedCell[],
52
+ plugins: ColumnsConfig,
53
+ isSettingsOpen: boolean,
54
+ isSelectable: boolean,
55
+ isEditable: boolean,
56
+ regularTable: RegularTableElement,
57
+ selectedRowsMap: LocalSelectedRowsMap,
58
+ selectedPositionMap: LocalSelectedPositionMap,
59
+ viewer: PerspectiveViewerElement,
60
+ ): void {
61
+ const hasSelected = selectedRowsMap.has(regularTable);
62
+ const selected = selectedRowsMap.get(regularTable);
63
+
64
+ for (const { element: td, metadata, isHeader } of cells) {
65
+ const column_name =
66
+ metadata.column_header?.[this._config.split_by.length];
67
+ const type = get_psp_type(this, metadata);
68
+ const plugin = column_name
69
+ ? plugins[column_name.toString()]
70
+ : undefined;
71
+ const is_numeric = type === "integer" || type === "float";
72
+
73
+ // Calculate aggregate depth visibility
74
+ metadata._is_hidden_by_aggregate_depth = ((x?: number) =>
75
+ x === 0 || x === undefined
76
+ ? false
77
+ : x - 1 <
78
+ Math.min(
79
+ this._config.group_by.length,
80
+ plugin?.aggregate_depth || 0,
81
+ ))(
82
+ (metadata.row_header as unknown[] | undefined)?.filter(
83
+ (x) => x !== undefined,
84
+ )?.length,
85
+ );
86
+
87
+ // Apply type-specific cell styling
88
+ if (is_numeric) {
89
+ cell_style_numeric.call(
90
+ this,
91
+ plugin as any,
92
+ td,
93
+ metadata as any,
94
+ isSettingsOpen,
95
+ );
96
+ } else if (type === "boolean") {
97
+ cell_style_boolean.call(this, plugin, td, metadata as any);
98
+ } else if (type === "string") {
99
+ cell_style_string.call(this, plugin as any, td, metadata as any);
100
+ } else if (type === "date" || type === "datetime") {
101
+ cell_style_datetime.call(this, plugin as any, td, metadata as any);
102
+ } else {
103
+ td.style.backgroundColor = "";
104
+ td.style.color = "";
105
+ }
106
+
107
+ // Apply common cell classes
108
+ td.classList.toggle(
109
+ "psp-bool-type",
110
+ type === "boolean" && metadata.user !== null,
111
+ );
112
+ td.classList.toggle("psp-null", metadata.value === null);
113
+ td.classList.toggle("psp-align-right", !isHeader && is_numeric);
114
+ td.classList.toggle("psp-align-left", isHeader || !is_numeric);
115
+ if (this._column_settings_selected_column) {
116
+ td.classList.toggle(
117
+ "psp-menu-open",
118
+ column_name === this._column_settings_selected_column,
119
+ );
120
+ } else {
121
+ td.classList.toggle("psp-menu-open", false);
122
+ }
123
+
124
+ td.classList.toggle(
125
+ "psp-color-mode-bar",
126
+ plugin?.number_fg_mode === "bar" && is_numeric,
127
+ );
128
+
129
+ // Apply row header styling
130
+ if (isHeader) {
131
+ cell_style_row_header.call(this, regularTable, td, metadata as any);
132
+ }
133
+
134
+ // Set data attributes
135
+ const tr = td.parentElement as HTMLElement;
136
+ if (tr) {
137
+ tr.dataset.y = String(metadata.y);
138
+ }
139
+
140
+ if (
141
+ metadata.row_header_x === undefined ||
142
+ metadata.row_header_x ===
143
+ (metadata.row_header as unknown[]).length - 1 ||
144
+ (metadata.row_header as unknown[])[metadata.row_header_x + 1] ===
145
+ undefined
146
+ ) {
147
+ td.dataset.y = String(metadata.y);
148
+ td.dataset.x = String(metadata.x);
149
+ } else {
150
+ delete td.dataset.y;
151
+ delete td.dataset.x;
152
+ }
153
+
154
+ // Apply selection styling (if selectable)
155
+ if (isSelectable) {
156
+ if (!hasSelected) {
157
+ td.classList.toggle("psp-row-selected", false);
158
+ td.classList.toggle("psp-row-subselected", false);
159
+ } else {
160
+ const id = this._ids[(metadata.y ?? 0) - (metadata.y0 ?? 0)];
161
+ const key_match = (selected as unknown[]).reduce<boolean>(
162
+ (agg, x, i) => agg && x === id[i],
163
+ true,
164
+ );
165
+
166
+ const selectedArr = selected as unknown[];
167
+ if (isHeader) {
168
+ if (
169
+ metadata.row_header_x !== undefined &&
170
+ !!id[metadata.row_header_x]
171
+ ) {
172
+ td.classList.toggle("psp-row-selected", false);
173
+ td.classList.toggle("psp-row-subselected", false);
174
+ } else {
175
+ td.classList.toggle(
176
+ "psp-row-selected",
177
+ id.length === selectedArr.length && key_match,
178
+ );
179
+ td.classList.toggle(
180
+ "psp-row-subselected",
181
+ id.length !== selectedArr.length && key_match,
182
+ );
183
+ }
184
+ } else {
185
+ td.classList.toggle(
186
+ "psp-row-selected",
187
+ id.length === selectedArr.length && key_match,
188
+ );
189
+ td.classList.toggle(
190
+ "psp-row-subselected",
191
+ id.length !== selectedArr.length && key_match,
192
+ );
193
+ }
194
+ }
195
+ }
196
+
197
+ // Apply editable styling (if editable)
198
+ if (!isHeader && metadata.x !== undefined) {
199
+ if (isEditable && this._is_editable[metadata.x]) {
200
+ const col_name =
201
+ metadata.column_header?.[this._config.split_by.length];
202
+ const col_name_str = col_name?.toString();
203
+ if (
204
+ col_name_str &&
205
+ type === "string" &&
206
+ plugins[col_name_str]?.format === "link"
207
+ ) {
208
+ td.toggleAttribute("contenteditable", false);
209
+ td.classList.toggle("boolean-editable", false);
210
+ } else if (type === "boolean") {
211
+ td.toggleAttribute("contenteditable", false);
212
+ td.classList.toggle(
213
+ "boolean-editable",
214
+ (metadata as { user?: unknown }).user !== null,
215
+ );
216
+ } else {
217
+ if (isEditable !== td.hasAttribute("contenteditable")) {
218
+ td.toggleAttribute("contenteditable", isEditable);
219
+ }
220
+ td.classList.toggle("boolean-editable", false);
221
+ }
222
+ } else {
223
+ td.toggleAttribute("contenteditable", false);
224
+ td.classList.toggle("boolean-editable", false);
225
+ }
226
+ }
227
+ }
228
+ }