@schukai/monster 3.86.0 → 3.86.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/package.json +1 -1
  3. package/source/components/content/copy.mjs +357 -359
  4. package/source/components/datatable/columnbar.mjs +5 -8
  5. package/source/components/datatable/datasource/dom.mjs +0 -1
  6. package/source/components/datatable/datatable.mjs +741 -741
  7. package/source/components/datatable/style/column-bar.pcss +27 -19
  8. package/source/components/datatable/style/datatable.pcss +6 -1
  9. package/source/components/datatable/stylesheet/column-bar.mjs +1 -1
  10. package/source/components/datatable/stylesheet/datatable.mjs +14 -7
  11. package/source/components/datatable/util.mjs +0 -1
  12. package/source/components/form/button-bar.mjs +1 -3
  13. package/source/components/form/style/field-set.pcss +41 -56
  14. package/source/components/form/stylesheet/button-bar.mjs +13 -6
  15. package/source/components/form/stylesheet/button.mjs +13 -6
  16. package/source/components/form/stylesheet/confirm-button.mjs +13 -6
  17. package/source/components/form/stylesheet/field-set.mjs +1 -1
  18. package/source/components/form/stylesheet/message-state-button.mjs +13 -6
  19. package/source/components/form/stylesheet/popper-button.mjs +13 -6
  20. package/source/components/form/stylesheet/select.mjs +13 -6
  21. package/source/components/form/stylesheet/state-button.mjs +13 -6
  22. package/source/components/layout/details.mjs +2 -2
  23. package/source/components/layout/stylesheet/panel.mjs +13 -6
  24. package/source/types/version.mjs +1 -1
  25. package/test/cases/monster.mjs +1 -1
  26. package/test/web/test.html +2 -2
  27. package/test/web/tests.js +192 -270
@@ -12,75 +12,75 @@
12
12
  * SPDX-License-Identifier: AGPL-3.0
13
13
  */
14
14
 
15
- import {Datasource} from "./datasource.mjs";
15
+ import { Datasource } from "./datasource.mjs";
16
16
  import {
17
- assembleMethodSymbol,
18
- CustomElement,
19
- registerCustomElement,
20
- getSlottedElements,
17
+ assembleMethodSymbol,
18
+ CustomElement,
19
+ registerCustomElement,
20
+ getSlottedElements,
21
21
  } from "../../dom/customelement.mjs";
22
22
  import {
23
- findTargetElementFromEvent,
24
- fireCustomEvent,
23
+ findTargetElementFromEvent,
24
+ fireCustomEvent,
25
25
  } from "../../dom/events.mjs";
26
- import {clone} from "../../util/clone.mjs";
26
+ import { clone } from "../../util/clone.mjs";
27
27
  import {
28
- isString,
29
- isFunction,
30
- isInstance,
31
- isObject,
32
- isArray,
28
+ isString,
29
+ isFunction,
30
+ isInstance,
31
+ isObject,
32
+ isArray,
33
33
  } from "../../types/is.mjs";
34
34
  import {
35
- validateArray,
36
- validateInteger,
37
- validateObject,
35
+ validateArray,
36
+ validateInteger,
37
+ validateObject,
38
38
  } from "../../types/validate.mjs";
39
- import {Observer} from "../../types/observer.mjs";
39
+ import { Observer } from "../../types/observer.mjs";
40
40
  import {
41
- ATTRIBUTE_DATATABLE_HEAD,
42
- ATTRIBUTE_DATATABLE_GRID_TEMPLATE,
43
- ATTRIBUTE_DATASOURCE_SELECTOR,
44
- ATTRIBUTE_DATATABLE_ALIGN,
45
- ATTRIBUTE_DATATABLE_SORTABLE,
46
- ATTRIBUTE_DATATABLE_MODE,
47
- ATTRIBUTE_DATATABLE_INDEX,
48
- ATTRIBUTE_DATATABLE_MODE_HIDDEN,
49
- ATTRIBUTE_DATATABLE_MODE_VISIBLE,
50
- ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
51
- ATTRIBUTE_DATATABLE_MODE_FIXED,
41
+ ATTRIBUTE_DATATABLE_HEAD,
42
+ ATTRIBUTE_DATATABLE_GRID_TEMPLATE,
43
+ ATTRIBUTE_DATASOURCE_SELECTOR,
44
+ ATTRIBUTE_DATATABLE_ALIGN,
45
+ ATTRIBUTE_DATATABLE_SORTABLE,
46
+ ATTRIBUTE_DATATABLE_MODE,
47
+ ATTRIBUTE_DATATABLE_INDEX,
48
+ ATTRIBUTE_DATATABLE_MODE_HIDDEN,
49
+ ATTRIBUTE_DATATABLE_MODE_VISIBLE,
50
+ ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
51
+ ATTRIBUTE_DATATABLE_MODE_FIXED,
52
52
  } from "./constants.mjs";
53
- import {instanceSymbol} from "../../constants.mjs";
53
+ import { instanceSymbol } from "../../constants.mjs";
54
54
  import {
55
- Header,
56
- createOrderStatement,
57
- DIRECTION_ASC,
58
- DIRECTION_DESC,
59
- DIRECTION_NONE,
55
+ Header,
56
+ createOrderStatement,
57
+ DIRECTION_ASC,
58
+ DIRECTION_DESC,
59
+ DIRECTION_NONE,
60
60
  } from "./datatable/header.mjs";
61
- import {DatatableStyleSheet} from "./stylesheet/datatable.mjs";
61
+ import { DatatableStyleSheet } from "./stylesheet/datatable.mjs";
62
62
  import {
63
- handleDataSourceChanges,
64
- datasourceLinkedElementSymbol,
63
+ handleDataSourceChanges,
64
+ datasourceLinkedElementSymbol,
65
65
  } from "./util.mjs";
66
66
  import "./columnbar.mjs";
67
67
  import "./filter-button.mjs";
68
68
  import {
69
- findElementWithSelectorUpwards,
70
- getDocument,
71
- getWindow,
69
+ findElementWithSelectorUpwards,
70
+ getDocument,
71
+ getWindow,
72
72
  } from "../../dom/util.mjs";
73
- import {addAttributeToken} from "../../dom/attributes.mjs";
74
- import {ATTRIBUTE_ERRORMESSAGE} from "../../dom/constants.mjs";
75
- import {getDocumentTranslations} from "../../i18n/translations.mjs";
73
+ import { addAttributeToken } from "../../dom/attributes.mjs";
74
+ import { ATTRIBUTE_ERRORMESSAGE } from "../../dom/constants.mjs";
75
+ import { getDocumentTranslations } from "../../i18n/translations.mjs";
76
76
  import "../state/state.mjs";
77
77
  import "../host/collapse.mjs";
78
- import {generateUniqueConfigKey} from "../host/util.mjs";
78
+ import { generateUniqueConfigKey } from "../host/util.mjs";
79
79
 
80
80
  import "./datasource/dom.mjs";
81
81
  import "./datasource/rest.mjs";
82
82
 
83
- export {DataTable};
83
+ export { DataTable };
84
84
 
