@schukai/monster 3.75.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 (43) hide show
  1. package/CHANGELOG.md +21 -8
  2. package/package.json +1 -1
  3. package/source/components/layout/collapse.mjs +361 -395
  4. package/source/components/layout/details.mjs +10 -40
  5. package/source/components/layout/iframe.mjs +358 -0
  6. package/source/components/layout/panel.mjs +10 -25
  7. package/source/components/layout/slider.mjs +11 -11
  8. package/source/components/layout/split-panel.mjs +7 -39
  9. package/source/components/layout/style/iframe.pcss +39 -0
  10. package/source/components/layout/style/panel.pcss +10 -3
  11. package/source/components/layout/style/split-panel.pcss +2 -0
  12. package/source/components/layout/stylesheet/iframe.mjs +38 -0
  13. package/source/components/layout/stylesheet/panel.mjs +1 -1
  14. package/source/components/layout/tabs.mjs +6 -35
  15. package/source/components/layout/width-toggle.mjs +10 -31
  16. package/source/components/tree-menu/tree-menu.mjs +16 -12
  17. package/source/math/random.mjs +2 -3
  18. package/source/monster.mjs +2 -1
  19. package/test/cases/components/form/button.mjs +2 -1
  20. package/test/cases/components/form/confirm-button.mjs +1 -1
  21. package/test/cases/components/form/form.mjs +1 -1
  22. package/test/cases/components/form/reload.mjs +1 -1
  23. package/test/cases/components/form/select.mjs +1 -1
  24. package/test/cases/components/form/state-button.mjs +1 -1
  25. package/test/cases/components/form/template.mjs +1 -1
  26. package/test/cases/components/form/toggle-switch.mjs +1 -1
  27. package/test/cases/components/form/tree-select.mjs +1 -1
  28. package/test/cases/components/host/details.mjs +1 -1
  29. package/test/cases/components/host/host.mjs +1 -1
  30. package/test/cases/components/host/overlay.mjs +1 -1
  31. package/test/cases/components/layout/panel.mjs +1 -1
  32. package/test/cases/components/layout/slit-panel.mjs +1 -1
  33. package/test/cases/components/layout/tabs.mjs +1 -1
  34. package/test/cases/components/notify/message.mjs +1 -1
  35. package/test/cases/components/notify/notify.mjs +1 -1
  36. package/test/cases/dom/customcontrol.mjs +1 -1
  37. package/test/cases/dom/customelement-initfromscripthost.mjs +1 -1
  38. package/test/cases/dom/customelement.mjs +1 -1
  39. package/test/cases/dom/resource/data.mjs +1 -1
  40. package/test/cases/dom/resource/link/stylesheet.mjs +1 -1
  41. package/test/cases/dom/resource/link.mjs +1 -1
  42. package/test/cases/dom/resource/script.mjs +1 -1
  43. package/test/cases/dom/updater.mjs +1 -1
@@ -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;
@@ -58,14 +58,14 @@ const configSymbol = Symbol("config");
58
58
  * @private
59
59
  * @type {string}
60
60
  */
61
- const ATTRIBUTE_CLON_FROM = ATTRIBUTE_PREFIX + "clone-from";
61
+ const ATTRIBUTE_CLONE_FROM = ATTRIBUTE_PREFIX + "clone-from";
62
62
 
