@schukai/monster 3.55.6 → 3.56.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 (40) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +2 -2
  3. package/source/components/datatable/change-button.mjs +265 -0
  4. package/source/components/datatable/dataset.mjs +76 -5
  5. package/source/components/datatable/datasource/dom.mjs +1 -1
  6. package/source/components/datatable/datasource/rest.mjs +401 -345
  7. package/source/components/datatable/datasource.mjs +8 -0
  8. package/source/components/datatable/datatable.mjs +600 -600
  9. package/source/components/datatable/filter/range.mjs +1 -3
  10. package/source/components/datatable/filter/select.mjs +1 -1
  11. package/source/components/datatable/filter.mjs +1 -3
  12. package/source/components/datatable/save-button.mjs +301 -0
  13. package/source/components/datatable/status.mjs +6 -2
  14. package/source/components/datatable/style/change-button.pcss +19 -0
  15. package/source/components/datatable/style/save-button.pcss +44 -0
  16. package/source/components/datatable/stylesheet/change-button.mjs +27 -0
  17. package/source/components/datatable/stylesheet/save-button.mjs +27 -0
  18. package/source/components/datatable/util.mjs +3 -1
  19. package/source/components/form/button-bar.mjs +3 -3
  20. package/source/components/form/button.mjs +1 -2
  21. package/source/components/form/form.mjs +1 -1
  22. package/source/components/form/message-state-button.mjs +1 -1
  23. package/source/components/form/select.mjs +1744 -1777
  24. package/source/components/form/state-button.mjs +1 -1
  25. package/source/components/form/tabs.mjs +3 -3
  26. package/source/components/form/tree-select.mjs +6 -2
  27. package/source/components/host/overlay.mjs +4 -1
  28. package/source/components/tree-menu/tree-menu.mjs +0 -1
  29. package/source/data/datasource/server/restapi.mjs +2 -3
  30. package/source/data/datasource/server.mjs +1 -1
  31. package/source/data/extend.mjs +55 -55
  32. package/source/data/pathfinder.mjs +6 -4
  33. package/source/dom/constants.mjs +9 -0
  34. package/source/dom/customelement.mjs +25 -7
  35. package/source/dom/updater.mjs +34 -3
  36. package/source/i18n/translations.mjs +1 -1
  37. package/source/monster.mjs +0 -1
  38. package/source/types/noderecursiveiterator.mjs +2 -3
  39. package/source/types/version.mjs +1 -1
  40. package/test/cases/monster.mjs +1 -1
@@ -3,63 +3,63 @@
3
3
  * SPDX-License-Identifier: AGPL-3.0
4
4
  */
5
5
 
6
- import {Datasource} from "./datasource.mjs";
6
+ import { Datasource } from "./datasource.mjs";
7
7
  import {
8
- assembleMethodSymbol,
9
- CustomElement,
10
- registerCustomElement,
11
- getSlottedElements,
8
+ assembleMethodSymbol,
9
+ CustomElement,
10
+ registerCustomElement,
11
+ getSlottedElements,
12
12
  } from "../../dom/customelement.mjs";
13
- import {findTargetElementFromEvent} from "../../dom/events.mjs";
13
+ import { findTargetElementFromEvent } from "../../dom/events.mjs";
14
14
  import {
15
- isString,
16
- isFunction,
17
- isInstance,
18
- isObject,
19
- isArray,
15
+ isString,
16
+ isFunction,
17
+ isInstance,
18
+ isObject,
19
+ isArray,
20
20
  } from "../../types/is.mjs";
21
- import {Observer} from "../../types/observer.mjs";
21
+ import { Observer } from "../../types/observer.mjs";
22
22
  import {
23
- ATTRIBUTE_DATATABLE_HEAD,
24
- ATTRIBUTE_DATATABLE_GRID_TEMPLATE,
25
- ATTRIBUTE_DATASOURCE_SELECTOR,
26
- ATTRIBUTE_DATATABLE_ALIGN,
27
- ATTRIBUTE_DATATABLE_SORTABLE,
28
- ATTRIBUTE_DATATABLE_MODE,
29
- ATTRIBUTE_DATATABLE_INDEX,
30
- ATTRIBUTE_DATATABLE_MODE_HIDDEN,
31
- ATTRIBUTE_DATATABLE_MODE_VISIBLE,
32
- ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
33
- ATTRIBUTE_DATATABLE_MODE_FIXED,
23
+ ATTRIBUTE_DATATABLE_HEAD,
24
+ ATTRIBUTE_DATATABLE_GRID_TEMPLATE,
25
+ ATTRIBUTE_DATASOURCE_SELECTOR,
26
+ ATTRIBUTE_DATATABLE_ALIGN,
27
+ ATTRIBUTE_DATATABLE_SORTABLE,
28
+ ATTRIBUTE_DATATABLE_MODE,
29
+ ATTRIBUTE_DATATABLE_INDEX,
30
+ ATTRIBUTE_DATATABLE_MODE_HIDDEN,
31
+ ATTRIBUTE_DATATABLE_MODE_VISIBLE,
32
+ ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
33
+ ATTRIBUTE_DATATABLE_MODE_FIXED,
34
34
  } from "./constants.mjs";
35
- import {instanceSymbol} from "../../constants.mjs";
35
+ import { instanceSymbol } from "../../constants.mjs";
36
36
  import {
37
- Header,
38
- createOrderStatement,
39
- DIRECTION_ASC,
40
- DIRECTION_DESC,
41
- DIRECTION_NONE,
37
+ Header,
38
+ createOrderStatement,
39
+ DIRECTION_ASC,
40
+ DIRECTION_DESC,
41
+ DIRECTION_NONE,
42
42
  } from "./datatable/header.mjs";
43
- import {getStoredFilterConfigKey} from "./filter/util.mjs";
44
- import {DatatableStyleSheet} from "./stylesheet/datatable.mjs";
43
+ import { getStoredFilterConfigKey } from "./filter/util.mjs";
44
+ import { DatatableStyleSheet } from "./stylesheet/datatable.mjs";
45
45
  import {
46
- handleDataSourceChanges,
47
- datasourceLinkedElementSymbol,
46
+ handleDataSourceChanges,
47
+ datasourceLinkedElementSymbol,
48
48
  } from "./util.mjs";
