@schukai/monster 3.53.0 → 3.55.0

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