63
63
  /**
64
64
  * A Slider
65
65
  *
66
- * @fragments /fragments/components/form/slider/
66
+ * @fragments /fragments/components/layout/slider/
67
67
  *
68
- * @example /examples/components/form/slider-simple
68
+ * @example /examples/components/layout/slider-simple
69
69
  *
70
70
  * @since 3.74.0
71
71
  * @copyright schukai GmbH
@@ -120,7 +120,7 @@ class Slider extends CustomElement {
120
120
  * @property {Object} autoPlay Auto play configuration
121
121
  * @property {number} autoPlay.delay=1500 Delay between slides
122
122
  * @property {number} autoPlay.startDelay=1000 Start delay
123
- * @property {string} autoPlay.direction="next" Direction of the auto play
123
+ * @property {string} autoPlay.direction="next" Direction of the autoplay
124
124
  * @property {boolean} autoPlay.mouseOverPause=true Pause on mouse over
125
125
  * @property {boolean} autoPlay.touchPause=true Pause on touch
126
126
  * @property {Object} classes CSS classes
@@ -352,10 +352,10 @@ function initCarousel() {
352
352
  const { slides, totalSlides } = getSlidesAndTotal.call(this);
353
353
  if (this.getOption("features.carousel") && totalSlides > 2) {
354
354
  const firstElement = slides[0].cloneNode(true);
355
- firstElement.setAttribute(ATTRIBUTE_CLON_FROM, 1);
355
+ firstElement.setAttribute(ATTRIBUTE_CLONE_FROM, 1);
356
356
 
357
357
  const lastElement = slides[totalSlides - 1].cloneNode(true);
358
- lastElement.setAttribute(ATTRIBUTE_CLON_FROM, totalSlides);
358
+ lastElement.setAttribute(ATTRIBUTE_CLONE_FROM, totalSlides);
359
359
  slides[totalSlides - 1].insertAdjacentElement("afterend", firstElement);
360
360
 
361
361
  slides[0].insertAdjacentElement("beforebegin", lastElement);
@@ -462,8 +462,8 @@ function moveTo(index) {
462
462
  if (this.getOption("features.carousel")) {
463
463
  slideIndex = index - 1;
464
464
 
465
- if (slides[index].hasAttribute(ATTRIBUTE_CLON_FROM)) {
466
- const from = parseInt(slides[index].getAttribute(ATTRIBUTE_CLON_FROM));
465
+ if (slides[index].hasAttribute(ATTRIBUTE_CLONE_FROM)) {
466
+ const from = parseInt(slides[index].getAttribute(ATTRIBUTE_CLONE_FROM));
467
467
 
468
468
  getWindow().requestAnimationFrame(() => {
469
469
  getWindow().requestAnimationFrame(() => {
@@ -633,14 +633,14 @@ function getTemplate() {
633
633
  // language=HTML
634
634
  return `
635
635
  <div data-monster-role="control" part="control">
636
- <div class="prev" data-monster-role="prev" part="prev">
636
+ <div class="prev" data-monster-role="prev" part="prev" part="prev">
637
637
  <slot name="prev"></slot>
638
638
  </div>
639
- <div data-monster-role="slider">
639
+ <div data-monster-role="slider" part="slides">
640
640
  <slot></slot>
641
641
  </div>
642
642
  <div data-monster-role="thumbnails"></div>
643
- <div class="next" data-monster-role="next" part="next">
643
+ <div class="next" data-monster-role="next" part="next" part="next">
644
644
  <slot name="next"></slot>
645
645
  </div>
646
646
  </div>`;
@@ -65,49 +65,17 @@ const TYPE_VERTICAL = "vertical";
65
65
  const TYPE_HORIZONTAL = "horizontal";
66
66
 
67
67
  /**
68
- * The SplitPanel control is a simple layout control that allows you to split the screen
69
- * into two parts. The split can be either vertical or horizontal. The control provides a
70
- * draggable handle that allows you to adjust the size of the two panels.
71
- *
72
- * <img src="./images/split-panel.png">
73
- *
74
- * You can create this control either by specifying the HTML tag <monster-split-panel />`
75
- * directly in the HTML or using Javascript via the `document.createElement('monster-split-panel');`
76
- * method.
77
- *
78
- * ```html
79
- * <monster-split-panel></monster-split-panel>
80
- * ```
81
- *
82
- * Or you can create this CustomControl directly in Javascript:
68
+ * A SplitPanel Control
83
69
  *
84
- * ```js
85
- * import '@schukai/monster/components/layout/split-panel.mjs';
86
- * document.createElement('monster-split-panel');
87
- * ```
70
+ * @fragments /fragments/components/layout/split-panel/
88
71
  *
89
- * It is best to hide unregistered elements with the css property `visibility: hidden;`
90
- *
91
- * ```css
92
- * <style>
93
- * *:not(:defined) {
94
- * visibility: hidden;
95
- * }
96
- * </style>
97
- * ```
98
- *
99
- * @startuml split-panel.png
100
- * skinparam monochrome true
101
- * skinparam shadowing false
102
- * HTMLElement <|-- CustomElement
103
- * CustomElement <|-- CustomControl
104
- * CustomControl <|-- SplitPanel
105
- * @enduml
72
+ * @example /examples/components/layout/split-panel-simple
106
73
  *
74
+ * @since 3.54.0
107
75
  * @copyright schukai GmbH
108
- * @memberOf Monster.Components.Layout
109
- * @summary A simple split screen layout
110
- * @fires Monster.Components.Layout.event:monster-dimension-changed
76
+ * @summary The SplitPanel control is a simple layout control that allows you to split the screen
77
+ * into two parts. The split can be either vertical or horizontal. The control provides a
78
+ * draggable handle that allows you to adjust the size of the two panels.
111
79
  */
112
80
  class SplitPanel extends CustomElement {
113
81
  /**
@@ -0,0 +1,39 @@
1
+
2
+ :host {
3
+ display: block;
4
+ border: none;
5
+ box-sizing: border-box;
6
+ padding: 0;
7
+ margin: 0;
8
+ height: fill-available;
9
+ height: -moz-available;
10
+ }
11
+
12
+
13
+ iframe {
14
+ display: block;
15
+ border: none;
16
+ box-sizing: border-box;
17
+
18
+ padding: 0;
19
+ margin: 0;
20
+
21
+ height: fill-available;
22
+ height: stretch;
23
+ width: 100%;
24
+ }
25
+
26
+
27
+ [data-monster-role="control"] {
28
+ display: flex;
29
+ flex-direction: column;
30
+ align-items: center;
31
+ justify-content: center;
32
+ width: 100%;
33
+ border: none;
34
+ box-sizing: border-box;
35
+ padding: 0;
36
+ margin: 0;
37
+ height: fill-available;
38
+ height: stretch;
39
+ }
@@ -14,7 +14,11 @@
14
14
  width: 100%;
15
15
  box-sizing: border-box;
16
16
  overflow: auto;
17
-
17
+
18
+ height: fill-available;
19
+ height: -moz-available;
20
+ height: stretch;
21
+
18
22
  }
19
23
 
20
24
  [data-monster-role="control"] {
@@ -26,8 +30,11 @@
26
30
  overflow: auto;
27
31
  scrollbar-width: thin;
28
32
  scrollbar-color: var(--monster-color-primary-1) var(--monster-bg-color-primary-1);
29
-
30
-
33
+
34
+ height: fill-available;
35
+ height: -moz-available;
36
+ height: stretch;
37
+
31
38
  //position: fixed;
32
39
  //top: 0;
33
40
  //left: 0;
@@ -9,6 +9,8 @@
9
9
  flex-direction: row;
10
10
  margin: 0;
11
11
  padding: 0;
12
+
13
+
12
14
 
13
15
  & .panel {
14
16
  flex-grow: 1;