49
49
  import "./columnbar.mjs";
50
50
  import "./filter-button.mjs";
51
- import {getDocument, getWindow} from "../../dom/util.mjs";
52
- import {addAttributeToken} from "../../dom/attributes.mjs";
53
- import {ATTRIBUTE_ERRORMESSAGE} from "../../dom/constants.mjs";
54
- import {getDocumentTranslations} from "../../i18n/translations.mjs";
51
+ import { getDocument, getWindow } from "../../dom/util.mjs";
52
+ import { addAttributeToken } from "../../dom/attributes.mjs";
53
+ import { ATTRIBUTE_ERRORMESSAGE } from "../../dom/constants.mjs";
54
+ import { getDocumentTranslations } from "../../i18n/translations.mjs";
55
55
  import "../state/state.mjs";
56
56
  import "../host/collapse.mjs";
57
- import {generateUniqueConfigKey} from "../host/util.mjs";
57
+ import { generateUniqueConfigKey } from "../host/util.mjs";
58
58
 
59
59
  import "./datasource/dom.mjs";
60
60
  import "./datasource/rest.mjs";
61
61
 
62
- export {DataTable};
62
+ export { DataTable };
63
63
 
64
64
  /**
65
65
  * @private
@@ -120,209 +120,209 @@ const columnBarElementSymbol = Symbol("columnBarElement");
120
120
  * @summary A data table
121
121
  */
