@schukai/monster 4.129.3 → 4.129.4

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/package.json CHANGED
@@ -1 +1 @@
1
- {"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.6","@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":"4.129.3"}
1
+ {"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.6","@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":"4.129.4"}
@@ -59,44 +59,7 @@ function positionPopper(controlElement, popperElement, options) {
59
59
  return;
60
60
  }
61
61
 
62
- teardownNativePopover(popperElement);
63
- popperElement.style.removeProperty("visibility");
64
- popperElement.style.display = "block";
65
-
66
- const arrowElement = popperElement.querySelector(
67
- "[data-monster-role=arrow]",
68
- );
69
- const floatingMiddleware = [...config.floatingMiddleware];
70
- if (
71
- arrowElement instanceof HTMLElement &&
72
- config.middlewareTokens.includes("arrow")
73
- ) {
74
- floatingMiddleware.push(arrow({ element: arrowElement }));
75
- }
76
-
77
- startAutoUpdate(controlElement, popperElement, () => {
78
- computePosition(
79
- controlElement,
80
- popperElement,
81
- Object.assign({}, config, {
82
- middleware: floatingMiddleware,
83
- }),
84
- ).then(({ x, y, placement, middlewareData }) => {
85
- Object.assign(popperElement.style, {
86
- top: "0",
87
- left: "0",
88
- transform: `translate(${roundByDPR(x)}px,${roundByDPR(y)}px)`,
89
- });
90
-
91
- if (middlewareData.arrow) {
92
- applyFloatingArrowStyles(
93
- arrowElement,
94
- placement,
95
- middlewareData.arrow,
96
- );
97
- }
98
- });
99
- });
62
+ enableFloatingPositioning(controlElement, popperElement, config);
100
63
  }).run();
101
64
  }
102
65
 
@@ -116,6 +79,47 @@ function openPositionedPopper(controlElement, popperElement, options) {
116
79
  popperElement.style.display = "block";
117
80
  }
118
81
 
82
+ function enableFloatingPositioning(controlElement, popperElement, config) {
83
+ teardownNativePopover(popperElement);
84
+ popperElement.style.removeProperty("visibility");
85
+ popperElement.style.display = "block";
86
+
87
+ startAutoUpdate(controlElement, popperElement, () => {
88
+ syncFloatingPopover(controlElement, popperElement, config);
89
+ });
90
+ syncFloatingPopover(controlElement, popperElement, config);
91
+ }
92
+
93
+ function syncFloatingPopover(controlElement, popperElement, config) {
94
+ const arrowElement = popperElement.querySelector("[data-monster-role=arrow]");
95
+ const floatingMiddleware = [...config.floatingMiddleware];
96
+
97
+ if (
98
+ arrowElement instanceof HTMLElement &&
99
+ config.middlewareTokens.includes("arrow")
100
+ ) {
101
+ floatingMiddleware.push(arrow({ element: arrowElement }));
102
+ }
103
+
104
+ computePosition(
105
+ controlElement,
106
+ popperElement,
107
+ Object.assign({}, config, {
108
+ middleware: floatingMiddleware,
109
+ }),
110
+ ).then(({ x, y, placement, middlewareData }) => {
111
+ Object.assign(popperElement.style, {
112
+ top: "0",
113
+ left: "0",
114
+ transform: `translate(${roundByDPR(x)}px,${roundByDPR(y)}px)`,
115
+ });
116
+
117
+ if (middlewareData.arrow) {
118
+ applyFloatingArrowStyles(arrowElement, placement, middlewareData.arrow);
119
+ }
120
+ });
121
+ }
122
+
119
123
  function closePositionedPopper(popperElement) {
120
124
  stopAutoUpdate(popperElement);
121
125
  cancelScheduledNativeArrowSync(popperElement);
@@ -404,6 +408,12 @@ function syncNativePopover(controlElement, popperElement, config) {
404
408
 
405
409
  applyNativePlacementStyles(popperElement, placement, offsetValue);
406
410
  popperElement.style.removeProperty("visibility");
411
+
412
+ if (hasViewportOverflow(popperElement)) {
413
+ enableFloatingPositioning(controlElement, popperElement, config);
414
+ return;
415
+ }
416
+
407
417
  syncNativeArrow(controlElement, popperElement);
408
418
  scheduleNativeArrowSync(controlElement, popperElement);
409
419
  }
@@ -861,6 +871,24 @@ function matchesPopoverOpen(popperElement) {
861
871
  }
862
872
  }
863
873
 
874
+ function hasViewportOverflow(popperElement) {
875
+ if (!(popperElement instanceof HTMLElement)) {
876
+ return false;
877
+ }
878
+
879
+ const rect = popperElement.getBoundingClientRect();
880
+ const tolerance = 1;
881
+ const viewportWidth = window.innerWidth;
882
+ const viewportHeight = window.innerHeight;
883
+
884
+ return (
885
+ rect.left < -tolerance ||
886
+ rect.top < -tolerance ||
887
+ rect.right > viewportWidth + tolerance ||
888
+ rect.bottom > viewportHeight + tolerance
889
+ );
890
+ }
891
+
864
892
  function clamp(value, min, max) {
865
893
  return Math.min(Math.max(value, min), max);
866
894
  }
@@ -9,29 +9,24 @@ let expect = chai.expect;
9
9
  chai.use(chaiDom);
10
10
 
11
11
  describe('ImageEditor', function () {
12
+ this.timeout(10000);
12
13
 
13
14
  let ImageEditor, document;
14
15
  let registerCustomElement;
15
16
  let CustomElement;
16
17
  let assembleMethodSymbol;
17
18
 
18
- before(function (done) {
19
- initJSDOM({}).then(() => {
20
- import("../../../../source/dom/customelement.mjs").then((domModule) => {
21
- registerCustomElement = domModule['registerCustomElement'];
22
- CustomElement = domModule['CustomElement'];
23
- assembleMethodSymbol = domModule['assembleMethodSymbol'];
24
- return import("../../../../source/components/content/image-editor.mjs");
25
- }).then((m) => {
26
- try {
27
- ImageEditor = m['ImageEditor'];
28
- document = getDocument();
29
- done();
30
- } catch (e) {
31
- done(e);
32
- }
33
- }).catch((e) => done(e));
34
- });
19
+ before(async function () {
20
+ await initJSDOM({});
21
+
22
+ const domModule = await import("../../../../source/dom/customelement.mjs");
23
+ registerCustomElement = domModule['registerCustomElement'];
24
+ CustomElement = domModule['CustomElement'];
25
+ assembleMethodSymbol = domModule['assembleMethodSymbol'];
26
+
27
+ const componentModule = await import("../../../../source/components/content/image-editor.mjs");
28
+ ImageEditor = componentModule['ImageEditor'];
29
+ document = getDocument();
35
30
  });
36
31
 
37
32
  beforeEach(() => {