@schukai/monster 4.136.2 → 4.136.3
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 +1 -1
- package/source/components/form/context-base.mjs +41 -6
- package/source/components/form/style/context-error.pcss +0 -2
- package/source/components/form/style/context-help.pcss +0 -2
- package/source/components/form/stylesheet/context-error.mjs +7 -14
- package/source/components/form/stylesheet/context-help.mjs +7 -14
- package/source/components/form/util/floating-ui.mjs +124 -9
- package/test/cases/components/form/context-help.mjs +47 -0
- package/test/cases/components/form/floating-ui.mjs +72 -0
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.
|
|
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.3"}
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { assembleMethodSymbol } from "../../dom/customelement.mjs";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
resolveClippingBoundaryElement,
|
|
18
|
+
resolveParentPopperContentBoundary,
|
|
19
|
+
} from "./util/floating-ui.mjs";
|
|
17
20
|
import { Popper } from "../layout/popper.mjs";
|
|
18
21
|
|
|
19
22
|
export { ContextBase };
|
|
@@ -85,17 +88,40 @@ class ContextBase extends Popper {
|
|
|
85
88
|
*/
|
|
86
89
|
resolvePopperOptions() {
|
|
87
90
|
const options = super.resolvePopperOptions();
|
|
88
|
-
const controlElement =
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
const { controlElement, popperElement } = getPopperElements.call(this);
|
|
92
|
+
const parentPopperBoundary = resolveParentPopperContentBoundary(
|
|
93
|
+
controlElement,
|
|
94
|
+
popperElement,
|
|
95
|
+
);
|
|
92
96
|
|
|
93
|
-
if (
|
|
97
|
+
if (
|
|
98
|
+
resolveClippingBoundaryElement(controlElement, popperElement) ||
|
|
99
|
+
parentPopperBoundary
|
|
100
|
+
) {
|
|
94
101
|
options.strategy = "fixed";
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
return options;
|
|
98
105
|
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Nested context poppers inside another popper need bounded height.
|
|
109
|
+
*
|
|
110
|
+
* @return {string}
|
|
111
|
+
*/
|
|
112
|
+
resolveContentOverflowMode() {
|
|
113
|
+
const configuredMode = super.resolveContentOverflowMode();
|
|
114
|
+
if (configuredMode !== "visible") {
|
|
115
|
+
return configuredMode;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const { controlElement, popperElement } = getPopperElements.call(this);
|
|
119
|
+
if (resolveParentPopperContentBoundary(controlElement, popperElement)) {
|
|
120
|
+
return "both";
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return configuredMode;
|
|
124
|
+
}
|
|
99
125
|
}
|
|
100
126
|
|
|
101
127
|
/**
|
|
@@ -126,6 +152,15 @@ function initContentObserver() {
|
|
|
126
152
|
});
|
|
127
153
|
}
|
|
128
154
|
|
|
155
|
+
function getPopperElements() {
|
|
156
|
+
return {
|
|
157
|
+
controlElement:
|
|
158
|
+
this.shadowRoot?.querySelector('[data-monster-role="control"]') || null,
|
|
159
|
+
popperElement:
|
|
160
|
+
this.shadowRoot?.querySelector('[data-monster-role="popper"]') || null,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
129
164
|
/**
|
|
130
165
|
* @private
|
|
131
166
|
* @return {void}
|
|
@@ -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 {ContextErrorStyleSheet}
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* @private
|
|
@@ -22,17 +22,10 @@ export { ContextErrorStyleSheet };
|
|
|
22
22
|
const ContextErrorStyleSheet = new CSSStyleSheet();
|
|
23
23
|
|
|
24
24
|
try {
|
|
25
|
-
|
|
26
|
-
`
|
|
25
|
+
ContextErrorStyleSheet.insertRule(`
|
|
27
26
|
@layer contexterror {
|
|
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));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}[data-monster-role=control]{line-height:1em;margin:0;padding:0;position:relative}[data-monster-role=control] [data-monster-role=button]{display:inline-block;position:relative}:is([data-monster-role=control] [data-monster-role=button]) svg{cursor:pointer}:is([data-monster-role=control] [data-monster-role=button]) svg.hidden{cursor:default;pointer-events:none;visibility:hidden}:host{display:inline-block;margin:0 .2em;padding:0;position:relative;vertical-align:bottom}div[data-monster-role=popper]{max-width:min(var(--monster-popper-max-width,calc(100vw - 2rem)),32rem)}div[data-monster-role=popper]>[part=content]{display:block;max-
|
|
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));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}[data-monster-role=control]{line-height:1em;margin:0;padding:0;position:relative}[data-monster-role=control] [data-monster-role=button]{display:inline-block;position:relative}:is([data-monster-role=control] [data-monster-role=button]) svg{cursor:pointer}:is([data-monster-role=control] [data-monster-role=button]) svg.hidden{cursor:default;pointer-events:none;visibility:hidden}:host{display:inline-block;margin:0 .2em;padding:0;position:relative;vertical-align:bottom}div[data-monster-role=popper]{max-width:min(var(--monster-popper-max-width,calc(100vw - 2rem)),32rem)}div[data-monster-role=popper]>[part=content]{display:block;max-width:100%;overflow-wrap:anywhere;text-wrap:pretty;white-space:normal;word-break:break-word}:host([disabled]) [data-monster-role=button] svg{cursor:default;pointer-events:none}
|
|
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
|
}
|
|
@@ -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 {ContextHelpStyleSheet}
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* @private
|
|
@@ -22,17 +22,10 @@ export { ContextHelpStyleSheet };
|
|
|
22
22
|
const ContextHelpStyleSheet = new CSSStyleSheet();
|
|
23
23
|
|
|
24
24
|
try {
|
|
25
|
-
|
|
26
|
-
`
|
|
25
|
+
ContextHelpStyleSheet.insertRule(`
|
|
27
26
|
@layer contexthelp {
|
|
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));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}[data-monster-role=control]{line-height:1em;margin:0;padding:0;position:relative}[data-monster-role=control] [data-monster-role=button]{display:inline-block;position:relative}:is([data-monster-role=control] [data-monster-role=button]) svg{cursor:pointer}:is([data-monster-role=control] [data-monster-role=button]) svg.hidden{cursor:default;pointer-events:none;visibility:hidden}div[data-monster-role=popper]{max-width:min(var(--monster-popper-max-width,calc(100vw - 2rem)),32rem);z-index:var(--monster-z-index-tooltip-overlay)}div[data-monster-role=popper]>[part=content]{display:block;max-
|
|
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));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}[data-monster-role=control]{line-height:1em;margin:0;padding:0;position:relative}[data-monster-role=control] [data-monster-role=button]{display:inline-block;position:relative}:is([data-monster-role=control] [data-monster-role=button]) svg{cursor:pointer}:is([data-monster-role=control] [data-monster-role=button]) svg.hidden{cursor:default;pointer-events:none;visibility:hidden}div[data-monster-role=popper]{max-width:min(var(--monster-popper-max-width,calc(100vw - 2rem)),32rem);z-index:var(--monster-z-index-tooltip-overlay)}div[data-monster-role=popper]>[part=content]{display:block;max-width:100%;overflow-wrap:anywhere;text-wrap:pretty;white-space:normal;word-break:break-word}:host{display:inline-block;margin:0 .2em;padding:0;position:relative;vertical-align:bottom}:host([disabled]) [data-monster-role=button] svg{cursor:default;pointer-events:none}
|
|
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
|
}
|
|
@@ -30,6 +30,7 @@ export {
|
|
|
30
30
|
applyAdaptiveFloatingElementSize,
|
|
31
31
|
closePositionedPopper,
|
|
32
32
|
resolveClippingBoundaryElement,
|
|
33
|
+
resolveParentPopperContentBoundary,
|
|
33
34
|
isPositionedPopperOpen,
|
|
34
35
|
openPositionedPopper,
|
|
35
36
|
positionPopper,
|
|
@@ -144,10 +145,12 @@ function normalizePopperConfig(options, controlElement, popperElement) {
|
|
|
144
145
|
options,
|
|
145
146
|
);
|
|
146
147
|
|
|
147
|
-
config.boundaryElement
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
if (!(config.boundaryElement instanceof HTMLElement)) {
|
|
149
|
+
config.boundaryElement = resolveClippingBoundaryElement(
|
|
150
|
+
controlElement,
|
|
151
|
+
popperElement,
|
|
152
|
+
);
|
|
153
|
+
}
|
|
151
154
|
config.detectOverflowOptions = buildDetectOverflowOptions(
|
|
152
155
|
config.boundaryElement,
|
|
153
156
|
);
|
|
@@ -283,6 +286,10 @@ function applyAdaptiveFloatingElementSize(
|
|
|
283
286
|
floatingElement,
|
|
284
287
|
{ availableWidth, availableHeight },
|
|
285
288
|
) {
|
|
289
|
+
const contentElement = getFloatingContentElement(floatingElement);
|
|
290
|
+
const usesVisibleOverflow =
|
|
291
|
+
contentElement instanceof HTMLElement &&
|
|
292
|
+
contentElement.dataset.monsterOverflowMode === "visible";
|
|
286
293
|
const maxWidth = clampAvailableDimension(
|
|
287
294
|
availableWidth,
|
|
288
295
|
readMaxDimension(floatingElement, "maxWidth"),
|
|
@@ -301,7 +308,7 @@ function applyAdaptiveFloatingElementSize(
|
|
|
301
308
|
nextStyle.maxWidth = "";
|
|
302
309
|
}
|
|
303
310
|
|
|
304
|
-
if (Number.isFinite(maxHeight) && maxHeight > 0) {
|
|
311
|
+
if (!usesVisibleOverflow && Number.isFinite(maxHeight) && maxHeight > 0) {
|
|
305
312
|
nextStyle.maxHeight = `${maxHeight}px`;
|
|
306
313
|
} else {
|
|
307
314
|
nextStyle.maxHeight = "";
|
|
@@ -332,14 +339,19 @@ function applyAdaptiveFloatingContentSize(floatingElement, maxHeight) {
|
|
|
332
339
|
Number.isFinite(maxHeight) ? maxHeight - reservedHeight : null,
|
|
333
340
|
readMaxDimension(contentElement, "maxHeight"),
|
|
334
341
|
);
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
342
|
+
const minimumReadableHeight = getMinimumReadableContentHeight(contentElement);
|
|
343
|
+
const nextContentMaxHeight =
|
|
344
|
+
Number.isFinite(contentMaxHeight) && contentMaxHeight > 0
|
|
345
|
+
? Math.max(contentMaxHeight, minimumReadableHeight)
|
|
346
|
+
: contentMaxHeight;
|
|
347
|
+
|
|
348
|
+
if (Number.isFinite(nextContentMaxHeight) && nextContentMaxHeight > 0) {
|
|
349
|
+
contentElement.style.maxHeight = `${nextContentMaxHeight}px`;
|
|
338
350
|
} else {
|
|
339
351
|
contentElement.style.maxHeight = "";
|
|
340
352
|
}
|
|
341
353
|
|
|
342
|
-
syncNestedScrollContainerHeight(contentElement,
|
|
354
|
+
syncNestedScrollContainerHeight(contentElement, nextContentMaxHeight);
|
|
343
355
|
}
|
|
344
356
|
|
|
345
357
|
function getFloatingContentElement(floatingElement) {
|
|
@@ -391,6 +403,63 @@ function readBoxDimension(rawValue) {
|
|
|
391
403
|
return Number.isFinite(value) ? value : 0;
|
|
392
404
|
}
|
|
393
405
|
|
|
406
|
+
function getMinimumReadableContentHeight(contentElement) {
|
|
407
|
+
if (!(contentElement instanceof HTMLElement)) {
|
|
408
|
+
return 0;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const measurementTarget =
|
|
412
|
+
getPrimaryReadableContentElement(contentElement) || contentElement;
|
|
413
|
+
const style = getComputedStyle(measurementTarget);
|
|
414
|
+
const lineHeight = readLineHeight(style);
|
|
415
|
+
const paddingHeight =
|
|
416
|
+
readBoxDimension(getComputedStyle(contentElement).paddingTop) +
|
|
417
|
+
readBoxDimension(getComputedStyle(contentElement).paddingBottom);
|
|
418
|
+
|
|
419
|
+
return Math.max(0, lineHeight + paddingHeight);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function readLineHeight(style) {
|
|
423
|
+
if (!style) {
|
|
424
|
+
return 0;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const lineHeight = Number.parseFloat(style.lineHeight);
|
|
428
|
+
if (Number.isFinite(lineHeight) && lineHeight > 0) {
|
|
429
|
+
return lineHeight;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const fontSize = Number.parseFloat(style.fontSize);
|
|
433
|
+
if (Number.isFinite(fontSize) && fontSize > 0) {
|
|
434
|
+
return fontSize * 1.4;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
return 0;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function getPrimaryReadableContentElement(contentElement) {
|
|
441
|
+
if (!(contentElement instanceof HTMLElement)) {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const slotElement = contentElement.querySelector("slot");
|
|
446
|
+
if (slotElement?.assignedElements instanceof Function) {
|
|
447
|
+
for (const element of slotElement.assignedElements({ flatten: true })) {
|
|
448
|
+
if (element instanceof HTMLElement) {
|
|
449
|
+
return element;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
for (const child of contentElement.children) {
|
|
455
|
+
if (child instanceof HTMLElement) {
|
|
456
|
+
return child;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
|
|
394
463
|
function syncNestedScrollContainerHeight(contentElement, contentMaxHeight) {
|
|
395
464
|
const nestedScrollableElement = getNestedScrollableElement(contentElement);
|
|
396
465
|
if (!(nestedScrollableElement instanceof HTMLElement)) {
|
|
@@ -539,6 +608,17 @@ function resolveClippingBoundaryElement(...elements) {
|
|
|
539
608
|
return null;
|
|
540
609
|
}
|
|
541
610
|
|
|
611
|
+
function resolveParentPopperContentBoundary(...elements) {
|
|
612
|
+
for (const element of elements) {
|
|
613
|
+
const clippingBoundary = findNearestIgnoredClippingContainer(element);
|
|
614
|
+
if (clippingBoundary instanceof HTMLElement) {
|
|
615
|
+
return clippingBoundary;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
return null;
|
|
620
|
+
}
|
|
621
|
+
|
|
542
622
|
function findNearestClippingContainer(element) {
|
|
543
623
|
let current = getComposedParent(element);
|
|
544
624
|
|
|
@@ -557,11 +637,46 @@ function findNearestClippingContainer(element) {
|
|
|
557
637
|
return null;
|
|
558
638
|
}
|
|
559
639
|
|
|
640
|
+
function findNearestIgnoredClippingContainer(element) {
|
|
641
|
+
let current = getComposedParent(element);
|
|
642
|
+
|
|
643
|
+
while (current) {
|
|
644
|
+
if (
|
|
645
|
+
current instanceof HTMLElement &&
|
|
646
|
+
shouldIgnoreClippingContainer(current) &&
|
|
647
|
+
shouldEscapeParentPopperContentWrapper(current)
|
|
648
|
+
) {
|
|
649
|
+
return current;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
current = getComposedParent(current);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
return null;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
function shouldEscapeParentPopperContentWrapper(element) {
|
|
659
|
+
if (!(element instanceof HTMLElement) || !isPopperContentWrapper(element)) {
|
|
660
|
+
return false;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
const overflowMode = element.getAttribute("data-monster-overflow-mode");
|
|
664
|
+
if (overflowMode === "both") {
|
|
665
|
+
return true;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
return isClippingContainer(getComputedStyle(element));
|
|
669
|
+
}
|
|
670
|
+
|
|
560
671
|
function getComposedParent(node) {
|
|
561
672
|
if (!node) {
|
|
562
673
|
return null;
|
|
563
674
|
}
|
|
564
675
|
|
|
676
|
+
if (node instanceof Element && node.assignedSlot) {
|
|
677
|
+
return node.assignedSlot;
|
|
678
|
+
}
|
|
679
|
+
|
|
565
680
|
if (node instanceof ShadowRoot) {
|
|
566
681
|
return node.host || null;
|
|
567
682
|
}
|
|
@@ -11,6 +11,7 @@ const global = getGlobal();
|
|
|
11
11
|
|
|
12
12
|
let ContextHelp;
|
|
13
13
|
let resolveClippingBoundaryElement;
|
|
14
|
+
let resolveParentPopperContentBoundary;
|
|
14
15
|
|
|
15
16
|
describe("ContextHelp", function () {
|
|
16
17
|
before(function (done) {
|
|
@@ -29,6 +30,8 @@ describe("ContextHelp", function () {
|
|
|
29
30
|
ContextHelp = contextHelpModule.ContextHelp;
|
|
30
31
|
resolveClippingBoundaryElement =
|
|
31
32
|
floatingUiModule.resolveClippingBoundaryElement;
|
|
33
|
+
resolveParentPopperContentBoundary =
|
|
34
|
+
floatingUiModule.resolveParentPopperContentBoundary;
|
|
32
35
|
done();
|
|
33
36
|
})
|
|
34
37
|
.catch((e) => done(e));
|
|
@@ -114,4 +117,48 @@ describe("ContextHelp", function () {
|
|
|
114
117
|
}
|
|
115
118
|
}, 0);
|
|
116
119
|
});
|
|
120
|
+
|
|
121
|
+
it("should switch to fixed positioning inside a parent popper content wrapper with overflow both", function (done) {
|
|
122
|
+
let mocks = document.getElementById("mocks");
|
|
123
|
+
const host = document.createElement("div");
|
|
124
|
+
const help = document.createElement("monster-context-help");
|
|
125
|
+
|
|
126
|
+
mocks.appendChild(host);
|
|
127
|
+
const shadowRoot = host.attachShadow({ mode: "open" });
|
|
128
|
+
shadowRoot.innerHTML = `
|
|
129
|
+
<div data-monster-role="popper">
|
|
130
|
+
<div part="content"
|
|
131
|
+
data-monster-overflow-mode="both">
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
`;
|
|
135
|
+
shadowRoot.querySelector('[part="content"]').appendChild(help);
|
|
136
|
+
help.innerHTML = "<p>Nested help</p>";
|
|
137
|
+
|
|
138
|
+
setTimeout(() => {
|
|
139
|
+
try {
|
|
140
|
+
const control = help.shadowRoot.querySelector(
|
|
141
|
+
'[data-monster-role="control"]',
|
|
142
|
+
);
|
|
143
|
+
const popper = help.shadowRoot.querySelector(
|
|
144
|
+
'[data-monster-role="popper"]',
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
expect(
|
|
148
|
+
resolveParentPopperContentBoundary(control, popper),
|
|
149
|
+
).to.equal(shadowRoot.querySelector('[part="content"]'));
|
|
150
|
+
|
|
151
|
+
const content = help.shadowRoot.querySelector('[part="content"]');
|
|
152
|
+
expect(content.getAttribute("data-monster-overflow-mode")).to.equal(
|
|
153
|
+
"both",
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
help.showDialog();
|
|
157
|
+
expect(popper.style.position).to.equal("fixed");
|
|
158
|
+
done();
|
|
159
|
+
} catch (e) {
|
|
160
|
+
done(e);
|
|
161
|
+
}
|
|
162
|
+
}, 0);
|
|
163
|
+
});
|
|
117
164
|
});
|
|
@@ -135,4 +135,76 @@ describe("form floating-ui boundary resolution", function () {
|
|
|
135
135
|
expect(content.style.maxWidth).to.equal("");
|
|
136
136
|
expect(content.style.maxHeight).to.equal("100px");
|
|
137
137
|
});
|
|
138
|
+
|
|
139
|
+
it("should not clamp the floating element height when content overflow is visible", function () {
|
|
140
|
+
const mocks = document.getElementById("mocks");
|
|
141
|
+
const popper = document.createElement("div");
|
|
142
|
+
const content = document.createElement("div");
|
|
143
|
+
|
|
144
|
+
popper.style.maxHeight = "300px";
|
|
145
|
+
content.style.maxHeight = "240px";
|
|
146
|
+
content.setAttribute("part", "content");
|
|
147
|
+
content.setAttribute("data-monster-overflow-mode", "visible");
|
|
148
|
+
|
|
149
|
+
popper.appendChild(content);
|
|
150
|
+
mocks.appendChild(popper);
|
|
151
|
+
|
|
152
|
+
applyAdaptiveFloatingElementSize(popper, {
|
|
153
|
+
availableWidth: 220,
|
|
154
|
+
availableHeight: 160,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
expect(popper.style.maxHeight).to.equal("");
|
|
158
|
+
expect(content.style.maxHeight).to.equal("240px");
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("should keep at least one readable line for scrollable content", function () {
|
|
162
|
+
const mocks = document.getElementById("mocks");
|
|
163
|
+
const popper = document.createElement("div");
|
|
164
|
+
const content = document.createElement("div");
|
|
165
|
+
|
|
166
|
+
popper.style.maxHeight = "300px";
|
|
167
|
+
content.setAttribute("part", "content");
|
|
168
|
+
content.textContent = "A long help text that still needs one readable line.";
|
|
169
|
+
content.style.fontSize = "16px";
|
|
170
|
+
content.style.lineHeight = "24px";
|
|
171
|
+
popper.appendChild(content);
|
|
172
|
+
mocks.appendChild(popper);
|
|
173
|
+
|
|
174
|
+
applyAdaptiveFloatingElementSize(popper, {
|
|
175
|
+
availableWidth: 220,
|
|
176
|
+
availableHeight: 10,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
expect(content.style.maxHeight).to.equal("24px");
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("should use the first slotted element line height for the minimum readable size", function () {
|
|
183
|
+
const mocks = document.getElementById("mocks");
|
|
184
|
+
const popperHost = document.createElement("div");
|
|
185
|
+
const slottedParagraph = document.createElement("p");
|
|
186
|
+
slottedParagraph.textContent = "Readable help line";
|
|
187
|
+
slottedParagraph.style.lineHeight = "26px";
|
|
188
|
+
|
|
189
|
+
mocks.appendChild(popperHost);
|
|
190
|
+
const shadowRoot = popperHost.attachShadow({ mode: "open" });
|
|
191
|
+
shadowRoot.innerHTML = `
|
|
192
|
+
<div data-monster-role="popper">
|
|
193
|
+
<div part="content">
|
|
194
|
+
<slot></slot>
|
|
195
|
+
</div>
|
|
196
|
+
</div>
|
|
197
|
+
`;
|
|
198
|
+
|
|
199
|
+
const popper = shadowRoot.querySelector('[data-monster-role="popper"]');
|
|
200
|
+
const content = shadowRoot.querySelector('[part="content"]');
|
|
201
|
+
popperHost.appendChild(slottedParagraph);
|
|
202
|
+
|
|
203
|
+
applyAdaptiveFloatingElementSize(popper, {
|
|
204
|
+
availableWidth: 220,
|
|
205
|
+
availableHeight: 10,
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
expect(content.style.maxHeight).to.equal("26px");
|
|
209
|
+
});
|
|
138
210
|
});
|