122
122
  class DataTable extends CustomElement {
123
- /**
124
- * This method is called by the `instanceof` operator.
125
- * @returns {symbol}
126
- */
127
- static get [instanceSymbol]() {
128
- return Symbol.for("@schukai/monster/components/datatable@@instance");
129
- }
130
-
131
- /**
132
- * To set the options via the html tag the attribute `data-monster-options` must be used.
133
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
134
- *
135
- * The individual configuration values can be found in the table.
136
- *
137
- * @property {Object} templates Template definitions
138
- * @property {string} templates.main Main template
139
- * @property {Object} datasource Datasource configuration
140
- * @property {string} datasource.selector Selector for the datasource
141
- * @property {Object} mapping Mapping configuration
142
- * @property {string} mapping.data Data mapping
143
- * @property {Array} data Data
144
- * @property {Array} headers Headers
145
- * @property {Object} responsive Responsive configuration
146
- * @property {number} responsive.breakpoint Breakpoint for responsive mode
147
- * @property {Object} labels Labels
148
- * @property {string} labels.theListContainsNoEntries Label for empty state
149
- * @property {Object} features Features
150
- * @property {boolean} features.settings Settings feature
151
- * @property {boolean} features.footer Footer feature
152
- * @property {boolean} features.autoInit Auto init feature (init datasource automatically)
153
- * @property {Object} templateMapping Template mapping
154
- * @property {string} templateMapping.row-key Row key
155
- * @property {string} templateMapping.filter-id Filter id
156
- **/
157
- get defaults() {
158
- return Object.assign(
159
- {},
160
- super.defaults,
161
- {
162
- templates: {
163
- main: getTemplate(),
164
- emptyState: getEmptyTemplate(),
165
- },
166
-
167
- datasource: {
168
- selector: null,
169
- },
170
-
171
- mapping: {
172
- data: "dataset",
173
- },
174
-
175
- data: [],
176
- headers: [],
177
-
178
- responsive: {
179
- breakpoint: 800,
180
- },
181
-
182
- labels: {
183
- theListContainsNoEntries: "The list contains no entries",
184
- },
185
-
186
- features: {
187
- settings: true,
188
- footer: true,
189
- autoInit: true,
190
- },
191
-
192
- templateMapping: {
193
- "row-key": null,
194
- "filter-id": null,
195
- },
196
- },
197
- initOptionsFromArguments.call(this),
198
- );
199
- }
200
-
201
- /**
202
- *
203
- * @param {string} selector
204
- * @returns {NodeListOf<*>}
205
- */
206
- getGridElements(selector) {
207
- return this[gridElementSymbol].querySelectorAll(selector);
208
- }
209
-
210
- /**
211
- *
212
- * @return {string}
213
- */
214
- static getTag() {
215
- return "monster-datatable";
216
- }
217
-
218
- /**
219
- *
220
- * @return {Monster.Components.Form.Form}
221
- */
222
- [assembleMethodSymbol]() {
223
- const rawKey = this.getOption("templateMapping.row-key");
224
-
225
- if (rawKey === null) {
226
- if (this.id !== null && this.id !== "") {
227
- const rawKey = this.getOption("templateMapping.row-key");
228
- if (rawKey === null) {
229
- this.setOption("templateMapping.row-key", this.id + "-row");
230
- }
231
- } else {
232
- this.setOption("templateMapping.row-key", "row");
233
- }
234
- }
235
-
236
- if (this.id !== null && this.id !== "") {
237
- this.setOption("templateMapping.filter-id", "" + this.id + "-filter");
238
- } else {
239
- this.setOption("templateMapping.filter-id", "filter");
240
- }
241
-
242
- super[assembleMethodSymbol]();
243
-
244
- initControlReferences.call(this);
245
- initEventHandler.call(this);
246
-
247
- const selector = this.getOption("datasource.selector");
248
-
249
- if (isString(selector)) {
250
- const elements = document.querySelectorAll(selector);
251
- if (elements.length !== 1) {
252
- throw new Error("the selector must match exactly one element");
253
- }
254
-
255
- const element = elements[0];
256
-
257
- if (!isInstance(element, Datasource)) {
258
- throw new TypeError("the element must be a datasource");
259
- }
260
-
261
- this[datasourceLinkedElementSymbol] = element;
262
-
263
- setTimeout(() => {
264
- handleDataSourceChanges.call(this);
265
- element.datasource.attachObserver(
266
- new Observer(handleDataSourceChanges.bind(this)),
267
- );
268
- }, 0);
269
- }
270
-
271
- getHostConfig
272
- .call(this, getColumnVisibilityConfigKey)
273
- .then((config) => {
274
- const headerOrderMap = new Map();
275
-
276
- getHostConfig
277
- .call(this, getStoredOrderConfigKey)
278
- .then((orderConfig) => {
279
- if (isArray(orderConfig) || orderConfig.length > 0) {
280
- for (let i = 0; i < orderConfig.length; i++) {
281
- const item = orderConfig[i];
282
- const parts = item.split(" ");
283
- const field = parts[0];
284
- const direction = parts[1] || DIRECTION_ASC;
285
- headerOrderMap.set(field, direction);
286
- }
287
- }
288
- })
289
- .then(() => {
290
- try {
291
- initGridAndStructs.call(this, config, headerOrderMap);
292
- } catch (error) {
293
- addAttributeToken(
294
- this,
295
- ATTRIBUTE_ERRORMESSAGE,
296
- error?.message || error.toString(),
297
- );
298
- }
299
-
300
- updateColumnBar.call(this);
301
- })
302
- .catch((error) => {
303
- addAttributeToken(
304
- this,
305
- ATTRIBUTE_ERRORMESSAGE,
306
- error?.message || error.toString(),
307
- );
308
- });
309
- })
310
- .catch((error) => {
311
- addAttributeToken(
312
- this,
313
- ATTRIBUTE_ERRORMESSAGE,
314
- error?.message || error.toString(),
315
- );
316
- });
317
- }
318
-
319
- /**
320
- *
321
- * @return {CSSStyleSheet[]}
322
- */
323
- static getCSSStyleSheet() {
324
- return [DatatableStyleSheet];
325
- }
123
+ /**
124
+ * This method is called by the `instanceof` operator.
125
+ * @returns {symbol}
126
+ */
127
+ static get [instanceSymbol]() {
128
+ return Symbol.for("@schukai/monster/components/datatable@@instance");
129
+ }
130
+
131
+ /**
132
+ * To set the options via the html tag the attribute `data-monster-options` must be used.
133
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
134
+ *
135
+ * The individual configuration values can be found in the table.
136
+ *
137
+ * @property {Object} templates Template definitions
138
+ * @property {string} templates.main Main template
139
+ * @property {Object} datasource Datasource configuration
140
+ * @property {string} datasource.selector Selector for the datasource
141
+ * @property {Object} mapping Mapping configuration
142
+ * @property {string} mapping.data Data mapping
143
+ * @property {Array} data Data
144
+ * @property {Array} headers Headers
145
+ * @property {Object} responsive Responsive configuration
146
+ * @property {number} responsive.breakpoint Breakpoint for responsive mode
147
+ * @property {Object} labels Labels
148
+ * @property {string} labels.theListContainsNoEntries Label for empty state
149
+ * @property {Object} features Features
150
+ * @property {boolean} features.settings Settings feature
151
+ * @property {boolean} features.footer Footer feature
152
+ * @property {boolean} features.autoInit Auto init feature (init datasource automatically)
153
+ * @property {Object} templateMapping Template mapping
154
+ * @property {string} templateMapping.row-key Row key
155
+ * @property {string} templateMapping.filter-id Filter id
156
+ **/
157
+ get defaults() {
158
+ return Object.assign(
159
+ {},
160
+ super.defaults,
161
+ {
162
+ templates: {
163
+ main: getTemplate(),
164
+ emptyState: getEmptyTemplate(),
165
+ },
166
+
167
+ datasource: {
168
+ selector: null,
169
+ },
170
+
171
+ mapping: {
172
+ data: "dataset",
173
+ },
174
+
175
+ data: [],
176
+ headers: [],
177
+
178
+ responsive: {
179
+ breakpoint: 800,
180
+ },
181
+
182
+ labels: {
183
+ theListContainsNoEntries: "The list contains no entries",
184
+ },
185
+
186
+ features: {
187
+ settings: true,
188
+ footer: true,
189
+ autoInit: true,
190
+ },
191
+
192
+ templateMapping: {
193
+ "row-key": null,
194
+ "filter-id": null,
195
+ },
196
+ },
197
+ initOptionsFromArguments.call(this),
198
+ );
199
+ }
200
+
201
+ /**
202
+ *
203
+ * @param {string} selector
204
+ * @returns {NodeListOf<*>}
205
+ */
206
+ getGridElements(selector) {
207
+ return this[gridElementSymbol].querySelectorAll(selector);
208
+ }
209
+
210
+ /**
211
+ *
212
+ * @return {string}
213
+ */
214
+ static getTag() {
215
+ return "monster-datatable";
216
+ }
217
+
218
+ /**
219
+ *
220
+ * @return {Monster.Components.Form.Form}
221
+ */
222
+ [assembleMethodSymbol]() {
223
+ const rawKey = this.getOption("templateMapping.row-key");
224
+
225
+ if (rawKey === null) {
226
+ if (this.id !== null && this.id !== "") {
227
+ const rawKey = this.getOption("templateMapping.row-key");
228
+ if (rawKey === null) {
229
+ this.setOption("templateMapping.row-key", this.id + "-row");
230
+ }
231
+ } else {
232
+ this.setOption("templateMapping.row-key", "row");
233
+ }
234
+ }
235
+
236
+ if (this.id !== null && this.id !== "") {
237
+ this.setOption("templateMapping.filter-id", "" + this.id + "-filter");
238
+ } else {
239
+ this.setOption("templateMapping.filter-id", "filter");
240
+ }
241
+
242
+ super[assembleMethodSymbol]();
243
+
244
+ initControlReferences.call(this);
245
+ initEventHandler.call(this);
246
+
247
+ const selector = this.getOption("datasource.selector");
248
+
249
+ if (isString(selector)) {
250
+ const elements = document.querySelectorAll(selector);
251
+ if (elements.length !== 1) {
252
+ throw new Error("the selector must match exactly one element");
253
+ }
254
+
255
+ const element = elements[0];
256
+
257
+ if (!isInstance(element, Datasource)) {
258
+ throw new TypeError("the element must be a datasource");
259
+ }
260
+
261
+ this[datasourceLinkedElementSymbol] = element;
262
+
263
+ setTimeout(() => {
264
+ handleDataSourceChanges.call(this);
265
+ element.datasource.attachObserver(
266
+ new Observer(handleDataSourceChanges.bind(this)),
267
+ );
268
+ }, 0);
269
+ }
270
+
271
+ getHostConfig
272
+ .call(this, getColumnVisibilityConfigKey)
273
+ .then((config) => {
274
+ const headerOrderMap = new Map();
275
+
276
+ getHostConfig
277
+ .call(this, getStoredOrderConfigKey)
278
+ .then((orderConfig) => {
279
+ if (isArray(orderConfig) || orderConfig.length > 0) {
280
+ for (let i = 0; i < orderConfig.length; i++) {
281
+ const item = orderConfig[i];
282
+ const parts = item.split(" ");
283
+ const field = parts[0];
284
+ const direction = parts[1] || DIRECTION_ASC;
285
+ headerOrderMap.set(field, direction);
286
+ }
287
+ }
288
+ })
289
+ .then(() => {
290
+ try {
291
+ initGridAndStructs.call(this, config, headerOrderMap);
292
+ } catch (error) {
293
+ addAttributeToken(
294
+ this,
295
+ ATTRIBUTE_ERRORMESSAGE,
296
+ error?.message || error.toString(),
297
+ );
298
+ }
299
+
300
+ updateColumnBar.call(this);
301
+ })
302
+ .catch((error) => {
303
+ addAttributeToken(
304
+ this,
305
+ ATTRIBUTE_ERRORMESSAGE,
306
+ error?.message || error.toString(),
307
+ );
308
+ });
309
+ })
310
+ .catch((error) => {
311
+ addAttributeToken(
312
+ this,
313
+ ATTRIBUTE_ERRORMESSAGE,
314
+ error?.message || error.toString(),
315
+ );
316
+ });
317
+ }
318
+
319
+ /**
320
+ *
321
+ * @return {CSSStyleSheet[]}
322
+ */
323
+ static getCSSStyleSheet() {
324
+ return [DatatableStyleSheet];
325
+ }
326
326
  }
