@schukai/monster 3.53.0 → 3.55.0

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