@schukai/monster 3.74.0 → 3.76.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 (61) hide show
  1. package/CHANGELOG.md +35 -6
  2. package/package.json +1 -1
  3. package/source/components/datatable/datasource/rest.mjs +0 -1
  4. package/source/components/form/api-button.mjs +0 -1
  5. package/source/components/form/context-error.mjs +0 -1
  6. package/source/components/form/context-help.mjs +0 -1
  7. package/source/components/form/message-state-button.mjs +0 -1
  8. package/source/components/form/popper-button.mjs +0 -1
  9. package/source/components/form/select.mjs +16 -5
  10. package/source/components/form/toggle-switch.mjs +0 -3
  11. package/source/components/form/tree-select.mjs +0 -1
  12. package/source/components/layout/collapse.mjs +361 -395
  13. package/source/components/layout/details.mjs +10 -40
  14. package/source/components/layout/iframe.mjs +358 -0
  15. package/source/components/layout/panel.mjs +10 -25
  16. package/source/components/layout/slider.mjs +420 -439
  17. package/source/components/layout/split-panel.mjs +7 -39
  18. package/source/components/layout/style/iframe.pcss +39 -0
  19. package/source/components/layout/style/panel.pcss +10 -3
  20. package/source/components/layout/style/split-panel.pcss +2 -0
  21. package/source/components/layout/stylesheet/iframe.mjs +38 -0
  22. package/source/components/layout/stylesheet/panel.mjs +1 -1
  23. package/source/components/layout/stylesheet/slider.mjs +13 -6
  24. package/source/components/layout/tabs.mjs +6 -35
  25. package/source/components/layout/width-toggle.mjs +10 -31
  26. package/source/components/navigation/table-of-content.mjs +0 -1
  27. package/source/components/tree-menu/dragable-tree-menu.mjs +4 -4
  28. package/source/components/tree-menu/tree-menu.mjs +16 -12
  29. package/source/data/datasource/server/restapi.mjs +1 -1
  30. package/source/dom/updater.mjs +767 -771
  31. package/source/math/random.mjs +2 -3
  32. package/source/monster.mjs +12 -3
  33. package/source/types/version.mjs +1 -1
  34. package/test/cases/components/form/button.mjs +2 -1
  35. package/test/cases/components/form/confirm-button.mjs +1 -1
  36. package/test/cases/components/form/form.mjs +1 -1
  37. package/test/cases/components/form/reload.mjs +1 -1
  38. package/test/cases/components/form/select.mjs +1 -1
  39. package/test/cases/components/form/state-button.mjs +1 -1
  40. package/test/cases/components/form/template.mjs +1 -1
  41. package/test/cases/components/form/toggle-switch.mjs +1 -1
  42. package/test/cases/components/form/tree-select.mjs +1 -1
  43. package/test/cases/components/host/details.mjs +1 -1
  44. package/test/cases/components/host/host.mjs +1 -1
  45. package/test/cases/components/host/overlay.mjs +1 -1
  46. package/test/cases/components/layout/panel.mjs +1 -1
  47. package/test/cases/components/layout/slit-panel.mjs +1 -1
  48. package/test/cases/components/layout/tabs.mjs +1 -1
  49. package/test/cases/components/notify/message.mjs +1 -1
  50. package/test/cases/components/notify/notify.mjs +1 -1
  51. package/test/cases/dom/customcontrol.mjs +1 -1
  52. package/test/cases/dom/customelement-initfromscripthost.mjs +1 -1
  53. package/test/cases/dom/customelement.mjs +1 -1
  54. package/test/cases/dom/resource/data.mjs +1 -1
  55. package/test/cases/dom/resource/link/stylesheet.mjs +1 -1
  56. package/test/cases/dom/resource/link.mjs +1 -1
  57. package/test/cases/dom/resource/script.mjs +1 -1
  58. package/test/cases/dom/updater.mjs +1 -1
  59. package/test/cases/monster.mjs +1 -1
  60. package/test/web/test.html +2 -2
  61. package/test/web/tests.js +6 -15
@@ -38,49 +38,15 @@ const buttonElementSymbol = Symbol("buttonElement");
38
38
  const buttonEventHandlerSymbol = Symbol("buttonEventHandler");