327
327
 
328
328
  /**
@@ -330,7 +330,7 @@ class DataTable extends CustomElement {
330
330
  * @returns {string}
331
331
  */
332
332
  function getColumnVisibilityConfigKey() {
333
- return generateUniqueConfigKey("datatable", this?.id, "columns-visibility");
333
+ return generateUniqueConfigKey("datatable", this?.id, "columns-visibility");
334
334
  }
335
335
 
336
336
  /**
@@ -338,7 +338,7 @@ function getColumnVisibilityConfigKey() {
338
338
  * @returns {string}
339
339
  */
340
340
  function getFilterConfigKey() {
341
- return generateUniqueConfigKey("datatable", this?.id, "filter");
341
+ return generateUniqueConfigKey("datatable", this?.id, "filter");
342
342
  }
343
343
 
344
344
  /**
@@ -346,292 +346,293 @@ function getFilterConfigKey() {
346
346
  * @returns {Promise}
347
347
  */
348
348
  function getHostConfig(callback) {
349
- const document = getDocument();
350
- const host = document.querySelector("monster-host");
351
-
352
- if (!(host && this.id)) {
353
- return Promise.resolve({});
354
- }
355
-
356
- if (!host || !isFunction(host?.getConfig)) {
357
- throw new TypeError("the host must be a monster-host");
358
- }
359
-
360
- const configKey = callback.call(this);
361
- return host.hasConfig(configKey).then((hasConfig) => {
362
- if (hasConfig) {
363
- return host.getConfig(configKey);
364
- } else {
365
- return {};
366
- }
367
- });
349
+ const document = getDocument();
350
+ const host = document.querySelector("monster-host");
351
+
352
+ if (!(host && this.id)) {
353
+ return Promise.resolve({});
354
+ }
355
+
356
+ if (!host || !isFunction(host?.getConfig)) {
357
+ throw new TypeError("the host must be a monster-host");
358
+ }
359
+
360
+ const configKey = callback.call(this);
361
+ return host.hasConfig(configKey).then((hasConfig) => {
362
+ if (hasConfig) {
363
+ return host.getConfig(configKey);
364
+ } else {
365
+ return {};
366
+ }
367
+ });
368
368
  }
369
369
 
370
370
  /**
371
371
  * @private
372
372
  */
373
373
  function updateColumnBar() {
374
- if (!this[columnBarElementSymbol]) {
375
- return;
376
- }
377
-
378
- const columns = [];
379
- for (const header of this.getOption("headers")) {
380
- const mode = header.getInternal("mode");
381
-
382
- if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
383
- continue;
384
- }
385
-
386
- columns.push({
387
- visible: mode !== ATTRIBUTE_DATATABLE_MODE_HIDDEN,
388
- name: header.label,
389
- index: header.index,
390
- });
391
- }
392
-
393
- this[columnBarElementSymbol].setOption("columns", columns);
374
+ if (!this[columnBarElementSymbol]) {
375
+ return;
376
+ }
377
+
378
+ const columns = [];
379
+ for (const header of this.getOption("headers")) {
380
+ const mode = header.getInternal("mode");
381
+
382
+ if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
383
+ continue;
384
+ }
385
+
386
+ columns.push({
387
+ visible: mode !== ATTRIBUTE_DATATABLE_MODE_HIDDEN,
388
+ name: header.label,
389
+ index: header.index,
390
+ });
391
+ }
392
+
393
+ this[columnBarElementSymbol].setOption("columns", columns);
394
394
  }
395
395
 
396
396
  /**
397
397
  * @private
398
398
  */
