@schukai/monster 4.38.5 → 4.38.7

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.
@@ -17,15 +17,15 @@ import { buildTree } from "../../data/buildtree.mjs";
17
17
  import { Datasource } from "../datatable/datasource.mjs";
18
18
  import { addAttributeToken } from "../../dom/attributes.mjs";
19
19
  import {
20
- ATTRIBUTE_ERRORMESSAGE,
21
- ATTRIBUTE_ROLE,
22
- ATTRIBUTE_UPDATER_INSERT_REFERENCE,
20
+ ATTRIBUTE_ERRORMESSAGE,
21
+ ATTRIBUTE_ROLE,
22
+ ATTRIBUTE_UPDATER_INSERT_REFERENCE,
23
23
  } from "../../dom/constants.mjs";
24
24
  import {
25
- assembleMethodSymbol,
26
- CustomElement,
27
- getSlottedElements,
28
- registerCustomElement,
25
+ assembleMethodSymbol,
26
+ CustomElement,
27
+ getSlottedElements,
28
+ registerCustomElement,
29
29
  } from "../../dom/customelement.mjs";
30
30
  import { findTargetElementFromEvent, fireEvent } from "../../dom/events.mjs";
31
31
  import { findElementWithSelectorUpwards } from "../../dom/util.mjs";
@@ -36,8 +36,8 @@ import { NodeRecursiveIterator } from "../../types/noderecursiveiterator.mjs";
36
36
  import { Observer } from "../../types/observer.mjs";
37
37
  import { validateInstance } from "../../types/validate.mjs";
38
38
  import {
39
- datasourceLinkedElementSymbol,
40
- handleDataSourceChanges,
39
+ datasourceLinkedElementSymbol,
40
+ handleDataSourceChanges,
41
41
  } from "../datatable/util.mjs";
42
42
  import { ATTRIBUTE_INTEND } from "./../constants.mjs";
43
43
  import { CommonStyleSheet } from "../stylesheet/common.mjs";
@@ -83,355 +83,355 @@ const firstRunDoneSymbol = Symbol("firstRunDone");
83
83
  * @fires entries-imported
84
84
  */