85
85
  /**
86
86
  * @private
@@ -127,363 +127,363 @@ const columnBarElementSymbol = Symbol("columnBarElement");
127
127
  * @fires monster-datatable-row-added
128
128
  **/
129
129
  class DataTable extends CustomElement {
130
- /**
131
- * This method is called by the `instanceof` operator.
132
- * @return {symbol}
133
- */
134
- static get [instanceSymbol]() {
135
- return Symbol.for("@schukai/monster/components/datatable@@instance");
136
- }
137
-
138
- /**
139
- * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
140
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
141
- *
142
- * The individual configuration values can be found in the table.
143
- *
144
- * @property {Object} templates Template definitions
145
- * @property {string} templates.main Main template
146
- * @property {Object} datasource Datasource configuration
147
- * @property {string} datasource.selector Selector for the datasource
148
- * @property {Object} mapping Mapping configuration
149
- * @property {string} mapping.data Data mapping
150
- * @property {Array} data Data
151
- * @property {Array} headers Headers
152
- * @property {Object} responsive Responsive configuration
153
- * @property {number} responsive.breakpoint Breakpoint for responsive mode
154
- * @property {Object} labels Labels
155
- * @property {string} labels.theListContainsNoEntries Label for empty state
156
- * @property {Object} classes Classes
157
- * @property {string} classes.container Container class
158
- * @property {Object} features Features
159
- * @property {boolean} features.settings Settings feature
160
- * @property {boolean} features.footer Footer feature
161
- * @property {boolean} features.autoInit Auto init feature (init datasource automatically)
162
- * @property {Object} templateMapping Template mapping
163
- * @property {string} templateMapping.row-key Row key
164
- * @property {string} templateMapping.filter-id Filter id
165
- **/
166
- get defaults() {
167
- return Object.assign(
168
- {},
169
- super.defaults,
170
- {
171
- templates: {
172
- main: getTemplate(),
173
- emptyState: getEmptyTemplate(),
174
- },
175
-
176
- datasource: {
177
- selector: null,
178
- },
179
-
180
- mapping: {
181
- data: "dataset",
182
- },
183
-
184
- data: [],
185
- headers: [],
186
-
187
- responsive: {
188
- breakpoint: 800,
189
- },
190
-
191
- labels: {
192
- theListContainsNoEntries: "The list contains no entries",
193
- },
194
-
195
- classes: {
196
- control: "monster-theme-control-container-1",
197
- container: "",
198
- row: "monster-theme-control-row-1",
199
- },
200
-
201
- features: {
202
- settings: true,
203
- footer: true,
204
- autoInit: true,
205
- },
206
-
207
- templateMapping: {
208
- "row-key": null,
209
- "filter-id": null,
210
- },
211
- },
212
- initOptionsFromArguments.call(this),
213
- );
214
- }
215
-
216
- /**
217
- *
218
- * @param {string} selector
219
- * @return {NodeListOf<*>}
220
- */
221
- getGridElements(selector) {
222
- return this[gridElementSymbol].querySelectorAll(selector);
223
- }
224
-
225
- /**
226
- *
227
- * @return {string}
228
- */
229
- static getTag() {
230
- return "monster-datatable";
231
- }
232
-
233
- /**
234
- * @return void
235
- */
236
- [assembleMethodSymbol]() {
237
- const rawKey = this.getOption("templateMapping.row-key");
238
-
239
- if (rawKey === null) {
240
- if (this.id !== null && this.id !== "") {
241
- const rawKey = this.getOption("templateMapping.row-key");
242
- if (rawKey === null) {
243
- this.setOption("templateMapping.row-key", this.id + "-row");
244
- }
245
- } else {
246
- this.setOption("templateMapping.row-key", "row");
247
- }
248
- }
249
-
250
- if (this.id !== null && this.id !== "") {
251
- this.setOption("templateMapping.filter-id", "" + this.id + "-filter");
252
- } else {
253
- this.setOption("templateMapping.filter-id", "filter");
254
- }
255
-
256
- super[assembleMethodSymbol]();
257
-
258
- initControlReferences.call(this);
259
- initEventHandler.call(this);
260
-
261
- const selector = this.getOption("datasource.selector");
262
-
263
- if (isString(selector)) {
264
- const element = findElementWithSelectorUpwards(this, selector);
265
- if (element === null) {
266
- throw new Error("the selector must match exactly one element");
267
- }
268
-
269
- if (!isInstance(element, Datasource)) {
270
- throw new TypeError("the element must be a datasource");
271
- }
272
-
273
- this[datasourceLinkedElementSymbol] = element;
274
-
275
- queueMicrotask(() => {
276
- handleDataSourceChanges.call(this);
277
- element.datasource.attachObserver(
278
- new Observer(handleDataSourceChanges.bind(this)),
279
- );
280
- });
281
- }
282
-
283
- getHostConfig
284
- .call(this, getColumnVisibilityConfigKey)
285
- .then((config) => {
286
- const headerOrderMap = new Map();
287
-
288
- getHostConfig
289
- .call(this, getStoredOrderConfigKey)
290
- .then((orderConfig) => {
291
- if (isArray(orderConfig) || orderConfig.length > 0) {
292
- for (let i = 0; i < orderConfig.length; i++) {
293
- const item = orderConfig[i];
294
- const parts = item.split(" ");
295
- const field = parts[0];
296
- const direction = parts[1] || DIRECTION_ASC;
297
- headerOrderMap.set(field, direction);
298
- }
299
- }
300
- })
301
- .then(() => {
302
- try {
303
- initGridAndStructs.call(this, config, headerOrderMap);
304
- } catch (error) {
305
- addAttributeToken(
306
- this,
307
- ATTRIBUTE_ERRORMESSAGE,
308
- error?.message || error.toString(),
309
- );
310
- }
311
-
312
- updateColumnBar.call(this);
313
- })
314
- .catch((error) => {
315
- addAttributeToken(
316
- this,
317
- ATTRIBUTE_ERRORMESSAGE,
318
- error?.message || error.toString(),
319
- );
320
- });
321
- })
322
- .catch((error) => {
323
- addAttributeToken(
324
- this,
325
- ATTRIBUTE_ERRORMESSAGE,
326
- error?.message || error.toString(),
327
- );
328
- });
329
- }
330
-
331
- /**
332
- * @return {CSSStyleSheet[]}
333
- */
334
- static getCSSStyleSheet() {
335
- return [DatatableStyleSheet];
336
- }
337
-
338
- /**
339
- * Copy a row from the datatable
340
- *
341
- * @param {number|string} fromIndex
342
- * @param {number|string} toIndex
343
- * @return {DataTable}
344
- * @fires monster-datatable-row-copied
345
- */
346
- copyRow(fromIndex, toIndex) {
347
- const datasource = this[datasourceLinkedElementSymbol];
348
- if (!datasource) {
349
- return this;
350
- }
351
- let d = datasource.data;
352
- let c = clone(d);
353
-
354
- let rows = c;
355
- const mapping = this.getOption("mapping.data");
356
-
357
- if (mapping) {
358
- rows = c?.[mapping];
359
- }
360
-
361
- if (rows === undefined || rows === null) {
362
- rows = [];
363
- }
364
-
365
- if (toIndex === undefined) {
366
- toIndex = rows.length;
367
- }
368
-
369
- if (isString(fromIndex)) {
370
- fromIndex = parseInt(fromIndex);
371
- }
372
- if (isString(toIndex)) {
373
- toIndex = parseInt(toIndex);
374
- }
375
-
376
- if (toIndex < 0 || toIndex > rows.length) {
377
- throw new RangeError("index out of bounds");
378
- }
379
-
380
- validateArray(rows);
381
- validateInteger(fromIndex);
382
- validateInteger(toIndex);
383
-
384
- if (fromIndex < 0 || fromIndex >= rows.length) {
385
- throw new RangeError("index out of bounds");
386
- }
387
-
388
- rows.splice(toIndex, 0, clone(rows[fromIndex]));
389
- datasource.data = c;
390
-
391
- fireCustomEvent(this, "monster-datatable-row-copied", {
392
- index: toIndex,
393
- });
394
-
395
- return this;
396
- }
397
-
398
- /**
399
- * Remove a row from the datatable
400
- *
401
- * @param {number|string} index
402
- * @return {DataTable}
403
- * @fires monster-datatable-row-removed
404
- */
405
- removeRow(index) {
406
- const datasource = this[datasourceLinkedElementSymbol];
407
- if (!datasource) {
408
- return this;
409
- }
410
- let d = datasource.data;
411
- let c = clone(d);
412
-
413
- let rows = c;
414
- const mapping = this.getOption("mapping.data");
415
-
416
- if (mapping) {
417
- rows = c?.[mapping];
418
- }
419
-
420
- if (rows === undefined || rows === null) {
421
- rows = [];
422
- }
423
-
424
- if (isString(index)) {
425
- index = parseInt(index);
426
- }
427
-
428
- validateArray(rows);
429
- validateInteger(index);
430
-
431
- if (index < 0 || index >= rows.length) {
432
- throw new RangeError("index out of bounds");
433
- }
434
- if (mapping) {
435
- rows = c?.[mapping];
436
- }
437
-
438
- rows.splice(index, 1);
439
- datasource.data = c;
440
-
441
- fireCustomEvent(this, "monster-datatable-row-removed", {
442
- index: index,
443
- });
444
-
445
- return this;
446
- }
447
-
448
- /**
449
- * Add a row to the datatable
450
- *
451
- * @param {Object} data
452
- * @return {DataTable}
453
- *
454
- * @fires monster-datatable-row-added
455
- **/
456
- addRow(data) {
457
- const datasource = this[datasourceLinkedElementSymbol];
458
- if (!datasource) {
459
- return this;
460
- }
461
- let d = datasource.data;
462
- let c = clone(d);
463
-
464
- let rows = c;
465
-
466
- const mapping = this.getOption("mapping.data");
467
- if (mapping) {
468
- rows = c?.[mapping];
469
- }
470
-
471
- if (rows === undefined || rows === null) {
472
- rows = [];
473
- }
474
-
475
- validateArray(rows);
476
- validateObject(data);
477
-
478
- rows.push(data);
479
- datasource.data = c;
480
-
481
- fireCustomEvent(this, "monster-datatable-row-added", {
482
- index: rows.length - 1,
483
- });
484
-
485
- return this;
486
- }
130
+ /**
131
+ * This method is called by the `instanceof` operator.
132
+ * @return {symbol}
133
+ */
134
+ static get [instanceSymbol]() {
135
+ return Symbol.for("@schukai/monster/components/datatable@@instance");
136
+ }
137
+
138
+ /**
139
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
140
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
141
+ *
142
+ * The individual configuration values can be found in the table.
143
+ *
144
+ * @property {Object} templates Template definitions
145
+ * @property {string} templates.main Main template
146
+ * @property {Object} datasource Datasource configuration
147
+ * @property {string} datasource.selector Selector for the datasource
148
+ * @property {Object} mapping Mapping configuration
149
+ * @property {string} mapping.data Data mapping
150
+ * @property {Array} data Data
151
+ * @property {Array} headers Headers
152
+ * @property {Object} responsive Responsive configuration
153
+ * @property {number} responsive.breakpoint Breakpoint for responsive mode
154
+ * @property {Object} labels Labels
155
+ * @property {string} labels.theListContainsNoEntries Label for empty state
156
+ * @property {Object} classes Classes
157
+ * @property {string} classes.container Container class
158
+ * @property {Object} features Features
159
+ * @property {boolean} features.settings Settings feature
160
+ * @property {boolean} features.footer Footer feature
161
+ * @property {boolean} features.autoInit Auto init feature (init datasource automatically)
162
+ * @property {Object} templateMapping Template mapping
163
+ * @property {string} templateMapping.row-key Row key
164
+ * @property {string} templateMapping.filter-id Filter id
165
+ **/
166
+ get defaults() {
167
+ return Object.assign(
168
+ {},
169
+ super.defaults,
170
+ {
171
+ templates: {
172
+ main: getTemplate(),
173
+ emptyState: getEmptyTemplate(),
174
+ },
175
+
176
+ datasource: {
177
+ selector: null,
178
+ },
179
+
180
+ mapping: {
181
+ data: "dataset",
182
+ },
183
+
184
+ data: [],
185
+ headers: [],
186
+
187
+ responsive: {
188
+ breakpoint: 800,
189
+ },
190
+
191
+ labels: {
192
+ theListContainsNoEntries: "The list contains no entries",
193
+ },
194
+
195
+ classes: {
196
+ control: "monster-theme-control-container-1",
197
+ container: "",
198
+ row: "monster-theme-control-row-1",
199
+ },
200
+
201
+ features: {
202
+ settings: true,
203
+ footer: true,
204
+ autoInit: true,
205
+ },
206
+
207
+ templateMapping: {
208
+ "row-key": null,
209
+ "filter-id": null,
210
+ },
211
+ },
212
+ initOptionsFromArguments.call(this),
213
+ );
214
+ }
215
+
216
+ /**
217
+ *
218
+ * @param {string} selector
219
+ * @return {NodeListOf<*>}
220
+ */
221
+ getGridElements(selector) {
222
+ return this[gridElementSymbol].querySelectorAll(selector);
223
+ }
224
+
225
+ /**
226
+ *
227
+ * @return {string}
228
+ */
229
+ static getTag() {
230
+ return "monster-datatable";
231
+ }
232
+
233
+ /**
234
+ * @return void
235
+ */
236
+ [assembleMethodSymbol]() {
237
+ const rawKey = this.getOption("templateMapping.row-key");
238
+
239
+ if (rawKey === null) {
240
+ if (this.id !== null && this.id !== "") {
241
+ const rawKey = this.getOption("templateMapping.row-key");
242
+ if (rawKey === null) {
243
+ this.setOption("templateMapping.row-key", this.id + "-row");
244
+ }
245
+ } else {
246
+ this.setOption("templateMapping.row-key", "row");
247
+ }
248
+ }
249
+
250
+ if (this.id !== null && this.id !== "") {
251
+ this.setOption("templateMapping.filter-id", "" + this.id + "-filter");
252
+ } else {
253
+ this.setOption("templateMapping.filter-id", "filter");
254
+ }
255
+
256
+ super[assembleMethodSymbol]();
257
+
258
+ initControlReferences.call(this);
259
+ initEventHandler.call(this);
260
+
261
+ const selector = this.getOption("datasource.selector");
262
+
263
+ if (isString(selector)) {
264
+ const element = findElementWithSelectorUpwards(this, selector);
265
+ if (element === null) {
266
+ throw new Error("the selector must match exactly one element");
267
+ }
268
+
269
+ if (!isInstance(element, Datasource)) {
270
+ throw new TypeError("the element must be a datasource");
271
+ }
272
+
273
+ this[datasourceLinkedElementSymbol] = element;
274
+
275
+ queueMicrotask(() => {
276
+ handleDataSourceChanges.call(this);
277
+ element.datasource.attachObserver(
278
+ new Observer(handleDataSourceChanges.bind(this)),
279
+ );
280
+ });
281
+ }
282
+
283
+ getHostConfig
284
+ .call(this, getColumnVisibilityConfigKey)
285
+ .then((config) => {
286
+ const headerOrderMap = new Map();
287
+
288
+ getHostConfig
289
+ .call(this, getStoredOrderConfigKey)
290
+ .then((orderConfig) => {
291
+ if (isArray(orderConfig) || orderConfig.length > 0) {
292
+ for (let i = 0; i < orderConfig.length; i++) {
293
+ const item = orderConfig[i];
294
+ const parts = item.split(" ");
295
+ const field = parts[0];
296
+ const direction = parts[1] || DIRECTION_ASC;
297
+ headerOrderMap.set(field, direction);
298
+ }
299
+ }
300
+ })
301
+ .then(() => {
302
+ try {
303
+ initGridAndStructs.call(this, config, headerOrderMap);
304
+ } catch (error) {
305
+ addAttributeToken(
306
+ this,
307
+ ATTRIBUTE_ERRORMESSAGE,
308
+ error?.message || error.toString(),
309
+ );
310
+ }
311
+
312
+ updateColumnBar.call(this);
313
+ })
314
+ .catch((error) => {
315
+ addAttributeToken(
316
+ this,
317
+ ATTRIBUTE_ERRORMESSAGE,
318
+ error?.message || error.toString(),
319
+ );
320
+ });
321
+ })
322
+ .catch((error) => {
323
+ addAttributeToken(
324
+ this,
325
+ ATTRIBUTE_ERRORMESSAGE,
326
+ error?.message || error.toString(),
327
+ );
328
+ });
329
+ }
330
+
331
+ /**
332
+ * @return {CSSStyleSheet[]}
333
+ */
334
+ static getCSSStyleSheet() {
335
+ return [DatatableStyleSheet];
336
+ }
337
+
338
+ /**
339
+ * Copy a row from the datatable
340
+ *
341
+ * @param {number|string} fromIndex
342
+ * @param {number|string} toIndex
343
+ * @return {DataTable}
344
+ * @fires monster-datatable-row-copied
345
+ */
346
+ copyRow(fromIndex, toIndex) {
347
+ const datasource = this[datasourceLinkedElementSymbol];
348
+ if (!datasource) {
349
+ return this;
350
+ }
351
+ let d = datasource.data;
352
+ let c = clone(d);
353
+
354
+ let rows = c;
355
+ const mapping = this.getOption("mapping.data");
356
+
357
+ if (mapping) {
358
+ rows = c?.[mapping];
359
+ }
360
+
361
+ if (rows === undefined || rows === null) {
362
+ rows = [];
363
+ }
364
+
365
+ if (toIndex === undefined) {
366
+ toIndex = rows.length;
367
+ }
368
+
369
+ if (isString(fromIndex)) {
370
+ fromIndex = parseInt(fromIndex);
371
+ }
372
+ if (isString(toIndex)) {
373
+ toIndex = parseInt(toIndex);
374
+ }
375
+
376
+ if (toIndex < 0 || toIndex > rows.length) {
377
+ throw new RangeError("index out of bounds");
378
+ }
379
+
380
+ validateArray(rows);
381
+ validateInteger(fromIndex);
382
+ validateInteger(toIndex);
383
+
384
+ if (fromIndex < 0 || fromIndex >= rows.length) {
385
+ throw new RangeError("index out of bounds");
386
+ }
387
+
388
+ rows.splice(toIndex, 0, clone(rows[fromIndex]));
389
+ datasource.data = c;
390
+
391
+ fireCustomEvent(this, "monster-datatable-row-copied", {
392
+ index: toIndex,
393
+ });
394
+
395
+ return this;
396
+ }
397
+
398
+ /**
399
+ * Remove a row from the datatable
400
+ *
401
+ * @param {number|string} index
402
+ * @return {DataTable}
403
+ * @fires monster-datatable-row-removed
404
+ */
405
+ removeRow(index) {
406
+ const datasource = this[datasourceLinkedElementSymbol];
407
+ if (!datasource) {
408
+ return this;
409
+ }
410
+ let d = datasource.data;
411
+ let c = clone(d);
412
+
413
+ let rows = c;
414
+ const mapping = this.getOption("mapping.data");
415
+
416
+ if (mapping) {
417
+ rows = c?.[mapping];
418
+ }
419
+
420
+ if (rows === undefined || rows === null) {
421
+ rows = [];
422
+ }
423
+
424
+ if (isString(index)) {
425
+ index = parseInt(index);
426
+ }
427
+
428
+ validateArray(rows);
429
+ validateInteger(index);
430
+
431
+ if (index < 0 || index >= rows.length) {
432
+ throw new RangeError("index out of bounds");
433
+ }
434
+ if (mapping) {
435
+ rows = c?.[mapping];
436
+ }
437
+
438
+ rows.splice(index, 1);
439
+ datasource.data = c;
440
+
441
+ fireCustomEvent(this, "monster-datatable-row-removed", {
442
+ index: index,
443
+ });
444
+
445
+ return this;
446
+ }
447
+
448
+ /**
449
+ * Add a row to the datatable
450
+ *
451
+ * @param {Object} data
452
+ * @return {DataTable}
453
+ *
454
+ * @fires monster-datatable-row-added
455
+ **/
456
+ addRow(data) {
457
+ const datasource = this[datasourceLinkedElementSymbol];
458
+ if (!datasource) {
459
+ return this;
460
+ }
461
+ let d = datasource.data;
462
+ let c = clone(d);
463
+
464
+ let rows = c;
465
+
466
+ const mapping = this.getOption("mapping.data");
467
+ if (mapping) {
468
+ rows = c?.[mapping];
469
+ }
470
+
471
+ if (rows === undefined || rows === null) {
472
+ rows = [];
473
+ }
474
+
475
+ validateArray(rows);
476
+ validateObject(data);
477
+
478
+ rows.push(data);
479
+ datasource.data = c;
480
+
481
+ fireCustomEvent(this, "monster-datatable-row-added", {
482
+ index: rows.length - 1,
483
+ });
484
+
485
+ return this;
486
+ }
487
487
  }