399
399
  function updateHeaderFromColumnBar() {
400
- if (!this[columnBarElementSymbol]) {
401
- return;
402
- }
400
+ if (!this[columnBarElementSymbol]) {
401
+ return;
402
+ }
403
403
 
404
- const options = this[columnBarElementSymbol].getOption("columns");
405
- if (!isArray(options)) return;
404
+ const options = this[columnBarElementSymbol].getOption("columns");
405
+ if (!isArray(options)) return;
406
406
 
407
- const invisibleMap = {};
407
+ const invisibleMap = {};
408
408
 
409
- for (let i = 0; i < options.length; i++) {
410
- const option = options[i];
411
- invisibleMap[option.index] = option.visible;
412
- }
409
+ for (let i = 0; i < options.length; i++) {
410
+ const option = options[i];
411
+ invisibleMap[option.index] = option.visible;
412
+ }
413
413
 
414
- for (const header of this.getOption("headers")) {
415
- const mode = header.getInternal("mode");
414
+ for (const header of this.getOption("headers")) {
415
+ const mode = header.getInternal("mode");
416
416
 
417
- if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
418
- continue;
419
- }
417
+ if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
418
+ continue;
419
+ }
420
420
 
421
- if (invisibleMap[header.index] === false) {
422
- header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_HIDDEN);
423
- } else {
424
- header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_VISIBLE);
425
- }
426
- }
421
+ if (invisibleMap[header.index] === false) {
422
+ header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_HIDDEN);
423
+ } else {
424
+ header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_VISIBLE);
425
+ }
426
+ }
427
427
  }
428
428
 
429
429
  /**
430
430
  * @private
431
431
  */
432
432
  function updateConfigColumnBar() {
433
- if (!this[columnBarElementSymbol]) {
434
- return;
435
- }
436
-
437
- const options = this[columnBarElementSymbol].getOption("columns");
438
- if (!isArray(options)) return;
439
-
440
- const map = {};
441
- for (let i = 0; i < options.length; i++) {
442
- const option = options[i];
443
- map[option.name] = option.visible;
444
- }
445
-
446
- const document = getDocument();
447
- const host = document.querySelector("monster-host");
448
- if (!(host && this.id)) {
449
- return;
450
- }
451
- const configKey = getColumnVisibilityConfigKey.call(this);
452
-
453
- try {
454
- host.setConfig(configKey, map);
455
- } catch (error) {
456
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
457
- }
433
+ if (!this[columnBarElementSymbol]) {
434
+ return;
435
+ }
436
+
437
+ const options = this[columnBarElementSymbol].getOption("columns");
438
+ if (!isArray(options)) return;
439
+
440
+ const map = {};
441
+ for (let i = 0; i < options.length; i++) {
442
+ const option = options[i];
443
+ map[option.name] = option.visible;
444
+ }
445
+
446
+ const document = getDocument();
447
+ const host = document.querySelector("monster-host");
448
+ if (!(host && this.id)) {
449
+ return;
450
+ }
451
+ const configKey = getColumnVisibilityConfigKey.call(this);
452
+
453
+ try {
454
+ host.setConfig(configKey, map);
455
+ } catch (error) {
456
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
457
+ }
458
458
  }
459
459
 
460
460
  /**
461
461
  * @private
462
462
  */
463
463
  function initEventHandler() {
464
- const self = this;
465
-
466
- getWindow().addEventListener("resize", (event) => {
467
- updateGrid.call(self);
468
- });
469
-
470
- self[columnBarElementSymbol].attachObserver(
471
- new Observer((e) => {
472
- updateHeaderFromColumnBar.call(self);
473
- updateGrid.call(self);
474
- updateConfigColumnBar.call(self);
475
- }),
476
- );
477
-
478
- self[gridHeadersElementSymbol].addEventListener("click", function (event) {
479
- let element = null;
480
- const datasource = self[datasourceLinkedElementSymbol];
481
- if (!datasource) {
482
- return;
483
- }
484
-
485
- element = findTargetElementFromEvent(event, ATTRIBUTE_DATATABLE_SORTABLE);
486
- if (element) {
487
- const index = element.parentNode.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
488
- const headers = self.getOption("headers");
489
-
490
- event.preventDefault();
491
-
492
- headers[index].changeDirection();
493
-
494
- setTimeout(function () {
495
- /** hotfix, normally this should be done via the updater, no idea why this is not possible. */
496
- element.setAttribute(
497
- ATTRIBUTE_DATATABLE_SORTABLE,
498
- `${headers[index].field} ${headers[index].direction}`,
499
- );
500
-
501
- storeOrderStatement.call(self, true);
502
- }, 0);
503
- }
504
- });
464
+ const self = this;
465
+
466
+ getWindow().addEventListener("resize", (event) => {
467
+ updateGrid.call(self);
468
+ });
469
+
470
+ self[columnBarElementSymbol].attachObserver(
471
+ new Observer((e) => {
472
+ updateHeaderFromColumnBar.call(self);
473
+ updateGrid.call(self);
474
+ updateConfigColumnBar.call(self);
475
+ }),
476
+ );
477
+
478
+ self[gridHeadersElementSymbol].addEventListener("click", function (event) {
479
+ let element = null;
480
+ const datasource = self[datasourceLinkedElementSymbol];
481
+ if (!datasource) {
482
+ return;
483
+ }
484
+
485
+ element = findTargetElementFromEvent(event, ATTRIBUTE_DATATABLE_SORTABLE);
486
+ if (element) {
487
+ const index = element.parentNode.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
488
+ const headers = self.getOption("headers");
489
+
490
+ event.preventDefault();
491
+
492
+ headers[index].changeDirection();
493
+
494
+ setTimeout(function () {
495
+ /** hotfix, normally this should be done via the updater, no idea why this is not possible. */
496
+ element.setAttribute(
497
+ ATTRIBUTE_DATATABLE_SORTABLE,
498
+ `${headers[index].field} ${headers[index].direction}`,
499
+ );
500
+
501
+ storeOrderStatement.call(self, true);
502
+ }, 0);
503
+ }
504
+ });
505
505
  }
506
506
 
507
507
  /**
508
508
  * @private
509
509
  */
