@schukai/monster 3.81.0 → 3.82.1

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
 
4
4
 
5
+ ## [3.82.1] - 2024-10-16
6
+
7
+ ### Bug Fixes
8
+
9
+ - wrong feature in iframe
10
+
11
+
12
+
13
+ ## [3.82.0] - 2024-10-16
14
+
15
+ ### Add Features
16
+
17
+ - new iframe feature for replace target
18
+
19
+
20
+
5
21
  ## [3.81.0] - 2024-10-15
6
22
 
7
23
  ### Add Features
package/package.json CHANGED
@@ -1 +1 @@
1
- {"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.11","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"3.81.0"}
1
+ {"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.11","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"3.82.1"}
@@ -10,20 +10,20 @@
10
10
  * For more information about purchasing a commercial license, please contact schukai GmbH.
11
11
  */
12
12
 
13
- import { instanceSymbol } from "../../constants.mjs";
14
- import { ATTRIBUTE_ROLE } from "../../dom/constants.mjs";
15
- import { CustomElement } from "../../dom/customelement.mjs";
13
+ import {instanceSymbol} from "../../constants.mjs";
14
+ import {ATTRIBUTE_ROLE} from "../../dom/constants.mjs";
15
+ import {CustomElement} from "../../dom/customelement.mjs";
16
16
  import {
17
- assembleMethodSymbol,
18
- registerCustomElement,
17
+ assembleMethodSymbol,
18
+ registerCustomElement,
19
19
  } from "../../dom/customelement.mjs";
20
- import { findTargetElementFromEvent } from "../../dom/events.mjs";
21
- import { isFunction } from "../../types/is.mjs";
22
- import { DeadMansSwitch } from "../../util/deadmansswitch.mjs";
23
- import { IframeStyleSheet } from "./stylesheet/iframe.mjs";
24
- import { fireCustomEvent } from "../../dom/events.mjs";
20
+ import {findTargetElementFromEvent} from "../../dom/events.mjs";
21
+ import {isFunction} from "../../types/is.mjs";
22
+ import {DeadMansSwitch} from "../../util/deadmansswitch.mjs";
23
+ import {IframeStyleSheet} from "./stylesheet/iframe.mjs";
24
+ import {fireCustomEvent} from "../../dom/events.mjs";
25
25
 
26
- export { Iframe };
26
+ export {Iframe};
27
27
 
28
28
  /**
29
29
  * @private
@@ -62,124 +62,134 @@ const timerCallbackSymbol = Symbol("timerCallback");
62
62
  * @summary A cool and fancy Iframe that can make your life easier and also looks good.
63
63
  */
64
64
  class Iframe extends CustomElement {
65
- /**
66
- * This method is called by the `instanceof` operator.
67
- * @return {symbol}
68
- */
69
- static get [instanceSymbol]() {
70
- return Symbol.for("@schukai/monster/components/layout/iframe@@instance");
71
- }
72
-
73
- /**
74
- *
75
- * @return {Components.Layout.Iframe
76
- */
77
- [assembleMethodSymbol]() {
78
- super[assembleMethodSymbol]();
79
- initControlReferences.call(this);
80
- initEventHandler.call(this);
81
- calcHeight.call(this);
82
- return this;
83
- }
84
-
85
- /**
86
- * This method is called by the dom and should not be called directly.
87
- *
88
- * @return {void}
89
- */
90
- connectedCallback() {
91
- super.connectedCallback();
92
- attachResizeObserver.call(this);
93
-
94
- // disable scrolling in parent node
95
- if (this.parentNode && this.parentNode instanceof HTMLElement) {
96
- this.parentNode.style.overflow = "hidden";
97
- }
98
- }
99
-
100
- /**
101
- * This method is called by the dom and should not be called directly.
102
- *
103
- * @return {void}
104
- */
105
- disconnectedCallback() {
106
- super.disconnectedCallback();
107
- disconnectResizeObserver.call(this);
108
- }
109
-
110
- /**
111
- * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
112
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
113
- *
114
- * The individual configuration values can be found in the table.
115
- *
116
- * @property {Object} templates Template definitions
117
- * @property {string} templates.main Main template
118
- * @property {Object} labels Label definitions
119
- * @property {Object} actions Callbacks
120
- * @property {string} actions.click="throw Error" Callback when clicked
121
- * @property {Object} features Features
122
- * @property {Object} classes CSS classes
123
- * @property {boolean} disabled=false Disabled state
124
- */
125
- get defaults() {
126
- return Object.assign({}, super.defaults, {
127
- templates: {
128
- main: getTemplate(),
129
- },
130
- src: null,
131
-
132
- /* "allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation"*/
133
- sandbox: null,
134
-
135
- labels: {},
136
- classes: {},
137
-
138
- name: "",
139
-
140
- referrerpolicy: "no-referrer",
141
-
142
- disabled: false,
143
- features: {
144
- allowfullscreen: true,
145
- allowpaymentrequest: true,
146
- loading: "egager",
147
- },
148
- actions: {
149
- click: () => {
150
- throw new Error("the click action is not defined");
151
- },
152
- },
153
- });
154
- }
155
-
156
- /**
157
- * @return {string}
158
- */
159
- static getTag() {
160
- return "monster-iframe";
161
- }
162
-
163
- /**
164
- * @return {CSSStyleSheet[]}
165
- */
166
- static getCSSStyleSheet() {
167
- return [IframeStyleSheet];
168
- }
65
+ /**
66
+ * This method is called by the `instanceof` operator.
67
+ * @return {symbol}
68
+ */
69
+ static get [instanceSymbol]() {
70
+ return Symbol.for("@schukai/monster/components/layout/iframe@@instance");
71
+ }
72
+
73
+ /**
74
+ *
75
+ * @return {Components.Layout.Iframe
76
+ * @fires monster-iframe-clicked
77
+ */
78
+ [assembleMethodSymbol]() {
79
+ super[assembleMethodSymbol]();
80
+ initControlReferences.call(this);
81
+ initEventHandler.call(this);
82
+ calcHeight.call(this);
83
+ return this;
84
+ }
85
+
86
+ /**
87
+ * This method is called by the dom and should not be called directly.
88
+ *
89
+ * @return {void}
90
+ */
91
+ connectedCallback() {
92
+ super.connectedCallback();
93
+ attachResizeObserver.call(this);
94
+
95
+ // disable scrolling in parent node
96
+ if (this.parentNode && this.parentNode instanceof HTMLElement) {
97
+ this.parentNode.style.overflow = "hidden";
98
+ }
99
+ }
100
+
101
+ /**
102
+ * This method is called by the dom and should not be called directly.
103
+ *
104
+ * @return {void}
105
+ */
106
+ disconnectedCallback() {
107
+ super.disconnectedCallback();
108
+ disconnectResizeObserver.call(this);
109
+ }
110
+
111
+ /**
112
+ * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
113
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
114
+ *
115
+ * The individual configuration values can be found in the table.
116
+ *
117
+ * @property {Object} templates Template definitions
118
+ * @property {string} templates.main Main template
119
+ * @property {Object} labels Label definitions
120
+ * @property {Object} actions Callbacks
121
+ * @property {string} actions.click="throw Error" Callback when clicked
122
+ * @property {Object} features Features
123
+ * @property {boolean} features.allowFullScreen=true Allow fullscreen
124
+ * @property {boolean} features.allowPaymentRequest=true Allow payment request
125
+ * @property {boolean} features.replaceTargets=true Replace parent target in iframe
126
+ * @property {string} loading="eager" Loading state
127
+ * @property {string} referrerPolicy="no-referrer" Referrer policy
128
+ * @property {string} src Source
129
+ * @property {Object} classes CSS classes
130
+ * @property {boolean} disabled=false Disabled state
131
+ */
132
+ get defaults() {
133
+ return Object.assign({}, super.defaults, {
134
+ templates: {
135
+ main: getTemplate(),
136
+ },
137
+ src: null,
138
+
139
+ /* "allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation"*/
140
+ sandbox: null,
141
+
142
+ labels: {},
143
+ classes: {},
144
+
145
+ name: "",
146
+
147
+ referrerPolicy: "no-referrer",
148
+
149
+ disabled: false,
150
+ features: {
151
+ allowFullScreen: true,
152
+ allowPaymentRequest: true,
153
+ replaceTargets: true,
154
+ },
155
+
156
+ loading: "eager",
157
+
158
+ actions: {
159
+ click: () => {
160
+ throw new Error("the click action is not defined");
161
+ },
162
+ },
163
+ });
164
+ }
165
+
166
+ /**
167
+ * @return {string}
168
+ */
169
+ static getTag() {
170
+ return "monster-iframe";
171
+ }
172
+
173
+ /**
174
+ * @return {CSSStyleSheet[]}
175
+ */
176
+ static getCSSStyleSheet() {
177
+ return [IframeStyleSheet];
178
+ }
169
179
  }
170
180
 
171
181
  /**
172
182
  * @private
173
183
  */
174
184
  function calcHeight() {
175
- this.style.boxSizing = "border-box";
185
+ this.style.boxSizing = "border-box";
176
186
 
177
- const height = calculateMaximumHeight.call(this, this.parentNode);
178
- if (height < 0 || isNaN(height)) {
179
- return;
180
- }
187
+ const height = calculateMaximumHeight.call(this, this.parentNode);
188
+ if (height < 0 || isNaN(height)) {
189
+ return;
190
+ }
181
191
 
182
- this[iframeElementSymbol].style.height = `${height}px`;
192
+ this[iframeElementSymbol].style.height = `${height}px`;
183
193
  }
184
194
 
185
195
  /**
@@ -188,128 +198,137 @@ function calcHeight() {
188
198
  * @return {*}
189
199
  */
190
200
  function calculateMaximumHeight(element) {
191
- let totalBottomBorder = 0;
192
- let totalBottomPadding = 0;
193
- let totalBottomMargin = 0;
194
- let totalOutlineHeight = 0;
195
- let totalBoxShadowHeight = 0;
196
- let currentElement = element;
197
-
198
- while (currentElement && currentElement !== document.body) {
199
- const style = window.getComputedStyle(currentElement);
200
- const boxSizing = style.boxSizing;
201
-
202
- const elementHeight = currentElement.getBoundingClientRect().height;
203
-
204
- const borderBottomWidth = parseFloat(style.borderBottomWidth);
205
- const paddingBottom = parseFloat(style.paddingBottom);
206
- const marginBottom = parseFloat(style.marginBottom);
207
-
208
- const outlineHeight = parseFloat(style.outlineWidth);
209
-
210
- totalBottomBorder += isNaN(borderBottomWidth) ? 0 : borderBottomWidth;
211
- totalBottomPadding +=
212
- isNaN(paddingBottom) || boxSizing === "border-box" ? 0 : paddingBottom;
213
- totalBottomMargin += isNaN(marginBottom) ? 0 : marginBottom;
214
- totalOutlineHeight += isNaN(outlineHeight) ? 0 : outlineHeight;
215
-
216
- const boxShadow = style.boxShadow;
217
- let boxShadowVerticalTotal = 0;
218
-
219
- if (boxShadow !== "none") {
220
- const boxShadowValues = boxShadow.split(" ");
221
- const verticalOffset = parseFloat(boxShadowValues[3]);
222
- const blurRadius = parseFloat(boxShadowValues[4]);
223
- const spreadRadius = parseFloat(boxShadowValues[5]);
224
-
225
- boxShadowVerticalTotal = verticalOffset + blurRadius + spreadRadius;
226
- }
227
-
228
- totalBoxShadowHeight += isNaN(boxShadowVerticalTotal)
229
- ? 0
230
- : boxShadowVerticalTotal;
231
-
232
- if (elementHeight > 200) {
233
- return (
234
- elementHeight -
235
- totalBottomBorder -
236
- totalBottomPadding -
237
- totalBottomMargin -
238
- totalOutlineHeight -
239
- totalBoxShadowHeight
240
- );
241
- }
242
-
243
- currentElement = currentElement.parentNode || currentElement.host;
244
- }
201
+ let totalBottomBorder = 0;
202
+ let totalBottomPadding = 0;
203
+ let totalBottomMargin = 0;
204
+ let totalOutlineHeight = 0;
205
+ let totalBoxShadowHeight = 0;
206
+ let currentElement = element;
207
+
208
+ while (currentElement && currentElement !== document.body) {
209
+ const style = window.getComputedStyle(currentElement);
210
+ const boxSizing = style.boxSizing;
211
+
212
+ const elementHeight = currentElement.getBoundingClientRect().height;
213
+
214
+ const borderBottomWidth = parseFloat(style.borderBottomWidth);
215
+ const paddingBottom = parseFloat(style.paddingBottom);
216
+ const marginBottom = parseFloat(style.marginBottom);
217
+
218
+ const outlineHeight = parseFloat(style.outlineWidth);
219
+
220
+ totalBottomBorder += isNaN(borderBottomWidth) ? 0 : borderBottomWidth;
221
+ totalBottomPadding +=
222
+ isNaN(paddingBottom) || boxSizing === "border-box" ? 0 : paddingBottom;
223
+ totalBottomMargin += isNaN(marginBottom) ? 0 : marginBottom;
224
+ totalOutlineHeight += isNaN(outlineHeight) ? 0 : outlineHeight;
225
+
226
+ const boxShadow = style.boxShadow;
227
+ let boxShadowVerticalTotal = 0;
228
+
229
+ if (boxShadow !== "none") {
230
+ const boxShadowValues = boxShadow.split(" ");
231
+ const verticalOffset = parseFloat(boxShadowValues[3]);
232
+ const blurRadius = parseFloat(boxShadowValues[4]);
233
+ const spreadRadius = parseFloat(boxShadowValues[5]);
234
+
235
+ boxShadowVerticalTotal = verticalOffset + blurRadius + spreadRadius;
236
+ }
237
+
238
+ totalBoxShadowHeight += isNaN(boxShadowVerticalTotal)
239
+ ? 0
240
+ : boxShadowVerticalTotal;
241
+
242
+ if (elementHeight > 200) {
243
+ return (
244
+ elementHeight -
245
+ totalBottomBorder -
246
+ totalBottomPadding -
247
+ totalBottomMargin -
248
+ totalOutlineHeight -
249
+ totalBoxShadowHeight
250
+ );
251
+ }
252
+
253
+ currentElement = currentElement.parentNode || currentElement.host;
254
+ }
245
255
  }
246
256
 
247
257
  /**
248
258
  * @private
249
259
  */
250
260
  function attachResizeObserver() {
251
- // against flickering
252
- this[resizeObserverSymbol] = new ResizeObserver(() => {
253
- if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
254
- try {
255
- this[timerCallbackSymbol].touch();
256
- return;
257
- } catch (e) {
258
- delete this[timerCallbackSymbol];
259
- }
260
- }
261
-
262
- this[timerCallbackSymbol] = new DeadMansSwitch(200, () => {
263
- calcHeight.call(this);
264
- });
265
- });
266
-
267
- this[resizeObserverSymbol].observe(this.ownerDocument.body);
268
- this[resizeObserverSymbol].observe(document.scrollingElement);
261
+ // against flickering
262
+ this[resizeObserverSymbol] = new ResizeObserver(() => {
263
+ if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
264
+ try {
265
+ this[timerCallbackSymbol].touch();
266
+ return;
267
+ } catch (e) {
268
+ delete this[timerCallbackSymbol];
269
+ }
270
+ }
271
+
272
+ this[timerCallbackSymbol] = new DeadMansSwitch(200, () => {
273
+ calcHeight.call(this);
274
+ });
275
+ });
276
+
277
+ this[resizeObserverSymbol].observe(this.ownerDocument.body);
278
+ this[resizeObserverSymbol].observe(document.scrollingElement);
269
279
  }