488
488
 
489
489
  /**
@@ -491,7 +491,7 @@ class DataTable extends CustomElement {
491
491
  * @return {string}
492
492
  */
493
493
  function getColumnVisibilityConfigKey() {
494
- return generateUniqueConfigKey("datatable", this?.id, "columns-visibility");
494
+ return generateUniqueConfigKey("datatable", this?.id, "columns-visibility");
495
495
  }
496
496
 
497
497
  /**
@@ -499,7 +499,7 @@ function getColumnVisibilityConfigKey() {
499
499
  * @return {string}
500
500
  */
501
501
  function getFilterConfigKey() {
502
- return generateUniqueConfigKey("datatable", this?.id, "filter");
502
+ return generateUniqueConfigKey("datatable", this?.id, "filter");
503
503
  }
504
504
 
505
505
  /**
@@ -507,291 +507,291 @@ function getFilterConfigKey() {
507
507
  * @return {Promise}
508
508
  */
509
509
  function getHostConfig(callback) {
510
- const host = findElementWithSelectorUpwards(this, "monster-host");
511
-
512
- if (!(host && this.id)) {
513
- return Promise.resolve({});
514
- }
515
-
516
- if (!host || !isFunction(host?.getConfig)) {
517
- throw new TypeError("the host must be a monster-host");
518
- }
519
-
520
- const configKey = callback.call(this);
521
- return host.hasConfig(configKey).then((hasConfig) => {
522
- if (hasConfig) {
523
- return host.getConfig(configKey);
524
- } else {
525
- return {};
526
- }
527
- });
510
+ const host = findElementWithSelectorUpwards(this, "monster-host");
511
+
512
+ if (!(host && this.id)) {
513
+ return Promise.resolve({});
514
+ }
515
+
516
+ if (!host || !isFunction(host?.getConfig)) {
517
+ throw new TypeError("the host must be a monster-host");
518
+ }
519
+
520
+ const configKey = callback.call(this);
521
+ return host.hasConfig(configKey).then((hasConfig) => {
522
+ if (hasConfig) {
523
+ return host.getConfig(configKey);
524
+ } else {
525
+ return {};
526
+ }
527
+ });
528
528
  }
