@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.
- package/dist/cdn/perspective-viewer-datagrid.js +4 -17
- package/dist/cdn/perspective-viewer-datagrid.js.map +4 -4
- package/dist/css/perspective-viewer-datagrid.css +1 -1
- package/dist/esm/color_utils.d.ts +9 -0
- package/dist/esm/custom_elements/datagrid.d.ts +52 -0
- package/dist/esm/custom_elements/toolbar.d.ts +10 -0
- package/dist/esm/data_listener/format_cell.d.ts +8 -0
- package/dist/esm/data_listener/format_tree_header.d.ts +13 -0
- package/dist/esm/data_listener/formatter_cache.d.ts +16 -0
- package/dist/esm/data_listener/index.d.ts +10 -0
- package/dist/esm/event_handlers/click/edit_click.d.ts +3 -0
- package/dist/esm/event_handlers/click.d.ts +7 -0
- package/dist/esm/event_handlers/deselect_all.d.ts +5 -0
- package/dist/esm/event_handlers/dispatch_click.d.ts +3 -0
- package/dist/esm/event_handlers/expand_collapse.d.ts +2 -0
- package/dist/esm/event_handlers/focus.d.ts +5 -0
- package/dist/esm/event_handlers/header_click.d.ts +3 -0
- package/dist/esm/event_handlers/keydown/edit_keydown.d.ts +4 -0
- package/dist/esm/event_handlers/row_select_click.d.ts +4 -0
- package/dist/esm/event_handlers/select_region.d.ts +9 -0
- package/dist/esm/event_handlers/sort.d.ts +7 -0
- package/dist/esm/get_cell_config.d.ts +8 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/model/column_overrides.d.ts +23 -0
- package/dist/esm/model/create.d.ts +3 -0
- package/dist/esm/model/index.d.ts +4 -0
- package/dist/esm/model/toolbar.d.ts +4 -0
- package/dist/esm/perspective-viewer-datagrid.js +3 -3
- package/dist/esm/perspective-viewer-datagrid.js.map +4 -4
- package/dist/esm/plugin/activate.d.ts +6 -0
- package/dist/esm/plugin/column_style_controls.d.ts +28 -0
- package/dist/esm/plugin/draw.d.ts +7 -0
- package/dist/esm/plugin/restore.d.ts +10 -0
- package/dist/esm/plugin/save.d.ts +2 -0
- package/dist/esm/style_handlers/body.d.ts +7 -0
- package/dist/esm/style_handlers/column_header.d.ts +13 -0
- package/dist/esm/style_handlers/consolidated.d.ts +57 -0
- package/dist/esm/style_handlers/editable.d.ts +7 -0
- package/dist/esm/style_handlers/focus.d.ts +16 -0
- package/dist/esm/style_handlers/group_header.d.ts +7 -0
- package/dist/esm/style_handlers/table_cell/boolean.d.ts +7 -0
- package/dist/esm/style_handlers/table_cell/cell_flash.d.ts +3 -0
- package/dist/esm/style_handlers/table_cell/datetime.d.ts +7 -0
- package/dist/esm/style_handlers/table_cell/numeric.d.ts +15 -0
- package/dist/esm/style_handlers/table_cell/row_header.d.ts +4 -0
- package/dist/esm/style_handlers/table_cell/string.d.ts +11 -0
- package/dist/esm/style_handlers/types.d.ts +20 -0
- package/dist/esm/types.d.ts +193 -0
- package/package.json +10 -5
- package/src/less/mitered-headers.less +65 -0
- package/src/less/pro.less +196 -0
- package/src/less/regular_table.less +509 -0
- package/src/less/row-hover.less +88 -0
- package/{index.d.ts → src/less/scrollbar.less} +18 -19
- package/src/less/sub-cell-scroll.less +82 -0
- package/src/less/toolbar.less +201 -0
- package/src/ts/color_utils.ts +70 -0
- package/src/ts/custom_elements/datagrid.ts +250 -0
- package/src/ts/custom_elements/toolbar.ts +75 -0
- package/src/ts/data_listener/format_cell.ts +84 -0
- package/src/ts/data_listener/format_tree_header.ts +82 -0
- package/src/ts/data_listener/formatter_cache.ts +191 -0
- package/src/ts/data_listener/index.ts +242 -0
- package/src/ts/event_handlers/click/edit_click.ts +73 -0
- package/src/ts/event_handlers/click.ts +92 -0
- package/src/ts/event_handlers/deselect_all.ts +28 -0
- package/src/ts/event_handlers/dispatch_click.ts +44 -0
- package/src/ts/event_handlers/expand_collapse.ts +44 -0
- package/src/ts/event_handlers/focus.ts +63 -0
- package/src/ts/event_handlers/header_click.ts +85 -0
- package/src/ts/event_handlers/keydown/edit_keydown.ts +213 -0
- package/src/ts/event_handlers/row_select_click.ts +87 -0
- package/src/ts/event_handlers/select_region.ts +427 -0
- package/src/ts/event_handlers/sort.ts +118 -0
- package/src/ts/get_cell_config.ts +68 -0
- package/src/ts/index.ts +49 -0
- package/src/ts/model/column_overrides.ts +112 -0
- package/src/ts/model/create.ts +247 -0
- package/src/ts/model/index.ts +19 -0
- package/src/ts/model/toolbar.ts +64 -0
- package/src/ts/plugin/activate.ts +235 -0
- package/src/ts/plugin/column_style_controls.ts +76 -0
- package/src/ts/plugin/draw.ts +69 -0
- package/src/ts/plugin/restore.ts +110 -0
- package/src/ts/plugin/save.ts +45 -0
- package/src/ts/style_handlers/body.ts +228 -0
- package/src/ts/style_handlers/column_header.ts +183 -0
- package/src/ts/style_handlers/consolidated.ts +223 -0
- package/src/ts/style_handlers/editable.ts +94 -0
- package/src/ts/style_handlers/focus.ts +106 -0
- package/src/ts/style_handlers/group_header.ts +78 -0
- package/src/ts/style_handlers/table_cell/boolean.ts +39 -0
- package/src/ts/style_handlers/table_cell/cell_flash.ts +75 -0
- package/src/ts/style_handlers/table_cell/datetime.ts +64 -0
- package/src/ts/style_handlers/table_cell/numeric.ts +186 -0
- package/src/ts/style_handlers/table_cell/row_header.ts +53 -0
- package/src/ts/style_handlers/table_cell/string.ts +102 -0
- package/src/ts/style_handlers/types.ts +41 -0
- package/src/ts/types.ts +279 -0
|
@@ -0,0 +1,250 @@
|
|
|
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 { PRIVATE_PLUGIN_SYMBOL } from "../model/index.js";
|
|
14
|
+
import { activate } from "../plugin/activate.js";
|
|
15
|
+
import { restore } from "../plugin/restore.js";
|
|
16
|
+
import { save } from "../plugin/save.js";
|
|
17
|
+
import { draw } from "../plugin/draw.js";
|
|
18
|
+
import column_style_controls, {
|
|
19
|
+
ColumnStyleOpts,
|
|
20
|
+
} from "../plugin/column_style_controls.js";
|
|
21
|
+
import datagridStyles from "../../../dist/css/perspective-viewer-datagrid.css";
|
|
22
|
+
import { format_raw } from "../data_listener/format_cell.js";
|
|
23
|
+
|
|
24
|
+
import type { View, ViewWindow } from "@perspective-dev/client";
|
|
25
|
+
import type { IPerspectiveViewerPlugin } from "@perspective-dev/viewer";
|
|
26
|
+
import type {
|
|
27
|
+
DatagridModel,
|
|
28
|
+
DatagridToolbarElement,
|
|
29
|
+
EditMode,
|
|
30
|
+
PerspectiveViewerElement,
|
|
31
|
+
DatagridPluginConfig,
|
|
32
|
+
ColumnsConfig,
|
|
33
|
+
} from "../types.js";
|
|
34
|
+
import { RegularTableElement } from "regular-table";
|
|
35
|
+
|
|
36
|
+
type RenderTarget = "shadow" | "light";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The custom element class for this plugin. The interface methods for this
|
|
40
|
+
*/
|
|
41
|
+
export class HTMLPerspectiveViewerDatagridPluginElement
|
|
42
|
+
extends HTMLElement
|
|
43
|
+
implements IPerspectiveViewerPlugin
|
|
44
|
+
{
|
|
45
|
+
private static _global_stylesheet_installed: boolean = false;
|
|
46
|
+
private static _sheet: CSSStyleSheet | undefined;
|
|
47
|
+
|
|
48
|
+
// Determines whether this datagrid renders in the light DOM. This will
|
|
49
|
+
// break style encapsulation and may cause inconsistent behavior.
|
|
50
|
+
static renderTarget: RenderTarget =
|
|
51
|
+
window.CSS?.supports &&
|
|
52
|
+
window.CSS?.supports("selector(:host-context(foo))")
|
|
53
|
+
? "shadow"
|
|
54
|
+
: "light";
|
|
55
|
+
|
|
56
|
+
regular_table: RegularTableElement;
|
|
57
|
+
model?: DatagridModel;
|
|
58
|
+
_toolbar?: DatagridToolbarElement;
|
|
59
|
+
_edit_button?: HTMLElement;
|
|
60
|
+
_scroll_lock?: HTMLElement;
|
|
61
|
+
_is_scroll_lock: boolean;
|
|
62
|
+
_edit_mode: EditMode;
|
|
63
|
+
_initialized?: boolean;
|
|
64
|
+
_reset_scroll_top?: boolean;
|
|
65
|
+
_reset_scroll_left?: boolean;
|
|
66
|
+
_reset_select?: boolean;
|
|
67
|
+
_reset_column_size?: boolean;
|
|
68
|
+
|
|
69
|
+
constructor() {
|
|
70
|
+
super();
|
|
71
|
+
this.regular_table = document.createElement(
|
|
72
|
+
"regular-table",
|
|
73
|
+
) as RegularTableElement;
|
|
74
|
+
this.regular_table.part = "regular-table";
|
|
75
|
+
this._is_scroll_lock = false;
|
|
76
|
+
this._edit_mode = "READ_ONLY";
|
|
77
|
+
const Elem = HTMLPerspectiveViewerDatagridPluginElement;
|
|
78
|
+
if (!Elem._sheet) {
|
|
79
|
+
Elem._sheet = new CSSStyleSheet();
|
|
80
|
+
Elem._sheet.replaceSync(datagridStyles);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (Elem.renderTarget === "shadow") {
|
|
84
|
+
const shadow = this.attachShadow({ mode: "open" });
|
|
85
|
+
shadow.adoptedStyleSheets.push(Elem._sheet);
|
|
86
|
+
} else if (
|
|
87
|
+
Elem.renderTarget === "light" &&
|
|
88
|
+
!Elem._global_stylesheet_installed
|
|
89
|
+
) {
|
|
90
|
+
Elem._global_stylesheet_installed = true;
|
|
91
|
+
document.adoptedStyleSheets.push(Elem._sheet);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
connectedCallback(): void {
|
|
96
|
+
if (!this._toolbar) {
|
|
97
|
+
this._toolbar = document.createElement(
|
|
98
|
+
"perspective-viewer-datagrid-toolbar",
|
|
99
|
+
) as DatagridToolbarElement;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const parent = this.parentElement;
|
|
103
|
+
if (parent) {
|
|
104
|
+
parent.appendChild(this._toolbar);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
disconnectedCallback(): void {
|
|
109
|
+
this._toolbar?.parentElement?.removeChild?.(this._toolbar);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async activate(view: View): Promise<void> {
|
|
113
|
+
return await activate.call(this, view);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
get name(): string {
|
|
117
|
+
return "Datagrid";
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
get category(): string {
|
|
121
|
+
return "Basic";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
get select_mode(): string {
|
|
125
|
+
return "toggle";
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
get min_config_columns(): number | undefined {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
get config_column_names(): string[] {
|
|
133
|
+
return ["Columns"];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Give the Datagrid a higher priority so it is loaded
|
|
138
|
+
* over the default charts by default.
|
|
139
|
+
*/
|
|
140
|
+
get priority(): number {
|
|
141
|
+
return 1;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
can_render_column_styles(type: string, _group: string): boolean {
|
|
145
|
+
return type !== "boolean";
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
column_style_controls(type: string, group: string): ColumnStyleOpts {
|
|
149
|
+
return column_style_controls.call(this, type as any, group);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async draw(view: View): Promise<void> {
|
|
153
|
+
return await draw.call(this, view);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async update(view: View): Promise<void> {
|
|
157
|
+
if (this.model === undefined) {
|
|
158
|
+
await this.draw(view);
|
|
159
|
+
} else if (this.model._config.split_by?.length > 0) {
|
|
160
|
+
const dimensions = await view.dimensions();
|
|
161
|
+
this.model._num_rows = dimensions.num_view_rows;
|
|
162
|
+
await this.regular_table.draw();
|
|
163
|
+
} else {
|
|
164
|
+
this.model._num_rows = await view.num_rows();
|
|
165
|
+
await this.regular_table.draw();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async render(viewport?: ViewWindow): Promise<string> {
|
|
170
|
+
const viewer = this.parentElement as PerspectiveViewerElement;
|
|
171
|
+
const view = await viewer.getView();
|
|
172
|
+
const json = await view.to_columns(viewport as any);
|
|
173
|
+
const cols = await view.column_paths(viewport as any);
|
|
174
|
+
|
|
175
|
+
const nrows =
|
|
176
|
+
viewport?.end_row !== undefined &&
|
|
177
|
+
viewport?.end_row !== null &&
|
|
178
|
+
viewport?.start_row !== undefined &&
|
|
179
|
+
viewport?.start_row !== null
|
|
180
|
+
? viewport.end_row - viewport.start_row
|
|
181
|
+
: await view.num_rows();
|
|
182
|
+
let out = "";
|
|
183
|
+
for (let ridx = 0; ridx < nrows; ridx++) {
|
|
184
|
+
for (const col_name of cols) {
|
|
185
|
+
const col = (json as Record<string, unknown[]>)[col_name];
|
|
186
|
+
const type = this.model!._schema[col_name];
|
|
187
|
+
const pluginConfig = (this.regular_table as any)[
|
|
188
|
+
PRIVATE_PLUGIN_SYMBOL
|
|
189
|
+
] as ColumnsConfig | undefined;
|
|
190
|
+
const columnName = col_name.split("|").at(-1)!;
|
|
191
|
+
const formatter = format_raw(
|
|
192
|
+
type,
|
|
193
|
+
pluginConfig?.[columnName] || {},
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
if (formatter) {
|
|
197
|
+
out += formatter.format(col[ridx]) + "\t";
|
|
198
|
+
} else {
|
|
199
|
+
out += col[ridx] + "\t";
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
out += "\n";
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return out.trim();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async resize(): Promise<void> {
|
|
209
|
+
if (!this.isConnected || this.offsetParent == null) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (this._initialized) {
|
|
214
|
+
await this.regular_table.draw();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async clear(): Promise<void> {
|
|
219
|
+
this.regular_table.resetAutoSize();
|
|
220
|
+
this.regular_table.clear();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async save(): Promise<any> {
|
|
224
|
+
return save.call(this);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async restore(
|
|
228
|
+
token: DatagridPluginConfig,
|
|
229
|
+
columns_config?: ColumnsConfig,
|
|
230
|
+
): Promise<any> {
|
|
231
|
+
return restore.call(this, token, columns_config ?? {});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async restyle(): Promise<void> {
|
|
235
|
+
// Get view from model if available, otherwise no-op
|
|
236
|
+
if (this.model?._view) {
|
|
237
|
+
await this.draw(this.model._view);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async delete(): Promise<void> {
|
|
242
|
+
this.disconnectedCallback();
|
|
243
|
+
this._toolbar = undefined;
|
|
244
|
+
if ((this.regular_table as any).table_model) {
|
|
245
|
+
this.regular_table.resetAutoSize();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
this.regular_table.clear();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
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 TOOLBAR_STYLE from "../../../dist/css/perspective-viewer-datagrid-toolbar.css";
|
|
14
|
+
import { toggle_edit_mode, toggle_scroll_lock } from "../model/toolbar.js";
|
|
15
|
+
import type {
|
|
16
|
+
DatagridPluginElement,
|
|
17
|
+
PerspectiveViewerElement,
|
|
18
|
+
} from "../types.js";
|
|
19
|
+
|
|
20
|
+
const stylesheet = new CSSStyleSheet();
|
|
21
|
+
stylesheet.replaceSync(TOOLBAR_STYLE);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The custom element for this plugin's toolbar, a component which displays in
|
|
25
|
+
* the host `<perspective-viewer>`'s status bar when this plugin is active.
|
|
26
|
+
* In the case of Datagrid, this comprises "Editable" and "Scroll Lock" toggle
|
|
27
|
+
* buttons.
|
|
28
|
+
*/
|
|
29
|
+
export class HTMLPerspectiveViewerDatagridToolbarElement extends HTMLElement {
|
|
30
|
+
private _initialized: boolean = false;
|
|
31
|
+
|
|
32
|
+
connectedCallback(): void {
|
|
33
|
+
if (this._initialized) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this._initialized = true;
|
|
38
|
+
this.setAttribute("slot", "statusbar-extra");
|
|
39
|
+
this.attachShadow({ mode: "open" });
|
|
40
|
+
this.shadowRoot!.adoptedStyleSheets.push(stylesheet);
|
|
41
|
+
this.shadowRoot!.innerHTML = `
|
|
42
|
+
<div id="toolbar">
|
|
43
|
+
<span class="hover-target">
|
|
44
|
+
<span id="scroll_lock" class="button">
|
|
45
|
+
<span></span>
|
|
46
|
+
</span>
|
|
47
|
+
</span>
|
|
48
|
+
<span class="hover-target">
|
|
49
|
+
<span id="edit_mode" class="button" data-edit-mode="READ_ONLY">
|
|
50
|
+
<span></span>
|
|
51
|
+
</span>
|
|
52
|
+
</span>
|
|
53
|
+
</div>
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
const viewer = this.parentElement as PerspectiveViewerElement;
|
|
57
|
+
const plugin = this.previousElementSibling as DatagridPluginElement;
|
|
58
|
+
|
|
59
|
+
plugin._scroll_lock = this.shadowRoot!.querySelector(
|
|
60
|
+
"#scroll_lock",
|
|
61
|
+
) as HTMLElement;
|
|
62
|
+
plugin._scroll_lock.addEventListener("click", () =>
|
|
63
|
+
toggle_scroll_lock.call(plugin),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
plugin._edit_button = this.shadowRoot!.querySelector(
|
|
67
|
+
"#edit_mode",
|
|
68
|
+
) as HTMLElement;
|
|
69
|
+
plugin._edit_button.addEventListener("click", () => {
|
|
70
|
+
toggle_edit_mode.call(plugin);
|
|
71
|
+
plugin.regular_table.draw();
|
|
72
|
+
viewer.dispatchEvent(new Event("perspective-config-update"));
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
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 { FormatterCache, Formatter } from "./formatter_cache.js";
|
|
14
|
+
import type { DatagridModel, ColumnsConfig, ColumnConfig } from "../types.js";
|
|
15
|
+
import { ColumnType } from "@perspective-dev/client";
|
|
16
|
+
|
|
17
|
+
const FORMAT_CACHE = new FormatterCache();
|
|
18
|
+
const MAX_BAR_WIDTH_PCT = 1;
|
|
19
|
+
|
|
20
|
+
export function format_raw(
|
|
21
|
+
type: ColumnType,
|
|
22
|
+
value: ColumnConfig,
|
|
23
|
+
): Formatter | false | undefined {
|
|
24
|
+
return FORMAT_CACHE.get(type, value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Format a single cell's text content as the content of a `<td>` or `<th>`.
|
|
29
|
+
*/
|
|
30
|
+
export function format_cell(
|
|
31
|
+
this: DatagridModel,
|
|
32
|
+
title: string,
|
|
33
|
+
val: unknown,
|
|
34
|
+
plugins: ColumnsConfig = {},
|
|
35
|
+
use_table_schema = false,
|
|
36
|
+
): string | HTMLElement | null {
|
|
37
|
+
if (val === null) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const type: ColumnType = ((use_table_schema && this._table_schema[title]) ||
|
|
42
|
+
this._schema[title] ||
|
|
43
|
+
"string") as ColumnType;
|
|
44
|
+
const plugin: ColumnConfig = plugins[title] || {};
|
|
45
|
+
const is_numeric = type === "integer" || type === "float";
|
|
46
|
+
|
|
47
|
+
if (is_numeric && plugin?.number_fg_mode === "bar") {
|
|
48
|
+
const a = Math.max(
|
|
49
|
+
0,
|
|
50
|
+
Math.min(
|
|
51
|
+
MAX_BAR_WIDTH_PCT,
|
|
52
|
+
Math.abs((val as number) / plugin.fg_gradient!) *
|
|
53
|
+
MAX_BAR_WIDTH_PCT,
|
|
54
|
+
),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const div = this._div_factory.get();
|
|
58
|
+
const anchor = (val as number) >= 0 ? "left" : "right";
|
|
59
|
+
const pct = (a * 100).toFixed(2);
|
|
60
|
+
div.setAttribute(
|
|
61
|
+
"style",
|
|
62
|
+
`width:calc(${pct}% - 4px);position:absolute;${anchor}:2px;height:80%;top:10%;pointer-events:none;`,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return div;
|
|
66
|
+
} else if (plugin?.format === "link" && type === "string") {
|
|
67
|
+
const anchor = document.createElement("a");
|
|
68
|
+
anchor.setAttribute("href", val as string);
|
|
69
|
+
anchor.setAttribute("target", "_blank");
|
|
70
|
+
anchor.textContent = val as string;
|
|
71
|
+
return anchor;
|
|
72
|
+
} else if (plugin?.format === "bold" && type === "string") {
|
|
73
|
+
const bold = document.createElement("b");
|
|
74
|
+
bold.textContent = val as string;
|
|
75
|
+
return bold;
|
|
76
|
+
} else if (plugin?.format === "italics" && type === "string") {
|
|
77
|
+
const italic = document.createElement("i");
|
|
78
|
+
italic.textContent = val as string;
|
|
79
|
+
return italic;
|
|
80
|
+
} else {
|
|
81
|
+
const formatter = FORMAT_CACHE.get(type, plugin);
|
|
82
|
+
return formatter ? formatter.format(val) : (val as string);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
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 { PRIVATE_PLUGIN_SYMBOL } from "../types.js";
|
|
14
|
+
import { format_cell } from "./format_cell.js";
|
|
15
|
+
import type { DatagridModel, RegularTable, ColumnsConfig } from "../types.js";
|
|
16
|
+
|
|
17
|
+
type RowHeaderCell = string | HTMLElement | { toString(): string };
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Format a single cell of the `group_by` tree header for __ROW_PATH__ data.
|
|
21
|
+
*/
|
|
22
|
+
export function* format_tree_header_row_path(
|
|
23
|
+
this: DatagridModel,
|
|
24
|
+
paths: unknown[][] = [],
|
|
25
|
+
row_headers: string[],
|
|
26
|
+
regularTable: RegularTable,
|
|
27
|
+
): Generator<RowHeaderCell[]> {
|
|
28
|
+
const plugins: ColumnsConfig =
|
|
29
|
+
(regularTable as any)[PRIVATE_PLUGIN_SYMBOL] || {};
|
|
30
|
+
for (let path of paths) {
|
|
31
|
+
const fullPath: unknown[] = ["TOTAL", ...path];
|
|
32
|
+
const last = fullPath[fullPath.length - 1];
|
|
33
|
+
let newPath: RowHeaderCell[] = fullPath
|
|
34
|
+
.slice(0, fullPath.length - 1)
|
|
35
|
+
.fill("") as string[];
|
|
36
|
+
const formatted = format_cell.call(
|
|
37
|
+
this,
|
|
38
|
+
row_headers[newPath.length - 1],
|
|
39
|
+
last,
|
|
40
|
+
plugins,
|
|
41
|
+
true,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
if (formatted instanceof HTMLElement) {
|
|
45
|
+
newPath = newPath.concat(formatted);
|
|
46
|
+
} else {
|
|
47
|
+
newPath = newPath.concat({ toString: () => formatted as string });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
newPath.length = row_headers.length + 1;
|
|
51
|
+
yield newPath;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Format a single cell of the `group_by` tree header.
|
|
57
|
+
*/
|
|
58
|
+
export function* format_tree_header(
|
|
59
|
+
this: DatagridModel,
|
|
60
|
+
paths: unknown[][] = [],
|
|
61
|
+
row_headers: string[],
|
|
62
|
+
regularTable: RegularTable,
|
|
63
|
+
): Generator<unknown[]> {
|
|
64
|
+
const plugins: ColumnsConfig =
|
|
65
|
+
(regularTable as any)[PRIVATE_PLUGIN_SYMBOL] || {};
|
|
66
|
+
for (const path of paths) {
|
|
67
|
+
const new_path: unknown[] = [""];
|
|
68
|
+
for (const idx in path) {
|
|
69
|
+
new_path.push(
|
|
70
|
+
format_cell.call(
|
|
71
|
+
this,
|
|
72
|
+
row_headers[idx],
|
|
73
|
+
path[idx],
|
|
74
|
+
plugins,
|
|
75
|
+
true,
|
|
76
|
+
),
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
yield path;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
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 { ColumnConfig } from "../types.js";
|
|
15
|
+
|
|
16
|
+
export interface Formatter {
|
|
17
|
+
format(val: unknown): string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class BooleanFormatter implements Formatter {
|
|
21
|
+
format(val: unknown): string {
|
|
22
|
+
return val ? "true" : "false";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// PluginConfig is a subset of ColumnConfig with the formatting properties
|
|
27
|
+
type PluginConfig = Pick<ColumnConfig, "date_format" | "number_format">;
|
|
28
|
+
|
|
29
|
+
const LEGACY_CONFIG: Record<
|
|
30
|
+
string,
|
|
31
|
+
{ format: Intl.NumberFormatOptions | Intl.DateTimeFormatOptions }
|
|
32
|
+
> = {
|
|
33
|
+
float: {
|
|
34
|
+
format: {
|
|
35
|
+
style: "decimal",
|
|
36
|
+
minimumFractionDigits: 2,
|
|
37
|
+
maximumFractionDigits: 2,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
datetime: {
|
|
41
|
+
format: {
|
|
42
|
+
dateStyle: "short",
|
|
43
|
+
timeStyle: "medium",
|
|
44
|
+
} as Intl.DateTimeFormatOptions,
|
|
45
|
+
},
|
|
46
|
+
date: {
|
|
47
|
+
format: {
|
|
48
|
+
dateStyle: "short",
|
|
49
|
+
} as Intl.DateTimeFormatOptions,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export class FormatterCache {
|
|
54
|
+
private _formatters: Map<string, Formatter | false>;
|
|
55
|
+
|
|
56
|
+
constructor() {
|
|
57
|
+
this._formatters = new Map();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private create_datetime_formatter(
|
|
61
|
+
_type: ColumnType,
|
|
62
|
+
plugin: PluginConfig,
|
|
63
|
+
): Intl.DateTimeFormat {
|
|
64
|
+
if (plugin.date_format?.format !== "custom") {
|
|
65
|
+
const options: Intl.DateTimeFormatOptions = {
|
|
66
|
+
timeZone: plugin.date_format?.timeZone,
|
|
67
|
+
dateStyle:
|
|
68
|
+
plugin.date_format?.dateStyle === "disabled"
|
|
69
|
+
? undefined
|
|
70
|
+
: (plugin.date_format?.dateStyle ?? "short"),
|
|
71
|
+
timeStyle:
|
|
72
|
+
plugin.date_format?.timeStyle === "disabled"
|
|
73
|
+
? undefined
|
|
74
|
+
: (plugin.date_format?.timeStyle ?? "medium"),
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return new Intl.DateTimeFormat(
|
|
78
|
+
navigator.languages as string[],
|
|
79
|
+
options,
|
|
80
|
+
);
|
|
81
|
+
} else {
|
|
82
|
+
const options: Intl.DateTimeFormatOptions = {
|
|
83
|
+
timeZone: plugin.date_format?.timeZone,
|
|
84
|
+
hour12: plugin.date_format?.hour12 ?? true,
|
|
85
|
+
fractionalSecondDigits:
|
|
86
|
+
plugin.date_format?.fractionalSecondDigits,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
if (plugin.date_format?.year !== "disabled") {
|
|
90
|
+
options.year = plugin.date_format?.year ?? "2-digit";
|
|
91
|
+
}
|
|
92
|
+
if (plugin.date_format?.month !== "disabled") {
|
|
93
|
+
options.month = plugin.date_format?.month ?? "numeric";
|
|
94
|
+
}
|
|
95
|
+
if (plugin.date_format?.day !== "disabled") {
|
|
96
|
+
options.day = plugin.date_format?.day ?? "numeric";
|
|
97
|
+
}
|
|
98
|
+
if (
|
|
99
|
+
plugin.date_format?.weekday &&
|
|
100
|
+
plugin.date_format?.weekday !== "disabled"
|
|
101
|
+
) {
|
|
102
|
+
options.weekday = plugin.date_format.weekday;
|
|
103
|
+
}
|
|
104
|
+
if (plugin.date_format?.hour !== "disabled") {
|
|
105
|
+
options.hour = plugin.date_format?.hour ?? "numeric";
|
|
106
|
+
}
|
|
107
|
+
if (plugin.date_format?.minute !== "disabled") {
|
|
108
|
+
options.minute = plugin.date_format?.minute ?? "numeric";
|
|
109
|
+
}
|
|
110
|
+
if (plugin.date_format?.second !== "disabled") {
|
|
111
|
+
options.second = plugin.date_format?.second ?? "numeric";
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return new Intl.DateTimeFormat(
|
|
115
|
+
navigator.languages as string[],
|
|
116
|
+
options,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private create_date_formatter(
|
|
122
|
+
_type: ColumnType,
|
|
123
|
+
plugin: PluginConfig,
|
|
124
|
+
): Intl.DateTimeFormat {
|
|
125
|
+
const options: Intl.DateTimeFormatOptions = {
|
|
126
|
+
timeZone: "utc",
|
|
127
|
+
dateStyle:
|
|
128
|
+
plugin.date_format?.dateStyle === "disabled"
|
|
129
|
+
? undefined
|
|
130
|
+
: (plugin.date_format?.dateStyle ?? "short"),
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
return new Intl.DateTimeFormat(
|
|
134
|
+
navigator.languages as string[],
|
|
135
|
+
options,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private create_number_formatter(
|
|
140
|
+
type: ColumnType,
|
|
141
|
+
plugin: PluginConfig,
|
|
142
|
+
): Intl.NumberFormat {
|
|
143
|
+
const format =
|
|
144
|
+
plugin.number_format ??
|
|
145
|
+
(LEGACY_CONFIG[type]?.format as Intl.NumberFormatOptions);
|
|
146
|
+
return new Intl.NumberFormat(navigator.languages as string[], format);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private create_boolean_formatter(
|
|
150
|
+
_type: ColumnType,
|
|
151
|
+
_plugin: PluginConfig,
|
|
152
|
+
): Formatter {
|
|
153
|
+
return new BooleanFormatter();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
get(type: ColumnType, plugin: PluginConfig): Formatter | false | undefined {
|
|
157
|
+
const formatter_key = [
|
|
158
|
+
type,
|
|
159
|
+
...Object.values(plugin.date_format ?? {}),
|
|
160
|
+
...Object.values(plugin.number_format ?? {}),
|
|
161
|
+
].join("-");
|
|
162
|
+
|
|
163
|
+
if (!this._formatters.has(formatter_key)) {
|
|
164
|
+
if (type === "date") {
|
|
165
|
+
this._formatters.set(
|
|
166
|
+
formatter_key,
|
|
167
|
+
this.create_date_formatter(type, plugin),
|
|
168
|
+
);
|
|
169
|
+
} else if (type === "datetime") {
|
|
170
|
+
this._formatters.set(
|
|
171
|
+
formatter_key,
|
|
172
|
+
this.create_datetime_formatter(type, plugin),
|
|
173
|
+
);
|
|
174
|
+
} else if (type === "integer" || type === "float") {
|
|
175
|
+
this._formatters.set(
|
|
176
|
+
formatter_key,
|
|
177
|
+
this.create_number_formatter(type, plugin),
|
|
178
|
+
);
|
|
179
|
+
} else if (type === "boolean") {
|
|
180
|
+
this._formatters.set(
|
|
181
|
+
formatter_key,
|
|
182
|
+
this.create_boolean_formatter(type, plugin),
|
|
183
|
+
);
|
|
184
|
+
} else {
|
|
185
|
+
this._formatters.set(formatter_key, false);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return this._formatters.get(formatter_key);
|
|
190
|
+
}
|
|
191
|
+
}
|