270
280
 
271
281
  function disconnectResizeObserver() {
272
- if (this[resizeObserverSymbol] instanceof ResizeObserver) {
273
- this[resizeObserverSymbol].disconnect();
274
- }
282
+ if (this[resizeObserverSymbol] instanceof ResizeObserver) {
283
+ this[resizeObserverSymbol].disconnect();
284
+ }
275
285
  }
276
286
 
277
287
  /**
278
288
  * @private
279
289
  * @return {initEventHandler}
280
- * @fires monster-iframe-clicked
281
290
  */
282
291
  function initEventHandler() {
283
- const self = this;
284
- const element = this[iframeElementSymbol];
285
-
286
- const type = "click";
287
-
288
- element.addEventListener(type, function (event) {
289
- const callback = self.getOption("actions.click");
290
-
291
- fireCustomEvent(self, "monster-iframe-clicked", {
292
- element: self,
293
- });
294
-
295
- if (!isFunction(callback)) {
296
- return;
297
- }
298
-
299
- const element = findTargetElementFromEvent(
300
- event,
301
- ATTRIBUTE_ROLE,
302
- "control",
303
- );
304
-
305
- if (!(element instanceof Node && self.hasNode(element))) {
306
- return;
307
- }
308
-
309
- callback.call(self, event);
310
- });
311
-
312
- return this;
292
+ const self = this;
293
+ const element = this[iframeElementSymbol];
294
+
295
+ const type = "click";
296
+
297
+ element.addEventListener(type, function (event) {
298
+ const callback = self.getOption("actions.click");
299
+
300
+ fireCustomEvent(self, "monster-iframe-clicked", {
301
+ element: self,
302
+ });
303
+
304
+ if (!isFunction(callback)) {
305
+ return;
306
+ }
307
+
308
+ const element = findTargetElementFromEvent(
309
+ event,
310
+ ATTRIBUTE_ROLE,
311
+ "control",
312
+ );
313
+
314
+ if (!(element instanceof Node && self.hasNode(element))) {
315
+ return;
316
+ }
317
+
318
+ callback.call(self, event);
319
+ });
320
+
321
+ this[iframeElementSymbol].addEventListener("load", () => {
322
+ calcHeight.call(this);
323
+ if (this.getOption("features.replaceTargets")) {
324
+ const links = this[iframeElementSymbol].contentDocument.querySelectorAll('a[target="_parent"], form[target="_parent"], a[target="_top"], form[target="_top"]');
325
+ links.forEach(function(link) {
326
+ link.target = '_self';
327
+ });
328
+ }
329
+ });
330
+
331
+ return this;
313
332
  }