510
510
  function initGridAndStructs(hostConfig, headerOrderMap) {
511
- const rowID = this.getOption("templateMapping.row-key");
512
-
513
- if (!this[gridElementSymbol]) {
514
- throw new Error("no grid element is defined");
515
- }
516
-
517
- let template;
518
- getSlottedElements.call(this).forEach((e) => {
519
- if (e instanceof HTMLTemplateElement && e.id === rowID) {
520
- template = e;
521
- }
522
- });
523
-
524
- if (!template) {
525
- throw new Error("no template is defined");
526
- }
527
-
528
- const rowCount = template.content.children.length;
529
-
530
- const headers = [];
531
-
532
- for (let i = 0; i < rowCount; i++) {
533
- let hClass = "";
534
- const row = template.content.children[i];
535
-
536
- let mode = "";
537
- if (row.hasAttribute(ATTRIBUTE_DATATABLE_MODE)) {
538
- mode = row.getAttribute(ATTRIBUTE_DATATABLE_MODE);
539
- }
540
-
541
- let grid = row.getAttribute(ATTRIBUTE_DATATABLE_GRID_TEMPLATE);
542
- if (!grid || grid === "" || grid === "auto") {
543
- grid = "minmax(0, 1fr)";
544
- }
545
-
546
- let label = "";
547
- let labelKey = "";
548
-
549
- if (row.hasAttribute(ATTRIBUTE_DATATABLE_HEAD)) {
550
- label = row.getAttribute(ATTRIBUTE_DATATABLE_HEAD);
551
- labelKey = label;
552
-
553
- try {
554
- if (label.startsWith("i18n:")) {
555
- label = label.substring(5, label.length);
556
- label = getDocumentTranslations().getText(label, label);
557
- }
558
- } catch (e) {
559
- label = "i18n error " + label;
560
- }
561
- }
562
-
563
- if (!label) {
564
- label = i + 1 + "";
565
- mode = ATTRIBUTE_DATATABLE_MODE_FIXED;
566
- labelKey = label;
567
- }
568
-
569
- if (isObject(hostConfig) && hostConfig.hasOwnProperty(label)) {
570
- if (hostConfig[label] === false) {
571
- mode = ATTRIBUTE_DATATABLE_MODE_HIDDEN;
572
- } else {
573
- mode = ATTRIBUTE_DATATABLE_MODE_VISIBLE;
574
- }
575
- }
576
-
577
- let align = "";
578
- if (row.hasAttribute(ATTRIBUTE_DATATABLE_ALIGN)) {
579
- align = row.getAttribute(ATTRIBUTE_DATATABLE_ALIGN);
580
- }
581
-
582
- switch (align) {
583
- case "center":
584
- hClass = "flex-center";
585
- break;
586
- case "end":
587
- hClass = "flex-end";
588
- break;
589
- case "start":
590
- hClass = "flex-start";
591
- break;
592
- default:
593
- hClass = "flex-start";
594
- }
595
-
596
- let field = "";
597
- let direction = DIRECTION_NONE;
598
- if (row.hasAttribute(ATTRIBUTE_DATATABLE_SORTABLE)) {
599
- field = row.getAttribute(ATTRIBUTE_DATATABLE_SORTABLE).trim();
600
- const parts = field.split(" ").map((item) => item.trim());
601
- field = parts[0];
602
-
603
- if (headerOrderMap.has(field)) {
604
- direction = headerOrderMap.get(field);
605
- } else if (parts.length === 2 && [DIRECTION_ASC, DIRECTION_DESC].indexOf(parts[1]) !== -1) {
606
- direction = parts[1];
607
- }
608
- }
609
-
610
- if (mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN) {
611
- hClass += " hidden";
612
- }
613
-
614
- const header = new Header();
615
- header.setInternals({
616
- field: field,
617
- label: label,
618
- classes: hClass,
619
- index: i,
620
- mode: mode,
621
- grid: grid,
622
- labelKey: labelKey,
623
- direction: direction,
624
- });
625
-
626
- headers.push(header);
627
- }
628
-
629
- this.setOption("headers", headers);
630
- setTimeout(() => {
631
- storeOrderStatement.call(this, this.getOption("features.autoInit"));
632
-
633
- },
634
- 0);
511
+ const rowID = this.getOption("templateMapping.row-key");
512
+
513
+ if (!this[gridElementSymbol]) {
514
+ throw new Error("no grid element is defined");
515
+ }
516
+
517
+ let template;
518
+ getSlottedElements.call(this).forEach((e) => {
519
+ if (e instanceof HTMLTemplateElement && e.id === rowID) {
520
+ template = e;
521
+ }
522
+ });
523
+
524
+ if (!template) {
525
+ throw new Error("no template is defined");
526
+ }
527
+
528
+ const rowCount = template.content.children.length;
529
+
530
+ const headers = [];
531
+
532
+ for (let i = 0; i < rowCount; i++) {
533
+ let hClass = "";
534
+ const row = template.content.children[i];
535
+
536
+ let mode = "";
537
+ if (row.hasAttribute(ATTRIBUTE_DATATABLE_MODE)) {
538
+ mode = row.getAttribute(ATTRIBUTE_DATATABLE_MODE);
539
+ }
540
+
541
+ let grid = row.getAttribute(ATTRIBUTE_DATATABLE_GRID_TEMPLATE);
542
+ if (!grid || grid === "" || grid === "auto") {
543
+ grid = "minmax(0, 1fr)";
544
+ }
545
+
546
+ let label = "";
547
+ let labelKey = "";
548
+
549
+ if (row.hasAttribute(ATTRIBUTE_DATATABLE_HEAD)) {
550
+ label = row.getAttribute(ATTRIBUTE_DATATABLE_HEAD);
551
+ labelKey = label;
552
+
553
+ try {
554
+ if (label.startsWith("i18n:")) {
555
+ label = label.substring(5, label.length);
556
+ label = getDocumentTranslations().getText(label, label);
557
+ }
558
+ } catch (e) {
559
+ label = "i18n error " + label;
560
+ }
561
+ }
562
+
563
+ if (!label) {
564
+ label = i + 1 + "";
565
+ mode = ATTRIBUTE_DATATABLE_MODE_FIXED;
566
+ labelKey = label;
567
+ }
568
+
569
+ if (isObject(hostConfig) && hostConfig.hasOwnProperty(label)) {
570
+ if (hostConfig[label] === false) {
571
+ mode = ATTRIBUTE_DATATABLE_MODE_HIDDEN;
572
+ } else {
573
+ mode = ATTRIBUTE_DATATABLE_MODE_VISIBLE;
574
+ }
575
+ }
576
+
577
+ let align = "";
578
+ if (row.hasAttribute(ATTRIBUTE_DATATABLE_ALIGN)) {
579
+ align = row.getAttribute(ATTRIBUTE_DATATABLE_ALIGN);
580
+ }
581
+
582
+ switch (align) {
583
+ case "center":
584
+ hClass = "flex-center";
585
+ break;
586
+ case "end":
587
+ hClass = "flex-end";
588
+ break;
589
+ case "start":
590
+ hClass = "flex-start";
591
+ break;
592
+ default:
593
+ hClass = "flex-start";
594
+ }
595
+
596
+ let field = "";
597
+ let direction = DIRECTION_NONE;
598
+ if (row.hasAttribute(ATTRIBUTE_DATATABLE_SORTABLE)) {
599
+ field = row.getAttribute(ATTRIBUTE_DATATABLE_SORTABLE).trim();
600
+ const parts = field.split(" ").map((item) => item.trim());
601
+ field = parts[0];
602
+
603
+ if (headerOrderMap.has(field)) {
604
+ direction = headerOrderMap.get(field);
605
+ } else if (
606
+ parts.length === 2 &&
607
+ [DIRECTION_ASC, DIRECTION_DESC].indexOf(parts[1]) !== -1
608
+ ) {
609
+ direction = parts[1];
610
+ }
611
+ }
612
+
613
+ if (mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN) {
614
+ hClass += " hidden";
615
+ }
616
+
617
+ const header = new Header();
618
+ header.setInternals({
619
+ field: field,
620
+ label: label,
621
+ classes: hClass,
622
+ index: i,
623
+ mode: mode,
624
+ grid: grid,
625
+ labelKey: labelKey,
626
+ direction: direction,
627
+ });
628
+
629
+ headers.push(header);
630
+ }
631
+
632
+ this.setOption("headers", headers);
633
+ setTimeout(() => {
634
+ storeOrderStatement.call(this, this.getOption("features.autoInit"));
635
+ }, 0);
635
636
  }