85
85
  class TreeMenu extends CustomElement {
86
- /**
87
- * This method is called by the `instanceof` operator.
88
- * @return {symbol}
89
- */
90
- static get [instanceSymbol]() {
91
- return Symbol.for("@schukai/monster/components/tree-menu@@instance");
92
- }
93
-
94
- /**
95
- */
96
- constructor() {
97
- super();
98
- this[preventChangeSymbol] = false;
99
- }
100
-
101
- /**
102
- * This method is called internal and should not be called directly.
103
- *
104
- * The defaults can be set either directly in the object or via an attribute in the HTML tag.
105
- * The value of the attribute `data-monster-options` in the HTML tag must be a JSON string.
106
- *
107
- * ```
108
- * <monster-treemenu data-monster-options="{}"></monster-treemenu>
109
- * ```
110
- *
111
- * Since 1.18.0 the JSON can be specified as a DataURI.
112
- *
113
- * ```
114
- * new Monster.Types.DataUrl(btoa(JSON.stringify({
115
- * shadowMode: 'open',
116
- * })),'application/json',true).toString()
117
- * ```
118
- * @property {Object} templates Template definitions
119
- * @property {string} templates.main Main template
120
- * @property {Datasource} datasource data source
121
- * @property {Object} mapping
122
- * @property {String} mapping.selector Path to select the appropriate entries
123
- * @property {String} mapping.labelTemplate template with the label placeholders in the form ${name}, where name is the key
124
- * @property {String} mapping.keyTemplate template with the key placeholders in the form ${name}, where name is the key
125
- * @property {String} mapping.rootReferences the root references
126
- * @property {String} mapping.idTemplate template with the id placeholders in the form ${name}, where name is the key
127
- * @property {String} mapping.parentKey the parent key
128
- * @property {String} mapping.selection the selection
129
- * @property {Function} mapping.filter a filter function to filter the entries
130
- * @property {Object} classes
131
- * @property {String} classes.control the class for the control element
132
- * @property {String} classes.label the class for the label element
133
- * @property {Object} actions
134
- * @property {Function} actions.open the action to open an entry (arguments, etnry, index, event)
135
- * @property {Function} actions.close the action to close an entry (arguments, etnry, index, event)
136
- * @property {Function} actions.select the action to select an entry (arguments, etnry, index, event)
137
- */
138
- get defaults() {
139
- return Object.assign({}, super.defaults, {
140
- classes: {
141
- control: "monster-theme-primary-1",
142
- label: "monster-theme-primary-1",
143
- },
144
-
145
- mapping: {
146
- rootReferences: ["0", undefined, null],
147
- idTemplate: "id",
148
- parentKey: "parent",
149
- selector: "*",
150
- labelTemplate: "",
151
- valueTemplate: "",
152
- iconTemplate: "",
153
- filter: undefined,
154
- },
155
-
156
- templates: {
157
- main: getTemplate(),
158
- },
159
-
160
- datasource: {
161
- selector: null,
162
- },
163
-
164
- actions: {
165
- open: null,
166
- close: null,
167
- select: (entry) => {
168
- console.warn("select action is not defined", entry);
169
- },
170
- },
171
-
172
- data: [],
173
- entries: [],
174
- });
175
- }
176
-
177
- /**
178
- * @return {void}
179
- */
180
- [assembleMethodSymbol]() {
181
- super[assembleMethodSymbol]();
182
-
183
- queueMicrotask(() => {
184
- initControlReferences.call(this);
185
- initEventHandler.call(this);
186
- initObserver.call(this);
187
- copyIconMap.call(this);
188
- });
189
- }
190
-
191
- /**
192
- * This method is called internal and should not be called directly.
193
- *
194
- * @return {CSSStyleSheet[]}
195
- */
196
- static getCSSStyleSheet() {
197
- return [CommonStyleSheet, TreeMenuStyleSheet];
198
- }
199
-
200
- /**
201
- * This method is called internal and should not be called directly.
202
- *
203
- * @return {string}
204
- */
205
- static getTag() {
206
- return "monster-tree-menu";
207
- }
208
-
209
- /**
210
- * @param {string} value
211
- * @param value
212
- */
213
- selectEntry(value) {
214
- this.shadowRoot
215
- .querySelectorAll("[data-monster-role=entry]")
216
- .forEach((entry) => {
217
- entry.classList.remove("selected");
218
- });
219
-
220
- value = String(value);
221
-
222
- const entries = this.getOption("entries");
223
- const index = entries.findIndex((entry) => entry.value === value);
224
-
225
- if (index === -1) {
226
- return;
227
- }
228
-
229
- const currentNode = this.shadowRoot.querySelector(
230
- "[data-monster-insert-reference=entries-" + index + "]",
231
- );
232
-
233
- if (!currentNode) {
234
- return;
235
- }
236
-
237
- currentNode.click();
238
-
239
- let intend = Number.parseInt(currentNode.getAttribute(ATTRIBUTE_INTEND));
240
-
241
- if (intend > 0) {
242
- const refSet = new Set();
243
- let ref = currentNode.previousElementSibling;
244
- while (ref?.hasAttribute(ATTRIBUTE_INTEND)) {
245
- const i = Number.parseInt(ref.getAttribute(ATTRIBUTE_INTEND));
246
-
247
- if (Number.isNaN(i)) {
248
- break;
249
- }
250
-
251
- if (i < intend) {
252
- if (ref.getAttribute("data-monster-state") !== "open") {
253
- ref.click();
254
- }
255
-
256
- if (i === 0) {
257
- break;
258
- }
259
- intend = i;
260
- }
261
- ref = ref.previousElementSibling;
262
- }
263
- }
264
- }
86
+ /**
87
+ * This method is called by the `instanceof` operator.
88
+ * @return {symbol}
89
+ */
90
+ static get [instanceSymbol]() {
91
+ return Symbol.for("@schukai/monster/components/tree-menu@@instance");
92
+ }
93
+
94
+ /**
95
+ */
96
+ constructor() {
97
+ super();
98
+ this[preventChangeSymbol] = false;
99
+ }
100
+
101
+ /**
102
+ * This method is called internal and should not be called directly.
103
+ *
104
+ * The defaults can be set either directly in the object or via an attribute in the HTML tag.
105
+ * The value of the attribute `data-monster-options` in the HTML tag must be a JSON string.
106
+ *
107
+ * ```
108
+ * <monster-treemenu data-monster-options="{}"></monster-treemenu>
109
+ * ```
110
+ *
111
+ * Since 1.18.0 the JSON can be specified as a DataURI.
112
+ *
113
+ * ```
114
+ * new Monster.Types.DataUrl(btoa(JSON.stringify({
115
+ * shadowMode: 'open',
116
+ * })),'application/json',true).toString()
117
+ * ```
118
+ * @property {Object} templates Template definitions
119
+ * @property {string} templates.main Main template
120
+ * @property {Datasource} datasource data source
121
+ * @property {Object} mapping
122
+ * @property {String} mapping.selector Path to select the appropriate entries
123
+ * @property {String} mapping.labelTemplate template with the label placeholders in the form ${name}, where name is the key
124
+ * @property {String} mapping.keyTemplate template with the key placeholders in the form ${name}, where name is the key
125
+ * @property {String} mapping.rootReferences the root references
126
+ * @property {String} mapping.idTemplate template with the id placeholders in the form ${name}, where name is the key
127
+ * @property {String} mapping.parentKey the parent key
128
+ * @property {String} mapping.selection the selection
129
+ * @property {Function} mapping.filter a filter function to filter the entries
130
+ * @property {Object} classes
131
+ * @property {String} classes.control the class for the control element
132
+ * @property {String} classes.label the class for the label element
133
+ * @property {Object} actions
134
+ * @property {Function} actions.open the action to open an entry (arguments, etnry, index, event)
135
+ * @property {Function} actions.close the action to close an entry (arguments, etnry, index, event)
136
+ * @property {Function} actions.select the action to select an entry (arguments, etnry, index, event)
137
+ */
138
+ get defaults() {
139
+ return Object.assign({}, super.defaults, {
140
+ classes: {
141
+ control: "monster-theme-primary-1",
142
+ label: "monster-theme-primary-1",
143
+ },
144
+
145
+ mapping: {
146
+ rootReferences: ["0", undefined, null],
147
+ idTemplate: "id",
148
+ parentKey: "parent",
149
+ selector: "*",
150
+ labelTemplate: "",
151
+ valueTemplate: "",
152
+ iconTemplate: "",
153
+ filter: undefined,
154
+ },
155
+
156
+ templates: {
157
+ main: getTemplate(),
158
+ },
159
+
160
+ datasource: {
161
+ selector: null,
162
+ },
163
+
164
+ actions: {
165
+ open: null,
166
+ close: null,
167
+ select: (entry) => {
168
+ console.warn("select action is not defined", entry);
169
+ },
170
+ },
171
+
172
+ data: [],
173
+ entries: [],
174
+ });
175
+ }
176
+
177
+ /**
178
+ * @return {void}
179
+ */
180
+ [assembleMethodSymbol]() {
181
+ super[assembleMethodSymbol]();
182
+
183
+ queueMicrotask(() => {
184
+ initControlReferences.call(this);
185
+ initEventHandler.call(this);
186
+ initObserver.call(this);
187
+ copyIconMap.call(this);
188
+ });
189
+ }
190
+
191
+ /**
192
+ * This method is called internal and should not be called directly.
193
+ *
194
+ * @return {CSSStyleSheet[]}
195
+ */
196
+ static getCSSStyleSheet() {
197
+ return [CommonStyleSheet, TreeMenuStyleSheet];
198
+ }
199
+
200
+ /**
201
+ * This method is called internal and should not be called directly.
202
+ *
203
+ * @return {string}
204
+ */
205
+ static getTag() {
206
+ return "monster-tree-menu";
207
+ }
208
+
209
+ /**
210
+ * @param {string} value
211
+ * @param value
212
+ */
213
+ selectEntry(value) {
214
+ this.shadowRoot
215
+ .querySelectorAll("[data-monster-role=entry]")
216
+ .forEach((entry) => {
217
+ entry.classList.remove("selected");
218
+ });
219
+
220
+ value = String(value);
221
+
222
+ const entries = this.getOption("entries");
223
+ const index = entries.findIndex((entry) => entry.value === value);
224
+
225
+ if (index === -1) {
226
+ return;
227
+ }
228
+
229
+ const currentNode = this.shadowRoot.querySelector(
230
+ "[data-monster-insert-reference=entries-" + index + "]",
231
+ );
232
+
233
+ if (!currentNode) {
234
+ return;
235
+ }
236
+
237
+ currentNode.click();
238
+
239
+ let intend = Number.parseInt(currentNode.getAttribute(ATTRIBUTE_INTEND));
240
+
241
+ if (intend > 0) {
242
+ const refSet = new Set();
243
+ let ref = currentNode.previousElementSibling;
244
+ while (ref?.hasAttribute(ATTRIBUTE_INTEND)) {
245
+ const i = Number.parseInt(ref.getAttribute(ATTRIBUTE_INTEND));
246
+
247
+ if (Number.isNaN(i)) {
248
+ break;
249
+ }
250
+
251
+ if (i < intend) {
252
+ if (ref.getAttribute("data-monster-state") !== "open") {
253
+ ref.click();
254
+ }
255
+
256
+ if (i === 0) {
257
+ break;
258
+ }
259
+ intend = i;
260
+ }
261
+ ref = ref.previousElementSibling;
262
+ }
263
+ }
264
+ }
265
265
  }