314
333
 
315
334
  /**
@@ -317,17 +336,17 @@ function initEventHandler() {
317
336
  * @return {void}
318
337
  */
319
338
  function initControlReferences() {
320
- if (!this.shadowRoot) {
321
- throw new Error("no shadow-root is defined");
322
- }
339
+ if (!this.shadowRoot) {
340
+ throw new Error("no shadow-root is defined");
341
+ }
323
342
 
324
- this[PanelElementSymbol] = this.shadowRoot.querySelector(
325
- "[data-monster-role=control]",
326
- );
343
+ this[PanelElementSymbol] = this.shadowRoot.querySelector(
344
+ "[data-monster-role=control]",
345
+ );
327
346
 
328
- this[iframeElementSymbol] = this.shadowRoot.querySelector(
329
- `[${ATTRIBUTE_ROLE}="control"] iframe`,
330
- );
347
+ this[iframeElementSymbol] = this.shadowRoot.querySelector(
348
+ `[${ATTRIBUTE_ROLE}="control"] iframe`,
349
+ );
331
350
  }
332
351
 
333
352
  /**
@@ -335,16 +354,16 @@ function initControlReferences() {
335
354
  * @return {string}
336
355
  */
337
356
  function getTemplate() {
338
- // language=HTML
339
- return `
357
+ // language=HTML
358
+ return `
340
359
  <div data-monster-role="control" part="control">
341
360
  <iframe data-monster-role="iframe"
342
361
  data-monster-attributes="sandbox path:sandbox,
343
362
  name path:name,
344
- referrerpolicy path:referrerpolicy,
345
- loading path:features.loading,
346
- allowpaymentrequest path:features.allowpaymentrequest,
347
- allowfullscreen path:features.allowfullscreen,
363
+ referrerpolicy path:referrerPolicy,
364
+ loading path:loading,
365
+ allowpaymentrequest path:features.allowPaymentRequest,
366
+ allowfullscreen path:features.allowFullScreen,
348
367
  src path:src"
349
368
  ></iframe>
350
369
  </div>`;