@schukai/monster 4.136.29 → 4.136.30

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.136.29"}
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.136.30"}
@@ -42,6 +42,7 @@ const floatingResizeObserverMap = new WeakMap();
42
42
  const floatingSyncCycleMap = new WeakMap();
43
43
  const floatingAppearanceFrameMap = new WeakMap();
44
44
  const floatingAppearanceTimeoutMap = new WeakMap();
45
+ const adaptiveScrollHeightDatasetKey = "monsterAdaptiveScrollHeight";
45
46
 
46
47
  /**
47
48
  * @private
@@ -417,13 +418,16 @@ function applyAdaptiveFloatingContentSize(floatingElement, maxHeight) {
417
418
  if (overflowMode === "horizontal" || overflowMode === "both") {
418
419
  // Overlay-aware modes keep the parent wrapper sized to the real inline content.
419
420
  // Nested poppers may still escape, but they must not inflate the outer popper height.
420
- applyOverlayAwareContentHeight(
421
+ const contentHeightConstrained = applyOverlayAwareContentHeight(
421
422
  contentElement,
422
423
  preferredContentHeight,
423
424
  nextContentMaxHeight,
424
425
  minimumReadableHeight,
425
426
  );
426
- syncNestedScrollContainerHeight(contentElement, nextContentMaxHeight);
427
+ syncNestedScrollContainerHeight(
428
+ contentElement,
429
+ contentHeightConstrained ? nextContentMaxHeight : null,
430
+ );
427
431
  return;
428
432
  }
429
433
 
@@ -462,14 +466,25 @@ function applyOverlayAwareContentHeight(
462
466
  : "visible";
463
467
  contentElement.style.overflowY = isConstrained ? "auto" : "visible";
464
468
 
465
- if (Number.isFinite(constrainedHeight) && constrainedHeight > 0) {
469
+ if (
470
+ isConstrained &&
471
+ Number.isFinite(constrainedHeight) &&
472
+ constrainedHeight > 0
473
+ ) {
466
474
  contentElement.style.height = `${constrainedHeight}px`;
467
475
  contentElement.style.maxHeight = `${constrainedHeight}px`;
468
- return;
476
+ return true;
469
477
  }
470
478
 
479
+ // overflow-x:auto computes overflow-y to auto in browsers, so an unconstrained
480
+ // horizontal wrapper must keep its natural height to avoid a spurious scrollbar.
471
481
  contentElement.style.removeProperty("height");
472
- contentElement.style.removeProperty("maxHeight");
482
+ if (Number.isFinite(contentMaxHeight) && contentMaxHeight > 0) {
483
+ contentElement.style.maxHeight = `${contentMaxHeight}px`;
484
+ } else {
485
+ contentElement.style.removeProperty("maxHeight");
486
+ }
487
+ return false;
473
488
  }
474
489
 
475
490
  function getFloatingContentElement(floatingElement) {
@@ -591,11 +606,19 @@ function syncNestedScrollContainerHeight(contentElement, contentMaxHeight) {
591
606
  );
592
607
  nestedScrollableElement.style.height = `${nextNestedHeight}px`;
593
608
  nestedScrollableElement.style.maxHeight = `${nextNestedHeight}px`;
609
+ nestedScrollableElement.dataset[adaptiveScrollHeightDatasetKey] = "true";
610
+ return;
611
+ }
612
+
613
+ if (
614
+ nestedScrollableElement.dataset[adaptiveScrollHeightDatasetKey] !== "true"
615
+ ) {
594
616
  return;
595
617
  }
596
618
 
597
619
  nestedScrollableElement.style.height = "";
598
620
  nestedScrollableElement.style.maxHeight = "";
621
+ delete nestedScrollableElement.dataset[adaptiveScrollHeightDatasetKey];
599
622
  }
600
623
 
601
624
  function resolveNestedScrollContainerHeight(
@@ -723,6 +746,7 @@ function resetAdaptiveFloatingElementSize(floatingElement) {
723
746
 
724
747
  nestedScrollableElement.style.removeProperty("height");
725
748
  nestedScrollableElement.style.removeProperty("maxHeight");
749
+ delete nestedScrollableElement.dataset[adaptiveScrollHeightDatasetKey];
726
750
  }
727
751
 
728
752
  function runFloatingUpdateHook(popperElement) {
@@ -334,5 +334,68 @@ describe("form floating-ui boundary resolution", function () {
334
334
 
335
335
  expect(content.style.overflowX).to.equal("auto");
336
336
  expect(content.style.overflowY).to.equal("visible");
337
+ expect(content.style.height).to.equal("");
338
+ expect(content.style.maxHeight).to.equal("200px");
339
+ });
340
+
341
+ it("should preserve declared nested scroll height when horizontal overlay content fits", function () {
342
+ const mocks = document.getElementById("mocks");
343
+ const popper = document.createElement("div");
344
+ const content = document.createElement("div");
345
+ const options = document.createElement("div");
346
+
347
+ content.setAttribute("part", "content");
348
+ content.setAttribute("data-monster-overflow-mode", "horizontal");
349
+ options.style.overflowY = "auto";
350
+ options.style.height = "72px";
351
+ options.style.maxHeight = "72px";
352
+
353
+ Object.defineProperty(content, "scrollHeight", {
354
+ configurable: true,
355
+ value: 120,
356
+ });
357
+ Object.defineProperty(options, "scrollHeight", {
358
+ configurable: true,
359
+ value: 72,
360
+ });
361
+
362
+ content.appendChild(options);
363
+ popper.appendChild(content);
364
+ mocks.appendChild(popper);
365
+
366
+ applyAdaptiveFloatingElementSize(popper, {
367
+ availableWidth: 240,
368
+ availableHeight: 200,
369
+ });
370
+
371
+ expect(options.style.height).to.equal("72px");
372
+ expect(options.style.maxHeight).to.equal("72px");
373
+ });
374
+
375
+ it("should constrain horizontal overlay-aware content height only when it exceeds available height", function () {
376
+ const mocks = document.getElementById("mocks");
377
+ const popper = document.createElement("div");
378
+ const content = document.createElement("div");
379
+
380
+ content.setAttribute("part", "content");
381
+ content.setAttribute("data-monster-overflow-mode", "horizontal");
382
+
383
+ Object.defineProperty(content, "scrollHeight", {
384
+ configurable: true,
385
+ value: 320,
386
+ });
387
+
388
+ popper.appendChild(content);
389
+ mocks.appendChild(popper);
390
+
391
+ applyAdaptiveFloatingElementSize(popper, {
392
+ availableWidth: 240,
393
+ availableHeight: 200,
394
+ });
395
+
396
+ expect(content.style.overflowX).to.equal("auto");
397
+ expect(content.style.overflowY).to.equal("auto");
398
+ expect(content.style.height).to.equal("200px");
399
+ expect(content.style.maxHeight).to.equal("200px");
337
400
  });
338
401
  });