266
266
 
267
267
  /**
268
268
  * @private
269
269
  */
270
270
  function copyIconMap() {
271
- const nodes = getSlottedElements.call(this, "svg", null);
272
- if (nodes.size > 0) {
273
- for (const node of nodes) {
274
- this.shadowRoot.appendChild(node);
275
- }
276
- }
271
+ const nodes = getSlottedElements.call(this, "svg", null);
272
+ if (nodes.size > 0) {
273
+ for (const node of nodes) {
274
+ this.shadowRoot.appendChild(node);
275
+ }
276
+ }
277
277
  }
278
278
 
279
279
  /**
280
280
  * @private
281
281
  */
282
282
  function initEventHandler() {
283
- const selector = this.getOption("datasource.selector");
284
-
285
- if (isString(selector)) {
286
- const element = findElementWithSelectorUpwards(this, selector);
287
- if (element === null) {
288
- throw new Error("the selector must match exactly one element");
289
- }
290
-
291
- if (!(element instanceof HTMLElement)) {
292
- throw new TypeError("the element must be an HTMLElement");
293
- }
294
-
295
- customElements.whenDefined(element.tagName.toLocaleLowerCase()).then(() => {
296
- if (!(element instanceof Datasource)) {
297
- throw new TypeError("the element must be a datasource");
298
- }
299
-
300
- this[datasourceLinkedElementSymbol] = element;
301
-
302
- handleDataSourceChanges.call(this);
303
- element.datasource.attachObserver(
304
- new Observer(handleDataSourceChanges.bind(this)),
305
- );
306
-
307
- this.attachObserver(
308
- new Observer(() => {
309
- if (this[preventChangeSymbol] === true) {
310
- return;
311
- }
312
- this[preventChangeSymbol] = true;
313
- queueMicrotask(() => {
314
- importEntries.call(this);
315
- });
316
- }),
317
- );
318
- });
319
- }
320
-
321
- this[openEntryEventHandlerSymbol] = (event) => {
322
- const container = findTargetElementFromEvent(
323
- event,
324
- ATTRIBUTE_ROLE,
325
- "entry",
326
- );
327
-
328
- if (!(container instanceof HTMLElement)) {
329
- return;
330
- }
331
-
332
- const index = container
333
- .getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
334
- .split("-")
335
- .pop();
336
-
337
- const currentEntry = this.getOption("entries." + index);
338
-
339
- if (currentEntry["has-children"] === false) {
340
- const doAction = this.getOption("actions.select");
341
-
342
- this.shadowRoot
343
- .querySelectorAll("[data-monster-role=entry].selected")
344
- .forEach((entry) => {
345
- entry.classList.remove("selected");
346
- });
347
-
348
- let intend = currentEntry.intend;
349
- if (intend > 0) {
350
- let ref = container.previousElementSibling;
351
- while (ref?.hasAttribute(ATTRIBUTE_INTEND)) {
352
- const i = Number.parseInt(ref.getAttribute(ATTRIBUTE_INTEND));
353
-
354
- if (Number.isNaN(i)) {
355
- break;
356
- }
357
-
358
- if (i < intend) {
359
- ref.classList.add("selected");
360
- if (i === 0) {
361
- break;
362
- }
363
- intend = i;
364
- }
365
- ref = ref.previousElementSibling;
366
- }
367
- }
368
-
369
- container.classList.add("selected");
370
-
371
- if (isFunction(doAction)) {
372
- doAction.call(this, currentEntry, index, event);
373
- }
374
- return;
375
- }
376
-
377
- const currentState = this.getOption("entries." + index + ".state");
378
-
379
- const newState = currentState === "close" ? "open" : "close";
380
-
381
- const doAction = this.getOption("actions." + newState);
382
- if (isFunction(doAction)) {
383
- doAction.call(this, this.getOption("entries." + index), index);
384
- }
385
-
386
- this.setOption("entries." + index + ".state", newState);
387
- const newVisibility = newState === "open" ? "visible" : "hidden";
388
-
389
- if (container.hasAttribute(ATTRIBUTE_INTEND)) {
390
- const intend = container.getAttribute(ATTRIBUTE_INTEND);
391
- let ref = container.nextElementSibling;
392
- const childIntend = parseInt(intend) + 1;
393
-
394
- const cmp = (a, b) => {
395
- if (newState === "open") {
396
- return a === b;
397
- }
398
-
399
- return a >= b;
400
- };
401
-
402
- while (ref?.hasAttribute(ATTRIBUTE_INTEND)) {
403
- const refIntend = ref.getAttribute(ATTRIBUTE_INTEND);
404
-
405
- if (!cmp(Number.parseInt(refIntend), childIntend)) {
406
- if (refIntend === intend) {
407
- break;
408
- }
409
- ref = ref.nextElementSibling;
410
- continue;
411
- }
412
-
413
- const refIndex = ref
414
- .getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
415
- .split("-")
416
- .pop();
417
-
418
- this.setOption("entries." + refIndex + ".visibility", newVisibility);
419
-
420
- if (newState === "close") {
421
- this.setOption("entries." + refIndex + ".state", "close");
422
- }
423
-
424
- ref = ref.nextElementSibling;
425
- }
426
- }
427
- };
428
-
429
- const types = this.getOption("toggleEventType", ["click"]);
430
- for (const [, type] of Object.entries(types)) {
431
- this.shadowRoot.addEventListener(type, this[openEntryEventHandlerSymbol]);
432
- }
433
-
434
- return this;
283
+ const selector = this.getOption("datasource.selector");
284
+
285
+ if (isString(selector)) {
286
+ const element = findElementWithSelectorUpwards(this, selector);
287
+ if (element === null) {
288
+ throw new Error("the selector must match exactly one element");
289
+ }
290
+
291
+ if (!(element instanceof HTMLElement)) {
292
+ throw new TypeError("the element must be an HTMLElement");
293
+ }
294
+
295
+ customElements.whenDefined(element.tagName.toLocaleLowerCase()).then(() => {
296
+ if (!(element instanceof Datasource)) {
297
+ throw new TypeError("the element must be a datasource");
298
+ }
299
+
300
+ this[datasourceLinkedElementSymbol] = element;
301
+
302
+ handleDataSourceChanges.call(this);
303
+ element.datasource.attachObserver(
304
+ new Observer(handleDataSourceChanges.bind(this)),
305
+ );
306
+
307
+ this.attachObserver(
308
+ new Observer(() => {
309
+ if (this[preventChangeSymbol] === true) {
310
+ return;
311
+ }
312
+ this[preventChangeSymbol] = true;
313
+ queueMicrotask(() => {
314
+ importEntries.call(this);
315
+ });
316
+ }),
317
+ );
318
+ });
319
+ }
320
+
321
+ this[openEntryEventHandlerSymbol] = (event) => {
322
+ const container = findTargetElementFromEvent(
323
+ event,
324
+ ATTRIBUTE_ROLE,
325
+ "entry",
326
+ );
327
+
328
+ if (!(container instanceof HTMLElement)) {
329
+ return;
330
+ }
331
+
332
+ const index = container
333
+ .getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
334
+ .split("-")
335
+ .pop();
336
+
337
+ const currentEntry = this.getOption("entries." + index);
338
+
339
+ if (currentEntry["has-children"] === false) {
340
+ const doAction = this.getOption("actions.select");
341
+
342
+ this.shadowRoot
343
+ .querySelectorAll("[data-monster-role=entry].selected")
344
+ .forEach((entry) => {
345
+ entry.classList.remove("selected");
346
+ });
347
+
348
+ let intend = currentEntry.intend;
349
+ if (intend > 0) {
350
+ let ref = container.previousElementSibling;
351
+ while (ref?.hasAttribute(ATTRIBUTE_INTEND)) {
352
+ const i = Number.parseInt(ref.getAttribute(ATTRIBUTE_INTEND));
353
+
354
+ if (Number.isNaN(i)) {
355
+ break;
356
+ }
357
+
358
+ if (i < intend) {
359
+ ref.classList.add("selected");
360
+ if (i === 0) {
361
+ break;
362
+ }
363
+ intend = i;
364
+ }
365
+ ref = ref.previousElementSibling;
366
+ }
367
+ }
368
+
369
+ container.classList.add("selected");
370
+
371
+ if (isFunction(doAction)) {
372
+ doAction.call(this, currentEntry, index, event);
373
+ }
374
+ return;
375
+ }
376
+
377
+ const currentState = this.getOption("entries." + index + ".state");
378
+
379
+ const newState = currentState === "close" ? "open" : "close";
380
+
381
+ const doAction = this.getOption("actions." + newState);
382
+ if (isFunction(doAction)) {
383
+ doAction.call(this, this.getOption("entries." + index), index);
384
+ }
385
+
386
+ this.setOption("entries." + index + ".state", newState);
387
+ const newVisibility = newState === "open" ? "visible" : "hidden";
388
+
389
+ if (container.hasAttribute(ATTRIBUTE_INTEND)) {
390
+ const intend = container.getAttribute(ATTRIBUTE_INTEND);
391
+ let ref = container.nextElementSibling;
392
+ const childIntend = parseInt(intend) + 1;
393
+
394
+ const cmp = (a, b) => {
395
+ if (newState === "open") {
396
+ return a === b;
397
+ }
398
+
399
+ return a >= b;
400
+ };
401
+
402
+ while (ref?.hasAttribute(ATTRIBUTE_INTEND)) {
403
+ const refIntend = ref.getAttribute(ATTRIBUTE_INTEND);
404
+
405
+ if (!cmp(Number.parseInt(refIntend), childIntend)) {
406
+ if (refIntend === intend) {
407
+ break;
408
+ }
409
+ ref = ref.nextElementSibling;
410
+ continue;
411
+ }
412
+
413
+ const refIndex = ref
414
+ .getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
415
+ .split("-")
416
+ .pop();
417
+
418
+ this.setOption("entries." + refIndex + ".visibility", newVisibility);
419
+
420
+ if (newState === "close") {
421
+ this.setOption("entries." + refIndex + ".state", "close");
422
+ }
423
+
424
+ ref = ref.nextElementSibling;
425
+ }
426
+ }
427
+ };
428
+
429
+ const types = this.getOption("toggleEventType", ["click"]);
430
+ for (const [, type] of Object.entries(types)) {
431
+ this.shadowRoot.addEventListener(type, this[openEntryEventHandlerSymbol]);
432
+ }
433
+
434
+ return this;
435
435
  }