39
39
 
40
40
  /**
41
- * The Details component is used to show a details.
41
+ * A Details component
42
42
  *
43
- * <img src="./images/details.png">
43
+ * @fragments /fragments/components/layout/details/
44
44
  *
45
- * Dependencies: the system uses functions of the [monsterjs](https://monsterjs.org/) library
46
- *
47
- * You can create this control either by specifying the HTML tag <monster-details />` directly in the HTML or using
48
- * Javascript via the `document.createElement('monster-details');` method.
49
- *
50
- * ```html
51
- * <monster-details></monster-details>
52
- * ```
53
- *
54
- * Or you can create this CustomControl directly in Javascript:
55
- *
56
- * ```js
57
- * import '@schukai/component-state/source/details.mjs';
58
- * document.createElement('monster-details');
59
- * ```
60
- *
61
- * The Body should have a class "hidden" to ensure that the styles are applied correctly.
62
- *
63
- * ```css
64
- * body.hidden {
65
- * visibility: hidden;
66
- * }
67
- * ```
68
- *
69
- * @startuml details.png
70
- * skinparam monochrome true
71
- * skinparam shadowing false
72
- * HTMLElement <|-- CustomElement
73
- * CustomElement <|-- Collapse
74
- * Collapse <|-- Details
75
- * @enduml
45
+ * @example /examples/components/layout/details-simple
76
46
  *
47
+ * @since 3.74.0
77
48
  * @copyright schukai GmbH
78
- * @memberOf Monster.Components.Layout
79
- * @summary A simple details component
80
- * @fires Monster.Components.Layout.Details.event:monster-details-before-open
81
- * @fires Monster.Components.Layout.Details.event:monster-details-open
82
- * @fires Monster.Components.Layout.Details.event:monster-details-before-close
83
- * @fires Monster.Components.Layout.Details.event:monster-details-closed
49
+ * @summary A simple but cool Details component
84
50
  */
