@schukai/monster 3.85.0 → 3.85.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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>