436
436
 
437
437
  /**
@@ -449,81 +449,79 @@ function initObserver() {}
449
449
  * @private
450
450
  */
451
451
  function importEntries() {
452
- const data = this.getOption("data");
453
- this[internalNodesSymbol] = new Map();
454
-
455
- const mappingOptions = this.getOption("mapping", {});
456
-
457
- const filter = mappingOptions?.["filter"];
458
- const rootReferences = mappingOptions?.["rootReferences"];
459
-
460
- const id = this.getOption("mapping.idTemplate");
461
- const parentKey = this.getOption("mapping.parentKey");
462
-
463
- const selector = mappingOptions?.["selector"];
464
-
465
- let filteredData;
466
- if (this[firstRunDoneSymbol] !== true) {
467
- filteredData = data?.filter(
468
- (entry) =>
469
- !entry[parentKey] ||
470
- entry[parentKey] === null ||
471
- entry[parentKey] === undefined ||
472
- entry[parentKey] === 0,
473
- );
474
- setTimeout(() => {
475
- this[firstRunDoneSymbol] = true;
476
- importEntries.call(this);
477
- }, 0);
478
- } else {
479
- filteredData = data;
480
- }
481
-
482
- let nodes;
483
- try {
484
- nodes = buildTree(filteredData, selector, id, parentKey, {
485
- filter,
486
- rootReferences,
487
- });
488
- } catch (error) {
489
- addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
490
- return this;
491
- }
492
-
493
- const options = [];
494
- for (const node of nodes) {
495
- const iterator = new NodeRecursiveIterator(node);
496
- for (const n of iterator) {
497
- const formattedValues = formatKeyLabel.call(this, n);
498
-
499
- const label = formattedValues?.label;
500
- const value = formattedValues?.value;
501
- const icon = formattedValues?.icon;
502
- const intend = n.level;
503
-
504
- const visibility = intend > 0 ? "hidden" : "visible";
505
- const state = "close";
506
-
507
- this[internalNodesSymbol].set(value, n);
508
-
509
- options.push({
510
- value,
511
- label,
512
- icon,
513
- intend,
514
- state,
515
- visibility,
516
- ["has-children"]: n.hasChildNodes(),
517
- });
518
- }
519
- }
520
-
521
- queueMicrotask(() => {
522
- this.setOption("entries", options);
523
- fireEvent(this, "entries-imported");
524
- });
525
-
526
- return this;
452
+ const data = this.getOption("data");
453
+ this[internalNodesSymbol] = new Map();
454
+
455
+ const mappingOptions = this.getOption("mapping", {});
456
+
457
+ const filter = mappingOptions?.["filter"];
458
+ const rootReferences = mappingOptions?.["rootReferences"];
459
+
460
+ const id = this.getOption("mapping.idTemplate");
461
+ const parentKey = this.getOption("mapping.parentKey");
462
+
463
+ const selector = mappingOptions?.["selector"];
464
+
465
+ let filteredData;
466
+ if (this[firstRunDoneSymbol] !== true) {
467
+ filteredData = data?.filter(
468
+ (entry) =>
469
+ !entry[parentKey] ||
470
+ entry[parentKey] === null ||
471
+ entry[parentKey] === undefined ||
472
+ entry[parentKey] === 0,
473
+ );
474
+ setTimeout(() => {
475
+ this[firstRunDoneSymbol] = true;
476
+ importEntries.call(this);
477
+ }, 0);
478
+ } else {
479
+ filteredData = data;
480
+ }
481
+
482
+ let nodes;
483
+ try {
484
+ nodes = buildTree(filteredData, selector, id, parentKey, {
485
+ filter,
486
+ rootReferences,
487
+ });
488
+ } catch (error) {
489
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
490
+ return this;
491
+ }
492
+
493
+ const options = [];
494
+ for (const node of nodes) {
495
+ const iterator = new NodeRecursiveIterator(node);
496
+ for (const n of iterator) {
497
+ const formattedValues = formatKeyLabel.call(this, n);
498
+
499
+ const label = formattedValues?.label;
500
+ const value = formattedValues?.value;
501
+ const icon = formattedValues?.icon;
502
+ const intend = n.level;
503
+
504
+ const visibility = intend > 0 ? "hidden" : "visible";
505
+ const state = "close";
506
+
507
+ this[internalNodesSymbol].set(value, n);
508
+
509
+ options.push({
510
+ value,
511
+ label,
512
+ icon,
513
+ intend,
514
+ state,
515
+ visibility,
516
+ ["has-children"]: n.hasChildNodes(),
517
+ });
518
+ }
519
+ }
520
+
521
+ this.setOption("entries", options);
522
+ fireEvent(this, "entries-imported");
523
+
524
+ return this;
527
525
  }
