@schukai/monster 4.140.3 → 4.141.0
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.
|
|
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.141.0"}
|
|
@@ -179,6 +179,13 @@ const ATTRIBUTE_OPTION_LAYOUT_ALIGNMENT =
|
|
|
179
179
|
const ATTRIBUTE_OPTION_LAYOUT_STACKED_ALIGNMENT =
|
|
180
180
|
"data-monster-option-layout-stacked-alignment";
|
|
181
181
|
|
|
182
|
+
/**
|
|
183
|
+
* @private
|
|
184
|
+
* @type {string}
|
|
185
|
+
*/
|
|
186
|
+
const ATTRIBUTE_OPTION_LAYOUT_STACKED_BREAKPOINT =
|
|
187
|
+
"data-monster-option-layout-stacked-breakpoint";
|
|
188
|
+
|
|
182
189
|
/**
|
|
183
190
|
* @private
|
|
184
191
|
* @type {string}
|
|
@@ -233,6 +240,7 @@ class ControlBar extends CustomElement {
|
|
|
233
240
|
layout: {
|
|
234
241
|
alignment: "left",
|
|
235
242
|
stackedAlignment: undefined,
|
|
243
|
+
stackedBreakpoint: undefined,
|
|
236
244
|
},
|
|
237
245
|
popper: {
|
|
238
246
|
placement: "left",
|
|
@@ -287,7 +295,11 @@ class ControlBar extends CustomElement {
|
|
|
287
295
|
*/
|
|
288
296
|
setOption(path, value) {
|
|
289
297
|
super.setOption(path, value);
|
|
290
|
-
if (
|
|
298
|
+
if (
|
|
299
|
+
path === "layout.alignment" ||
|
|
300
|
+
path === "layout.stackedAlignment" ||
|
|
301
|
+
path === "layout.stackedBreakpoint"
|
|
302
|
+
) {
|
|
291
303
|
syncLayoutState.call(this);
|
|
292
304
|
}
|
|
293
305
|
return this;
|
|
@@ -339,6 +351,7 @@ class ControlBar extends CustomElement {
|
|
|
339
351
|
attributes.push(ATTRIBUTE_POPPER_POSITION);
|
|
340
352
|
attributes.push(ATTRIBUTE_OPTION_LAYOUT_ALIGNMENT);
|
|
341
353
|
attributes.push(ATTRIBUTE_OPTION_LAYOUT_STACKED_ALIGNMENT);
|
|
354
|
+
attributes.push(ATTRIBUTE_OPTION_LAYOUT_STACKED_BREAKPOINT);
|
|
342
355
|
return attributes;
|
|
343
356
|
}
|
|
344
357
|
|
|
@@ -531,6 +544,11 @@ function initEventHandler() {
|
|
|
531
544
|
syncLayoutState.call(self);
|
|
532
545
|
};
|
|
533
546
|
|
|
547
|
+
self[attributeObserverSymbol][ATTRIBUTE_OPTION_LAYOUT_STACKED_BREAKPOINT] =
|
|
548
|
+
() => {
|
|
549
|
+
syncLayoutState.call(self);
|
|
550
|
+
};
|
|
551
|
+
|
|
534
552
|
self[resizeObserverSymbol] = new ResizeObserver(() => {
|
|
535
553
|
scheduleLayout.call(self, { measure: true, layout: true });
|
|
536
554
|
});
|
|
@@ -743,9 +761,11 @@ function rearrangeItems() {
|
|
|
743
761
|
|
|
744
762
|
const shouldShowSwitch =
|
|
745
763
|
layout.itemsToMoveToPopper.length > 0 && hasItems;
|
|
764
|
+
const shouldUseStackedLayout =
|
|
765
|
+
shouldShowSwitch || isStackedBreakpointMatched.call(this);
|
|
746
766
|
|
|
747
767
|
suppressLayoutFeedback.call(this);
|
|
748
|
-
setLayoutStackedState.call(this,
|
|
768
|
+
setLayoutStackedState.call(this, shouldUseStackedLayout);
|
|
749
769
|
|
|
750
770
|
for (const item of layout.itemsToMoveToPopper) {
|
|
751
771
|
if (item.getAttribute("slot") !== "popper") {
|
|
@@ -1207,6 +1227,7 @@ function calculateControlBarDimensions() {
|
|
|
1207
1227
|
}
|
|
1208
1228
|
|
|
1209
1229
|
this[dimensionsSymbol].setVia("data.visible", !(width === 0));
|
|
1230
|
+
this[dimensionsSymbol].setVia("data.containerWidth", width);
|
|
1210
1231
|
|
|
1211
1232
|
const itemReferences = [];
|
|
1212
1233
|
|
|
@@ -1509,6 +1530,37 @@ function syncLayoutState() {
|
|
|
1509
1530
|
scheduleLayout.call(this, { measure: true, layout: true });
|
|
1510
1531
|
}
|
|
1511
1532
|
|
|
1533
|
+
/**
|
|
1534
|
+
* @private
|
|
1535
|
+
* @return {boolean}
|
|
1536
|
+
*/
|
|
1537
|
+
function isStackedBreakpointMatched() {
|
|
1538
|
+
const breakpoint = this.getOption("layout.stackedBreakpoint");
|
|
1539
|
+
if (typeof breakpoint !== "string" || breakpoint.trim() === "") {
|
|
1540
|
+
return false;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
let width = 0;
|
|
1544
|
+
try {
|
|
1545
|
+
width = this[dimensionsSymbol].getVia("data.containerWidth");
|
|
1546
|
+
} catch {
|
|
1547
|
+
try {
|
|
1548
|
+
width = this[dimensionsSymbol].getVia("data.space");
|
|
1549
|
+
} catch {}
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
if (!(width > 0)) {
|
|
1553
|
+
return false;
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
const breakpointWidth = getComputedCssPixels(breakpoint);
|
|
1557
|
+
if (!(breakpointWidth > 0)) {
|
|
1558
|
+
return false;
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
return width <= breakpointWidth;
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1512
1564
|
/**
|
|
1513
1565
|
* @private
|
|
1514
1566
|
* @param {boolean} stacked
|
|
@@ -1618,6 +1670,7 @@ function getLayoutChangedEventDetail() {
|
|
|
1618
1670
|
configuredAlignment: this.getOption("layout.alignment", "left"),
|
|
1619
1671
|
stacked,
|
|
1620
1672
|
stackedAlignment: this.getOption("layout.stackedAlignment"),
|
|
1673
|
+
stackedBreakpoint: this.getOption("layout.stackedBreakpoint"),
|
|
1621
1674
|
};
|
|
1622
1675
|
}
|
|
1623
1676
|
|
|
@@ -161,6 +161,7 @@ describe("ControlBar", function () {
|
|
|
161
161
|
configuredAlignment: "left",
|
|
162
162
|
stacked: false,
|
|
163
163
|
stackedAlignment: undefined,
|
|
164
|
+
stackedBreakpoint: undefined,
|
|
164
165
|
});
|
|
165
166
|
});
|
|
166
167
|
|
|
@@ -660,4 +661,94 @@ describe("ControlBar", function () {
|
|
|
660
661
|
globalThis.requestAnimationFrame = originalGlobalRequestAnimationFrame;
|
|
661
662
|
}
|
|
662
663
|
});
|
|
664
|
+
|
|
665
|
+
it("should apply stacked alignment below the configured container breakpoint without overflow", async function () {
|
|
666
|
+
const originalRequestAnimationFrame = window.requestAnimationFrame;
|
|
667
|
+
const originalGlobalRequestAnimationFrame = globalThis.requestAnimationFrame;
|
|
668
|
+
|
|
669
|
+
const scheduledCallbacks = [];
|
|
670
|
+
const flushFrames = async () => {
|
|
671
|
+
while (scheduledCallbacks.length > 0) {
|
|
672
|
+
scheduledCallbacks.shift()();
|
|
673
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
try {
|
|
678
|
+
window.requestAnimationFrame = (callback) => {
|
|
679
|
+
scheduledCallbacks.push(callback);
|
|
680
|
+
return scheduledCallbacks.length;
|
|
681
|
+
};
|
|
682
|
+
globalThis.requestAnimationFrame = window.requestAnimationFrame;
|
|
683
|
+
|
|
684
|
+
const mocks = document.getElementById("mocks");
|
|
685
|
+
mocks.innerHTML = `
|
|
686
|
+
<div id="breakpoint-bar-wrapper">
|
|
687
|
+
<monster-control-bar
|
|
688
|
+
id="breakpoint-bar"
|
|
689
|
+
data-monster-option-layout-alignment="right"
|
|
690
|
+
data-monster-option-layout-stacked-alignment="left"
|
|
691
|
+
data-monster-option-layout-stacked-breakpoint="100px"
|
|
692
|
+
>
|
|
693
|
+
<button id="breakpoint-button">Run</button>
|
|
694
|
+
</monster-control-bar>
|
|
695
|
+
</div>
|
|
696
|
+
`;
|
|
697
|
+
|
|
698
|
+
const wrapper = document.getElementById("breakpoint-bar-wrapper");
|
|
699
|
+
const button = document.getElementById("breakpoint-button");
|
|
700
|
+
const bar = document.getElementById("breakpoint-bar");
|
|
701
|
+
const controlBar = bar.shadowRoot.querySelector(
|
|
702
|
+
'[data-monster-role="control-bar"]',
|
|
703
|
+
);
|
|
704
|
+
const switchButton = bar.shadowRoot.querySelector(
|
|
705
|
+
'[data-monster-role="switch"]',
|
|
706
|
+
);
|
|
707
|
+
|
|
708
|
+
wrapper.style.boxSizing = "border-box";
|
|
709
|
+
Object.defineProperty(wrapper, "clientWidth", {
|
|
710
|
+
configurable: true,
|
|
711
|
+
value: 90,
|
|
712
|
+
});
|
|
713
|
+
Object.defineProperty(button, "offsetWidth", {
|
|
714
|
+
configurable: true,
|
|
715
|
+
value: 40,
|
|
716
|
+
});
|
|
717
|
+
Object.defineProperty(button, "offsetHeight", {
|
|
718
|
+
configurable: true,
|
|
719
|
+
value: 30,
|
|
720
|
+
});
|
|
721
|
+
button.getBoundingClientRect = () => ({
|
|
722
|
+
width: 40,
|
|
723
|
+
height: 30,
|
|
724
|
+
top: 0,
|
|
725
|
+
right: 40,
|
|
726
|
+
bottom: 30,
|
|
727
|
+
left: 0,
|
|
728
|
+
x: 0,
|
|
729
|
+
y: 0,
|
|
730
|
+
toJSON: () => {},
|
|
731
|
+
});
|
|
732
|
+
Object.defineProperty(switchButton, "offsetWidth", {
|
|
733
|
+
configurable: true,
|
|
734
|
+
value: 20,
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
await flushFrames();
|
|
738
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
739
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
740
|
+
|
|
741
|
+
expect(switchButton.hasAttribute("hidden")).to.be.true;
|
|
742
|
+
expect(button.hasAttribute("slot")).to.be.false;
|
|
743
|
+
expect(controlBar.getAttribute("data-monster-layout-stacked")).to.equal(
|
|
744
|
+
"true",
|
|
745
|
+
);
|
|
746
|
+
expect(controlBar.getAttribute("data-monster-layout-alignment")).to.equal(
|
|
747
|
+
"left",
|
|
748
|
+
);
|
|
749
|
+
} finally {
|
|
750
|
+
window.requestAnimationFrame = originalRequestAnimationFrame;
|
|
751
|
+
globalThis.requestAnimationFrame = originalGlobalRequestAnimationFrame;
|
|
752
|
+
}
|
|
753
|
+
});
|
|
663
754
|
});
|