529
529
 
530
530
  /**
531
531
  * @private
532
532
  */
533
533
  function updateColumnBar() {
534
- if (!this[columnBarElementSymbol]) {
535
- return;
536
- }
537
-
538
- const columns = [];
539
- for (const header of this.getOption("headers")) {
540
- const mode = header.getInternal("mode");
541
-
542
- if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
543
- continue;
544
- }
545
-
546
- columns.push({
547
- visible: mode !== ATTRIBUTE_DATATABLE_MODE_HIDDEN,
548
- name: header.label,
549
- index: header.index,
550
- });
551
- }
552
-
553
- this[columnBarElementSymbol].setOption("columns", columns);
534
+ if (!this[columnBarElementSymbol]) {
535
+ return;
536
+ }
537
+
538
+ const columns = [];
539
+ for (const header of this.getOption("headers")) {
540
+ const mode = header.getInternal("mode");
541
+
542
+ if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
543
+ continue;
544
+ }
545
+
546
+ columns.push({
547
+ visible: mode !== ATTRIBUTE_DATATABLE_MODE_HIDDEN,
548
+ name: header.label,
549
+ index: header.index,
550
+ });
551
+ }
552
+
553
+ this[columnBarElementSymbol].setOption("columns", columns);
554
554
  }
555
555
 
