@schukai/monster 3.71.3 → 3.73.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 (119) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/package.json +1 -1
  3. package/source/components/datatable/dataset.mjs +268 -272
  4. package/source/components/datatable/datasource/dom.mjs +2 -2
  5. package/source/components/datatable/datasource/rest.mjs +408 -410
  6. package/source/components/datatable/filter.mjs +0 -1
  7. package/source/components/datatable/style/datatable.pcss +7 -5
  8. package/source/components/datatable/style/embedded-pagination.pcss +1 -1
  9. package/source/components/datatable/style/pagination.pcss +1 -1
  10. package/source/components/datatable/stylesheet/change-button.mjs +2 -4
  11. package/source/components/datatable/stylesheet/column-bar.mjs +2 -4
  12. package/source/components/datatable/stylesheet/dataset.mjs +2 -4
  13. package/source/components/datatable/stylesheet/datasource.mjs +1 -3
  14. package/source/components/datatable/stylesheet/datatable.mjs +2 -4
  15. package/source/components/datatable/stylesheet/embedded-pagination.mjs +1 -1
  16. package/source/components/datatable/stylesheet/filter-button.mjs +1 -3
  17. package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +14 -7
  18. package/source/components/datatable/stylesheet/filter-date-range.mjs +1 -3
  19. package/source/components/datatable/stylesheet/filter-range.mjs +1 -3
  20. package/source/components/datatable/stylesheet/filter.mjs +2 -4
  21. package/source/components/datatable/stylesheet/pagination.mjs +2 -4
  22. package/source/components/datatable/stylesheet/save-button.mjs +2 -4
  23. package/source/components/datatable/stylesheet/select-filter.mjs +2 -4
  24. package/source/components/datatable/stylesheet/status.mjs +2 -4
  25. package/source/components/form/context-help.mjs +1 -1
  26. package/source/components/form/field-set.mjs +219 -219
  27. package/source/components/form/form.mjs +309 -185
  28. package/source/components/form/reload.mjs +211 -211
  29. package/source/components/form/select.mjs +12 -13
  30. package/source/components/form/style/field-set.pcss +2 -2
  31. package/source/components/form/style/form.pcss +8 -0
  32. package/source/components/form/stylesheet/action-button.mjs +2 -4
  33. package/source/components/form/stylesheet/api-button.mjs +1 -3
  34. package/source/components/form/stylesheet/button-bar.mjs +2 -4
  35. package/source/components/form/stylesheet/button.mjs +2 -4
  36. package/source/components/form/stylesheet/confirm-button.mjs +2 -4
  37. package/source/components/form/stylesheet/context-error.mjs +2 -4
  38. package/source/components/form/stylesheet/context-help.mjs +2 -4
  39. package/source/components/form/stylesheet/field-set.mjs +14 -7
  40. package/source/components/form/stylesheet/form.mjs +14 -7
  41. package/source/components/form/stylesheet/message-state-button.mjs +1 -3
  42. package/source/components/form/stylesheet/popper-button.mjs +2 -4
  43. package/source/components/form/stylesheet/select.mjs +14 -7
  44. package/source/components/form/stylesheet/state-button.mjs +2 -4
  45. package/source/components/form/stylesheet/tree-select.mjs +1 -3
  46. package/source/components/host/stylesheet/call-button.mjs +2 -4
  47. package/source/components/host/stylesheet/config-manager.mjs +1 -3
  48. package/source/components/host/stylesheet/host.mjs +2 -4
  49. package/source/components/host/stylesheet/overlay.mjs +2 -4
  50. package/source/components/host/stylesheet/toggle-button.mjs +2 -4
  51. package/source/components/host/stylesheet/viewer.mjs +2 -4
  52. package/source/components/layout/style/collapse.pcss +2 -2
  53. package/source/components/layout/style/details.pcss +2 -2
  54. package/source/components/layout/stylesheet/collapse.mjs +14 -7
  55. package/source/components/layout/stylesheet/details.mjs +2 -4
  56. package/source/components/layout/stylesheet/panel.mjs +2 -4
  57. package/source/components/layout/stylesheet/popper.mjs +2 -4
  58. package/source/components/layout/stylesheet/split-panel.mjs +1 -3
  59. package/source/components/layout/stylesheet/tabs.mjs +2 -4
  60. package/source/components/layout/stylesheet/width-toggle.mjs +1 -3
  61. package/source/components/layout/tabs.mjs +0 -1
  62. package/source/components/navigation/stylesheet/table-of-content.mjs +2 -4
  63. package/source/components/notify/stylesheet/message.mjs +2 -4
  64. package/source/components/notify/stylesheet/notify.mjs +2 -4
  65. package/source/components/state/stylesheet/log.mjs +2 -4
  66. package/source/components/state/stylesheet/state.mjs +2 -4
  67. package/source/components/style/control.pcss +5 -0
  68. package/source/components/style/data-grid.pcss +2 -2
  69. package/source/components/style/mixin/typography.pcss +7 -1
  70. package/source/components/style/normalize.pcss +1 -1
  71. package/source/components/stylesheet/badge.mjs +1 -3
  72. package/source/components/stylesheet/border.mjs +1 -3
  73. package/source/components/stylesheet/button.mjs +1 -3
  74. package/source/components/stylesheet/card.mjs +1 -3
  75. package/source/components/stylesheet/color.mjs +1 -3
  76. package/source/components/stylesheet/common.mjs +1 -3
  77. package/source/components/stylesheet/control.mjs +2 -4
  78. package/source/components/stylesheet/data-grid.mjs +2 -4
  79. package/source/components/stylesheet/display.mjs +1 -3
  80. package/source/components/stylesheet/floating-ui.mjs +1 -3
  81. package/source/components/stylesheet/form.mjs +13 -6
  82. package/source/components/stylesheet/host.mjs +1 -3
  83. package/source/components/stylesheet/icons.mjs +1 -3
  84. package/source/components/stylesheet/mixin/badge.mjs +1 -3
  85. package/source/components/stylesheet/mixin/button.mjs +1 -3
  86. package/source/components/stylesheet/mixin/form.mjs +13 -6
  87. package/source/components/stylesheet/mixin/hover.mjs +1 -3
  88. package/source/components/stylesheet/mixin/icon.mjs +1 -3
  89. package/source/components/stylesheet/mixin/media.mjs +1 -3
  90. package/source/components/stylesheet/mixin/property.mjs +13 -6
  91. package/source/components/stylesheet/mixin/skeleton.mjs +1 -3
  92. package/source/components/stylesheet/mixin/spinner.mjs +1 -3
  93. package/source/components/stylesheet/mixin/typography.mjs +1 -3
  94. package/source/components/stylesheet/normalize.mjs +1 -3
  95. package/source/components/stylesheet/popper.mjs +1 -3
  96. package/source/components/stylesheet/property.mjs +2 -4
  97. package/source/components/stylesheet/ripple.mjs +1 -3
  98. package/source/components/stylesheet/skeleton.mjs +1 -3
  99. package/source/components/stylesheet/space.mjs +1 -3
  100. package/source/components/stylesheet/spinner.mjs +1 -3
  101. package/source/components/stylesheet/table.mjs +1 -3
  102. package/source/components/stylesheet/theme.mjs +1 -3
  103. package/source/components/stylesheet/typography.mjs +13 -6
  104. package/source/components/tree-menu/dragable-tree-menu.mjs +693 -0
  105. package/source/components/tree-menu/style/tree-menu.pcss +69 -42
  106. package/source/components/tree-menu/stylesheet/tree-menu.mjs +2 -4
  107. package/source/components/tree-menu/tree-menu.mjs +260 -331
  108. package/source/data/datasource/server/restapi.mjs +194 -191
  109. package/source/data/datasource/server.mjs +107 -105
  110. package/source/data/diff.mjs +1 -1
  111. package/source/dom/constants.mjs +18 -0
  112. package/source/dom/customelement.mjs +2 -6
  113. package/source/dom/slotted.mjs +6 -1
  114. package/source/dom/updater.mjs +2 -0
  115. package/test/cases/components/host/details.mjs +1 -1
  116. package/test/cases/components/host/host.mjs +1 -1
  117. package/test/cases/components/host/overlay.mjs +1 -1
  118. package/test/cases/dom/customcontrol.mjs +1 -1
  119. package/test/cases/dom/customelement.mjs +2 -2