528
526
 
529
527
  /**
@@ -533,27 +531,27 @@ function importEntries() {
533
531
  * @private
534
532
  */
535
533
  function formatKeyLabel(node) {
536
- validateInstance(node, Node);
534
+ validateInstance(node, Node);
537
535
 
538
- const label = new Formatter(node.value).format(
539
- this.getOption("mapping.labelTemplate"),
540
- );
536
+ const label = new Formatter(node.value).format(
537
+ this.getOption("mapping.labelTemplate"),
538
+ );
541
539
 
542
- const value = new Formatter(node.value).format(
543
- this.getOption("mapping.valueTemplate"),
544
- );
540
+ const value = new Formatter(node.value).format(
541
+ this.getOption("mapping.valueTemplate"),
542
+ );
545
543
 
546
- const iconID = new Formatter(node.value).format(
547
- this.getOption("mapping.iconTemplate"),
548
- );
544
+ const iconID = new Formatter(node.value).format(
545
+ this.getOption("mapping.iconTemplate"),
546
+ );
549
547
 
550
- const icon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><use xlink:href="#${iconID}"></use></svg>`;
548
+ const icon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><use xlink:href="#${iconID}"></use></svg>`;
551
549
 
552
- return {
553
- value,
554
- label,
555
- icon,
556
- };
550
+ return {
551
+ value,
552
+ label,
553
+ icon,
554
+ };
557
555
  }
558
556
 
559
557
  /**
@@ -561,15 +559,15 @@ function formatKeyLabel(node) {
561
559
  * @return {TreeMenu}
562
560
  */
563
561
  function initControlReferences() {
564
- if (!this.shadowRoot) {
565
- throw new Error("no shadow-root is defined");
566
- }
562
+ if (!this.shadowRoot) {
563
+ throw new Error("no shadow-root is defined");
564
+ }
567
565
 
568
- this[controlElementSymbol] = this.shadowRoot.querySelector(
569
- "[data-monster-role=control]",
570
- );
566
+ this[controlElementSymbol] = this.shadowRoot.querySelector(
567
+ "[data-monster-role=control]",
568
+ );
571
569
 
572
- return this;
570
+ return this;
573
571
  }
574
572
 
575
573
  /**
@@ -577,8 +575,8 @@ function initControlReferences() {
577
575
  * @return {string}
578
576
  */
579
577
  function getTemplate() {
580
- // language=HTML
581
- return `
578
+ // language=HTML
579
+ return `
582
580
  <slot></slot>
583
581
 
584
582
  <template id="entries">