85
51
  class Details extends Collapse {
86
52
  /**
@@ -215,13 +181,17 @@ function initButtonLabel() {
215
181
  if (this.hasAttribute(ATTRIBUTE_BUTTON_LABEL)) {
216
182
  label = this.getAttribute(ATTRIBUTE_BUTTON_LABEL);
217
183
  } else {
218
- label = this.innerText;
184
+ label = this.getOption("labels.button", "Details");
219
185
  }
220
186
 
221
187
  if (!isString(label)) {
222
188
  label = "";
223
189
  }
224
190
 
191
+ if (label==="") {
192
+ label = this.innerText;
193
+ }
194
+
225
195
  label = label.trim();
226
196
 
227
197
  if (label === "") {
@@ -0,0 +1,358 @@
1
+ /**
2
+ * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
3
+ * Node module: @schukai/monster
4
+ *
5
+ * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
6
+ * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
7
+ *
8
+ * For those who do not wish to adhere to the AGPLv3, a commercial license is available.
9
+ * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
10
+ * For more information about purchasing a commercial license, please contact schukai GmbH.
11
+ */
12
+
13
+ import { instanceSymbol } from "../../constants.mjs";
14
+ import { addAttributeToken } from "../../dom/attributes.mjs";
15
+ import {
16
+ ATTRIBUTE_ERRORMESSAGE,
17
+ ATTRIBUTE_ROLE,
18
+ } from "../../dom/constants.mjs";
19
+ import { CustomControl } from "../../dom/customcontrol.mjs";
20
+ import { CustomElement } from "../../dom/customelement.mjs";
21
+ import {
22
+ assembleMethodSymbol,
23
+ registerCustomElement,
24
+ } from "../../dom/customelement.mjs";
25
+ import { findTargetElementFromEvent } from "../../dom/events.mjs";
26
+ import { isFunction } from "../../types/is.mjs";
27
+ import { DeadMansSwitch } from "../../util/deadmansswitch.mjs";
28
+ import { IframeStyleSheet } from "./stylesheet/iframe.mjs";
29
+ import { fireCustomEvent } from "../../dom/events.mjs";
30
+
31
+ export { Iframe };
32
+
33
+ /**
34
+ * @private
35
+ * @type {symbol}
36
+ */
37
+ export const iframeElementSymbol = Symbol("iframeElement");
38
+
39
+ /**
40
+ * @private
41
+ * @type {symbol}
42
+ */
43
+ const PanelElementSymbol = Symbol("PanelElement");
44
+
45
+ /**
46
+ * local symbol
47
+ * @private
48
+ * @type {symbol}
49
+ */
50
+ const resizeObserverSymbol = Symbol("resizeObserver");
51
+
52
+ /**
53
+ * @private
54
+ * @type {symbol}
55
+ */
56
+ const timerCallbackSymbol = Symbol("timerCallback");
57
+
58
+ /**
59
+ * A Iframe Control
60
+ *
61
+ * @fragments /fragments/components/layout/iframe/
62
+ *
63
+ * @example /examples/components/layout/iframe-simple
64
+ *
65
+ * @since 3.76.0
66
+ * @copyright schukai GmbH
67
+ * @summary A cool and fancy Iframe that can make your life easier and also looks good.
68
+ */
69
+ class Iframe extends CustomElement {
70
+ /**
71
+ * This method is called by the `instanceof` operator.
72
+ * @returns {symbol}
73
+ */
74
+ static get [instanceSymbol]() {
75
+ return Symbol.for("@schukai/monster/components/layout/iframe@@instance");
76
+ }
77
+
78
+ /**
79
+ *
80
+ * @return {Components.Layout.Iframe
81
+ */
82
+ [assembleMethodSymbol]() {
83
+ super[assembleMethodSymbol]();
84
+ initControlReferences.call(this);
85
+ initEventHandler.call(this);
86
+ calcHeight.call(this);
87
+ return this;
88
+ }
89
+
90
+ /**
91
+ * This method is called by the dom and should not be called directly.
92
+ *
93
+ * @return {void}
94
+ */
95
+ connectedCallback() {
96
+ super.connectedCallback();
97
+ attachResizeObserver.call(this);
98
+
99
+ // disable scrolling in parent node
100
+ if (this.parentNode && this.parentNode instanceof HTMLElement) {
101
+ this.parentNode.style.overflow = "hidden";
102
+ }
103
+ }
104
+
105
+ /**
106
+ * This method is called by the dom and should not be called directly.
107
+ *
108
+ * @return {void}
109
+ */
110
+ disconnectedCallback() {
111
+ super.disconnectedCallback();
112
+ disconnectResizeObserver.call(this);
113
+ }
114
+
115
+ /**
116
+ * To set the options via the HTML Tag the attribute `data-monster-options` must be used.
117
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
118
+ *
119
+ * The individual configuration values can be found in the table.
120
+ *
121
+ * @property {Object} templates Template definitions
122
+ * @property {string} templates.main Main template
123
+ * @property {Object} labels Label definitions
124
+ * @property {Object} actions Callbacks
125
+ * @property {string} actions.click="throw Error" Callback when clicked
126
+ * @property {Object} features Features
127
+ * @property {Object} classes CSS classes
128
+ * @property {boolean} disabled=false Disabled state
129
+ */
130
+ get defaults() {
131
+ return Object.assign({}, super.defaults, {
132
+ templates: {
133
+ main: getTemplate(),
134
+ },
135
+ src: null,
136
+
137
+ /* "allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation"*/
138
+ sandbox: null,
139
+
140
+ labels: {},
141
+ classes: {},
142
+
143
+ name: "",
144
+
145
+ referrerpolicy: "no-referrer",
146
+
147
+ disabled: false,
148
+ features: {
149
+ allowfullscreen: true,
150
+ allowpaymentrequest: true,
151
+ loading: "egager",
152
+ },
153
+ actions: {
154
+ click: () => {
155
+ throw new Error("the click action is not defined");
156
+ },
157
+ },
158
+ });
159
+ }
160
+
161
+ /**
162
+ * @return {string}
163
+ */
164
+ static getTag() {
165
+ return "monster-iframe";
166
+ }
167
+
168
+ /**
169
+ * @return {CSSStyleSheet[]}
170
+ */
171
+ static getCSSStyleSheet() {
172
+ return [IframeStyleSheet];
173
+ }
174
+ }
175
+
176
+ /**
177
+ * @private
178
+ */
179
+ function calcHeight() {
180
+ this.style.boxSizing = "border-box";
181
+
182
+ const height = calculateMaximumHeight.call(this, this.parentNode);
183
+ console.log("height", height);
184
+ if (height < 0 || isNaN(height)) {
185
+ return;
186
+ }
187
+
188
+ this[iframeElementSymbol].style.height = `${height}px`;
189
+ }
190
+
191
+ /**
192
+ * Calculate the maximum height of an element based on the window's inner height
193
+ * @param element
194
+ * @returns {*}
195
+ */
196
+ function calculateMaximumHeight(element) {
197
+ let totalBottomBorder = 0;
198
+ let totalBottomPadding = 0;
199
+ let totalBottomMargin = 0;
200
+ let totalOutlineHeight = 0;
201
+ let totalBoxShadowHeight = 0;
202
+ let currentElement = element;
203
+
204
+ while (currentElement && currentElement !== document.body) {
205
+ const style = window.getComputedStyle(currentElement);
206
+ const boxSizing = style.boxSizing;
207
+
208
+ const elementHeight = currentElement.getBoundingClientRect().height;
209
+
210
+ const borderBottomWidth = parseFloat(style.borderBottomWidth);
211
+ const paddingBottom = parseFloat(style.paddingBottom);
212
+ const marginBottom = parseFloat(style.marginBottom);
213
+
214
+ const outlineHeight = parseFloat(style.outlineWidth);
215
+
216
+ totalBottomBorder += isNaN(borderBottomWidth) ? 0 : borderBottomWidth;
217
+ totalBottomPadding +=
218
+ isNaN(paddingBottom) || boxSizing === "border-box" ? 0 : paddingBottom;
219
+ totalBottomMargin += isNaN(marginBottom) ? 0 : marginBottom;
220
+ totalOutlineHeight += isNaN(outlineHeight) ? 0 : outlineHeight;
221
+
222
+ const boxShadow = style.boxShadow;
223
+ let boxShadowVerticalTotal = 0;
224
+
225
+ if (boxShadow !== "none") {
226
+ const boxShadowValues = boxShadow.split(" ");
227
+ const verticalOffset = parseFloat(boxShadowValues[3]);
228
+ const blurRadius = parseFloat(boxShadowValues[4]);
229
+ const spreadRadius = parseFloat(boxShadowValues[5]);
230
+
231
+ boxShadowVerticalTotal = verticalOffset + blurRadius + spreadRadius;
232
+ }
233
+
234
+ totalBoxShadowHeight += isNaN(boxShadowVerticalTotal)
235
+ ? 0
236
+ : boxShadowVerticalTotal;
237
+
238
+ if (elementHeight > 200) {
239
+ return (
240
+ elementHeight -
241
+ totalBottomBorder -
242
+ totalBottomPadding -
243
+ totalBottomMargin -
244
+ totalOutlineHeight -
245
+ totalBoxShadowHeight
246
+ );
247
+ }
248
+
249
+ currentElement = currentElement.parentNode || currentElement.host;
250
+ }
251
+ }
252
+
253
+ /**
254
+ * @private
255
+ */
256
+ function attachResizeObserver() {
257
+ // against flickering
258
+ this[resizeObserverSymbol] = new ResizeObserver(() => {
259
+ if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
260
+ try {
261
+ this[timerCallbackSymbol].touch();
262
+ return;
263
+ } catch (e) {
264
+ delete this[timerCallbackSymbol];
265
+ }
266
+ }
267
+
268
+ this[timerCallbackSymbol] = new DeadMansSwitch(200, () => {
269
+ calcHeight.call(this);
270
+ });
271
+ });
272
+
273
+ this[resizeObserverSymbol].observe(this.ownerDocument.body);
274
+ this[resizeObserverSymbol].observe(document.scrollingElement);
275
+ }
276
+
277
+ function disconnectResizeObserver() {
278
+ if (this[resizeObserverSymbol] instanceof ResizeObserver) {
279
+ this[resizeObserverSymbol].disconnect();
280
+ }
281
+ }
282
+
283
+ /**
284
+ * @private
285
+ * @return {initEventHandler}
286
+ * @fires monster-iframe-clicked
287
+ */
288
+ function initEventHandler() {
289
+ const self = this;
290
+ const element = this[iframeElementSymbol];
291
+
292
+ const type = "click";
293
+
294
+ element.addEventListener(type, function (event) {
295
+ const callback = self.getOption("actions.click");
296
+
297
+ fireCustomEvent(self, "monster-iframe-clicked", {
298
+ element: self,
299
+ });
300
+
301
+ if (!isFunction(callback)) {
302
+ return;
303
+ }
304
+
305
+ const element = findTargetElementFromEvent(
306
+ event,
307
+ ATTRIBUTE_ROLE,
308
+ "control",
309
+ );
310
+
311
+ if (!(element instanceof Node && self.hasNode(element))) {
312
+ return;
313
+ }
314
+
315
+ callback.call(self, event);
316
+ });
317
+
318
+ return this;
319
+ }
320
+
321
+ /**
322
+ * @private
323
+ * @return {void}
324
+ */
325
+ function initControlReferences() {
326
+ if (!this.shadowRoot) {
327
+ throw new Error("no shadow-root is defined");
328
+ }
329
+
330
+ this[PanelElementSymbol] = this.shadowRoot.querySelector(
331
+ "[data-monster-role=control]",
332
+ );
333
+
334
+ this[iframeElementSymbol] = this.shadowRoot.querySelector(
335
+ `[${ATTRIBUTE_ROLE}="control"] iframe`,
336
+ );
337
+ }
338
+
339
+ /**
340
+ * @private
341
+ * @return {string}
342
+ */
343
+ function getTemplate() {
344
+ // language=HTML
345
+ return `
346
+ <div data-monster-role="control" part="control">
347
+ <iframe data-monster-role="iframe"
348
+ data-monster-attributes="sandbox path:sandbox,
349
+ name path:name,
350
+ referrerpolicy path:referrerpolicy,
351
+ loading path:features.loading,
352
+ allowpaymentrequest path:features.allowpaymentrequest,
353
+ allowfullscreen path:features.allowfullscreen,
354
+ src path:src"
355
+ ></iframe></div>`;
356
+ }
357
+
358
+ registerCustomElement(Iframe);
@@ -44,35 +44,15 @@ const resizeObserverSymbol = Symbol("resizeObserver");
44
44
  const timerCallbackSymbol = Symbol("timerCallback");
