@schukai/monster 3.85.1 → 3.85.2

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