556
556
  /**
557
557
  * @private
558
558
  */
559
559
  function updateHeaderFromColumnBar() {
560
- if (!this[columnBarElementSymbol]) {
561
- return;
562
- }
560
+ if (!this[columnBarElementSymbol]) {
561
+ return;
562
+ }
563
563
 
564
- const options = this[columnBarElementSymbol].getOption("columns");
565
- if (!isArray(options)) return;
564
+ const options = this[columnBarElementSymbol].getOption("columns");
565
+ if (!isArray(options)) return;
566
566
 
567
- const invisibleMap = {};
567
+ const invisibleMap = {};
568
568
 
569
- for (let i = 0; i < options.length; i++) {
570
- const option = options[i];
571
- invisibleMap[option.index] = option.visible;
572
- }
569
+ for (let i = 0; i < options.length; i++) {
570
+ const option = options[i];
571
+ invisibleMap[option.index] = option.visible;
572
+ }
573
573
 
574
- for (const header of this.getOption("headers")) {
575
- const mode = header.getInternal("mode");
574
+ for (const header of this.getOption("headers")) {
575
+ const mode = header.getInternal("mode");
576
576
 
577
- if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
578
- continue;
579
- }
577
+ if (mode === ATTRIBUTE_DATATABLE_MODE_FIXED) {
578
+ continue;
579
+ }
580
580
 
581
- if (invisibleMap[header.index] === false) {
582
- header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_HIDDEN);
583
- } else {
584
- header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_VISIBLE);
585
- }
586
- }
581
+ if (invisibleMap[header.index] === false) {
582
+ header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_HIDDEN);
583
+ } else {
584
+ header.setInternal("mode", ATTRIBUTE_DATATABLE_MODE_VISIBLE);
585
+ }
586
+ }
587
587
  }
588
588
 
589
589
  /**
590
590
  * @private
591
591
  */
592
592
  function updateConfigColumnBar() {
593
- if (!this[columnBarElementSymbol]) {
594
- return;
595
- }
596
-
597
- const options = this[columnBarElementSymbol].getOption("columns");
598
- if (!isArray(options)) return;
599
-
600
- const map = {};
601
- for (let i = 0; i < options.length; i++) {
602
- const option = options[i];
603
- map[option.name] = option.visible;
604
- }
605
-
606
- const host = findElementWithSelectorUpwards(this, "monster-host");
607
- if (!(host && this.id)) {
608
- return;
609
- }
610
- const configKey = getColumnVisibilityConfigKey.call(this);
611
-
612
- try {
613
- host.setConfig(configKey, map);
614
- } catch (error) {
615
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
616
- }
593
+ if (!this[columnBarElementSymbol]) {
594
+ return;
595
+ }
596
+
597
+ const options = this[columnBarElementSymbol].getOption("columns");
598
+ if (!isArray(options)) return;
599
+
600
+ const map = {};
601
+ for (let i = 0; i < options.length; i++) {
602
+ const option = options[i];
603
+ map[option.name] = option.visible;
604
+ }
605
+
606
+ const host = findElementWithSelectorUpwards(this, "monster-host");
607
+ if (!(host && this.id)) {
608
+ return;
609
+ }
610
+ const configKey = getColumnVisibilityConfigKey.call(this);
611
+
612
+ try {
613
+ host.setConfig(configKey, map);
614
+ } catch (error) {
615
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
616
+ }
617
617
  }
618
618
 
619
619
  /**
620
620
  * @private
621
621
  */
