@schukai/monster 4.136.18 → 4.136.19

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.18"}
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.19"}
@@ -286,12 +286,8 @@ function calcAndSetNavigationTopScrollableParentContext() {
286
286
 
287
287
  const parentRect = this[scrollableParentSymbol].getBoundingClientRect();
288
288
  const rect = this.getBoundingClientRect();
289
- const thisTop = rect.top - parentRect.top;
290
289
  const thisBottom = rect.bottom - parentRect.top;
291
- let top = 0;
292
- if (thisTop < 0) {
293
- top = -1 * thisTop;
294
- }
290
+ let top = this[scrollableParentSymbol].scrollTop || 0;
295
291
 
296
292
  const offset = this.getOption("offset");
297
293
  if (offset > 0) {
@@ -536,6 +532,20 @@ function initEventHandler() {
536
532
  * @return {HTMLElement|Window} - The found scrollable parent or the Window object.
537
533
  */
538
534
  function findScrollableParent(element) {
535
+ function isScrollable(elementToCheck) {
536
+ const styles = window.getComputedStyle(elementToCheck);
537
+ const overflowY = styles.overflowY;
538
+ const canScrollY =
539
+ (overflowY === "scroll" || overflowY === "auto") &&
540
+ elementToCheck.scrollHeight > elementToCheck.clientHeight;
541
+ const overflowX = styles.overflowX;
542
+ const canScrollX =
543
+ (overflowX === "scroll" || overflowX === "auto") &&
544
+ elementToCheck.scrollWidth > elementToCheck.clientWidth;
545
+
546
+ return canScrollY || canScrollX;
547
+ }
548
+
539
549
  // Helper function to find the next parent element, checking for Shadow DOM
540
550
  function getNextParent(elem) {
541
551
  // If the element is in a Shadow DOM, attempt to climb up to the host
@@ -551,9 +561,7 @@ function findScrollableParent(element) {
551
561
 
552
562
  let parent = getNextParent(element);
553
563
  while (parent) {
554
- // Check the scroll properties of the element
555
- const overflowY = window.getComputedStyle(parent).overflowY;
556
- if (overflowY === "scroll" || overflowY === "auto") {
564
+ if (isScrollable(parent)) {
557
565
  return parent;
558
566
  }
559
567
  parent = getNextParent(parent); // Move to the next parent element
@@ -0,0 +1,115 @@
1
+ 'use strict';
2
+
3
+ import * as chai from 'chai';
4
+ import { getDocument } from "../../../../source/dom/util.mjs";
5
+ import { chaiDom } from "../../../util/chai-dom.mjs";
6
+ import { initJSDOM } from "../../../util/jsdom.mjs";
7
+
8
+ let expect = chai.expect;
9
+ chai.use(chaiDom);
10
+
11
+ describe('TableOfContent', function () {
12
+ this.timeout(10000);
13
+
14
+ let document;
15
+
16
+ before(async function () {
17
+ await initJSDOM({});
18
+ globalThis.IntersectionObserver = class {
19
+ observe() {}
20
+ disconnect() {}
21
+ unobserve() {}
22
+ };
23
+ globalThis.HTMLHeadingElement ??= globalThis.HTMLElement;
24
+ await import("../../../../source/components/navigation/table-of-content.mjs");
25
+ document = getDocument();
26
+ });
27
+
28
+ beforeEach(() => {
29
+ let mocks = document.getElementById('mocks');
30
+ mocks.innerHTML = '<div id="target"></div>';
31
+ });
32
+
33
+ afterEach(() => {
34
+ let mocks = document.getElementById('mocks');
35
+ mocks.innerHTML = '';
36
+ });
37
+
38
+ it('should bind to the first actually scrollable parent', function (done) {
39
+ const target = document.getElementById('target');
40
+ const outerScroller = document.createElement('div');
41
+ const innerWrapper = document.createElement('div');
42
+ const tableOfContent = document.createElement('monster-table-of-content');
43
+ const heading = document.createElement('h2');
44
+ const paragraph = document.createElement('p');
45
+
46
+ heading.textContent = 'Introduction';
47
+ paragraph.textContent = 'Content';
48
+ tableOfContent.appendChild(heading);
49
+ tableOfContent.appendChild(paragraph);
50
+
51
+ Object.defineProperties(outerScroller, {
52
+ clientHeight: { configurable: true, value: 200 },
53
+ scrollHeight: { configurable: true, value: 600 },
54
+ clientWidth: { configurable: true, value: 300 },
55
+ scrollWidth: { configurable: true, value: 300 },
56
+ });
57
+
58
+ Object.defineProperties(innerWrapper, {
59
+ clientHeight: { configurable: true, value: 400 },
60
+ scrollHeight: { configurable: true, value: 400 },
61
+ clientWidth: { configurable: true, value: 300 },
62
+ scrollWidth: { configurable: true, value: 300 },
63
+ });
64
+
65
+ outerScroller.style.overflowY = 'auto';
66
+ innerWrapper.style.overflowY = 'auto';
67
+
68
+ outerScroller.getBoundingClientRect = () => ({
69
+ top: 0,
70
+ bottom: 200,
71
+ left: 0,
72
+ right: 300,
73
+ width: 300,
74
+ height: 200,
75
+ x: 0,
76
+ y: 0,
77
+ });
78
+
79
+ tableOfContent.getBoundingClientRect = () => ({
80
+ top: outerScroller.scrollTop ? -20 : 100,
81
+ bottom: outerScroller.scrollTop ? 80 : 200,
82
+ left: 0,
83
+ right: 300,
84
+ width: 300,
85
+ height: 100,
86
+ x: 0,
87
+ y: outerScroller.scrollTop ? -20 : 100,
88
+ });
89
+
90
+ innerWrapper.appendChild(tableOfContent);
91
+ outerScroller.appendChild(innerWrapper);
92
+ target.appendChild(outerScroller);
93
+
94
+ setTimeout(() => {
95
+ try {
96
+ const navigation = tableOfContent.shadowRoot.querySelector('.navigation');
97
+ expect(navigation.style.top).to.equal('50px');
98
+
99
+ outerScroller.scrollTop = 120;
100
+ outerScroller.dispatchEvent(new window.Event('scroll'));
101
+
102
+ setTimeout(() => {
103
+ try {
104
+ expect(navigation.style.top).to.equal('170px');
105
+ done();
106
+ } catch (error) {
107
+ done(error);
108
+ }
109
+ }, 20);
110
+ } catch (error) {
111
+ done(error);
112
+ }
113
+ }, 30);
114
+ });
115
+ });