636
637
 
637
638
  /**
@@ -639,80 +640,79 @@ function initGridAndStructs(hostConfig, headerOrderMap) {
639
640
  * @returns {string}
640
641
  */
641
642
  export function getStoredOrderConfigKey() {
642
- return generateUniqueConfigKey("datatable", this?.id, "stored-order");
643
+ return generateUniqueConfigKey("datatable", this?.id, "stored-order");
643
644
  }
644
645
 
645
646
  /**
646
647
  * @private
647
648
  */
648
649
  function storeOrderStatement(doFetch) {
649
-
650
- const headers = this.getOption("headers");
651
- const statement = createOrderStatement(headers);
652
- setDataSource.call(this, {orderBy: statement}, doFetch);
653
-
654
- const document = getDocument();
655
- const host = document.querySelector("monster-host");
656
- if (!(host && this.id)) {
657
- return;
658
- }
659
-
660
- const configKey = getStoredOrderConfigKey.call(this);
661
-
662
- // statement explode with , and remove all empty
663
- const list = statement.split(",").filter((item) => item.trim() !== "");
664
- if (list.length === 0) {
665
- // host.deleteConfig(configKey);
666
- return;
667
- }
668
-
669
- host.setConfig(configKey, list);
650
+ const headers = this.getOption("headers");
651
+ const statement = createOrderStatement(headers);
652
+ setDataSource.call(this, { orderBy: statement }, doFetch);
653
+
654
+ const document = getDocument();
655
+ const host = document.querySelector("monster-host");
656
+ if (!(host && this.id)) {
657
+ return;
658
+ }
659
+
660
+ const configKey = getStoredOrderConfigKey.call(this);
661
+
662
+ // statement explode with , and remove all empty
663
+ const list = statement.split(",").filter((item) => item.trim() !== "");
664
+ if (list.length === 0) {
665
+ // host.deleteConfig(configKey);
666
+ return;
667
+ }
668
+
669
+ host.setConfig(configKey, list);
670
670
  }
671
671
 
672
672
  /**
673
673
  * @private
674
674
  */
675
675
  function updateGrid() {
676
- if (!this[gridElementSymbol]) {
677
- throw new Error("no grid element is defined");
678
- }
679
-
680
- let gridTemplateColumns = "";
681
-
682
- const headers = this.getOption("headers");
683
-
684
- let styles = "";
685
-
686
- for (let i = 0; i < headers.length; i++) {
687
- const header = headers[i];
688
-
689
- if (header.mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN) {
690
- styles += `[data-monster-role=datatable]>[data-monster-head="${header.labelKey}"] { display: none; }\n`;
691
- styles += `[data-monster-role=datatable-headers]>[data-monster-index="${header.index}"] { display: none; }\n`;
692
- } else {
693
- gridTemplateColumns += `${header.grid} `;
694
- }
695
- }
696
-
697
- const sheet = new CSSStyleSheet();
698
- if (styles !== "") sheet.replaceSync(styles);
699
- this.shadowRoot.adoptedStyleSheets = [...DataTable.getCSSStyleSheet(), sheet];
700
-
701
- const bodyWidth = getDocument().body.getBoundingClientRect().width;
702
-
703
- const breakpoint = this.getOption("responsive.breakpoint");
704
-
705
- if (bodyWidth > breakpoint) {
706
- this[
707
- gridElementSymbol
708
- ].style.gridTemplateColumns = `${gridTemplateColumns}`;
709
- this[
710
- gridHeadersElementSymbol
711
- ].style.gridTemplateColumns = `${gridTemplateColumns}`;
712
- } else {
713
- this[gridElementSymbol].style.gridTemplateColumns = "auto";
714
- this[gridHeadersElementSymbol].style.gridTemplateColumns = "auto";
715
- }
676
+ if (!this[gridElementSymbol]) {
677
+ throw new Error("no grid element is defined");
678
+ }
679
+
680
+ let gridTemplateColumns = "";
681
+
682
+ const headers = this.getOption("headers");
683
+
684
+ let styles = "";
685
+
686
+ for (let i = 0; i < headers.length; i++) {
687
+ const header = headers[i];
688
+
689
+ if (header.mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN) {
690
+ styles += `[data-monster-role=datatable]>[data-monster-head="${header.labelKey}"] { display: none; }\n`;
691
+ styles += `[data-monster-role=datatable-headers]>[data-monster-index="${header.index}"] { display: none; }\n`;
692
+ } else {
693
+ gridTemplateColumns += `${header.grid} `;
694
+ }
695
+ }
696
+
697
+ const sheet = new CSSStyleSheet();
698
+ if (styles !== "") sheet.replaceSync(styles);
699
+ this.shadowRoot.adoptedStyleSheets = [...DataTable.getCSSStyleSheet(), sheet];
700
+
701
+ const bodyWidth = getDocument().body.getBoundingClientRect().width;
702
+
703
+ const breakpoint = this.getOption("responsive.breakpoint");
704
+
705
+ if (bodyWidth > breakpoint) {
706
+ this[
707
+ gridElementSymbol
708
+ ].style.gridTemplateColumns = `${gridTemplateColumns}`;
709
+ this[
710
+ gridHeadersElementSymbol
711
+ ].style.gridTemplateColumns = `${gridTemplateColumns}`;
712
+ } else {
713
+ this[gridElementSymbol].style.gridTemplateColumns = "auto";
714
+ this[gridHeadersElementSymbol].style.gridTemplateColumns = "auto";
715
+ }
716
716
  }