622
622
  function initEventHandler() {
623
- const self = this;
624
-
625
- getWindow().addEventListener("resize", (event) => {
626
- updateGrid.call(self);
627
- });
628
-
629
- self[columnBarElementSymbol].attachObserver(
630
- new Observer((e) => {
631
- updateHeaderFromColumnBar.call(self);
632
- updateGrid.call(self);
633
- updateConfigColumnBar.call(self);
634
- }),
635
- );
636
-
637
- self[gridHeadersElementSymbol].addEventListener("click", function (event) {
638
- let element = null;
639
- const datasource = self[datasourceLinkedElementSymbol];
640
- if (!datasource) {
641
- return;
642
- }
643
-
644
- element = findTargetElementFromEvent(event, ATTRIBUTE_DATATABLE_SORTABLE);
645
- if (element) {
646
- const index = element.parentNode.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
647
- const headers = self.getOption("headers");
648
-
649
- event.preventDefault();
650
-
651
- headers[index].changeDirection();
652
-
653
- queueMicrotask(function () {
654
- /** hotfix, normally this should be done via the updater, no idea why this is not possible. */
655
- element.setAttribute(
656
- ATTRIBUTE_DATATABLE_SORTABLE,
657
- `${headers[index].field} ${headers[index].direction}`,
658
- );
659
-
660
- storeOrderStatement.call(self, true);
661
- });
662
- }
663
- });
623
+ const self = this;
624
+
625
+ getWindow().addEventListener("resize", (event) => {
626
+ updateGrid.call(self);
627
+ });
628
+
629
+ self[columnBarElementSymbol].attachObserver(
630
+ new Observer((e) => {
631
+ updateHeaderFromColumnBar.call(self);
632
+ updateGrid.call(self);
633
+ updateConfigColumnBar.call(self);
634
+ }),
635
+ );
636
+
637
+ self[gridHeadersElementSymbol].addEventListener("click", function (event) {
638
+ let element = null;
639
+ const datasource = self[datasourceLinkedElementSymbol];
640
+ if (!datasource) {
641
+ return;
642
+ }
643
+
644
+ element = findTargetElementFromEvent(event, ATTRIBUTE_DATATABLE_SORTABLE);
645
+ if (element) {
646
+ const index = element.parentNode.getAttribute(ATTRIBUTE_DATATABLE_INDEX);
647
+ const headers = self.getOption("headers");
648
+
649
+ event.preventDefault();
650
+
651
+ headers[index].changeDirection();
652
+
653
+ queueMicrotask(function () {
654
+ /** hotfix, normally this should be done via the updater, no idea why this is not possible. */
655
+ element.setAttribute(
656
+ ATTRIBUTE_DATATABLE_SORTABLE,
657
+ `${headers[index].field} ${headers[index].direction}`,
658
+ );
659
+
660
+ storeOrderStatement.call(self, true);
661
+ });
662
+ }
663
+ });
664
664
  }
665
665
 
666
666
  /**
667
667
  * @private
668
668
  */
