@schukai/monster 4.136.26 → 4.136.27

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.26"}
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.27"}
@@ -456,7 +456,10 @@ function applyOverlayAwareContentHeight(
456
456
  preferredHeight > contentMaxHeight;
457
457
 
458
458
  contentElement.style.removeProperty("overflow");
459
- contentElement.style.overflowX = "visible";
459
+ contentElement.style.overflowX =
460
+ contentElement.dataset.monsterOverflowMode === "horizontal"
461
+ ? "auto"
462
+ : "visible";
460
463
  contentElement.style.overflowY = isConstrained ? "auto" : "visible";
461
464
 
462
465
  if (Number.isFinite(constrainedHeight) && constrainedHeight > 0) {
@@ -203,6 +203,9 @@ class Tabs extends CustomElement {
203
203
  standard: [],
204
204
  popper: [],
205
205
  },
206
+ updater: {
207
+ batchUpdates: true,
208
+ },
206
209
  fetch: {
207
210
  redirect: "error",
208
211
  method: "GET",
@@ -43,7 +43,8 @@ div[data-monster-role="popper"] > [part="content"] {
43
43
  div[data-monster-role="popper"]
44
44
  > [part="content"][data-monster-overflow-mode="horizontal"] {
45
45
  clip-path: none;
46
- overflow: visible;
46
+ overflow-x: auto;
47
+ overflow-y: visible;
47
48
  }
48
49
  div[data-monster-role="popper"]
49
50
  > [part="content"][data-monster-overflow-mode="visible"] {
@@ -47,7 +47,8 @@ div[data-monster-role=popper] {
47
47
  }
48
48
 
49
49
  & > [part=content][data-monster-overflow-mode=horizontal] {
50
- overflow: visible;
50
+ overflow-x: auto;
51
+ overflow-y: visible;
51
52
  clip-path: none;
52
53
  }
53
54
 
@@ -25,7 +25,7 @@ try {
25
25
  FloatingUiStyleSheet.insertRule(
26
26
  `
27
27
  @layer floatingui {
28
- 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));opacity:1;padding:1.1em;position:absolute;top:0;transition:opacity var(--monster-popper-fade-duration,.14s) var(--monster-popper-fade-timing,cubic-bezier(.2,0,0,1));width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper][data-monster-appearance=opening]{opacity:0}div[data-monster-role=popper][data-monster-appearance=open]{opacity:1}@media (prefers-reduced-motion:reduce){div[data-monster-role=popper]{transition:none}}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
+ 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));opacity:1;padding:1.1em;position:absolute;top:0;transition:opacity var(--monster-popper-fade-duration,.14s) var(--monster-popper-fade-timing,cubic-bezier(.2,0,0,1));width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper][data-monster-appearance=opening]{opacity:0}div[data-monster-role=popper][data-monster-appearance=open]{opacity:1}@media (prefers-reduced-motion:reduce){div[data-monster-role=popper]{transition:none}}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-x:auto;overflow-y: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}
29
29
  }`,
30
30
  0,
31
31
  );
@@ -310,4 +310,29 @@ describe("form floating-ui boundary resolution", function () {
310
310
  expect(popper.style.width).to.equal("240px");
311
311
  expect(popper.style.minWidth).to.equal("240px");
312
312
  });
313
+
314
+ it("should constrain horizontal overlay-aware content on the inline axis", function () {
315
+ const mocks = document.getElementById("mocks");
316
+ const popper = document.createElement("div");
317
+ const content = document.createElement("div");
318
+
319
+ content.setAttribute("part", "content");
320
+ content.setAttribute("data-monster-overflow-mode", "horizontal");
321
+
322
+ Object.defineProperty(content, "scrollHeight", {
323
+ configurable: true,
324
+ value: 120,
325
+ });
326
+
327
+ popper.appendChild(content);
328
+ mocks.appendChild(popper);
329
+
330
+ applyAdaptiveFloatingElementSize(popper, {
331
+ availableWidth: 240,
332
+ availableHeight: 200,
333
+ });
334
+
335
+ expect(content.style.overflowX).to.equal("auto");
336
+ expect(content.style.overflowY).to.equal("visible");
337
+ });
313
338
  });
@@ -2,6 +2,7 @@ import {getGlobal} from "../../../../source/types/global.mjs";
2
2
  import * as chai from 'chai';
3
3
  import {chaiDom} from "../../../util/chai-dom.mjs";
4
4
  import {initJSDOM} from "../../../util/jsdom.mjs";
5
+ import {ResizeObserverMock} from "../../../util/resize-observer.mjs";
5
6
 
6
7
  let expect = chai.expect;
7
8
  chai.use(chaiDom);
@@ -61,6 +62,35 @@ let htmlOverflow = `
61
62
  `;
62
63
 
63
64
  let Tabs;
65
+ let restoreBoundingClientRect = null;
66
+ let restoreResizeObserver = null;
67
+
68
+ function waitForCondition(check, {timeout = 4000, interval = 10} = {}) {
69
+ const startedAt = Date.now();
70
+
71
+ return new Promise((resolve, reject) => {
72
+ const tick = () => {
73
+ try {
74
+ if (check() === true) {
75
+ resolve();
76
+ return;
77
+ }
78
+ } catch (e) {
79
+ reject(e);
80
+ return;
81
+ }
82
+
83
+ if (Date.now() - startedAt > timeout) {
84
+ reject(new Error('condition timed out'));
85
+ return;
86
+ }
87
+
88
+ setTimeout(tick, interval);
89
+ };
90
+
91
+ tick();
92
+ });
93
+ }
64
94
 
65
95
  describe('Tabs', function () {
66
96
 
@@ -92,6 +122,14 @@ describe('Tabs', function () {
92
122
  describe('document.createElement()', function () {
93
123
 
94
124
  afterEach(() => {
125
+ if (restoreBoundingClientRect instanceof Function) {
126
+ restoreBoundingClientRect();
127
+ restoreBoundingClientRect = null;
128
+ }
129
+ if (restoreResizeObserver instanceof Function) {
130
+ restoreResizeObserver();
131
+ restoreResizeObserver = null;
132
+ }
95
133
  let mocks = document.getElementById('mocks');
96
134
  mocks.innerHTML = "";
97
135
  })
@@ -219,10 +257,35 @@ describe('Tabs', function () {
219
257
  });
220
258
 
221
259
  it('should move overflowing tabs into the popper without losing them', function (done) {
260
+ this.timeout(5000);
222
261
 
223
262
  let mocks = document.getElementById('mocks');
263
+ const OriginalResizeObserver = window.ResizeObserver;
264
+ const originalGlobalResizeObserver = global.ResizeObserver;
265
+ class TrackingResizeObserver extends ResizeObserverMock {
266
+ static instances = [];
267
+ static callbackCount = 0;
268
+
269
+ constructor(callback) {
270
+ super((entries, observer) => {
271
+ TrackingResizeObserver.callbackCount++;
272
+ callback(entries, observer);
273
+ });
274
+ TrackingResizeObserver.instances.push(this);
275
+ }
276
+ }
277
+ window.ResizeObserver = TrackingResizeObserver;
278
+ global.ResizeObserver = TrackingResizeObserver;
279
+ restoreResizeObserver = () => {
280
+ window.ResizeObserver = OriginalResizeObserver;
281
+ global.ResizeObserver = originalGlobalResizeObserver;
282
+ };
224
283
  const originalGetBoundingClientRect =
225
284
  global.HTMLElement.prototype.getBoundingClientRect;
285
+ restoreBoundingClientRect = () => {
286
+ global.HTMLElement.prototype.getBoundingClientRect =
287
+ originalGetBoundingClientRect;
288
+ };
226
289
  global.HTMLElement.prototype.getBoundingClientRect = function () {
227
290
  const role = this.getAttribute?.('data-monster-role');
228
291
  const label = this.textContent?.trim() || '';
@@ -258,63 +321,90 @@ describe('Tabs', function () {
258
321
 
259
322
  mocks.innerHTML = htmlOverflow;
260
323
 
261
- setTimeout(() => {
324
+ waitForCondition(() => {
325
+ const tabs = document.getElementById('overflow-tabs');
326
+ const switchButton = tabs?.shadowRoot?.querySelector(
327
+ '[data-monster-role="switch"]',
328
+ );
329
+ const standardButtons = tabs?.getOption?.('buttons.standard') || [];
330
+ const popperButtons = tabs?.getOption?.('buttons.popper') || [];
331
+
332
+ return (
333
+ tabs instanceof Tabs &&
334
+ switchButton !== null &&
335
+ standardButtons.length > 0 &&
336
+ popperButtons.length > 0 &&
337
+ standardButtons.length + popperButtons.length === 11 &&
338
+ switchButton.classList.contains('hidden') === false
339
+ );
340
+ }).then(() => {
262
341
  try {
263
342
  const tabs = document.getElementById('overflow-tabs');
264
343
  expect(tabs).is.instanceof(Tabs);
265
-
266
- setTimeout(() => {
267
- try {
268
- const switchButton = tabs.shadowRoot.querySelector(
269
- '[data-monster-role="switch"]',
344
+ const switchButton = tabs.shadowRoot.querySelector(
345
+ '[data-monster-role="switch"]',
346
+ );
347
+ let standardButtons = tabs.getOption('buttons.standard');
348
+ let popperButtons = tabs.getOption('buttons.popper');
349
+
350
+ expect(switchButton).to.not.equal(null);
351
+ expect(standardButtons.length).to.be.greaterThan(0);
352
+ expect(popperButtons.length).to.be.greaterThan(0);
353
+ expect(standardButtons.length + popperButtons.length).to.equal(11);
354
+ expect(switchButton.classList.contains('hidden')).to.equal(false);
355
+
356
+ const resizeObserver = TrackingResizeObserver.instances.find(
357
+ (observer) => observer.elements.includes(tabs.shadowRoot.querySelector('[data-monster-role="nav"]')),
358
+ );
359
+ expect(resizeObserver).to.not.equal(undefined);
360
+ resizeObserver.triggerResize([]);
361
+
362
+ return waitForCondition(() => {
363
+ return (
364
+ TrackingResizeObserver.callbackCount > 0 &&
365
+ tabs.getOption('buttons.standard').length === 11 &&
366
+ tabs.getOption('buttons.popper').length === 0
367
+ );
368
+ }).then(() => {
369
+ return waitForCondition(() => {
370
+ standardButtons = tabs.getOption('buttons.standard');
371
+ popperButtons = tabs.getOption('buttons.popper');
372
+ return (
373
+ standardButtons.length > 0 &&
374
+ popperButtons.length > 0 &&
375
+ standardButtons.length + popperButtons.length === 11 &&
376
+ new Set(
377
+ standardButtons
378
+ .concat(popperButtons)
379
+ .map((button) => button.reference),
380
+ ).size === 11
270
381
  );
271
- let standardButtons = tabs.getOption('buttons.standard');
272
- let popperButtons = tabs.getOption('buttons.popper');
273
-
274
- expect(switchButton).to.not.equal(null);
275
- expect(standardButtons.length).to.be.greaterThan(0);
276
- expect(popperButtons.length).to.be.greaterThan(0);
277
- expect(
278
- standardButtons.length + popperButtons.length,
279
- ).to.equal(11);
280
- expect(switchButton.classList.contains('hidden')).to.equal(false);
281
-
282
- window.dispatchEvent(new Event('resize'));
283
- setTimeout(() => {
284
- try {
285
- standardButtons = tabs.getOption('buttons.standard');
286
- popperButtons = tabs.getOption('buttons.popper');
287
- expect(standardButtons.length).to.be.greaterThan(0);
288
- expect(popperButtons.length).to.be.greaterThan(0);
289
- expect(
290
- standardButtons.length + popperButtons.length,
291
- ).to.equal(11);
292
- expect(
293
- new Set(
294
- standardButtons.concat(popperButtons).map((button) => button.reference),
295
- ).size,
296
- ).to.equal(11);
297
- global.HTMLElement.prototype.getBoundingClientRect =
298
- originalGetBoundingClientRect;
299
- done();
300
- } catch (e) {
301
- global.HTMLElement.prototype.getBoundingClientRect =
302
- originalGetBoundingClientRect;
303
- done(e);
304
- }
305
- }, 250);
306
- } catch (e) {
307
- global.HTMLElement.prototype.getBoundingClientRect =
308
- originalGetBoundingClientRect;
309
- done(e);
310
- }
311
- }, 250);
382
+ });
383
+ }).then(() => {
384
+ restoreBoundingClientRect();
385
+ restoreBoundingClientRect = null;
386
+ restoreResizeObserver();
387
+ restoreResizeObserver = null;
388
+ done();
389
+ });
312
390
  } catch (e) {
313
- global.HTMLElement.prototype.getBoundingClientRect =
314
- originalGetBoundingClientRect;
391
+ restoreBoundingClientRect();
392
+ restoreBoundingClientRect = null;
393
+ restoreResizeObserver();
394
+ restoreResizeObserver = null;
315
395
  return done(e);
316
396
  }
317
- }, 0);
397
+ }).catch((e) => {
398
+ if (restoreBoundingClientRect instanceof Function) {
399
+ restoreBoundingClientRect();
400
+ restoreBoundingClientRect = null;
401
+ }
402
+ if (restoreResizeObserver instanceof Function) {
403
+ restoreResizeObserver();
404
+ restoreResizeObserver = null;
405
+ }
406
+ done(e);
407
+ });
318
408
  });
319
409
 
320
410
  });