@schukai/monster 3.75.0 → 3.76.0

Sign up to get free protection for your applications and to get access to all the features.
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;