@schukai/monster 4.129.0 → 4.129.1
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 +3 -0
- package/package.json +1 -1
- package/source/components/form/message-state-button.mjs +233 -18
- package/source/components/form/style/message-state-button.pcss +46 -3
- package/source/components/form/stylesheet/message-state-button.mjs +7 -14
- package/source/components/form/stylesheet/popper-button.mjs +7 -14
- package/source/components/layout/popper.mjs +72 -1
- package/source/components/layout/stylesheet/popper.mjs +7 -14
- package/source/components/style/floating-ui.css +1 -49
- package/source/components/style/floating-ui.pcss +10 -0
- package/source/components/stylesheet/floating-ui.mjs +7 -14
- package/source/dom/util/extract-keys.mjs +46 -10
- package/source/dom/util/init-options-from-attributes.mjs +4 -2
- package/source/dom/util/set-option-from-attribute.mjs +4 -2
- package/test/cases/components/form/message-state-button.mjs +272 -0
- package/test/cases/components/form/popper-button.mjs +89 -0
- package/test/cases/dom/util/extract-keys.mjs +34 -23
- package/test/cases/dom/util/init-options-from-attributes.mjs +21 -0
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
import { ATTRIBUTE_ROLE } from "../../dom/constants.mjs";
|
|
22
22
|
import {
|
|
23
23
|
assembleMethodSymbol,
|
|
24
|
+
attributeObserverSymbol,
|
|
24
25
|
CustomElement,
|
|
25
26
|
registerCustomElement,
|
|
26
27
|
} from "../../dom/customelement.mjs";
|
|
@@ -79,6 +80,13 @@ const buttonElementSymbol = Symbol("buttonElement");
|
|
|
79
80
|
*/
|
|
80
81
|
const popperElementSymbol = Symbol("popperElement");
|
|
81
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Symbol for content element reference
|
|
85
|
+
* @private
|
|
86
|
+
* @type {symbol}
|
|
87
|
+
*/
|
|
88
|
+
const contentElementSymbol = Symbol("contentElement");
|
|
89
|
+
|
|
82
90
|
/**
|
|
83
91
|
* Symbol for arrow element reference
|
|
84
92
|
* @private
|
|
@@ -143,6 +151,7 @@ class Popper extends CustomElement {
|
|
|
143
151
|
* @property {Object} popper - Positioning options
|
|
144
152
|
* @property {string} popper.placement - Placement: top|bottom|left|right
|
|
145
153
|
* @property {Array} popper.middleware - Positioning middleware functions
|
|
154
|
+
* @property {string} popper.contentOverflow - Content clipping mode: both|horizontal
|
|
146
155
|
* @property {Object} features - Feature flags
|
|
147
156
|
* @property {boolean} features.preventOpenEventSent - Prevent open event
|
|
148
157
|
* @returns {Object} Default options merged with parent defaults
|
|
@@ -157,6 +166,7 @@ class Popper extends CustomElement {
|
|
|
157
166
|
popper: {
|
|
158
167
|
placement: "top",
|
|
159
168
|
middleware: ["autoPlacement", "shift", "offset:15", "arrow"],
|
|
169
|
+
contentOverflow: "both",
|
|
160
170
|
},
|
|
161
171
|
features: {
|
|
162
172
|
preventOpenEventSent: false,
|
|
@@ -172,9 +182,24 @@ class Popper extends CustomElement {
|
|
|
172
182
|
[assembleMethodSymbol]() {
|
|
173
183
|
super[assembleMethodSymbol]();
|
|
174
184
|
initControlReferences.call(this);
|
|
185
|
+
initOverflowObserver.call(this);
|
|
186
|
+
applyContentOverflowMode.call(this);
|
|
175
187
|
initEventHandler.call(this);
|
|
176
188
|
}
|
|
177
189
|
|
|
190
|
+
/**
|
|
191
|
+
* @inheritdoc
|
|
192
|
+
*/
|
|
193
|
+
setOption(path, value) {
|
|
194
|
+
super.setOption(path, value);
|
|
195
|
+
|
|
196
|
+
if (path === "popper.contentOverflow") {
|
|
197
|
+
applyContentOverflowMode.call(this);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return this;
|
|
201
|
+
}
|
|
202
|
+
|
|
178
203
|
/**
|
|
179
204
|
* Gets the custom element tag name
|
|
180
205
|
* @return {string} The tag name
|
|
@@ -245,6 +270,16 @@ class Popper extends CustomElement {
|
|
|
245
270
|
return this;
|
|
246
271
|
}
|
|
247
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Resolves the effective content overflow mode for the rendered wrapper.
|
|
275
|
+
* Subclasses can override this when the configured option is only an intermediate mode.
|
|
276
|
+
*
|
|
277
|
+
* @return {string}
|
|
278
|
+
*/
|
|
279
|
+
resolveContentOverflowMode() {
|
|
280
|
+
return this.getOption("popper.contentOverflow", "both");
|
|
281
|
+
}
|
|
282
|
+
|
|
248
283
|
/**
|
|
249
284
|
* Hides the popper element
|
|
250
285
|
* @return {Popper} The popper instance
|
|
@@ -485,6 +520,8 @@ function show() {
|
|
|
485
520
|
self,
|
|
486
521
|
});
|
|
487
522
|
|
|
523
|
+
applyContentOverflowMode.call(self);
|
|
524
|
+
|
|
488
525
|
popperElement.style.visibility = "hidden";
|
|
489
526
|
popperElement.style.display = STYLE_DISPLAY_MODE_BLOCK;
|
|
490
527
|
|
|
@@ -520,6 +557,8 @@ function updatePopper() {
|
|
|
520
557
|
return;
|
|
521
558
|
}
|
|
522
559
|
|
|
560
|
+
applyContentOverflowMode.call(this);
|
|
561
|
+
|
|
523
562
|
positionPopper.call(
|
|
524
563
|
this,
|
|
525
564
|
this[controlElementSymbol],
|
|
@@ -596,9 +635,39 @@ function initControlReferences() {
|
|
|
596
635
|
this[arrowElementSymbol] = this.shadowRoot.querySelector(
|
|
597
636
|
`[${ATTRIBUTE_ROLE}=arrow]`,
|
|
598
637
|
);
|
|
638
|
+
this[contentElementSymbol] = this.shadowRoot.querySelector(`[part="content"]`);
|
|
599
639
|
return this;
|
|
600
640
|
}
|
|
601
641
|
|
|
642
|
+
/**
|
|
643
|
+
* Keeps the rendered content wrapper in sync with the configured overflow mode
|
|
644
|
+
* @private
|
|
645
|
+
* @return {void}
|
|
646
|
+
*/
|
|
647
|
+
function initOverflowObserver() {
|
|
648
|
+
this[attributeObserverSymbol]["data-monster-option-popper-content-overflow"] =
|
|
649
|
+
() => {
|
|
650
|
+
applyContentOverflowMode.call(this);
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Applies the current content overflow mode to the rendered wrapper element
|
|
656
|
+
* @private
|
|
657
|
+
* @return {void}
|
|
658
|
+
*/
|
|
659
|
+
function applyContentOverflowMode() {
|
|
660
|
+
const contentElement = this[contentElementSymbol];
|
|
661
|
+
if (!(contentElement instanceof HTMLElement)) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
contentElement.setAttribute(
|
|
666
|
+
"data-monster-overflow-mode",
|
|
667
|
+
this.resolveContentOverflowMode(),
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
|
|
602
671
|
/**
|
|
603
672
|
* Gets the main template HTML
|
|
604
673
|
* @private
|
|
@@ -612,7 +681,9 @@ function getTemplate() {
|
|
|
612
681
|
|
|
613
682
|
<div data-monster-role="popper" part="popper" tabindex="-1" class="monster-color-primary-1">
|
|
614
683
|
<div data-monster-role="arrow"></div>
|
|
615
|
-
<div part="content"
|
|
684
|
+
<div part="content"
|
|
685
|
+
class="flex"
|
|
686
|
+
data-monster-replace="path:content">
|
|
616
687
|
</div>
|
|
617
688
|
</div>
|
|
618
689
|
</div>
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
* For more information about purchasing a commercial license, please contact Volker Schukai.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import {addAttributeToken} from "../../../dom/attributes.mjs";
|
|
14
|
+
import {ATTRIBUTE_ERRORMESSAGE} from "../../../dom/constants.mjs";
|
|
15
15
|
|
|
16
|
-
export {
|
|
16
|
+
export {PopperStyleSheet}
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* @private
|
|
@@ -22,17 +22,10 @@ export { PopperStyleSheet };
|
|
|
22
22
|
const PopperStyleSheet = new CSSStyleSheet();
|
|
23
23
|
|
|
24
24
|
try {
|
|
25
|
-
|
|
26
|
-
`
|
|
25
|
+
PopperStyleSheet.insertRule(`
|
|
27
26
|
@layer popper {
|
|
28
|
-
[data-monster-role=control]{box-sizing:border-box;outline:none;width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}:host{box-sizing:border-box;display:block}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));padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}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] 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}[data-monster-role=control]{display:flex;position:relative}
|
|
29
|
-
}`,
|
|
30
|
-
0,
|
|
31
|
-
);
|
|
27
|
+
[data-monster-role=control]{box-sizing:border-box;outline:none;width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}:host{box-sizing:border-box;display:block}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));padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}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:inset(calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0 calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0);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}[data-monster-role=control]{display:flex;position:relative}
|
|
28
|
+
}`, 0);
|
|
32
29
|
} catch (e) {
|
|
33
|
-
|
|
34
|
-
document.getRootNode().querySelector("html"),
|
|
35
|
-
ATTRIBUTE_ERRORMESSAGE,
|
|
36
|
-
e + "",
|
|
37
|
-
);
|
|
30
|
+
addAttributeToken(document.getRootNode().querySelector('html'), ATTRIBUTE_ERRORMESSAGE, e + "");
|
|
38
31
|
}
|
|
@@ -1,50 +1,2 @@
|
|
|
1
1
|
/** generated from floating-ui.pcss **/
|
|
2
|
-
div[data-monster-role=
|
|
3
|
-
align-content: center;
|
|
4
|
-
background: var(--monster-bg-color-primary-1);
|
|
5
|
-
border-color: var(--monster-bg-color-primary-4);
|
|
6
|
-
border-radius: var(--monster-border-radius);
|
|
7
|
-
border-style: var(--monster-border-style);
|
|
8
|
-
border-width: var(--monster-border-width);
|
|
9
|
-
box-shadow: var(--monster-box-shadow-1);
|
|
10
|
-
box-sizing: border-box;
|
|
11
|
-
color: var(--monster-color-primary-1);
|
|
12
|
-
display: none;
|
|
13
|
-
justify-content: space-between;
|
|
14
|
-
left: 0;
|
|
15
|
-
max-height: var(--monster-popper-max-height, calc(100vh - 2rem));
|
|
16
|
-
max-width: var(--monster-popper-max-width, calc(100vw - 2rem));
|
|
17
|
-
padding: 1.1em;
|
|
18
|
-
position: absolute;
|
|
19
|
-
top: 0;
|
|
20
|
-
width: -moz-max-content;
|
|
21
|
-
width: max-content;
|
|
22
|
-
z-index: var(--monster-z-index-modal);
|
|
23
|
-
}
|
|
24
|
-
div[data-monster-role="popper"] > [part="content"] {
|
|
25
|
-
max-height: var(--monster-popper-content-max-height, calc(100vh - 4.2rem));
|
|
26
|
-
max-width: 100%;
|
|
27
|
-
overflow: auto;
|
|
28
|
-
}
|
|
29
|
-
div[data-monster-role="popper"] div[data-monster-role="arrow"] {
|
|
30
|
-
background: var(--monster-bg-color-primary-1);
|
|
31
|
-
height: calc(
|
|
32
|
-
max(
|
|
33
|
-
var(--monster-popper-witharrrow-distance),
|
|
34
|
-
-1 *
|
|
35
|
-
var(--monster-popper-witharrrow-distance)
|
|
36
|
-
) *
|
|
37
|
-
2
|
|
38
|
-
);
|
|
39
|
-
pointer-events: none;
|
|
40
|
-
position: absolute;
|
|
41
|
-
width: calc(
|
|
42
|
-
max(
|
|
43
|
-
var(--monster-popper-witharrrow-distance),
|
|
44
|
-
-1 *
|
|
45
|
-
var(--monster-popper-witharrrow-distance)
|
|
46
|
-
) *
|
|
47
|
-
2
|
|
48
|
-
);
|
|
49
|
-
z-index: -1;
|
|
50
|
-
}
|
|
2
|
+
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));padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}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:inset(calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0 calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0);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,6 +29,16 @@ div[data-monster-role=popper] {
|
|
|
29
29
|
max-height: var(--monster-popper-content-max-height, calc(100vh - 4.2rem));
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
& > [part=content][data-monster-overflow-mode=horizontal] {
|
|
33
|
+
overflow: visible;
|
|
34
|
+
clip-path: inset(
|
|
35
|
+
calc(-1 * var(--monster-popper-content-block-overflow, 100vh))
|
|
36
|
+
0
|
|
37
|
+
calc(-1 * var(--monster-popper-content-block-overflow, 100vh))
|
|
38
|
+
0
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
32
42
|
& div[data-monster-role=arrow] {
|
|
33
43
|
position: absolute;
|
|
34
44
|
width: calc(2 * max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance)));
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
* For more information about purchasing a commercial license, please contact Volker Schukai.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import {addAttributeToken} from "../../dom/attributes.mjs";
|
|
14
|
+
import {ATTRIBUTE_ERRORMESSAGE} from "../../dom/constants.mjs";
|
|
15
15
|
|
|
16
|
-
export {
|
|
16
|
+
export {FloatingUiStyleSheet}
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* @private
|
|
@@ -22,17 +22,10 @@ export { FloatingUiStyleSheet };
|
|
|
22
22
|
const FloatingUiStyleSheet = new CSSStyleSheet();
|
|
23
23
|
|
|
24
24
|
try {
|
|
25
|
-
|
|
26
|
-
`
|
|
25
|
+
FloatingUiStyleSheet.insertRule(`
|
|
27
26
|
@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));padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}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] 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
|
-
}`,
|
|
30
|
-
0,
|
|
31
|
-
);
|
|
27
|
+
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));padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}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:inset(calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0 calc(var(--monster-popper-content-block-overflow, 100vh)*-1) 0);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
|
+
}`, 0);
|
|
32
29
|
} catch (e) {
|
|
33
|
-
|
|
34
|
-
document.getRootNode().querySelector("html"),
|
|
35
|
-
ATTRIBUTE_ERRORMESSAGE,
|
|
36
|
-
e + "",
|
|
37
|
-
);
|
|
30
|
+
addAttributeToken(document.getRootNode().querySelector('html'), ATTRIBUTE_ERRORMESSAGE, e + "");
|
|
38
31
|
}
|
|
@@ -32,32 +32,68 @@ function extractKeys(
|
|
|
32
32
|
) {
|
|
33
33
|
const resultMap = new Map();
|
|
34
34
|
|
|
35
|
-
function
|
|
35
|
+
function normalizeKeySegment(value) {
|
|
36
|
+
return String(value).toLowerCase();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function toKebabCase(value) {
|
|
40
|
+
return String(value)
|
|
41
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
42
|
+
.toLowerCase();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function appendKeys(compactKey, kebabKey, valuePath) {
|
|
46
|
+
resultMap.set(compactKey, valuePath);
|
|
47
|
+
if (kebabKey !== compactKey) {
|
|
48
|
+
resultMap.set(kebabKey, valuePath);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function helper(
|
|
53
|
+
currentObj,
|
|
54
|
+
currentCompactKeyPrefix,
|
|
55
|
+
currentKebabKeyPrefix,
|
|
56
|
+
currentValuePrefix,
|
|
57
|
+
) {
|
|
36
58
|
for (const key in currentObj) {
|
|
59
|
+
const compactSegment = normalizeKeySegment(key);
|
|
60
|
+
const kebabSegment = toKebabCase(key);
|
|
61
|
+
|
|
37
62
|
if (
|
|
38
63
|
currentObj[key] !== null &&
|
|
39
64
|
typeof currentObj[key] === "object" &&
|
|
40
65
|
!Array.isArray(currentObj[key])
|
|
41
66
|
) {
|
|
42
|
-
const
|
|
43
|
-
?
|
|
44
|
-
:
|
|
67
|
+
const newCompactKeyPrefix = currentCompactKeyPrefix
|
|
68
|
+
? currentCompactKeyPrefix + keySeparator + compactSegment
|
|
69
|
+
: compactSegment;
|
|
70
|
+
const newKebabKeyPrefix = currentKebabKeyPrefix
|
|
71
|
+
? currentKebabKeyPrefix + keySeparator + kebabSegment
|
|
72
|
+
: kebabSegment;
|
|
45
73
|
const newValuePrefix = currentValuePrefix
|
|
46
74
|
? currentValuePrefix + valueSeparator + key
|
|
47
75
|
: key;
|
|
48
|
-
helper(
|
|
76
|
+
helper(
|
|
77
|
+
currentObj[key],
|
|
78
|
+
newCompactKeyPrefix,
|
|
79
|
+
newKebabKeyPrefix,
|
|
80
|
+
newValuePrefix,
|
|
81
|
+
);
|
|
49
82
|
} else {
|
|
50
|
-
const
|
|
51
|
-
?
|
|
52
|
-
:
|
|
83
|
+
const finalCompactKey = currentCompactKeyPrefix
|
|
84
|
+
? currentCompactKeyPrefix + keySeparator + compactSegment
|
|
85
|
+
: compactSegment;
|
|
86
|
+
const finalKebabKey = currentKebabKeyPrefix
|
|
87
|
+
? currentKebabKeyPrefix + keySeparator + kebabSegment
|
|
88
|
+
: kebabSegment;
|
|
53
89
|
const finalValue = currentValuePrefix
|
|
54
90
|
? currentValuePrefix + valueSeparator + key
|
|
55
91
|
: key;
|
|
56
|
-
|
|
92
|
+
appendKeys(finalCompactKey, finalKebabKey, finalValue);
|
|
57
93
|
}
|
|
58
94
|
}
|
|
59
95
|
}
|
|
60
96
|
|
|
61
|
-
helper(obj, keyPrefix, keyPrefix);
|
|
97
|
+
helper(obj, keyPrefix, keyPrefix, keyPrefix);
|
|
62
98
|
return resultMap;
|
|
63
99
|
}
|
|
@@ -29,8 +29,10 @@ export { initOptionsFromAttributes };
|
|
|
29
29
|
/**
|
|
30
30
|
* Initializes the given options object based on the attributes of the current DOM element.
|
|
31
31
|
* The function looks for attributes with the prefix 'data-monster-option-', and maps them to
|
|
32
|
-
* properties in the options object. It
|
|
33
|
-
*
|
|
32
|
+
* properties in the options object. It supports both the historic compact form and kebab-case aliases
|
|
33
|
+
* for camelCase option names.
|
|
34
|
+
* For example, the attributes 'data-monster-option-url' and
|
|
35
|
+
* 'data-monster-option-popper-content-overflow' map to 'url' and 'popper.contentOverflow'.
|
|
34
36
|
*
|
|
35
37
|
* With the mapping parameter, the attribute value can be mapped to a different value.
|
|
36
38
|
* For example, the attribute 'data-monster-option-foo' maps to the 'bar' property in the options object.
|
|
@@ -30,8 +30,10 @@ export { setOptionFromAttribute };
|
|
|
30
30
|
/**
|
|
31
31
|
* Set the given options object based on the attributes of the current DOM element.
|
|
32
32
|
* The function looks for attributes with the prefix 'data-monster-option-', and maps them to
|
|
33
|
-
* properties in the options object. It
|
|
34
|
-
*
|
|
33
|
+
* properties in the options object. It supports both the historic compact form and kebab-case aliases
|
|
34
|
+
* for camelCase option names.
|
|
35
|
+
* For example, the attributes 'data-monster-option-url' and
|
|
36
|
+
* 'data-monster-option-popper-content-overflow' map to 'url' and 'popper.contentOverflow'.
|
|
35
37
|
*
|
|
36
38
|
* With the mapping parameter, the attribute value can be mapped to a different value.
|
|
37
39
|
* For example, the attribute 'data-monster-option-foo' maps to the 'bar' property in the options object.
|
|
@@ -216,4 +216,276 @@ describe("MessageStateButton", function () {
|
|
|
216
216
|
}, 0);
|
|
217
217
|
});
|
|
218
218
|
});
|
|
219
|
+
|
|
220
|
+
describe("popper content presentation", function () {
|
|
221
|
+
afterEach(() => {
|
|
222
|
+
let mocks = document.getElementById("mocks");
|
|
223
|
+
mocks.innerHTML = "";
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it("should resolve plain prose content to default popper clipping", function (done) {
|
|
227
|
+
let mocks = document.getElementById("mocks");
|
|
228
|
+
const button = document.createElement("monster-message-state-button");
|
|
229
|
+
button.innerHTML = "Save";
|
|
230
|
+
mocks.appendChild(button);
|
|
231
|
+
|
|
232
|
+
setTimeout(() => {
|
|
233
|
+
try {
|
|
234
|
+
button.setMessage("<div><strong>Saved</strong><p>plain html</p></div>");
|
|
235
|
+
button.showMessage();
|
|
236
|
+
|
|
237
|
+
setTimeout(() => {
|
|
238
|
+
try {
|
|
239
|
+
const content = button.shadowRoot.querySelector('[part="content"]');
|
|
240
|
+
const message = button.shadowRoot.querySelector(
|
|
241
|
+
'[data-monster-role="message"]',
|
|
242
|
+
);
|
|
243
|
+
expect(content).to.exist;
|
|
244
|
+
expect(content.getAttribute("data-monster-overflow-mode")).to.equal(
|
|
245
|
+
"both",
|
|
246
|
+
);
|
|
247
|
+
expect(
|
|
248
|
+
content.getAttribute("data-monster-message-layout"),
|
|
249
|
+
).to.equal("prose");
|
|
250
|
+
expect(
|
|
251
|
+
message.getAttribute("data-monster-message-layout"),
|
|
252
|
+
).to.equal("prose");
|
|
253
|
+
done();
|
|
254
|
+
} catch (e) {
|
|
255
|
+
done(e);
|
|
256
|
+
}
|
|
257
|
+
}, 0);
|
|
258
|
+
} catch (e) {
|
|
259
|
+
done(e);
|
|
260
|
+
}
|
|
261
|
+
}, 0);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it("should resolve nested select message content to horizontal clipping only", function (done) {
|
|
265
|
+
let mocks = document.getElementById("mocks");
|
|
266
|
+
const button = document.createElement("monster-message-state-button");
|
|
267
|
+
button.innerHTML = "Save";
|
|
268
|
+
mocks.appendChild(button);
|
|
269
|
+
|
|
270
|
+
setTimeout(() => {
|
|
271
|
+
try {
|
|
272
|
+
const wrapper = document.createElement("div");
|
|
273
|
+
wrapper.appendChild(document.createElement("monster-select"));
|
|
274
|
+
button.setMessage(wrapper);
|
|
275
|
+
button.showMessage();
|
|
276
|
+
|
|
277
|
+
setTimeout(() => {
|
|
278
|
+
try {
|
|
279
|
+
const content = button.shadowRoot.querySelector('[part="content"]');
|
|
280
|
+
const message = button.shadowRoot.querySelector(
|
|
281
|
+
'[data-monster-role="message"]',
|
|
282
|
+
);
|
|
283
|
+
expect(content).to.exist;
|
|
284
|
+
expect(content.getAttribute("data-monster-overflow-mode")).to.equal(
|
|
285
|
+
"horizontal",
|
|
286
|
+
);
|
|
287
|
+
expect(
|
|
288
|
+
content.getAttribute("data-monster-message-layout"),
|
|
289
|
+
).to.equal("overlay");
|
|
290
|
+
expect(
|
|
291
|
+
message.getAttribute("data-monster-message-layout"),
|
|
292
|
+
).to.equal("overlay");
|
|
293
|
+
done();
|
|
294
|
+
} catch (e) {
|
|
295
|
+
done(e);
|
|
296
|
+
}
|
|
297
|
+
}, 0);
|
|
298
|
+
} catch (e) {
|
|
299
|
+
done(e);
|
|
300
|
+
}
|
|
301
|
+
}, 0);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it("should resolve wide plain content to the wide layout", function (done) {
|
|
305
|
+
let mocks = document.getElementById("mocks");
|
|
306
|
+
const button = document.createElement("monster-message-state-button");
|
|
307
|
+
button.innerHTML = "Save";
|
|
308
|
+
mocks.appendChild(button);
|
|
309
|
+
|
|
310
|
+
setTimeout(() => {
|
|
311
|
+
try {
|
|
312
|
+
const wrapper = document.createElement("div");
|
|
313
|
+
const line = document.createElement("div");
|
|
314
|
+
line.setAttribute(
|
|
315
|
+
"style",
|
|
316
|
+
"white-space: nowrap; overflow-x: auto;",
|
|
317
|
+
);
|
|
318
|
+
line.textContent =
|
|
319
|
+
"this is intentionally a single long line to trigger wide layout";
|
|
320
|
+
wrapper.appendChild(line);
|
|
321
|
+
|
|
322
|
+
button.setMessage(wrapper);
|
|
323
|
+
button.showMessage();
|
|
324
|
+
|
|
325
|
+
setTimeout(() => {
|
|
326
|
+
try {
|
|
327
|
+
const content = button.shadowRoot.querySelector('[part="content"]');
|
|
328
|
+
const message = button.shadowRoot.querySelector(
|
|
329
|
+
'[data-monster-role="message"]',
|
|
330
|
+
);
|
|
331
|
+
expect(content).to.exist;
|
|
332
|
+
expect(content.getAttribute("data-monster-overflow-mode")).to.equal(
|
|
333
|
+
"both",
|
|
334
|
+
);
|
|
335
|
+
expect(
|
|
336
|
+
content.getAttribute("data-monster-message-layout"),
|
|
337
|
+
).to.equal("wide");
|
|
338
|
+
expect(
|
|
339
|
+
message.getAttribute("data-monster-message-layout"),
|
|
340
|
+
).to.equal("wide");
|
|
341
|
+
done();
|
|
342
|
+
} catch (e) {
|
|
343
|
+
done(e);
|
|
344
|
+
}
|
|
345
|
+
}, 0);
|
|
346
|
+
} catch (e) {
|
|
347
|
+
done(e);
|
|
348
|
+
}
|
|
349
|
+
}, 0);
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
describe("message width behavior", function () {
|
|
354
|
+
let originalInnerWidth;
|
|
355
|
+
let originalGetBoundingClientRect;
|
|
356
|
+
|
|
357
|
+
beforeEach(() => {
|
|
358
|
+
originalInnerWidth = window.innerWidth;
|
|
359
|
+
originalGetBoundingClientRect = HTMLElement.prototype.getBoundingClientRect;
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
afterEach(() => {
|
|
363
|
+
Object.defineProperty(window, "innerWidth", {
|
|
364
|
+
configurable: true,
|
|
365
|
+
writable: true,
|
|
366
|
+
value: originalInnerWidth,
|
|
367
|
+
});
|
|
368
|
+
HTMLElement.prototype.getBoundingClientRect = originalGetBoundingClientRect;
|
|
369
|
+
let mocks = document.getElementById("mocks");
|
|
370
|
+
mocks.innerHTML = "";
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it("should keep prose content on a readable max width", function (done) {
|
|
374
|
+
let mocks = document.getElementById("mocks");
|
|
375
|
+
const button = document.createElement("monster-message-state-button");
|
|
376
|
+
button.innerHTML = "Save";
|
|
377
|
+
mocks.appendChild(button);
|
|
378
|
+
|
|
379
|
+
Object.defineProperty(window, "innerWidth", {
|
|
380
|
+
configurable: true,
|
|
381
|
+
writable: true,
|
|
382
|
+
value: 800,
|
|
383
|
+
});
|
|
384
|
+
HTMLElement.prototype.getBoundingClientRect = function () {
|
|
385
|
+
if (this?.getAttribute?.("data-measurement") === "true") {
|
|
386
|
+
return {
|
|
387
|
+
width: 900,
|
|
388
|
+
height: 120,
|
|
389
|
+
top: 0,
|
|
390
|
+
left: 0,
|
|
391
|
+
right: 900,
|
|
392
|
+
bottom: 120,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return {
|
|
397
|
+
width: 100,
|
|
398
|
+
height: 40,
|
|
399
|
+
top: 0,
|
|
400
|
+
left: 0,
|
|
401
|
+
right: 100,
|
|
402
|
+
bottom: 40,
|
|
403
|
+
};
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
setTimeout(() => {
|
|
407
|
+
try {
|
|
408
|
+
button.setMessage(
|
|
409
|
+
"<div><p>This long prose content should wrap instead of forcing the message popper to use the full viewport width.</p></div>",
|
|
410
|
+
);
|
|
411
|
+
button.showMessage();
|
|
412
|
+
|
|
413
|
+
setTimeout(() => {
|
|
414
|
+
try {
|
|
415
|
+
const popper = button.shadowRoot.querySelector(
|
|
416
|
+
'[data-monster-role="popper"]',
|
|
417
|
+
);
|
|
418
|
+
expect(popper.style.width).to.equal("512px");
|
|
419
|
+
expect(popper.style.maxWidth).to.equal("512px");
|
|
420
|
+
done();
|
|
421
|
+
} catch (e) {
|
|
422
|
+
done(e);
|
|
423
|
+
}
|
|
424
|
+
}, 0);
|
|
425
|
+
} catch (e) {
|
|
426
|
+
done(e);
|
|
427
|
+
}
|
|
428
|
+
}, 0);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it("should allow wide content to grow until the viewport limit", function (done) {
|
|
432
|
+
let mocks = document.getElementById("mocks");
|
|
433
|
+
const button = document.createElement("monster-message-state-button");
|
|
434
|
+
button.innerHTML = "Save";
|
|
435
|
+
mocks.appendChild(button);
|
|
436
|
+
|
|
437
|
+
Object.defineProperty(window, "innerWidth", {
|
|
438
|
+
configurable: true,
|
|
439
|
+
writable: true,
|
|
440
|
+
value: 800,
|
|
441
|
+
});
|
|
442
|
+
HTMLElement.prototype.getBoundingClientRect = function () {
|
|
443
|
+
if (this?.getAttribute?.("data-measurement") === "true") {
|
|
444
|
+
return {
|
|
445
|
+
width: 900,
|
|
446
|
+
height: 120,
|
|
447
|
+
top: 0,
|
|
448
|
+
left: 0,
|
|
449
|
+
right: 900,
|
|
450
|
+
bottom: 120,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
return {
|
|
455
|
+
width: 100,
|
|
456
|
+
height: 40,
|
|
457
|
+
top: 0,
|
|
458
|
+
left: 0,
|
|
459
|
+
right: 100,
|
|
460
|
+
bottom: 40,
|
|
461
|
+
};
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
setTimeout(() => {
|
|
465
|
+
try {
|
|
466
|
+
const wrapper = document.createElement("div");
|
|
467
|
+
wrapper.setAttribute("data-monster-message-layout", "wide");
|
|
468
|
+
wrapper.textContent =
|
|
469
|
+
"wide content placeholder that should grow until the viewport edge";
|
|
470
|
+
button.setMessage(wrapper);
|
|
471
|
+
button.showMessage();
|
|
472
|
+
|
|
473
|
+
setTimeout(() => {
|
|
474
|
+
try {
|
|
475
|
+
const popper = button.shadowRoot.querySelector(
|
|
476
|
+
'[data-monster-role="popper"]',
|
|
477
|
+
);
|
|
478
|
+
expect(popper.style.width).to.equal("768px");
|
|
479
|
+
expect(popper.style.maxWidth).to.equal("768px");
|
|
480
|
+
done();
|
|
481
|
+
} catch (e) {
|
|
482
|
+
done(e);
|
|
483
|
+
}
|
|
484
|
+
}, 0);
|
|
485
|
+
} catch (e) {
|
|
486
|
+
done(e);
|
|
487
|
+
}
|
|
488
|
+
}, 0);
|
|
489
|
+
});
|
|
490
|
+
});
|
|
219
491
|
});
|