@perspective-dev/viewer-datagrid 4.0.0 → 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,112 @@
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 type {
14
+ ColumnOverrides,
15
+ DatagridPluginElement,
16
+ RegularTable,
17
+ } from "../types.js";
18
+
19
+ interface RegularTableWithOverrides {
20
+ restoreColumnSizes(overrides: Record<number, number | undefined>): void;
21
+ saveColumnSizes(): Record<number, number | undefined>;
22
+ }
23
+
24
+ interface DatagridPluginWithCache extends DatagridPluginElement {
25
+ _cached_column_sizes?: ColumnOverrides;
26
+ }
27
+
28
+ /**
29
+ * Restore a saved column width override token.
30
+ *
31
+ * @param old_sizes An object previously returned by a call to
32
+ * `save_column_size_overrides()`
33
+ * @param cache A flag indicating whether this value should
34
+ * be cached so a future `resetAutoSize()` call does not clear it.
35
+ */
36
+ export function restore_column_size_overrides(
37
+ this: DatagridPluginWithCache,
38
+ old_sizes: ColumnOverrides,
39
+ cache = false,
40
+ ): void {
41
+ if (!this._initialized) {
42
+ return;
43
+ }
44
+
45
+ if (cache) {
46
+ this._cached_column_sizes = old_sizes;
47
+ }
48
+
49
+ const overrides: Record<number, number | undefined> = {};
50
+ const { group_by } = this.model!._config;
51
+ const tree_header_offset = group_by?.length > 0 ? group_by.length + 1 : 0;
52
+
53
+ for (const key of Object.keys(old_sizes)) {
54
+ if (key === "__ROW_PATH__") {
55
+ overrides[tree_header_offset - 1] = old_sizes[key] as
56
+ | number
57
+ | undefined;
58
+ } else {
59
+ const index = this.model!._column_paths.indexOf(key);
60
+ overrides[index + tree_header_offset] = old_sizes[key] as
61
+ | number
62
+ | undefined;
63
+ }
64
+ }
65
+
66
+ (this.regular_table as RegularTableWithOverrides).restoreColumnSizes(
67
+ overrides,
68
+ );
69
+ }
70
+
71
+ /**
72
+ * Extract the current user-overriden column widths from
73
+ * `regular-table`. This function depends on the internal
74
+ * implementation of `regular-table` and may break!
75
+ *
76
+ * @returns An Object-as-dictionary keyed by column_path string, and
77
+ * valued by the column's user-overridden pixel width.
78
+ */
79
+ export function save_column_size_overrides(
80
+ this: DatagridPluginWithCache,
81
+ ): ColumnOverrides {
82
+ if (!this._initialized) {
83
+ return {};
84
+ }
85
+
86
+ if (this._cached_column_sizes) {
87
+ const x = this._cached_column_sizes;
88
+ this._cached_column_sizes = undefined;
89
+ return x;
90
+ }
91
+
92
+ const overrides = (
93
+ this.regular_table as RegularTableWithOverrides
94
+ ).saveColumnSizes();
95
+ const { group_by } = this.model!._config;
96
+ const tree_header_offset = group_by?.length > 0 ? group_by.length + 1 : 0;
97
+
98
+ const old_sizes: ColumnOverrides = {};
99
+ for (const key of Object.keys(overrides)) {
100
+ const numKey = Number(key);
101
+ if (overrides[numKey] !== undefined) {
102
+ const index = numKey - tree_header_offset;
103
+ if (index > -1) {
104
+ old_sizes[this.model!._column_paths[index]] = overrides[numKey];
105
+ } else if (index === -1) {
106
+ old_sizes["__ROW_PATH__"] = overrides[numKey];
107
+ }
108
+ }
109
+ }
110
+
111
+ return old_sizes;
112
+ }
@@ -0,0 +1,247 @@
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 chroma from "chroma-js";
14
+ import { createDataListener } from "../data_listener/index.js";
15
+ import { blend, make_color_record } from "../color_utils.js";
16
+ import type {
17
+ ColumnType,
18
+ Table,
19
+ View,
20
+ ViewConfig,
21
+ } from "@perspective-dev/client";
22
+ import type {
23
+ DatagridModel,
24
+ DatagridPluginElement,
25
+ RegularTable,
26
+ Schema,
27
+ CellMeta,
28
+ ElemFactory,
29
+ EditMode,
30
+ PerspectiveViewerElement,
31
+ } from "../types.js";
32
+
33
+ function get_rule(regular: HTMLElement, tag: string, def: string): string {
34
+ const color = window.getComputedStyle(regular).getPropertyValue(tag).trim();
35
+ if (color.length > 0) {
36
+ return color;
37
+ } else {
38
+ return def;
39
+ }
40
+ }
41
+
42
+ class ElemFactoryImpl implements ElemFactory {
43
+ private _name: string;
44
+ private _elements: HTMLElement[];
45
+ private _index: number;
46
+
47
+ constructor(name: string) {
48
+ this._name = name;
49
+ this._elements = [];
50
+ this._index = 0;
51
+ }
52
+
53
+ clear(): void {
54
+ this._index = 0;
55
+ }
56
+
57
+ get(): HTMLElement {
58
+ if (!this._elements[this._index]) {
59
+ this._elements[this._index] = document.createElement(this._name);
60
+ }
61
+ const elem = this._elements[this._index];
62
+ this._index += 1;
63
+ return elem;
64
+ }
65
+ }
66
+
67
+ function get_psp_type(this: DatagridModel, metadata: CellMeta): ColumnType {
68
+ if (metadata.x !== undefined && metadata.x >= 0) {
69
+ return this._column_types[metadata.x];
70
+ } else {
71
+ return this._row_header_types[metadata.row_header_x! - 1];
72
+ }
73
+ }
74
+
75
+ export async function createModel(
76
+ this: DatagridPluginElement,
77
+ regular: RegularTable,
78
+ table: Table,
79
+ view: View,
80
+ extend: Partial<DatagridModel> = {},
81
+ ): Promise<DatagridModel> {
82
+ const config = (await view.get_config()) as ViewConfig;
83
+ if (this?.model?._config) {
84
+ const old = this.model._config;
85
+ let group_by_changed = old.group_by.length !== config.group_by.length;
86
+ const type_changed =
87
+ (old.group_by.length === 0 || config.group_by.length === 0) &&
88
+ group_by_changed;
89
+
90
+ if (!group_by_changed) {
91
+ for (const lvl in old.group_by) {
92
+ group_by_changed ||= config.group_by[lvl] !== old.group_by[lvl];
93
+ }
94
+ }
95
+
96
+ let split_by_changed = old.split_by.length !== config.split_by.length;
97
+ if (split_by_changed) {
98
+ for (const lvl in old.split_by) {
99
+ split_by_changed ||= config.split_by[lvl] !== old.split_by[lvl];
100
+ }
101
+ }
102
+
103
+ let columns_changed = old.columns.length !== config.columns.length;
104
+ if (columns_changed) {
105
+ for (const lvl in old.columns) {
106
+ columns_changed ||= config.columns[lvl] !== old.columns[lvl];
107
+ }
108
+ }
109
+
110
+ let filter_changed = old.filter.length !== config.filter.length;
111
+ if (filter_changed) {
112
+ for (const lvl in old.filter) {
113
+ for (const i in config.filter[lvl]) {
114
+ filter_changed ||=
115
+ config.filter[lvl][i as unknown as number] !==
116
+ old.filter[lvl][i as unknown as number];
117
+ }
118
+ }
119
+ }
120
+
121
+ let sort_changed = old.sort.length !== config.sort.length;
122
+ if (sort_changed) {
123
+ for (const lvl in old.sort) {
124
+ for (const i in config.sort[lvl]) {
125
+ sort_changed ||=
126
+ config.sort[lvl][i as unknown as number] !==
127
+ old.sort[lvl][i as unknown as number];
128
+ }
129
+ }
130
+ }
131
+
132
+ this._reset_scroll_top = group_by_changed;
133
+ this._reset_scroll_left = split_by_changed;
134
+ this._reset_select =
135
+ group_by_changed ||
136
+ split_by_changed ||
137
+ filter_changed ||
138
+ sort_changed ||
139
+ columns_changed;
140
+
141
+ this._reset_column_size =
142
+ split_by_changed ||
143
+ group_by_changed ||
144
+ columns_changed ||
145
+ type_changed;
146
+ }
147
+
148
+ const [table_schema, num_rows, schema, expression_schema, _edit_port] =
149
+ await Promise.all([
150
+ table.schema(),
151
+ view.num_rows(),
152
+ view.schema(),
153
+ view.expression_schema(),
154
+ (this.parentElement as PerspectiveViewerElement).getEditPort(),
155
+ ]);
156
+
157
+ const _plugin_background = chroma(
158
+ get_rule(regular, "--plugin--background", "#FFFFFF"),
159
+ ).rgb();
160
+
161
+ const _pos_fg_color = make_color_record(
162
+ get_rule(regular, "--rt-pos-cell--color", "#338DCD"),
163
+ );
164
+
165
+ const _neg_fg_color = make_color_record(
166
+ get_rule(regular, "--rt-neg-cell--color", "#FF5942"),
167
+ );
168
+
169
+ const _pos_bg_color = make_color_record(
170
+ blend(_pos_fg_color[0], _plugin_background),
171
+ );
172
+
173
+ const _neg_bg_color = make_color_record(
174
+ blend(_neg_fg_color[0], _plugin_background),
175
+ );
176
+
177
+ const _color = make_color_record(
178
+ get_rule(regular, "--active--color", "#ff0000"),
179
+ );
180
+
181
+ const _schema: Schema = {
182
+ ...(schema as Schema),
183
+ ...(expression_schema as Schema),
184
+ };
185
+ const _table_schema: Schema = {
186
+ ...(table_schema as Schema),
187
+ ...(expression_schema as Schema),
188
+ };
189
+
190
+ const _column_paths: string[] = [];
191
+ const _is_editable: boolean[] = [];
192
+ const _column_types: ColumnType[] = [];
193
+
194
+ const _edit_mode: EditMode = this._edit_mode || "READ_ONLY";
195
+ this._edit_button!.dataset.editMode = _edit_mode;
196
+
197
+ const model: DatagridModel = Object.assign(extend, {
198
+ _edit_port,
199
+ _view: view,
200
+ _table: table,
201
+ _table_schema,
202
+ _config: config,
203
+ _num_rows: num_rows,
204
+ _schema,
205
+ _ids: [],
206
+ _plugin_background,
207
+ _color,
208
+ _pos_fg_color,
209
+ _neg_fg_color,
210
+ _pos_bg_color,
211
+ _neg_bg_color,
212
+ _column_paths,
213
+ _column_types,
214
+ _is_editable,
215
+ _edit_mode,
216
+ _selection_state: {
217
+ selected_areas: [],
218
+ dirty: false,
219
+ },
220
+ _row_header_types: config.group_by.map((column_path) => {
221
+ return _table_schema[column_path];
222
+ }),
223
+ _series_color_map: new Map<string, string>(),
224
+ _series_color_seed: new Map<string, number>(),
225
+ get_psp_type,
226
+ _div_factory: extend._div_factory || new ElemFactoryImpl("div"),
227
+ }) as DatagridModel;
228
+
229
+ regular.setDataListener(
230
+ createDataListener(this.parentElement as PerspectiveViewerElement).bind(
231
+ model,
232
+ regular,
233
+ ) as any,
234
+ {
235
+ virtual_mode: (window
236
+ .getComputedStyle(regular)
237
+ .getPropertyValue("--datagrid-virtual-mode")
238
+ ?.trim() || "both") as
239
+ | "both"
240
+ | "horizontal"
241
+ | "vertical"
242
+ | "none",
243
+ },
244
+ );
245
+
246
+ return model;
247
+ }
@@ -0,0 +1,19 @@
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
+ export { PRIVATE_PLUGIN_SYMBOL } from "../types.js";
14
+ export { createModel } from "./create.js";
15
+ export { toggle_edit_mode, toggle_scroll_lock } from "./toolbar.js";
16
+ export {
17
+ save_column_size_overrides,
18
+ restore_column_size_overrides,
19
+ } from "./column_overrides.js";
@@ -0,0 +1,64 @@
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 type { DatagridPluginElement, EditMode } from "../types.js";
14
+
15
+ export const EDIT_MODES: readonly EditMode[] = [
16
+ "READ_ONLY",
17
+ "EDIT",
18
+ "SELECT_ROW",
19
+ "SELECT_COLUMN",
20
+ "SELECT_REGION",
21
+ ] as const;
22
+
23
+ export function toggle_edit_mode(
24
+ this: DatagridPluginElement,
25
+ mode?: EditMode,
26
+ ): void {
27
+ if (typeof mode === "undefined") {
28
+ mode =
29
+ EDIT_MODES[
30
+ (EDIT_MODES.indexOf(this._edit_mode) + 1) % EDIT_MODES.length
31
+ ];
32
+ }
33
+
34
+ (this.parentElement as any)?.setSelection?.();
35
+ this._edit_mode = mode;
36
+ if (this.model) {
37
+ this.model._edit_mode = mode;
38
+ this.model._selection_state = {
39
+ selected_areas: [],
40
+ dirty: true,
41
+ };
42
+ }
43
+
44
+ if (this._edit_button !== undefined) {
45
+ this._edit_button.dataset.editMode = mode;
46
+ }
47
+
48
+ this.dataset.editMode = mode;
49
+ }
50
+
51
+ export function toggle_scroll_lock(
52
+ this: DatagridPluginElement,
53
+ force?: boolean,
54
+ ): void {
55
+ if (typeof force === "undefined") {
56
+ force = !this._is_scroll_lock;
57
+ }
58
+
59
+ this._is_scroll_lock = force;
60
+ this.classList.toggle("sub-cell-scroll-disabled", force);
61
+ if (this._scroll_lock !== undefined) {
62
+ this._scroll_lock.classList.toggle("lock-scroll", force);
63
+ }
64
+ }
@@ -0,0 +1,235 @@
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 { style_selected_column } from "../style_handlers/column_header.js";
14
+ import {
15
+ click_listener,
16
+ mousedown_listener,
17
+ } from "../event_handlers/header_click.js";
18
+
19
+ import { focusinListener, focusoutListener } from "../event_handlers/focus.js";
20
+ import { keydownListener, clickListener } from "../event_handlers/click.js";
21
+
22
+ import { selectionListener } from "../event_handlers/row_select_click.js";
23
+ import { deselect_all_listener } from "../event_handlers/deselect_all.js";
24
+
25
+ import { createModel } from "../model/create.js";
26
+ import { dispatch_click_listener } from "../event_handlers/dispatch_click.js";
27
+
28
+ import { addAreaMouseSelection } from "../event_handlers/select_region.js";
29
+
30
+ import {
31
+ createConsolidatedStyleListener,
32
+ installConsolidatedStyleMethods,
33
+ } from "../style_handlers/consolidated.js";
34
+
35
+ import type { View } from "@perspective-dev/client";
36
+ import type {
37
+ DatagridPluginElement,
38
+ PerspectiveViewerElement,
39
+ SelectedPosition,
40
+ } from "../types.js";
41
+ import type { RegularTableElement } from "regular-table";
42
+
43
+ interface ToggleColumnSettingsEvent extends CustomEvent {
44
+ detail: {
45
+ column_name: string | null;
46
+ open: boolean;
47
+ };
48
+ }
49
+
50
+ /**
51
+ * Lazy initialize this plugin with various listeners.
52
+ */
53
+ export async function activate(
54
+ this: DatagridPluginElement,
55
+ view: View,
56
+ ): Promise<void> {
57
+ const viewer = this.parentElement as PerspectiveViewerElement;
58
+ const table = await viewer.getTable();
59
+
60
+ if (!this._initialized) {
61
+ this.innerHTML = "";
62
+ if (this.shadowRoot) {
63
+ this.shadowRoot.appendChild(this.regular_table);
64
+ } else {
65
+ this.appendChild(this.regular_table);
66
+ }
67
+
68
+ this.model = await createModel.call(
69
+ this,
70
+ this.regular_table,
71
+ table,
72
+ view,
73
+ );
74
+
75
+ if (!this.model) {
76
+ return;
77
+ }
78
+
79
+ addAreaMouseSelection(this, this.regular_table, {
80
+ className: "psp-select-region",
81
+ });
82
+
83
+ // Create shared state maps for selection and focus tracking
84
+ const selected_rows_map = new WeakMap<
85
+ RegularTableElement,
86
+ Set<number>
87
+ >();
88
+ const selected_position_map = new WeakMap<
89
+ RegularTableElement,
90
+ SelectedPosition
91
+ >();
92
+
93
+ // Install consolidated style methods on model prototype
94
+ installConsolidatedStyleMethods(this.model);
95
+
96
+ // Single consolidated style listener replaces:
97
+ // - table_cell_style_listener
98
+ // - group_header_style_listener
99
+ // - column_header_style_listener
100
+ // - selectionStyleListener
101
+ // - editable_style_listener
102
+ // - focus_style_listener
103
+ this.regular_table.addStyleListener(
104
+ createConsolidatedStyleListener(
105
+ this,
106
+ selected_rows_map as any,
107
+ selected_position_map as any,
108
+ ).bind(this.model, this.regular_table, viewer),
109
+ );
110
+
111
+ // uh ..
112
+ this.regular_table.addEventListener(
113
+ "click",
114
+ click_listener.bind(
115
+ this.model,
116
+ this.regular_table,
117
+ ) as EventListener,
118
+ );
119
+
120
+ this.regular_table.addEventListener(
121
+ "mousedown",
122
+ selectionListener.bind(
123
+ this.model,
124
+ this.regular_table,
125
+ viewer,
126
+ selected_rows_map as any,
127
+ ) as unknown as EventListener,
128
+ );
129
+
130
+ this.regular_table.addEventListener(
131
+ "psp-deselect-all",
132
+ deselect_all_listener.bind(
133
+ this.model,
134
+ this.regular_table,
135
+ viewer,
136
+ selected_rows_map as any,
137
+ ) as unknown as EventListener,
138
+ );
139
+
140
+ // User event click
141
+ this.regular_table.addEventListener(
142
+ "click",
143
+ dispatch_click_listener.bind(
144
+ this.model,
145
+ this.regular_table,
146
+ viewer,
147
+ ) as unknown as EventListener,
148
+ );
149
+
150
+ // tree collapse, expand, edit button headers
151
+ this.regular_table.addEventListener(
152
+ "mousedown",
153
+ mousedown_listener.bind(
154
+ this.model,
155
+ this.regular_table,
156
+ viewer,
157
+ ) as unknown as EventListener,
158
+ );
159
+
160
+ // Editing event handlers (style handling is now in consolidated listener)
161
+ // TODO relies on this.model._is_editable
162
+ this.regular_table.addEventListener(
163
+ "click",
164
+ clickListener.bind(
165
+ this.model,
166
+ this.regular_table,
167
+ viewer,
168
+ ) as EventListener,
169
+ );
170
+
171
+ this.regular_table.addEventListener(
172
+ "focusin",
173
+ focusinListener.bind(
174
+ this.model,
175
+ this.regular_table,
176
+ viewer,
177
+ selected_position_map as any,
178
+ ) as EventListener,
179
+ );
180
+
181
+ this.regular_table.addEventListener(
182
+ "focusout",
183
+ focusoutListener.bind(
184
+ this.model,
185
+ this.regular_table,
186
+ viewer,
187
+ selected_position_map as any,
188
+ ) as EventListener,
189
+ );
190
+
191
+ this.regular_table.addEventListener(
192
+ "keydown",
193
+ keydownListener.bind(
194
+ this.model,
195
+ this.regular_table,
196
+ viewer,
197
+ selected_position_map as any,
198
+ ) as EventListener,
199
+ );
200
+
201
+ // viewer event listeners
202
+ viewer.addEventListener(
203
+ "perspective-toggle-column-settings",
204
+ (event: Event) => {
205
+ const toggleEvent = event as ToggleColumnSettingsEvent;
206
+ if (this.isConnected) {
207
+ style_selected_column.call(
208
+ this.model!,
209
+ this.regular_table,
210
+ viewer,
211
+ toggleEvent.detail.column_name ?? undefined,
212
+ );
213
+ if (!toggleEvent.detail.open) {
214
+ this.model!._column_settings_selected_column =
215
+ undefined;
216
+ return;
217
+ }
218
+
219
+ this.model!._column_settings_selected_column =
220
+ toggleEvent.detail.column_name ?? undefined;
221
+ }
222
+ },
223
+ );
224
+
225
+ this._initialized = true;
226
+ } else {
227
+ await createModel.call(
228
+ this,
229
+ this.regular_table,
230
+ table,
231
+ view,
232
+ this.model,
233
+ );
234
+ }
235
+ }