@schukai/monster 4.129.9 → 4.129.10

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"},"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.9"}
1
+ {"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.6"},"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.10"}
@@ -160,6 +160,9 @@ class PopperButton extends Popper {
160
160
  },
161
161
  mode: "click",
162
162
  value: null,
163
+ popper: Object.assign({}, super.defaults.popper, {
164
+ contentOverflow: "smart",
165
+ }),
163
166
 
164
167
  aria: {
165
168
  role: null,
@@ -309,7 +309,8 @@ function findNearestClippingContainer(element) {
309
309
  while (current) {
310
310
  if (
311
311
  current instanceof HTMLElement &&
312
- isClippingContainer(getComputedStyle(current))
312
+ isClippingContainer(getComputedStyle(current)) &&
313
+ !shouldIgnoreClippingContainer(current)
313
314
  ) {
314
315
  return current;
315
316
  }
@@ -341,6 +342,41 @@ function getComposedParent(node) {
341
342
  return node.parentNode || null;
342
343
  }
343
344
 
345
+ function shouldIgnoreClippingContainer(element) {
346
+ if (!(element instanceof HTMLElement)) {
347
+ return false;
348
+ }
349
+
350
+ if (!isPopperContentWrapper(element)) {
351
+ return false;
352
+ }
353
+
354
+ const parent = getComposedParent(element);
355
+ return (
356
+ parent instanceof HTMLElement &&
357
+ parent.getAttribute("data-monster-role") === "popper"
358
+ );
359
+ }
360
+
361
+ function isPopperContentWrapper(element) {
362
+ if (!(element instanceof HTMLElement)) {
363
+ return false;
364
+ }
365
+
366
+ if (!element.hasAttribute("data-monster-overflow-mode")) {
367
+ return false;
368
+ }
369
+
370
+ const part = element.getAttribute("part");
371
+ return (
372
+ isString(part) &&
373
+ part
374
+ .split(/\s+/)
375
+ .filter((token) => token.length > 0)
376
+ .includes("content")
377
+ );
378
+ }
379
+
344
380
  function isClippingContainer(style) {
345
381
  if (!style) {
346
382
  return false;
@@ -155,7 +155,7 @@ class Popper extends CustomElement {
155
155
  * @property {Object} popper - Positioning options
156
156
  * @property {string} popper.placement - Placement: top|bottom|left|right
157
157
  * @property {Array} popper.middleware - Positioning middleware functions
158
- * @property {string} popper.contentOverflow - Content clipping mode: both|horizontal|visible
158
+ * @property {string} popper.contentOverflow - Content clipping mode: both|horizontal|visible|smart
159
159
  * @property {Object} features - Feature flags
160
160
  * @property {boolean} features.preventOpenEventSent - Prevent open event
161
161
  * @returns {Object} Default options merged with parent defaults
@@ -200,6 +200,10 @@ class Popper extends CustomElement {
200
200
 
201
201
  if (path === "popper.contentOverflow") {
202
202
  applyContentOverflowMode.call(this);
203
+ } else if (path === "content") {
204
+ queueMicrotask(() => {
205
+ applyContentOverflowMode.call(this);
206
+ });
203
207
  }
204
208
 
205
209
  return this;
@@ -282,7 +286,16 @@ class Popper extends CustomElement {
282
286
  * @return {string}
283
287
  */
284
288
  resolveContentOverflowMode() {
285
- return this.getOption("popper.contentOverflow", "both");
289
+ const configuredMode = this.getOption("popper.contentOverflow", "both");
290
+ if (configuredMode !== "smart") {
291
+ return configuredMode;
292
+ }
293
+
294
+ if (containsNestedOverlayContent(this.getOption("content"))) {
295
+ return "horizontal";
296
+ }
297
+
298
+ return "both";
286
299
  }
287
300
 
288
301
  /**
@@ -702,6 +715,9 @@ function initOverflowObserver() {
702
715
  () => {
703
716
  applyContentOverflowMode.call(this);
704
717
  };
718
+ this[attributeObserverSymbol]["data-monster-option-content"] = () => {
719
+ applyContentOverflowMode.call(this);
720
+ };
705
721
  }
706
722
 
707
723
  /**
@@ -743,4 +759,31 @@ function getTemplate() {
743
759
  `;
744
760
  }
745
761
 
762
+ function containsNestedOverlayContent(content) {
763
+ const selector = [
764
+ "monster-details",
765
+ "monster-message-state-button",
766
+ "monster-popper",
767
+ "monster-popper-button",
768
+ "monster-select",
769
+ "details",
770
+ ].join(",");
771
+
772
+ if (typeof content === "string") {
773
+ const container = document.createElement("div");
774
+ container.innerHTML = content;
775
+ return container.querySelector(selector) instanceof HTMLElement;
776
+ }
777
+
778
+ if (!(content instanceof HTMLElement)) {
779
+ return false;
780
+ }
781
+
782
+ if (content.matches(selector)) {
783
+ return true;
784
+ }
785
+
786
+ return content.querySelector(selector) instanceof HTMLElement;
787
+ }
788
+
746
789
  registerCustomElement(Popper);
@@ -25,7 +25,7 @@ try {
25
25
  PopperStyleSheet.insertRule(
26
26
  `
27
27
  @layer popper {
28
- [data-monster-role=control]{box-sizing:border-box;outline:none;width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}:host{box-sizing:border-box;display:block}div[data-monster-role=popper]{align-content:center;background:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);box-sizing:border-box;color:var(--monster-color-primary-1);display:none;justify-content:space-between;left:0;max-height:var(--monster-popper-max-height,calc(100vh - 2rem));max-width:var(--monster-popper-max-width,calc(100vw - 2rem));padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper]>[part=content]{max-height:var(--monster-popper-content-max-height,calc(100vh - 4.2rem));max-width:100%;overflow:auto}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=horizontal]{clip-path:inset(calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0 calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0);overflow:visible}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=visible]{clip-path:none;max-height:none;max-width:none;overflow:visible}div[data-monster-role=popper] div[data-monster-role=arrow]{background:var(--monster-bg-color-primary-1);height:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);pointer-events:none;position:absolute;width:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);z-index:-1}[data-monster-role=control]{display:flex;position:relative}
28
+ [data-monster-role=control]{box-sizing:border-box;outline:none;width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}:host{box-sizing:border-box;display:block}div[data-monster-role=popper]{align-content:center;background:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);box-sizing:border-box;color:var(--monster-color-primary-1);display:none;justify-content:space-between;left:0;max-height:var(--monster-popper-max-height,calc(100vh - 2rem));max-width:var(--monster-popper-max-width,calc(100vw - 2rem));padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper]>[part=content]{max-height:var(--monster-popper-content-max-height,calc(100vh - 4.2rem));max-width:100%;overflow:auto}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=horizontal]{clip-path:none;overflow:visible}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=visible]{clip-path:none;max-height:none;max-width:none;overflow:visible}div[data-monster-role=popper] div[data-monster-role=arrow]{background:var(--monster-bg-color-primary-1);height:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);pointer-events:none;position:absolute;width:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);z-index:-1}[data-monster-role=control]{display:flex;position:relative}
29
29
  }`,
30
30
  0,
31
31
  );
@@ -1,2 +1,2 @@
1
1
  /** generated from floating-ui.pcss **/
2
- div[data-monster-role=popper]{align-content:center;background:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);box-sizing:border-box;color:var(--monster-color-primary-1);display:none;justify-content:space-between;left:0;max-height:var(--monster-popper-max-height,calc(100vh - 2rem));max-width:var(--monster-popper-max-width,calc(100vw - 2rem));padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper]>[part=content]{max-height:var(--monster-popper-content-max-height,calc(100vh - 4.2rem));max-width:100%;overflow:auto}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=horizontal]{clip-path:inset(calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0 calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0);overflow:visible}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=visible]{clip-path:none;max-height:none;max-width:none;overflow:visible}div[data-monster-role=popper] div[data-monster-role=arrow]{background:var(--monster-bg-color-primary-1);height:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);pointer-events:none;position:absolute;width:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);z-index:-1}
2
+ div[data-monster-role=popper]{align-content:center;background:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);box-sizing:border-box;color:var(--monster-color-primary-1);display:none;justify-content:space-between;left:0;max-height:var(--monster-popper-max-height,calc(100vh - 2rem));max-width:var(--monster-popper-max-width,calc(100vw - 2rem));padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper]>[part=content]{max-height:var(--monster-popper-content-max-height,calc(100vh - 4.2rem));max-width:100%;overflow:auto}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=horizontal]{clip-path:none;overflow:visible}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=visible]{clip-path:none;max-height:none;max-width:none;overflow:visible}div[data-monster-role=popper] div[data-monster-role=arrow]{background:var(--monster-bg-color-primary-1);height:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);pointer-events:none;position:absolute;width:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);z-index:-1}
@@ -31,12 +31,7 @@ div[data-monster-role=popper] {
31
31
 
32
32
  & > [part=content][data-monster-overflow-mode=horizontal] {
33
33
  overflow: visible;
34
- clip-path: inset(
35
- calc(-1 * var(--monster-popper-content-block-overflow, 100vh))
36
- 0
37
- calc(-1 * var(--monster-popper-content-block-overflow, 100vh))
38
- 0
39
- );
34
+ clip-path: none;
40
35
  }
41
36
 
42
37
  & > [part=content][data-monster-overflow-mode=visible] {
@@ -24,7 +24,7 @@ const FloatingUiStyleSheet = new CSSStyleSheet();
24
24
  try {
25
25
  FloatingUiStyleSheet.insertRule(`
26
26
  @layer floatingui {
27
- div[data-monster-role=popper]{align-content:center;background:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);box-sizing:border-box;color:var(--monster-color-primary-1);display:none;justify-content:space-between;left:0;max-height:var(--monster-popper-max-height,calc(100vh - 2rem));max-width:var(--monster-popper-max-width,calc(100vw - 2rem));padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper]>[part=content]{max-height:var(--monster-popper-content-max-height,calc(100vh - 4.2rem));max-width:100%;overflow:auto}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=horizontal]{clip-path:inset(calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0 calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0);overflow:visible}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=visible]{clip-path:none;max-height:none;max-width:none;overflow:visible}div[data-monster-role=popper] div[data-monster-role=arrow]{background:var(--monster-bg-color-primary-1);height:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);pointer-events:none;position:absolute;width:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);z-index:-1}
27
+ div[data-monster-role=popper]{align-content:center;background:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);box-sizing:border-box;color:var(--monster-color-primary-1);display:none;justify-content:space-between;left:0;max-height:var(--monster-popper-max-height,calc(100vh - 2rem));max-width:var(--monster-popper-max-width,calc(100vw - 2rem));padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper]>[part=content]{max-height:var(--monster-popper-content-max-height,calc(100vh - 4.2rem));max-width:100%;overflow:auto}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=horizontal]{clip-path:none;overflow:visible}div[data-monster-role=popper]>[part=content][data-monster-overflow-mode=visible]{clip-path:none;max-height:none;max-width:none;overflow:visible}div[data-monster-role=popper] div[data-monster-role=arrow]{background:var(--monster-bg-color-primary-1);height:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);pointer-events:none;position:absolute;width:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);z-index:-1}
28
28
  }`, 0);
29
29
  } catch (e) {
30
30
  addAttributeToken(document.getRootNode().querySelector('html'), ATTRIBUTE_ERRORMESSAGE, e + "");
@@ -0,0 +1,61 @@
1
+ import * as chai from "chai";
2
+ import { initJSDOM } from "../../../util/jsdom.mjs";
3
+
4
+ let expect = chai.expect;
5
+
6
+ let resolveClippingBoundaryElement;
7
+
8
+ describe("form floating-ui boundary resolution", function () {
9
+ before(function (done) {
10
+ initJSDOM()
11
+ .then(() => {
12
+ return import(
13
+ "../../../../source/components/form/util/floating-ui.mjs"
14
+ );
15
+ })
16
+ .then((m) => {
17
+ resolveClippingBoundaryElement = m.resolveClippingBoundaryElement;
18
+ done();
19
+ })
20
+ .catch((e) => done(e));
21
+ });
22
+
23
+ afterEach(() => {
24
+ const mocks = document.getElementById("mocks");
25
+ mocks.innerHTML = "";
26
+ });
27
+
28
+ it("should ignore parent popper content wrappers as clipping boundaries for nested controls", function () {
29
+ const mocks = document.getElementById("mocks");
30
+ const wrapper = document.createElement("div");
31
+ const popperHost = document.createElement("div");
32
+ const selectHost = document.createElement("div");
33
+
34
+ wrapper.style.overflow = "hidden";
35
+ mocks.appendChild(wrapper);
36
+ wrapper.appendChild(popperHost);
37
+
38
+ const popperShadow = popperHost.attachShadow({ mode: "open" });
39
+ popperShadow.innerHTML = `
40
+ <div data-monster-role="popper">
41
+ <div part="content"
42
+ data-monster-overflow-mode="both"
43
+ style="overflow: auto;">
44
+ </div>
45
+ </div>
46
+ `;
47
+
48
+ popperShadow.querySelector('[part="content"]').appendChild(selectHost);
49
+
50
+ const selectShadow = selectHost.attachShadow({ mode: "open" });
51
+ selectShadow.innerHTML = `
52
+ <div data-monster-role="control"></div>
53
+ <div data-monster-role="popper"></div>
54
+ `;
55
+
56
+ const control = selectShadow.querySelector('[data-monster-role="control"]');
57
+ const popper = selectShadow.querySelector('[data-monster-role="popper"]');
58
+
59
+ expect(resolveClippingBoundaryElement(control, popper)).to.equal(wrapper);
60
+ });
61
+ });
@@ -62,6 +62,37 @@ describe("PopperButton", function () {
62
62
  }, 0);
63
63
  });
64
64
 
65
+ it("should resolve nested overlay content to horizontal overflow by default", function (done) {
66
+ let mocks = document.getElementById("mocks");
67
+ const button = document.createElement("monster-popper-button");
68
+ mocks.appendChild(button);
69
+
70
+ setTimeout(() => {
71
+ try {
72
+ const content = button.shadowRoot.querySelector('[part="content"]');
73
+ expect(content).to.exist;
74
+
75
+ button.setOption(
76
+ "content",
77
+ "<div><monster-select></monster-select></div>",
78
+ );
79
+
80
+ setTimeout(() => {
81
+ try {
82
+ expect(
83
+ content.getAttribute("data-monster-overflow-mode"),
84
+ ).to.equal("horizontal");
85
+ done();
86
+ } catch (e) {
87
+ done(e);
88
+ }
89
+ }, 0);
90
+ } catch (e) {
91
+ done(e);
92
+ }
93
+ }, 0);
94
+ });
95
+
65
96
  it("should apply visible content overflow mode to the rendered content wrapper", function (done) {
66
97
  let mocks = document.getElementById("mocks");
67
98
  const button = document.createElement("monster-popper-button");