@@ -13,10 +13,9 @@
13
13
  */
14
14
 
15
15
  import { buildTree } from "../../data/buildtree.mjs";
16
- import { Datasource } from "../../data/datasource.mjs";
16
+ import { Datasource } from "../datatable/datasource.mjs";
17
17
  import { addAttributeToken } from "../../dom/attributes.mjs";
18
18
  import {
19
- ATTRIBUTE_DISABLED,
20
19
  ATTRIBUTE_ERRORMESSAGE,
21
20
  ATTRIBUTE_ROLE,
22
21
  ATTRIBUTE_UPDATER_INSERT_REFERENCE,
@@ -24,17 +23,22 @@ import {
24
23
  import {
25
24
  assembleMethodSymbol,
26
25
  CustomElement,
26
+ getSlottedElements,
27
27
  initMethodSymbol,
28
28
  registerCustomElement,
29
29
  } from "../../dom/customelement.mjs";
30
30
  import { findTargetElementFromEvent } from "../../dom/events.mjs";
31
+ import { findElementWithSelectorUpwards } from "../../dom/util.mjs";
31
32
  import { Formatter } from "../../text/formatter.mjs";
32
- import { isObject } from "../../types/is.mjs";
33
+ import { isFunction, isString } from "../../types/is.mjs";
33
34
  import { Node } from "../../types/node.mjs";
34
35
  import { NodeRecursiveIterator } from "../../types/noderecursiveiterator.mjs";
35
36
  import { Observer } from "../../types/observer.mjs";
36
- import { ProxyObserver } from "../../types/proxyobserver.mjs";
37
37
  import { validateInstance } from "../../types/validate.mjs";
38
+ import {
39
+ datasourceLinkedElementSymbol,
40
+ handleDataSourceChanges,
41
+ } from "../datatable/util.mjs";
38
42
  import { ATTRIBUTE_INTEND } from "./../constants.mjs";
39
43
  import { CommonStyleSheet } from "../stylesheet/common.mjs";
40
44
  import { TreeMenuStyleSheet } from "./stylesheet/tree-menu.mjs";
@@ -51,48 +55,19 @@ const internalNodesSymbol = Symbol("internalNodes");
51
55
  * @private
52
56
  * @type {symbol}
53
57
  */
54
- const controlElementSymbol = Symbol("controlElement");
55
-
56
- /**
57
- * @private
58
- * @type {symbol}
59
- */
60
- const openEntryEventHandlerSymbol = Symbol("openEntryEventHandler");
61
-
62
- /**
63
- * @private
64
- * @type {symbol}
65
- */
66
- const dragstartEventHandlerSymbol = Symbol("dragstartEventHandler");
67
- /**
68
- * @private
69
- * @type {symbol}
70
- */
71
- const dragenterEventHandlerSymbol = Symbol("dragenterEventHandler");
72
-
73
- /**
74
- * @private
75
- * @type {symbol}
76
- */
77
- const dragleaveEventHandlerSymbol = Symbol("dragleaveEventHandler");
78
-
79
- /**
80
- * @private
81
- * @type {symbol}
82
- */
83
- const dragEventHandlerSymbol = Symbol("dragEventHandler");
58
+ const preventChangeSymbol = Symbol("preventChangeCounter");
84
59
 
85
60
  /**
86
61
  * @private
87
62
  * @type {symbol}
88
63
  */
89
- const dragoverEventHandlerSymbol = Symbol("dragoverEventHandler");
64
+ const controlElementSymbol = Symbol("controlElement");
90
65
 
91
66
  /**
92
67
  * @private
93
68
  * @type {symbol}
94
69
  */
95
- const dropEventHandlerSymbol = Symbol("dropEventHandlerSymbol");
70
+ const openEntryEventHandlerSymbol = Symbol("openEntryEventHandler");
96
71
 
97
72
  /**
98
73
  * TreeMenu
@@ -121,11 +96,15 @@ const dropEventHandlerSymbol = Symbol("dropEventHandlerSymbol");
121
96
  * @enduml
122
97
  * @since 1.0.0
123
98
  * @copyright schukai GmbH
124
- * @memberOf Monster.Components.TreeMenu
125
99
  * @summary A TreeMenu control
126
100
  * @fires Monster.Components.TreeMenu.event:monster-fetched
127
101
  */
128
102
  class TreeMenu extends CustomElement {
103
+ constructor() {
104
+ super();
105
+ this[preventChangeSymbol] = false;
106
+ }
107
+
129
108
  /**
130
109
  * This method is called internal and should not be called directly.
131
110
  *
@@ -143,7 +122,6 @@ class TreeMenu extends CustomElement {
143
122
  * shadowMode: 'open',
144
123
  * })),'application/json',true).toString()
145
124
  * ```
146
- * @property {Object} toggleEventType=click,touch List of event types to be observed for opening the dropdown
147
125
  * @property {Object} templates Template definitions
148
126
  * @property {string} templates.main Main template
149
127
  * @property {Datasource} datasource data source
@@ -153,44 +131,46 @@ class TreeMenu extends CustomElement {
153
131
  * @property {String} mapping.keyTemplate="" template with the key placeholders in the form ${name}, where name is the key
154
132
  * @property {String} mapping.rootReferences=['0', undefined, null]
155
133
  * @property {String} mapping.idTemplate=id
156
- * @property {String} mapping.parentTemplate=parent
134
+ * @property {String} mapping.parentKey=parent
157
135
  * @property {String} mapping.selection
158
136
  */
159
137
  get defaults() {
160
- return Object.assign(
161
- {},
162
- super.defaults,
163
- {
164
- toggleEventType: ["click", "touch"],
165
- mapping: {
166
- rootReferences: ["0", undefined, null],
167
- idTemplate: "id",
168
- parentTemplate: "parent",
169
- selector: "*",
170
- labelTemplate: "",
171
- valueTemplate: "",
172
- filter: undefined,
173
- },
174
- templates: {
175
- main: getTemplate(),
138
+ return Object.assign({}, super.defaults, {
139
+ classes: {
140
+ control: "monster-theme-primary-1",
141
+ label: "monster-theme-primary-1",
142
+ },
143
+
144
+ mapping: {
145
+ rootReferences: ["0", undefined, null],
146
+ idTemplate: "id",
147
+ parentKey: "parent",
148
+ selector: "*",
149
+ labelTemplate: "",
150
+ valueTemplate: "",
151
+ iconTemplate: "",
152
+ filter: undefined,
153
+ },
154
+
155
+ templates: {
156
+ main: getTemplate(),
157
+ },
158
+
159
+ datasource: {
160
+ selector: null,
161
+ },
162
+
163
+ actions: {
164
+ open: null,
165
+ close: null,
166
+ select: (entry) => {
167
+ throw new Error("no action defined for select");
176
168
  },
177
- datasource: undefined,
178
- entries: [],
179
169
  },
180
- initOptionsFromArguments.call(this),
181
- );
182
- }
183
170
 
184
- /**
185
- * This method determines which attributes are to be monitored by `attributeChangedCallback()`.
186
- *
187
- * @return {string[]}
188
- * @since 1.15.0
189
- */
190
- static get observedAttributes() {
191
- const list = super.observedAttributes;
192
- //list.push(ATTRIBUTE_FORM_URL);
193
- return list;
171
+ data: [],
172
+ entries: [],
173
+ });
194
174
  }
195
175
 
196
176
  /**
@@ -201,18 +181,17 @@ class TreeMenu extends CustomElement {
201
181
  }
202
182
 
203
183
  /**
204
- *
205
- * @return {Monster.Components.TreeMenu.Form}
184
+ * @return {void}
206
185
  */
207
186
  [assembleMethodSymbol]() {
208
187
  super[assembleMethodSymbol]();
209
188
 
210
189
  initControlReferences.call(this);
211
190
  initEventHandler.call(this);
212
- importEntriesFromDatasource.call(this);
213
191
  initObserver.call(this);
214
-
215
- return this;
192
+ setTimeout(() => {
193
+ copyIconMap.call(this);
194
+ }, 0);
216
195
  }
217
196
 
218
197
  /**
@@ -232,13 +211,113 @@ class TreeMenu extends CustomElement {
232
211
  static getTag() {
233
212
  return "monster-tree-menu";
234
213
  }
214
+
215
+ /**
216
+ * @param {string} value
217
+ * @param value
218
+ */
219
+ selectEntry(value) {
220
+ this.shadowRoot
221
+ .querySelectorAll("[data-monster-role=entry]")
222
+ .forEach((entry) => {
223
+ entry.classList.remove("selected");
224
+ });
225
+
226
+ value = String(value);
227
+
228
+ const entries = this.getOption("entries");
229
+ const index = entries.findIndex((entry) => entry.value === value);
230
+
231
+ if (index === -1) {
232
+ return;
233
+ }
234
+
235
+ const currentNode = this.shadowRoot.querySelector(
236
+ "[data-monster-insert-reference=entries-" + index + "]",
237
+ );
238
+
239
+ console.log(currentNode);
240
+
241
+ currentNode.click();
242
+
243
+ let intend = parseInt(currentNode.getAttribute(ATTRIBUTE_INTEND));
244
+
245
+ if (intend > 0) {
246
+ let ref = currentNode.previousElementSibling;
247
+ while (ref && ref.hasAttribute(ATTRIBUTE_INTEND)) {
248
+ const i = parseInt(ref.getAttribute(ATTRIBUTE_INTEND));
249
+
250
+ if (isNaN(i)) {
251
+ break;
252
+ }
253
+
254
+ if (i < intend) {
255
+ if (ref.getAttribute("data-monster-state") !== "open") {
256
+ ref.click();
257
+ }
258
+
259
+ if (i === 0) {
260
+ break;
261
+ }
262
+ intend = i;
263
+ }
264
+ ref = ref.previousElementSibling;
265
+ }
266
+ }
267
+ }
268
+ }
269
+
270
+ /**
271
+ * @private
272
+ */
273
+ function copyIconMap() {
274
+ const nodes = getSlottedElements.call(this, "svg", null);
275
+ if (nodes.size > 0) {
276
+ for (const node of nodes) {
277
+ this.shadowRoot.appendChild(node);
278
+ }
279
+ }
235
280
  }
236
281
 
237
282
  /**
238
283
  * @private
239
284
  */
240
285
  function initEventHandler() {
241
- switchToConfig.call(this);
286
+ const selector = this.getOption("datasource.selector");
287
+
288
+ if (isString(selector)) {
289
+ const element = findElementWithSelectorUpwards(this, selector);
290
+ if (element === null) {
291
+ throw new Error("the selector must match exactly one element");
292
+ }
293
+
294
+ if (!(element instanceof HTMLElement)) {
295
+ throw new TypeError("the element must be an HTMLElement");
296
+ }
297
+
298
+ customElements.whenDefined(element.tagName.toLocaleLowerCase()).then(() => {
299
+ if (!(element instanceof Datasource)) {
300
+ throw new TypeError("the element must be a datasource");
301
+ }
302
+
303
+ this[datasourceLinkedElementSymbol] = element;
304
+
305
+ handleDataSourceChanges.call(this);
306
+ element.datasource.attachObserver(
307
+ new Observer(handleDataSourceChanges.bind(this)),
308
+ );
309
+
310
+ this.attachObserver(
311
+ new Observer(() => {
312
+ if (this[preventChangeSymbol] === true) {
313
+ return;
314
+ }
315
+ this[preventChangeSymbol] = true;
316
+ importEntries.call(this);
317
+ }),
318
+ );
319
+ });
320
+ }
242
321
 
243
322
  this[openEntryEventHandlerSymbol] = (event) => {
244
323
  const container = findTargetElementFromEvent(
@@ -246,26 +325,70 @@ function initEventHandler() {
246
325
  ATTRIBUTE_ROLE,
247
326
  "entry",
248
327
  );
328
+
249
329
  if (!(container instanceof HTMLElement)) {
250
330
  return;
251
331
  }
252
332
 
253
- //let container = findClosestByAttribute(element, ATTRIBUTE_ROLE, 'option');
254
333
  const index = container
255
334
  .getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
256
335
  .split("-")
257
336
  .pop();
258
337
 
338
+ const currentEntry = this.getOption("entries." + index);
339
+
340
+ if (currentEntry["has-children"] === false) {
341
+ const doAction = this.getOption("actions.select");
342
+
343
+ this.shadowRoot
344
+ .querySelectorAll("[data-monster-role=entry].selected")
345
+ .forEach((entry) => {
346
+ entry.classList.remove("selected");
347
+ });
348
+
349
+ let intend = currentEntry.intend;
350
+ if (intend > 0) {
351
+ let ref = container.previousElementSibling;
352
+ while (ref && ref.hasAttribute(ATTRIBUTE_INTEND)) {
353
+ const i = parseInt(ref.getAttribute(ATTRIBUTE_INTEND));
354
+
355
+ if (isNaN(i)) {
356
+ break;
357
+ }
358
+
359
+ if (i < intend) {
360
+ ref.classList.add("selected");
361
+ if (i === 0) {
362
+ break;
363
+ }
364
+ intend = i;
365
+ }
366
+ ref = ref.previousElementSibling;
367
+ }
368
+ }
369
+
370
+ container.classList.add("selected");
371
+
372
+ if (isFunction(doAction)) {
373
+ doAction.call(this, currentEntry, index);
374
+ }
375
+ return;
376
+ }
377
+
259
378
  const currentState = this.getOption("entries." + index + ".state");
260
379
 
261
380
  const newState = currentState === "close" ? "open" : "close";
262
- this.setOption("entries." + index + ".state", newState);
263
381
 
382
+ const doAction = this.getOption("actions." + newState);
383
+ if (isFunction(doAction)) {
384
+ doAction.call(this, this.getOption("entries." + index), index);
385
+ }
386
+
387
+ this.setOption("entries." + index + ".state", newState);
264
388
  const newVisibility = newState === "open" ? "visible" : "hidden";
265
389
 
266
390
  if (container.hasAttribute(ATTRIBUTE_INTEND)) {
267
391
  const intend = container.getAttribute(ATTRIBUTE_INTEND);
268
-
269
392
  let ref = container.nextElementSibling;
270
393
  const childIntend = parseInt(intend) + 1;
271
394
 
@@ -277,15 +400,22 @@ function initEventHandler() {
277
400
  return a >= b;
278
401
  };
279
402
 
280
- while (
281
- ref &&
282
- ref.hasAttribute(ATTRIBUTE_INTEND) &&
283
- cmp(parseInt(ref.getAttribute(ATTRIBUTE_INTEND)), childIntend)
284
- ) {
403
+ while (ref && ref.hasAttribute(ATTRIBUTE_INTEND)) {
404
+ const refIntend = ref.getAttribute(ATTRIBUTE_INTEND);
405
+
406
+ if (!cmp(parseInt(refIntend), childIntend)) {
407
+ if (refIntend === intend) {
408
+ break;
409
+ }
410
+ ref = ref.nextElementSibling;
411
+ continue;
412
+ }
413
+
285
414
  const refIndex = ref
286
415
  .getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
287
416
  .split("-")
288
417
  .pop();
418
+
289
419
  this.setOption("entries." + refIndex + ".visibility", newVisibility);
290
420
 
291
421
  if (newState === "close") {
@@ -302,28 +432,12 @@ function initEventHandler() {
302
432
  this.shadowRoot.addEventListener(type, this[openEntryEventHandlerSymbol]);
303
433
  }
304
434
 
305
- // for (const [, type] of Object.entries(types)) {
306
- //
307
- // self[controlElementSymbol].addEventListener(type, function (event) {
308
- //
309
- // const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, 'entry');
310
- // if (!(element instanceof HTMLElement)) {
311
- // return;
312
- // }
313
- //
314
- // toggle.call(self);
315
- //
316
- //
317
- // })
318
- //
319
- // }
320
-
321
435
  return this;
322
436
  }
323
437
 
324
438
  /**
325
439
  * @private
326
- * @this Form
440
+ * @this {TreeMenu}
327
441
  */
328
442
  function initObserver() {}
329
443
 
@@ -331,12 +445,12 @@ function initObserver() {}
331
445
  * Import Menu Entries from dataset
332
446
  *
333
447
  * @since 1.0.0
334
- * @param {array|object|Map|Set} data
335
448
  * @return {TreeMenu}
336
449
  * @throws {Error} map is not iterable
337
450
  * @private
338
451
  */
339
- function importEntries(data) {
452
+ function importEntries() {
453
+ const data = this.getOption("data");
340
454
  this[internalNodesSymbol] = new Map();
341
455
 
342
456
  const mappingOptions = this.getOption("mapping", {});
@@ -344,15 +458,20 @@ function importEntries(data) {
344
458
  const filter = mappingOptions?.["filter"];
345
459
  const rootReferences = mappingOptions?.["rootReferences"];
346
460
 
347
- const id = this.getOption("mapping.idTemplate", "id");
348
- const parentID = this.getOption("mapping.parentTemplate", "parent");
461
+ const id = this.getOption("mapping.idTemplate");
462
+ const parentKey = this.getOption("mapping.parentKey");
349
463
 
350
464
  const selector = mappingOptions?.["selector"];
351
465
 
352
- const nodes = buildTree(data, selector, id, parentID, {
353
- filter,
354
- rootReferences,
355
- });
466
+ let nodes;
467
+ try {
468
+ nodes = buildTree(data, selector, id, parentKey, {
469
+ filter,
470
+ rootReferences,
471
+ });
472
+ } catch (error) {
473
+ addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, String(error));
474
+ }
356
475
 
357
476
  const options = [];
358
477
  for (const node of nodes) {
@@ -360,8 +479,9 @@ function importEntries(data) {
360
479
  for (const n of iterator) {
361
480
  const formattedValues = formatKeyLabel.call(this, n);
362
481
 
363
- const label = formattedValues.label;
364
- const value = formattedValues.value;
482
+ const label = formattedValues?.label;
483
+ const value = formattedValues?.value;
484
+ const icon = formattedValues?.icon;
365
485
  const intend = n.level;
366
486
 
367
487
  const visibility = intend > 0 ? "hidden" : "visible";
@@ -372,6 +492,7 @@ function importEntries(data) {
372
492
  options.push({
373
493
  value,
374
494
  label,
495
+ icon,
375
496
  intend,
376
497
  state,
377
498
  visibility,
@@ -381,74 +502,43 @@ function importEntries(data) {
381
502
  }
382
503
 
383
504
  this.setOption("entries", options);
384
- return this;
385
- }
386
-
387
- /**
388
- * @private
389
- */
390
- function importEntriesFromDatasource() {
391
- const self = this;
392
- self.setAttribute(ATTRIBUTE_DISABLED, ATTRIBUTE_DISABLED);
393
-
394
- const datasource = self.getOption("datasource");
395
- if (!(datasource instanceof Datasource)) {
396
- addAttributeToken(
397
- self,
398
- ATTRIBUTE_ERRORMESSAGE,
399
- "datasource is not defined",
400
- );
401
- return;
402
- }
403
505
 
404
- datasource.attachObserver(
405
- new Observer(function () {
406
- if (isObject(this) && this instanceof ProxyObserver) {
407
- importEntries.call(self, datasource.get());
408
- }
409
- }),
410
- );
411
-
412
- datasource
413
- .read()
414
- .then(() => {
415
- new Processing(() => {
416
- self.removeAttribute(ATTRIBUTE_DISABLED);
417
- }).run();
418
- })
419
- .catch((e) => {
420
- addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, e.toString());
421
- });
422
-
423
- return self;
506
+ return this;
424
507
  }
425
508
 
426
509
  /**
427
510
  *
428
511
  * @param {Node} node
429
512
  * @return {array<label, value>}
430
- * @memberOf Monster.Components.TreeMenu
431
513
  * @private
432
514
  */
433
515
  function formatKeyLabel(node) {
434
516
  validateInstance(node, Node);
435
517
 
436
518
  const label = new Formatter(node.value).format(
437
- this.getOption("mapping.labelTemplate", ""),
519
+ this.getOption("mapping.labelTemplate"),
438
520
  );
521
+
439
522
  const value = new Formatter(node.value).format(
440
- this.getOption("mapping.valueTemplate", ""),
523
+ this.getOption("mapping.valueTemplate"),
524
+ );
525
+
526
+ const iconID = new Formatter(node.value).format(
527
+ this.getOption("mapping.iconTemplate"),
441
528
  );
442
529
 
530
+ const icon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><use xlink:href="#${iconID}"></use></svg>`;
531
+
443
532
  return {
444
533
  value,
445
534
  label,
535
+ icon,
446
536
  };
447
537
  }
448
538
 
449
539
  /**
450
540
  * @private
451
- * @return {Monster.Components.TreeMenu.Form}
541
+ * @return {TreeMenu}
452
542
  */
453
543
  function initControlReferences() {
454
544
  if (!this.shadowRoot) {
@@ -458,173 +548,10 @@ function initControlReferences() {
458
548
  this[controlElementSymbol] = this.shadowRoot.querySelector(
459
549
  "[data-monster-role=control]",
460
550
  );
461
- return this;
462
- }
463
-
464
- /**
465
- *
466
- * ```
467
- * <monster-tree-menu data-monster-url="https://example.com/"></monster-tree-menu>
468
- * ```
469
-
470
- * @private
471
- * @return {object}
472
- */
473
- function initOptionsFromArguments() {
474
- const options = {};
475
-
476
- // let url = self.getAttribute(ATTRIBUTE_FORM_URL);
477
- //
478
- // if (isString(url)) {
479
- // options['url'] = new URL(url, document.location).toString()
480
- // }
481
-
482
- return options;
483
- }
484
-
485
- function switchToConfig() {
486
- if (!this.shadowRoot) {
487
- throw new Error("no shadow-root is defined");
488
- }
489
-
490
- this[dragoverEventHandlerSymbol] = (event) => {
491
- const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "entry");
492
- event.preventDefault();
493
- if (!(element instanceof HTMLElement)) {
494
- return;
495
- }
496
-
497
- const dropzone = document.createElement("div");
498
- dropzone.classList.add("dropzone");
499
-
500
- element.prepend(dropzone);
501
-
502
- console.log("over", element.outerHTML, event);
503
-
504
- event.dataTransfer.dropEffect = "move";
505
- };
506
551
 
507
- this[dragenterEventHandlerSymbol] = (event) => {
508
- const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "entry");
509
- console.log("enter", element.outerHTML, event);
510
-
511
- event.dataTransfer.dropEffect = "move";
512
- event.preventDefault();
513
- };
514
-
515
- this[dragleaveEventHandlerSymbol] = (event) => {
516
- const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "entry");
517
-
518
- event.preventDefault();
519
- if (!(element instanceof HTMLElement)) {
520
- return;
521
- }
522
-
523
- console.log("leave", element.outerHTML, event);
524
-
525
- event.dataTransfer.dropEffect = "move";
526
- event.preventDefault();
527
- };
528
-
529
- this[dragEventHandlerSymbol] = (event) => {
530
- event.preventDefault();
531
- };
532
-
533
- this[dropEventHandlerSymbol] = (event) => {
534
- const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "entry");
535
- console.log("drop", element.outerHTML, event);
536
- event.preventDefault();
537
- };
538
-
539
- this[dragstartEventHandlerSymbol] = (event) => {
540
- const element = findTargetElementFromEvent(event, ATTRIBUTE_ROLE, "entry");
541
- if (!(element instanceof HTMLElement)) {
542
- return;
543
- }
544
-
545
- //let container = findClosestByAttribute(element, ATTRIBUTE_ROLE, 'option');
546
- const index = element
547
- .getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
548
- .split("-")
549
- .pop();
550
-
551
- const currentState = this.getOption("entries." + index + ".state");
552
- event.dataTransfer.setData("text/plain", "22");
553
- event.dataTransfer.setData("text/html", "22");
554
- event.dataTransfer.effectAllowed = "move";
555
- };
556
-
557
- this[controlElementSymbol].addEventListener(
558
- "dragstart",
559
- this[dragstartEventHandlerSymbol],
560
- );
561
- this[controlElementSymbol].addEventListener(
562
- "dragenter",
563
- this[dragenterEventHandlerSymbol],
564
- );
565
- this[controlElementSymbol].addEventListener(
566
- "dragleave",
567
- this[dragleaveEventHandlerSymbol],
568
- );
569
- this[controlElementSymbol].addEventListener(
570
- "dragover",
571
- this[dragoverEventHandlerSymbol],
572
- );
573
- this[controlElementSymbol].addEventListener(
574
- "drop",
575
- this[dropEventHandlerSymbol],
576
- );
552
+ return this;
577
553
  }
578
554
 
579
- // /**
580
- // * @private
581
- // * @throws {Error} missing default slot
582
- // * @throws {Error} no shadow-root is defined
583
- // * @throws {Error} missing url
584
- // * @throws {Error} we won't be able to read the data
585
- // * @throws {Error} request failed
586
- // * @throws {Error} not found
587
- // * @throws {Error} undefined status or type
588
- // * @fires Monster.Components.TreeMenu.event:monster-fetched
589
- // */
590
- // function initIntersectionObserver() {
591
- // const self = this;
592
- //
593
- // if (self[intersectionObserverWasInitialized] === true) {
594
- // return
595
- // }
596
- //
597
- // self[intersectionObserverWasInitialized] = true;
598
- //
599
- // let options = {
600
- // threshold: [0.5]
601
- // }
602
- //
603
- // const callback = (entries, observer) => {
604
- //
605
- // for (const [, entry] of entries.entries()) {
606
- // if (entry.isIntersecting === true) {
607
- // if (!self.hasAttribute(ATTRIBUTE_FORM_RELOAD) || self.getAttribute(ATTRIBUTE_FORM_RELOAD).toLowerCase() === 'onshow') {
608
- // observer.disconnect();
609
- // }
610
- //
611
- // try {
612
- // loadContent.call(self);
613
- // } catch (e) {
614
- // self.setAttribute(ATTRIBUTE_ERRORMESSAGE, e.toString());
615
- // }
616
- //
617
- //
618
- // }
619
- // }
620
- // }
621
- //
622
- // const observer = new IntersectionObserver(callback, options);
623
- // observer.observe(self);
624
- //
625
- //
626
- // }
627
-
628
555
  /**
629
556
  * @private
630
557
  * @return {string}
@@ -632,29 +559,31 @@ function switchToConfig() {
632
559
  function getTemplate() {
633
560
  // language=HTML
634
561
  return `
562
+ <slot></slot>
563
+
635
564
  <template id="entries">
636
565
  <div data-monster-role="entry"
637
- draggable="true"
638
566
  data-monster-attributes="
639
567
  data-monster-intend path:entries.intend,
640
568
  data-monster-state path:entries.state,
641
569
  data-monster-visibility path:entries.visibility,
642
570
  data-monster-filtered path:entries.filtered,
643
571
  data-monster-has-children path:entries.has-children">
644
-
645
- <button data-monster-role="button"
646
- data-monster-attributes="
647
- type path:type,
648
- role path:role,
649
- value path:entries.value,
650
- name path:name,
651
- part path:type | prefix:option- | suffix: form" tabindex="-1">
652
- <span data-monster-role="folder-handler"></span>
653
- <span data-monster-replace="path:entries | index:label" part="entry-label"></span>
654
- </button>
572
+ <div data-monster-role="button"
573
+ data-monster-attributes="
574
+ value path:entries.value | tostring
575
+ " tabindex="0">
576
+ <div data-monster-role="status-badges"></div>
577
+ <div data-monster-role="icon" data-monster-replace="path:entries.icon">
578
+
579
+ </div>
580
+ <div data-monster-replace="path:entries.label"
581
+ part="entry-label"
582
+ data-monster-attributes="class static:id"></div>
583
+ </div>
655
584
  </template>
656
585
 
657
- <div data-monster-role="control" part="control">
586
+ <div data-monster-role="control" part="control" data-monster-attributes="class path:classes.control">
658
587
  <div part="entries" data-monster-role="entries"
659
588
  data-monster-insert="entries path:entries"
660
589
  tabindex="-1"></div>