669
669
  function initGridAndStructs(hostConfig, headerOrderMap) {
670
- const rowID = this.getOption("templateMapping.row-key");
671
-
672
- if (!this[gridElementSymbol]) {
673
- throw new Error("no grid element is defined");
674
- }
675
-
676
- let template;
677
- getSlottedElements.call(this).forEach((e) => {
678
- if (e instanceof HTMLTemplateElement && e.id === rowID) {
679
- template = e;
680
- }
681
- });
682
-
683
- if (!template) {
684
- throw new Error("no template is defined");
685
- }
686
-
687
- const rowCount = template.content.children.length;
688
-
689
- const headers = [];
690
-
691
- for (let i = 0; i < rowCount; i++) {
692
- let hClass = "";
693
- const row = template.content.children[i];
694
-
695
- let mode = "";
696
- if (row.hasAttribute(ATTRIBUTE_DATATABLE_MODE)) {
697
- mode = row.getAttribute(ATTRIBUTE_DATATABLE_MODE);
698
- }
699
-
700
- let grid = row.getAttribute(ATTRIBUTE_DATATABLE_GRID_TEMPLATE);
701
- if (!grid || grid === "" || grid === "auto") {
702
- grid = "minmax(0, 1fr)";
703
- }
704
-
705
- let label = "";
706
- let labelKey = "";
707
-
708
- if (row.hasAttribute(ATTRIBUTE_DATATABLE_HEAD)) {
709
- label = row.getAttribute(ATTRIBUTE_DATATABLE_HEAD);
710
- labelKey = label;
711
-
712
- try {
713
- if (label.startsWith("i18n:")) {
714
- label = label.substring(5, label.length);
715
- label = getDocumentTranslations().getText(label, label);
716
- }
717
- } catch (e) {
718
- label = "i18n error " + label;
719
- }
720
- }
721
-
722
- if (!label) {
723
- label = i + 1 + "";
724
- mode = ATTRIBUTE_DATATABLE_MODE_FIXED;
725
- labelKey = label;
726
- }
727
-
728
- if (isObject(hostConfig) && hostConfig.hasOwnProperty(label)) {
729
- if (hostConfig[label] === false) {
730
- mode = ATTRIBUTE_DATATABLE_MODE_HIDDEN;
731
- } else {
732
- mode = ATTRIBUTE_DATATABLE_MODE_VISIBLE;
733
- }
734
- }
735
-
736
- let align = "";
737
- if (row.hasAttribute(ATTRIBUTE_DATATABLE_ALIGN)) {
738
- align = row.getAttribute(ATTRIBUTE_DATATABLE_ALIGN);
739
- }
740
-
741
- switch (align) {
742
- case "center":
743
- hClass = "flex-center";
744
- break;
745
- case "end":
746
- hClass = "flex-end";
747
- break;
748
- case "start":
749
- hClass = "flex-start";
750
- break;
751
- default:
752
- hClass = "flex-start";
753
- }
754
-
755
- let field = "";
756
- let direction = DIRECTION_NONE;
757
- if (row.hasAttribute(ATTRIBUTE_DATATABLE_SORTABLE)) {
758
- field = row.getAttribute(ATTRIBUTE_DATATABLE_SORTABLE).trim();
759
- const parts = field.split(" ").map((item) => item.trim());
760
- field = parts[0];
761
-
762
- if (headerOrderMap.has(field)) {
763
- direction = headerOrderMap.get(field);
764
- } else if (
765
- parts.length === 2 &&
766
- [DIRECTION_ASC, DIRECTION_DESC].indexOf(parts[1]) !== -1
767
- ) {
768
- direction = parts[1];
769
- }
770
- }
771
-
772
- if (mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN) {
773
- hClass += " hidden";
774
- }
775
-
776
- const header = new Header();
777
- header.setInternals({
778
- field: field,
779
- label: label,
780
- classes: hClass,
781
- index: i,
782
- mode: mode,
783
- grid: grid,
784
- labelKey: labelKey,
785
- direction: direction,
786
- });
787
-
788
- headers.push(header);
789
- }
790
-
791
- this.setOption("headers", headers);
792
- queueMicrotask(() => {
793
- storeOrderStatement.call(this, this.getOption("features.autoInit"));
794
- });
670
+ const rowID = this.getOption("templateMapping.row-key");
671
+
672
+ if (!this[gridElementSymbol]) {
673
+ throw new Error("no grid element is defined");
674
+ }
675
+
676
+ let template;
677
+ getSlottedElements.call(this).forEach((e) => {
678
+ if (e instanceof HTMLTemplateElement && e.id === rowID) {
679
+ template = e;
680
+ }
681
+ });
682
+
683
+ if (!template) {
684
+ throw new Error("no template is defined");
685
+ }
686
+
687
+ const rowCount = template.content.children.length;
688
+
689
+ const headers = [];
690
+
691
+ for (let i = 0; i < rowCount; i++) {
692
+ let hClass = "";
693
+ const row = template.content.children[i];
694
+
695
+ let mode = "";
696
+ if (row.hasAttribute(ATTRIBUTE_DATATABLE_MODE)) {
697
+ mode = row.getAttribute(ATTRIBUTE_DATATABLE_MODE);
698
+ }
699
+
700
+ let grid = row.getAttribute(ATTRIBUTE_DATATABLE_GRID_TEMPLATE);
701
+ if (!grid || grid === "" || grid === "auto") {
702
+ grid = "minmax(0, 1fr)";
703
+ }
704
+
705
+ let label = "";
706
+ let labelKey = "";
707
+
708
+ if (row.hasAttribute(ATTRIBUTE_DATATABLE_HEAD)) {
709
+ label = row.getAttribute(ATTRIBUTE_DATATABLE_HEAD);
710
+ labelKey = label;
711
+
712
+ try {
713
+ if (label.startsWith("i18n:")) {
714
+ label = label.substring(5, label.length);
715
+ label = getDocumentTranslations().getText(label, label);
716
+ }
717
+ } catch (e) {
718
+ label = "i18n error " + label;
719
+ }
720
+ }
721
+
722
+ if (!label) {
723
+ label = i + 1 + "";
724
+ mode = ATTRIBUTE_DATATABLE_MODE_FIXED;
725
+ labelKey = label;
726
+ }
727
+
728
+ if (isObject(hostConfig) && hostConfig.hasOwnProperty(label)) {
729
+ if (hostConfig[label] === false) {
730
+ mode = ATTRIBUTE_DATATABLE_MODE_HIDDEN;
731
+ } else {
732
+ mode = ATTRIBUTE_DATATABLE_MODE_VISIBLE;
733
+ }
734
+ }
735
+
736
+ let align = "";
737
+ if (row.hasAttribute(ATTRIBUTE_DATATABLE_ALIGN)) {
738
+ align = row.getAttribute(ATTRIBUTE_DATATABLE_ALIGN);
739
+ }
740
+
741
+ switch (align) {
742
+ case "center":
743
+ hClass = "flex-center";
744
+ break;
745
+ case "end":
746
+ hClass = "flex-end";
747
+ break;
748
+ case "start":
749
+ hClass = "flex-start";
750
+ break;
751
+ default:
752
+ hClass = "flex-start";
753
+ }
754
+
755
+ let field = "";
756
+ let direction = DIRECTION_NONE;
757
+ if (row.hasAttribute(ATTRIBUTE_DATATABLE_SORTABLE)) {
758
+ field = row.getAttribute(ATTRIBUTE_DATATABLE_SORTABLE).trim();
759
+ const parts = field.split(" ").map((item) => item.trim());
760
+ field = parts[0];
761
+
762
+ if (headerOrderMap.has(field)) {
763
+ direction = headerOrderMap.get(field);
764
+ } else if (
765
+ parts.length === 2 &&
766
+ [DIRECTION_ASC, DIRECTION_DESC].indexOf(parts[1]) !== -1
767
+ ) {
768
+ direction = parts[1];
769
+ }
770
+ }
771
+
772
+ if (mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN) {
773
+ hClass += " hidden";
774
+ }
775
+
776
+ const header = new Header();
777
+ header.setInternals({
778
+ field: field,
779
+ label: label,
780
+ classes: hClass,
781
+ index: i,
782
+ mode: mode,
783
+ grid: grid,
784
+ labelKey: labelKey,
785
+ direction: direction,
786
+ });
787
+
788
+ headers.push(header);
789
+ }
790
+
791
+ this.setOption("headers", headers);
792
+ queueMicrotask(() => {
793
+ storeOrderStatement.call(this, this.getOption("features.autoInit"));
794
+ });
795
795
  }
796
796
 
797
797
  /**
@@ -799,75 +799,75 @@ function initGridAndStructs(hostConfig, headerOrderMap) {
799
799
  * @return {string}
800
800
  */
801
801
  export function getStoredOrderConfigKey() {
802
- return generateUniqueConfigKey("datatable", this?.id, "stored-order");
802
+ return generateUniqueConfigKey("datatable", this?.id, "stored-order");
803
803
  }
804
804
 
805
805
  /**
806
806
  * @private
807
807
  */
808
808
  function storeOrderStatement(doFetch) {
809
- const headers = this.getOption("headers");
810
- const statement = createOrderStatement(headers);
811
- setDataSource.call(this, {orderBy: statement}, doFetch);
809
+ const headers = this.getOption("headers");
810
+ const statement = createOrderStatement(headers);
811
+ setDataSource.call(this, { orderBy: statement }, doFetch);
812
812
 
813
- const host = findElementWithSelectorUpwards(this, "monster-host");
814
- if (!(host && this.id)) {
815
- return;
816
- }
813
+ const host = findElementWithSelectorUpwards(this, "monster-host");
814
+ if (!(host && this.id)) {
815
+ return;
816
+ }
817
817
 
818
- const configKey = getStoredOrderConfigKey.call(this);
818
+ const configKey = getStoredOrderConfigKey.call(this);
819
819
 
820
- // statement explode with , and remove all empty
821
- const list = statement.split(",").filter((item) => item.trim() !== "");
822
- if (list.length === 0) {
823
- return;
824
- }
820
+ // statement explode with , and remove all empty
821
+ const list = statement.split(",").filter((item) => item.trim() !== "");
822
+ if (list.length === 0) {
823
+ return;
824
+ }
825
825
 
826
- host.setConfig(configKey, list);
826
+ host.setConfig(configKey, list);
827
827
  }
828
828
 
829
829
  /**
830
830
  * @private
831
831
  */