45
45
 
46
46
  /**
47
- * The Panel component is used to display a panel, isn't that cool?
47
+ * A Slider
48
48
  *
49
- * <img src="./images/panel.png">
49
+ * @fragments /fragments/components/layout/panel/
50
50
  *
51
- * You can create this control either by specifying the HTML tag <monster-panel />` directly in the HTML or using
52
- * Javascript via the `document.createElement('monster-panel');` method.
53
- *
54
- * ```html
55
- * <monster-panel></monster-panel>
56
- * ```
57
- *
58
- * Or you can create this CustomControl directly in Javascript:
59
- *
60
- * ```js
61
- * import '@schukai/monster/components/layout/panel.mjs';
62
- * document.createElement('monster-panel');
63
- * ```
64
- *
65
- * @startuml panel.png
66
- * skinparam monochrome true
67
- * skinparam shadowing false
68
- * HTMLElement <|-- CustomElement
69
- * CustomElement <|-- CustomControl
70
- * CustomControl <|-- Panel
71
- * @enduml
51
+ * @example /examples/components/layout/panel-simple
72
52
  *
53
+ * @since 3.54.0
73
54
  * @copyright schukai GmbH
74
- * @memberOf Monster.Components.Layout
75
- * @summary A simple panel component
55
+ * @summary The Panel component is used to display a panel, isn't that cool?
76
56
  */
77
57
  class Panel extends CustomElement {
78
58
  /**
@@ -169,6 +149,11 @@ function calcHeight() {
169
149
  this.style.height = `${height}px`;
170
150
  }
171
151
 
152
+ /**
153
+ * Calculate the maximum height of an element based on the window's inner height
154
+ * @param element
155
+ * @returns {*}
156
+ */
172
157
  function calculateMaximumHeight(element) {
173
158
  let totalBottomBorder = 0;
174
159
  let totalBottomPadding = 0;