717
717
 
718
718
  /**
@@ -720,20 +720,20 @@ function updateGrid() {
720
720
  * @param {Monster.Components.Datatable.Header[]} headers
721
721
  * @param {bool} doFetch
722
722
  */
723
- function setDataSource({orderBy}, doFetch) {
724
- const datasource = this[datasourceLinkedElementSymbol];
723
+ function setDataSource({ orderBy }, doFetch) {
724
+ const datasource = this[datasourceLinkedElementSymbol];
725
725
 
726
- if (!datasource) {
727
- return;
728
- }
726
+ if (!datasource) {
727
+ return;
728
+ }
729
729
 
730
- if (isFunction(datasource?.setParameters)) {
731
- datasource.setParameters({orderBy});
732
- }
730
+ if (isFunction(datasource?.setParameters)) {
731
+ datasource.setParameters({ orderBy });
732
+ }
733
733
 
734
- if (doFetch !== false && isFunction(datasource?.fetch)) {
735
- datasource.fetch();
736
- }
734
+ if (doFetch !== false && isFunction(datasource?.fetch)) {
735
+ datasource.fetch();
736
+ }
737
737
  }
738
738
 
739
739
  /**
@@ -741,20 +741,20 @@ function setDataSource({orderBy}, doFetch) {
741
741
  * @return {Monster.Components.Datatable.Form}
742
742
  */
743
743
  function initControlReferences() {
744
- if (!this.shadowRoot) {
745
- throw new Error("no shadow-root is defined");
746
- }
747
-
748
- this[gridElementSymbol] = this.shadowRoot.querySelector(
749
- "[data-monster-role=datatable]",
750
- );
751
- this[gridHeadersElementSymbol] = this.shadowRoot.querySelector(
752
- "[data-monster-role=datatable-headers]",
753
- );
754
- this[columnBarElementSymbol] =
755
- this.shadowRoot.querySelector("monster-column-bar");
756
-
757
- return this;
744
+ if (!this.shadowRoot) {
745
+ throw new Error("no shadow-root is defined");
746
+ }
747
+
748
+ this[gridElementSymbol] = this.shadowRoot.querySelector(
749
+ "[data-monster-role=datatable]",
750
+ );
751
+ this[gridHeadersElementSymbol] = this.shadowRoot.querySelector(
752
+ "[data-monster-role=datatable-headers]",
753
+ );
754
+ this[columnBarElementSymbol] =
755
+ this.shadowRoot.querySelector("monster-column-bar");
756
+
757
+ return this;
758
758
  }
759
759
 
760
760
  /**
@@ -764,22 +764,22 @@ function initControlReferences() {
764
764
  * @throws {Error} the datasource could not be initialized
765
765
  */
766
766
  function initOptionsFromArguments() {
767
- const options = {};
768
- const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
769
-
770
- if (selector) {
771
- options.datasource = {selector: selector};
772
- }
773
-
774
- const breakpoint = this.getAttribute(
775
- ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
776
- );
777
- if (breakpoint) {
778
- options.responsive = {};
779
- options.responsive.breakpoint = parseInt(breakpoint);
780
- }
781
-
782
- return options;
767
+ const options = {};
768
+ const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
769
+
770
+ if (selector) {
771
+ options.datasource = { selector: selector };
772
+ }
773
+
774
+ const breakpoint = this.getAttribute(
775
+ ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
776
+ );
777
+ if (breakpoint) {
778
+ options.responsive = {};
779
+ options.responsive.breakpoint = parseInt(breakpoint);
780
+ }
781
+
782
+ return options;
783
783
  }
784
784
 
785
785
  /**
@@ -787,7 +787,7 @@ function initOptionsFromArguments() {
787
787
  * @return {string}
788
788
  */
789
789
  function getEmptyTemplate() {
790
- return `<monster-state data-monster-role="empty-without-action">
790
+ return `<monster-state data-monster-role="empty-without-action">
791
791
  <div part="visual">
792
792
  <svg width="4rem" height="4rem" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
793
793
  <path d="m21.5 22h-19c-1.378 0-2.5-1.121-2.5-2.5v-7c0-.07.015-.141.044-.205l3.969-8.82c.404-.896 1.299-1.475 2.28-1.475h11.414c.981 0 1.876.579 2.28 1.475l3.969 8.82c.029.064.044.135.044.205v7c0 1.379-1.122 2.5-2.5 2.5zm-20.5-9.393v6.893c0 .827.673 1.5 1.5 1.5h19c.827 0 1.5-.673 1.5-1.5v-6.893l-3.925-8.723c-.242-.536-.779-.884-1.368-.884h-11.414c-.589 0-1.126.348-1.368.885z"/>
@@ -805,8 +805,8 @@ function getEmptyTemplate() {
805
805
  * @return {string}
806
806
  */
807
807
  function getTemplate() {
808
- // language=HTML
809
- return `
808
+ // language=HTML
809
+ return `
810
810
  <div data-monster-role="control" part="control">
811
811
  <template id="headers-row">
812
812
  <div data-monster-attributes="class path:headers-row.classname,