@schukai/monster 4.43.15 → 4.43.16
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/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.7.4","@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.43.
|
|
1
|
+
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.7.4","@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.43.16"}
|
|
@@ -111,7 +111,6 @@ class SiteNavigation extends CustomElement {
|
|
|
111
111
|
requestAnimationFrame(() => {
|
|
112
112
|
populateTabs.call(this);
|
|
113
113
|
});
|
|
114
|
-
|
|
115
114
|
}
|
|
116
115
|
|
|
117
116
|
disconnectedCallback() {
|
|
@@ -304,7 +303,7 @@ function detachResizeObserver() {
|
|
|
304
303
|
}
|
|
305
304
|
|
|
306
305
|
/**
|
|
307
|
-
* Sets up interaction logic (hover or
|
|
306
|
+
* Sets up interaction logic (hover, click, or touch) for a submenu.
|
|
308
307
|
* This function is called recursively for nested submenus.
|
|
309
308
|
* @private
|
|
310
309
|
* @this {SiteNavigation}
|
|
@@ -323,111 +322,174 @@ function setupSubmenu(parentLi, context = "visible", level = 1) {
|
|
|
323
322
|
}
|
|
324
323
|
|
|
325
324
|
const interaction = this.getOption("interactionModel", "auto");
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
(interaction === "auto" && context === "visible");
|
|
325
|
+
const isTouchDevice =
|
|
326
|
+
"ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
329
327
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
328
|
+
const effectiveInteraction =
|
|
329
|
+
interaction === "auto"
|
|
330
|
+
? context === "visible"
|
|
331
|
+
? "hover"
|
|
332
|
+
: "click"
|
|
333
|
+
: interaction;
|
|
334
|
+
|
|
335
|
+
const component = this;
|
|
336
|
+
let cleanup;
|
|
335
337
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
338
|
+
const immediateHide = () => {
|
|
339
|
+
submenu.style.display = "none";
|
|
340
|
+
Object.assign(submenu.style, {
|
|
341
|
+
maxHeight: "",
|
|
342
|
+
overflowY: "",
|
|
343
|
+
});
|
|
344
|
+
submenu
|
|
345
|
+
.querySelectorAll(
|
|
346
|
+
"ul[style*='display: block'], div[part='mega-menu'][style*='display: block']",
|
|
347
|
+
)
|
|
348
|
+
.forEach((sub) => {
|
|
349
|
+
sub.style.display = "none";
|
|
341
350
|
});
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
351
|
+
fireCustomEvent(this, "monster-submenu-hide", {
|
|
352
|
+
context,
|
|
353
|
+
trigger: parentLi,
|
|
354
|
+
submenu,
|
|
355
|
+
level,
|
|
356
|
+
});
|
|
357
|
+
if (cleanup) {
|
|
358
|
+
cleanup();
|
|
359
|
+
cleanup = null;
|
|
360
|
+
}
|
|
361
|
+
if (level === 1 && component[activeSubmenuHiderSymbol] === immediateHide) {
|
|
362
|
+
component[activeSubmenuHiderSymbol] = null;
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
const show = () => {
|
|
367
|
+
component[hideHamburgerMenuSymbol]?.();
|
|
368
|
+
if (level === 1) {
|
|
369
|
+
if (
|
|
370
|
+
component[activeSubmenuHiderSymbol] &&
|
|
371
|
+
component[activeSubmenuHiderSymbol] !== immediateHide
|
|
372
|
+
) {
|
|
373
|
+
component[activeSubmenuHiderSymbol]();
|
|
374
|
+
}
|
|
375
|
+
component[activeSubmenuHiderSymbol] = immediateHide;
|
|
376
|
+
} else {
|
|
377
|
+
[...parentLi.parentElement.children]
|
|
378
|
+
.filter((li) => li !== parentLi)
|
|
379
|
+
.forEach((sibling) => {
|
|
380
|
+
const siblingSubmenu = sibling.querySelector(
|
|
381
|
+
":scope > ul, :scope > div[part='mega-menu']",
|
|
382
|
+
);
|
|
383
|
+
if (siblingSubmenu) {
|
|
384
|
+
siblingSubmenu.style.display = "none";
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
submenu.style.display = "block";
|
|
389
|
+
fireCustomEvent(this, "monster-submenu-show", {
|
|
390
|
+
context,
|
|
391
|
+
trigger: parentLi,
|
|
392
|
+
submenu,
|
|
393
|
+
level,
|
|
394
|
+
});
|
|
395
|
+
if (!cleanup) {
|
|
396
|
+
cleanup = autoUpdate(parentLi, submenu, () => {
|
|
397
|
+
const middleware = [offset(8), flip(), shift({ padding: 8 })];
|
|
398
|
+
const containsSubmenus = submenu.querySelector(
|
|
399
|
+
"ul, div[part='mega-menu']",
|
|
400
|
+
);
|
|
401
|
+
if (!containsSubmenus) {
|
|
402
|
+
middleware.push(
|
|
403
|
+
size({
|
|
404
|
+
apply: ({ availableHeight, elements }) => {
|
|
405
|
+
Object.assign(elements.floating.style, {
|
|
406
|
+
maxHeight: `${availableHeight}px`,
|
|
407
|
+
overflowY: "auto",
|
|
408
|
+
});
|
|
409
|
+
},
|
|
410
|
+
padding: 8,
|
|
411
|
+
}),
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
computePosition(parentLi, submenu, {
|
|
415
|
+
placement: level === 1 ? "bottom-start" : "right-start",
|
|
416
|
+
middleware: middleware,
|
|
417
|
+
}).then(({ x, y, strategy }) => {
|
|
418
|
+
Object.assign(submenu.style, {
|
|
419
|
+
position: strategy,
|
|
420
|
+
left: `${x}px`,
|
|
421
|
+
top: `${y}px`,
|
|
422
|
+
});
|
|
348
423
|
});
|
|
349
|
-
fireCustomEvent(this, "monster-submenu-hide", {
|
|
350
|
-
context,
|
|
351
|
-
trigger: parentLi,
|
|
352
|
-
submenu,
|
|
353
|
-
level,
|
|
354
424
|
});
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
if (effectiveInteraction === "hover" && isTouchDevice) {
|
|
429
|
+
let lastTap = 0;
|
|
430
|
+
const DOUBLE_TAP_DELAY = 300;
|
|
431
|
+
const anchor = parentLi.querySelector(":scope > a");
|
|
432
|
+
|
|
433
|
+
if (!anchor) return;
|
|
434
|
+
|
|
435
|
+
const handleOutsideClickForSubmenu = (event) => {
|
|
359
436
|
if (
|
|
360
|
-
|
|
361
|
-
|
|
437
|
+
submenu.style.display === "block" &&
|
|
438
|
+
!parentLi.contains(event.target)
|
|
362
439
|
) {
|
|
363
|
-
|
|
440
|
+
immediateHide();
|
|
441
|
+
document.removeEventListener(
|
|
442
|
+
"click",
|
|
443
|
+
handleOutsideClickForSubmenu,
|
|
444
|
+
true,
|
|
445
|
+
);
|
|
364
446
|
}
|
|
365
447
|
};
|
|
366
448
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
449
|
+
anchor.addEventListener("click", (event) => {
|
|
450
|
+
const now = Date.now();
|
|
451
|
+
const timeSinceLastTap = now - lastTap;
|
|
452
|
+
lastTap = now;
|
|
453
|
+
|
|
454
|
+
if (timeSinceLastTap < DOUBLE_TAP_DELAY && timeSinceLastTap > 0) {
|
|
455
|
+
lastTap = 0;
|
|
456
|
+
document.removeEventListener(
|
|
457
|
+
"click",
|
|
458
|
+
handleOutsideClickForSubmenu,
|
|
459
|
+
true,
|
|
460
|
+
);
|
|
461
|
+
immediateHide();
|
|
377
462
|
} else {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
submenu.style.display = "block";
|
|
390
|
-
fireCustomEvent(this, "monster-submenu-show", {
|
|
391
|
-
context,
|
|
392
|
-
trigger: parentLi,
|
|
393
|
-
submenu,
|
|
394
|
-
level,
|
|
395
|
-
});
|
|
396
|
-
if (!cleanup) {
|
|
397
|
-
cleanup = autoUpdate(parentLi, submenu, () => {
|
|
398
|
-
const middleware = [offset(8), flip(), shift({ padding: 8 })];
|
|
399
|
-
const containsSubmenus = submenu.querySelector(
|
|
400
|
-
"ul, div[part='mega-menu']",
|
|
463
|
+
event.preventDefault();
|
|
464
|
+
event.stopPropagation();
|
|
465
|
+
|
|
466
|
+
const isMenuOpen = submenu.style.display === "block";
|
|
467
|
+
|
|
468
|
+
if (isMenuOpen) {
|
|
469
|
+
document.removeEventListener(
|
|
470
|
+
"click",
|
|
471
|
+
handleOutsideClickForSubmenu,
|
|
472
|
+
true,
|
|
401
473
|
);
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
},
|
|
411
|
-
padding: 8,
|
|
412
|
-
}),
|
|
474
|
+
immediateHide();
|
|
475
|
+
} else {
|
|
476
|
+
show();
|
|
477
|
+
setTimeout(() => {
|
|
478
|
+
document.addEventListener(
|
|
479
|
+
"click",
|
|
480
|
+
handleOutsideClickForSubmenu,
|
|
481
|
+
true,
|
|
413
482
|
);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
placement: level === 1 ? "bottom-start" : "right-start",
|
|
417
|
-
middleware: middleware,
|
|
418
|
-
}).then(({ x, y, strategy }) => {
|
|
419
|
-
Object.assign(submenu.style, {
|
|
420
|
-
position: strategy,
|
|
421
|
-
left: `${x}px`,
|
|
422
|
-
top: `${y}px`,
|
|
423
|
-
});
|
|
424
|
-
});
|
|
425
|
-
});
|
|
483
|
+
}, 0);
|
|
484
|
+
}
|
|
426
485
|
}
|
|
427
|
-
};
|
|
486
|
+
});
|
|
487
|
+
} else if (effectiveInteraction === "hover" && !isTouchDevice) {
|
|
488
|
+
let hideTimeout;
|
|
489
|
+
let isHovering = false;
|
|
428
490
|
|
|
429
491
|
const handleMouseEnter = () => {
|
|
430
|
-
isHovering = true;
|
|
492
|
+
isHovering = true;
|
|
431
493
|
clearTimeout(hideTimeout);
|
|
432
494
|
if (submenu.style.display !== "block") {
|
|
433
495
|
show();
|
|
@@ -435,7 +497,7 @@ function setupSubmenu(parentLi, context = "visible", level = 1) {
|
|
|
435
497
|
};
|
|
436
498
|
|
|
437
499
|
const handleMouseLeave = () => {
|
|
438
|
-
isHovering = false;
|
|
500
|
+
isHovering = false;
|
|
439
501
|
hideTimeout = setTimeout(() => {
|
|
440
502
|
if (!isHovering) {
|
|
441
503
|
immediateHide();
|
|
@@ -524,7 +586,6 @@ function cloneNavItem(item) {
|
|
|
524
586
|
* @this {SiteNavigation}
|
|
525
587
|
*/
|
|
526
588
|
function populateTabs() {
|
|
527
|
-
|
|
528
589
|
const visibleList = this[visibleElementsSymbol];
|
|
529
590
|
const hiddenList = this[hiddenElementsSymbol];
|
|
530
591
|
const hamburgerButton = this[hamburgerButtonSymbol];
|
|
@@ -551,7 +612,6 @@ function populateTabs() {
|
|
|
551
612
|
return;
|
|
552
613
|
}
|
|
553
614
|
|
|
554
|
-
|
|
555
615
|
const navWidth = navEl.clientWidth;
|
|
556
616
|
|
|
557
617
|
const originalDisplay = hamburgerButton.style.display;
|
|
@@ -607,7 +667,7 @@ function populateTabs() {
|
|
|
607
667
|
visibleList.appendChild(firstHiddenItemClone);
|
|
608
668
|
const firstHiddenItemWidth =
|
|
609
669
|
firstHiddenItemClone.getBoundingClientRect().width;
|
|
610
|
-
visibleList.removeChild(firstHiddenItemClone);
|
|
670
|
+
visibleList.removeChild(firstHiddenItemClone);
|
|
611
671
|
|
|
612
672
|
const gap = parseFloat(getComputedStyle(visibleList).gap || "0") || 0;
|
|
613
673
|
if (visibleItemsWidth + gap + firstHiddenItemWidth <= navWidth) {
|