832
832
  function updateGrid() {
833
- if (!this[gridElementSymbol]) {
834
- throw new Error("no grid element is defined");
835
- }
833
+ if (!this[gridElementSymbol]) {
834
+ throw new Error("no grid element is defined");
835
+ }
836
836
 
837
- let gridTemplateColumns = "";
837
+ let gridTemplateColumns = "";
838
838
 
839
- const headers = this.getOption("headers");
839
+ const headers = this.getOption("headers");
840
840
 
841
- let styles = "";
841
+ let styles = "";
842
842
 
843
- for (let i = 0; i < headers.length; i++) {
844
- const header = headers[i];
843
+ for (let i = 0; i < headers.length; i++) {
844
+ const header = headers[i];
845
845
 
846
- if (header.mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN) {
847
- styles += `[data-monster-role=datatable]>[data-monster-head="${header.labelKey}"] { display: none; }\n`;
848
- styles += `[data-monster-role=datatable-headers]>[data-monster-index="${header.index}"] { display: none; }\n`;
849
- } else {
850
- gridTemplateColumns += `${header.grid} `;
851
- }
852
- }
846
+ if (header.mode === ATTRIBUTE_DATATABLE_MODE_HIDDEN) {
847
+ styles += `[data-monster-role=datatable]>[data-monster-head="${header.labelKey}"] { display: none; }\n`;
848
+ styles += `[data-monster-role=datatable-headers]>[data-monster-index="${header.index}"] { display: none; }\n`;
849
+ } else {
850
+ gridTemplateColumns += `${header.grid} `;
851
+ }
852
+ }
853
853
 
854
- const sheet = new CSSStyleSheet();
855
- if (styles !== "") sheet.replaceSync(styles);
856
- this.shadowRoot.adoptedStyleSheets = [...DataTable.getCSSStyleSheet(), sheet];
854
+ const sheet = new CSSStyleSheet();
855
+ if (styles !== "") sheet.replaceSync(styles);
856
+ this.shadowRoot.adoptedStyleSheets = [...DataTable.getCSSStyleSheet(), sheet];
857
857
 
858
- const bodyWidth = getDocument().body.getBoundingClientRect().width;
858
+ const bodyWidth = getDocument().body.getBoundingClientRect().width;
859
859
 
860
- const breakpoint = this.getOption("responsive.breakpoint");
860
+ const breakpoint = this.getOption("responsive.breakpoint");
861
861
 
862
- if (bodyWidth > breakpoint) {
863
- this[gridElementSymbol].style.gridTemplateColumns =
864
- `${gridTemplateColumns}`;
865
- this[gridHeadersElementSymbol].style.gridTemplateColumns =
866
- `${gridTemplateColumns}`;
867
- } else {
868
- this[gridElementSymbol].style.gridTemplateColumns = "auto";
869
- this[gridHeadersElementSymbol].style.gridTemplateColumns = "auto";
870
- }
862
+ if (bodyWidth > breakpoint) {
863
+ this[gridElementSymbol].style.gridTemplateColumns =
864
+ `${gridTemplateColumns}`;
865
+ this[gridHeadersElementSymbol].style.gridTemplateColumns =
866
+ `${gridTemplateColumns}`;
867
+ } else {
868
+ this[gridElementSymbol].style.gridTemplateColumns = "auto";
869
+ this[gridHeadersElementSymbol].style.gridTemplateColumns = "auto";
870
+ }
871
871
  }
872
872
 
873
873
  /**
@@ -875,20 +875,20 @@ function updateGrid() {
875
875
  * @param {Monster.Components.Datatable.Header[]} headers
876
876
  * @param {bool} doFetch
877
877
  */
878
- function setDataSource({orderBy}, doFetch) {
879
- const datasource = this[datasourceLinkedElementSymbol];
878
+ function setDataSource({ orderBy }, doFetch) {
879
+ const datasource = this[datasourceLinkedElementSymbol];
880
880
 
881
- if (!datasource) {
882
- return;
883
- }
881
+ if (!datasource) {
882
+ return;
883
+ }
884
884
 
885
- if (isFunction(datasource?.setParameters)) {
886
- datasource.setParameters({orderBy});
887
- }
885
+ if (isFunction(datasource?.setParameters)) {
886
+ datasource.setParameters({ orderBy });
887
+ }
888
888
 
889
- if (doFetch !== false && isFunction(datasource?.fetch)) {
890
- datasource.fetch();
891
- }
889
+ if (doFetch !== false && isFunction(datasource?.fetch)) {
890
+ datasource.fetch();
891
+ }
892
892
  }
893
893
 
894
894
  /**
@@ -896,20 +896,20 @@ function setDataSource({orderBy}, doFetch) {
896
896
  * @return {Monster.Components.Datatable.Form}
897
897
  */
898
898
  function initControlReferences() {
899
- if (!this.shadowRoot) {
900
- throw new Error("no shadow-root is defined");
901
- }
902
-
903
- this[gridElementSymbol] = this.shadowRoot.querySelector(
904
- "[data-monster-role=datatable]",
905
- );
906
- this[gridHeadersElementSymbol] = this.shadowRoot.querySelector(
907
- "[data-monster-role=datatable-headers]",
908
- );
909
- this[columnBarElementSymbol] =
910
- this.shadowRoot.querySelector("monster-column-bar");
911
-
912
- return this;
899
+ if (!this.shadowRoot) {
900
+ throw new Error("no shadow-root is defined");
901
+ }
902
+
903
+ this[gridElementSymbol] = this.shadowRoot.querySelector(
904
+ "[data-monster-role=datatable]",
905
+ );
906
+ this[gridHeadersElementSymbol] = this.shadowRoot.querySelector(
907
+ "[data-monster-role=datatable-headers]",
908
+ );
909
+ this[columnBarElementSymbol] =
910
+ this.shadowRoot.querySelector("monster-column-bar");
911
+
912
+ return this;
913
913
  }
914
914
 
915
915
  /**
@@ -919,22 +919,22 @@ function initControlReferences() {
919
919
  * @throws {Error} the datasource could not be initialized
920
920
  */
921
921
  function initOptionsFromArguments() {
922
- const options = {};
923
- const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
924
-
925
- if (selector) {
926
- options.datasource = {selector: selector};
927
- }
928
-
929
- const breakpoint = this.getAttribute(
930
- ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
931
- );
932
- if (breakpoint) {
933
- options.responsive = {};
934
- options.responsive.breakpoint = parseInt(breakpoint);
935
- }
936
-
937
- return options;
922
+ const options = {};
923
+ const selector = this.getAttribute(ATTRIBUTE_DATASOURCE_SELECTOR);
924
+
925
+ if (selector) {
926
+ options.datasource = { selector: selector };
927
+ }
928
+
929
+ const breakpoint = this.getAttribute(
930
+ ATTRIBUTE_DATATABLE_RESPONSIVE_BREAKPOINT,
931
+ );
932
+ if (breakpoint) {
933
+ options.responsive = {};
934
+ options.responsive.breakpoint = parseInt(breakpoint);
935
+ }
936
+
937
+ return options;
938
938
  }
939
939
 
940
940
  /**
@@ -942,7 +942,7 @@ function initOptionsFromArguments() {
942
942
  * @return {string}
943
943
  */
944
944
  function getEmptyTemplate() {
945
- return `<monster-state data-monster-role="empty-without-action">
945
+ return `<monster-state data-monster-role="empty-without-action">
946
946
  <div part="visual">
947
947
  <svg width="4rem" height="4rem" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
948
948
  <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"/>
@@ -960,8 +960,8 @@ function getEmptyTemplate() {
960
960
  * @return {string}
961
961
  */
962
962
  function getTemplate() {
963
- // language=HTML
964
- return `
963
+ // language=HTML
964
+ return `
965
965
  <div data-monster-role="control" part="control" data-monster-attributes="class path:classes.control">
966
966
  <template id="headers-row">
967
967
  <div data-monster-attributes="class path:headers-row.classes,