@schukai/monster 4.129.5 → 4.129.7
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/datatable/columnbar.mjs +12 -9
- package/source/components/form/confirm-button.mjs +1 -0
- package/source/components/form/util/floating-ui.mjs +5 -2
- package/source/components/form/util/popper.mjs +322 -14
- package/source/components/layout/tabs.mjs +7 -6
- package/source/components/layout/vertical-tabs.mjs +7 -6
- package/test/cases/components/form/confirm-button.mjs +30 -14
- package/test/cases/components/form/login.mjs +6 -11
- package/test/cases/components/form/popper-button.mjs +21 -0
- package/test/cases/dom/updater.mjs +15 -4
- package/test/util/jsdom.mjs +1 -0
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.6"
|
|
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.129.7"}
|
|
@@ -21,11 +21,14 @@ import {
|
|
|
21
21
|
import { findTargetElementFromEvent } from "../../dom/events.mjs";
|
|
22
22
|
import { clone } from "../../util/clone.mjs";
|
|
23
23
|
import { ColumnBarStyleSheet } from "./stylesheet/column-bar.mjs";
|
|
24
|
-
import { createPopper } from "@popperjs/core";
|
|
25
24
|
import { getLocaleOfDocument } from "../../dom/locale.mjs";
|
|
26
25
|
import { hasObjectLink } from "../../dom/attributes.mjs";
|
|
27
26
|
import { customElementUpdaterLinkSymbol } from "../../dom/constants.mjs";
|
|
28
27
|
import { getGlobalObject } from "../../types/global.mjs";
|
|
28
|
+
import {
|
|
29
|
+
createFloatingPopper,
|
|
30
|
+
popperInstanceSymbol,
|
|
31
|
+
} from "../form/util/popper.mjs";
|
|
29
32
|
|
|
30
33
|
export { ColumnBar };
|
|
31
34
|
|
|
@@ -53,12 +56,6 @@ const settingsLayerElementSymbol = Symbol("settingsLayerElement");
|
|
|
53
56
|
*/
|
|
54
57
|
const dotsContainerElementSymbol = Symbol("dotsContainerElement");
|
|
55
58
|
|
|
56
|
-
/**
|
|
57
|
-
* @private
|
|
58
|
-
* @type {symbol}
|
|
59
|
-
*/
|
|
60
|
-
const popperInstanceSymbol = Symbol("popperInstance");
|
|
61
|
-
|
|
62
59
|
/**
|
|
63
60
|
* @private
|
|
64
61
|
* @type {symbol}
|
|
@@ -226,7 +223,11 @@ class ColumnBar extends CustomElement {
|
|
|
226
223
|
}
|
|
227
224
|
|
|
228
225
|
if (typeof this[dotsFrameRequestSymbol] === "number") {
|
|
229
|
-
|
|
226
|
+
const cancelFrame =
|
|
227
|
+
typeof globalThis.cancelAnimationFrame === "function"
|
|
228
|
+
? globalThis.cancelAnimationFrame.bind(globalThis)
|
|
229
|
+
: globalThis.clearTimeout.bind(globalThis);
|
|
230
|
+
cancelFrame(this[dotsFrameRequestSymbol]);
|
|
230
231
|
this[dotsFrameRequestSymbol] = null;
|
|
231
232
|
}
|
|
232
233
|
|
|
@@ -241,6 +242,8 @@ class ColumnBar extends CustomElement {
|
|
|
241
242
|
);
|
|
242
243
|
this[closeEventHandlerSymbol] = null;
|
|
243
244
|
}
|
|
245
|
+
|
|
246
|
+
this[popperInstanceSymbol]?.destroy();
|
|
244
247
|
}
|
|
245
248
|
|
|
246
249
|
/**
|
|
@@ -350,7 +353,7 @@ function initControlReferences() {
|
|
|
350
353
|
function initEventHandler() {
|
|
351
354
|
const self = this;
|
|
352
355
|
|
|
353
|
-
self[popperInstanceSymbol] =
|
|
356
|
+
self[popperInstanceSymbol] = createFloatingPopper(
|
|
354
357
|
self[settingsButtonElementSymbol],
|
|
355
358
|
self[settingsLayerElementSymbol],
|
|
356
359
|
{
|
|
@@ -98,6 +98,7 @@ class ConfirmButton extends PopperButton {
|
|
|
98
98
|
},
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
+
obj["popper"]["strategy"] = "fixed";
|
|
101
102
|
obj["classes"]["confirmButton"] = "monster-button-primary";
|
|
102
103
|
obj["classes"]["cancelButton"] = "monster-button-secondary";
|
|
103
104
|
obj["actions"]["cancel"] = (e) => {
|
|
@@ -19,10 +19,10 @@ import {
|
|
|
19
19
|
computePosition,
|
|
20
20
|
offset,
|
|
21
21
|
flip,
|
|
22
|
+
hide,
|
|
22
23
|
size,
|
|
23
24
|
shift,
|
|
24
25
|
} from "@floating-ui/dom";
|
|
25
|
-
import { hide } from "@popperjs/core";
|
|
26
26
|
import { isArray, isFunction, isObject, isString } from "../../../types/is.mjs";
|
|
27
27
|
import { Processing } from "../../../util/processing.mjs";
|
|
28
28
|
|
|
@@ -55,11 +55,11 @@ function openPositionedPopper(controlElement, popperElement, options) {
|
|
|
55
55
|
|
|
56
56
|
stopAutoUpdate(popperElement);
|
|
57
57
|
popperElement.style.display = "block";
|
|
58
|
+
popperElement.style.position = config.strategy;
|
|
58
59
|
popperElement.style.removeProperty("transform");
|
|
59
60
|
|
|
60
61
|
// Keep the call signature stable even though only Floating UI is used now.
|
|
61
62
|
void controlElement;
|
|
62
|
-
void config;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function enableFloatingPositioning(controlElement, popperElement, config) {
|
|
@@ -93,6 +93,7 @@ function syncFloatingPopover(controlElement, popperElement, config) {
|
|
|
93
93
|
Object.assign(popperElement.style, {
|
|
94
94
|
top: "0",
|
|
95
95
|
left: "0",
|
|
96
|
+
position: config.strategy,
|
|
96
97
|
transform: `translate(${roundByDPR(x)}px,${roundByDPR(y)}px)`,
|
|
97
98
|
});
|
|
98
99
|
|
|
@@ -106,6 +107,7 @@ function closePositionedPopper(popperElement) {
|
|
|
106
107
|
stopAutoUpdate(popperElement);
|
|
107
108
|
popperElement.style.display = "none";
|
|
108
109
|
popperElement.style.removeProperty("visibility");
|
|
110
|
+
popperElement.style.removeProperty("position");
|
|
109
111
|
popperElement.style.removeProperty("transform");
|
|
110
112
|
}
|
|
111
113
|
|
|
@@ -119,6 +121,7 @@ function normalizePopperConfig(options) {
|
|
|
119
121
|
{
|
|
120
122
|
placement: "top",
|
|
121
123
|
engine: "floating",
|
|
124
|
+
strategy: "absolute",
|
|
122
125
|
},
|
|
123
126
|
options,
|
|
124
127
|
);
|
|
@@ -12,11 +12,33 @@
|
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
import {
|
|
16
|
+
arrow,
|
|
17
|
+
autoPlacement,
|
|
18
|
+
autoUpdate,
|
|
19
|
+
computePosition,
|
|
20
|
+
flip,
|
|
21
|
+
hide,
|
|
22
|
+
offset,
|
|
23
|
+
shift,
|
|
24
|
+
size,
|
|
25
|
+
} from "@floating-ui/dom";
|
|
15
26
|
import { extend } from "../../../data/extend.mjs";
|
|
16
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
isArray,
|
|
29
|
+
isElement,
|
|
30
|
+
isFunction,
|
|
31
|
+
isNumber,
|
|
32
|
+
isObject,
|
|
33
|
+
isString,
|
|
34
|
+
} from "../../../types/is.mjs";
|
|
17
35
|
import { validateBoolean } from "../../../types/validate.mjs";
|
|
18
36
|
|
|
19
|
-
export {
|
|
37
|
+
export {
|
|
38
|
+
createFloatingPopper,
|
|
39
|
+
setEventListenersModifiers,
|
|
40
|
+
popperInstanceSymbol,
|
|
41
|
+
};
|
|
20
42
|
|
|
21
43
|
/**
|
|
22
44
|
* @private
|
|
@@ -24,6 +46,65 @@ export { setEventListenersModifiers, popperInstanceSymbol };
|
|
|
24
46
|
*/
|
|
25
47
|
const popperInstanceSymbol = Symbol("popperInstance");
|
|
26
48
|
|
|
49
|
+
/**
|
|
50
|
+
* @private
|
|
51
|
+
* @type {symbol}
|
|
52
|
+
*/
|
|
53
|
+
const optionsSymbol = Symbol("options");
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @private
|
|
57
|
+
* @type {symbol}
|
|
58
|
+
*/
|
|
59
|
+
const referenceElementSymbol = Symbol("referenceElement");
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @private
|
|
63
|
+
* @type {symbol}
|
|
64
|
+
*/
|
|
65
|
+
const popperElementSymbol = Symbol("popperElement");
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @private
|
|
69
|
+
* @type {symbol}
|
|
70
|
+
*/
|
|
71
|
+
const autoUpdateCleanupSymbol = Symbol("autoUpdateCleanup");
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @private
|
|
75
|
+
* @param {HTMLElement} referenceElement
|
|
76
|
+
* @param {HTMLElement} popperElement
|
|
77
|
+
* @param {object} options
|
|
78
|
+
* @return {{destroy: Function, setOptions: Function, update: Function}}
|
|
79
|
+
*/
|
|
80
|
+
function createFloatingPopper(referenceElement, popperElement, options = {}) {
|
|
81
|
+
const instance = {
|
|
82
|
+
[referenceElementSymbol]: referenceElement,
|
|
83
|
+
[popperElementSymbol]: popperElement,
|
|
84
|
+
[optionsSymbol]: normalizeOptions(options),
|
|
85
|
+
[autoUpdateCleanupSymbol]: null,
|
|
86
|
+
destroy() {
|
|
87
|
+
stopAutoUpdate(instance);
|
|
88
|
+
},
|
|
89
|
+
setOptions(nextOptions) {
|
|
90
|
+
const normalizedOptions = isFunction(nextOptions)
|
|
91
|
+
? nextOptions(instance[optionsSymbol])
|
|
92
|
+
: nextOptions;
|
|
93
|
+
|
|
94
|
+
instance[optionsSymbol] = normalizeOptions(normalizedOptions);
|
|
95
|
+
syncAutoUpdate(instance);
|
|
96
|
+
return instance.update();
|
|
97
|
+
},
|
|
98
|
+
update() {
|
|
99
|
+
return updatePosition(instance);
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
syncAutoUpdate(instance);
|
|
104
|
+
|
|
105
|
+
return instance;
|
|
106
|
+
}
|
|
107
|
+
|
|
27
108
|
/**
|
|
28
109
|
* @private
|
|
29
110
|
* @this {CustomElement}
|
|
@@ -31,25 +112,252 @@ const popperInstanceSymbol = Symbol("popperInstance");
|
|
|
31
112
|
*/
|
|
32
113
|
function setEventListenersModifiers(mode) {
|
|
33
114
|
const options = extend({}, this.getOption("popper"));
|
|
34
|
-
const modifiers = options?.
|
|
115
|
+
const modifiers = options?.modifiers;
|
|
35
116
|
|
|
36
117
|
if (!isArray(modifiers)) {
|
|
37
|
-
options
|
|
118
|
+
options.modifiers = [];
|
|
38
119
|
}
|
|
39
120
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
options["modifiers"].push({
|
|
121
|
+
const existingModifier = options.modifiers.find((entry) => {
|
|
122
|
+
return entry?.name === "eventListeners";
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (existingModifier) {
|
|
126
|
+
existingModifier.enabled = validateBoolean(mode);
|
|
127
|
+
} else {
|
|
128
|
+
options.modifiers.push({
|
|
49
129
|
name: "eventListeners",
|
|
50
130
|
enabled: validateBoolean(mode),
|
|
51
131
|
});
|
|
52
132
|
}
|
|
53
133
|
|
|
54
|
-
this[popperInstanceSymbol].setOptions(options);
|
|
134
|
+
return this[popperInstanceSymbol].setOptions(options);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @private
|
|
139
|
+
* @param {object} instance
|
|
140
|
+
* @return {Promise<void>}
|
|
141
|
+
*/
|
|
142
|
+
function updatePosition(instance) {
|
|
143
|
+
const referenceElement = instance[referenceElementSymbol];
|
|
144
|
+
const popperElement = instance[popperElementSymbol];
|
|
145
|
+
const options = instance[optionsSymbol];
|
|
146
|
+
|
|
147
|
+
if (!isElement(referenceElement) || !isElement(popperElement)) {
|
|
148
|
+
return Promise.resolve();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return computePosition(referenceElement, popperElement, {
|
|
152
|
+
placement: options.placement,
|
|
153
|
+
strategy: options.strategy,
|
|
154
|
+
middleware: options.middleware,
|
|
155
|
+
}).then(({ x, y, strategy }) => {
|
|
156
|
+
Object.assign(popperElement.style, {
|
|
157
|
+
position: strategy,
|
|
158
|
+
left: `${roundByDPR(x)}px`,
|
|
159
|
+
top: `${roundByDPR(y)}px`,
|
|
160
|
+
transform: "",
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @private
|
|
167
|
+
* @param {object} instance
|
|
168
|
+
* @return {void}
|
|
169
|
+
*/
|
|
170
|
+
function syncAutoUpdate(instance) {
|
|
171
|
+
stopAutoUpdate(instance);
|
|
172
|
+
|
|
173
|
+
if (instance[optionsSymbol].eventListeners !== true) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
instance[autoUpdateCleanupSymbol] = autoUpdate(
|
|
178
|
+
instance[referenceElementSymbol],
|
|
179
|
+
instance[popperElementSymbol],
|
|
180
|
+
() => {
|
|
181
|
+
void instance.update();
|
|
182
|
+
},
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* @private
|
|
188
|
+
* @param {object} instance
|
|
189
|
+
* @return {void}
|
|
190
|
+
*/
|
|
191
|
+
function stopAutoUpdate(instance) {
|
|
192
|
+
const cleanup = instance[autoUpdateCleanupSymbol];
|
|
193
|
+
if (typeof cleanup === "function") {
|
|
194
|
+
cleanup();
|
|
195
|
+
}
|
|
196
|
+
instance[autoUpdateCleanupSymbol] = null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @private
|
|
201
|
+
* @param {object} options
|
|
202
|
+
* @return {object}
|
|
203
|
+
*/
|
|
204
|
+
function normalizeOptions(options) {
|
|
205
|
+
const config = extend(
|
|
206
|
+
{
|
|
207
|
+
placement: "bottom",
|
|
208
|
+
strategy: "absolute",
|
|
209
|
+
modifiers: [],
|
|
210
|
+
},
|
|
211
|
+
options || {},
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
config.eventListeners = normalizeEventListeners(config.modifiers);
|
|
215
|
+
config.middleware = normalizeMiddleware(config);
|
|
216
|
+
|
|
217
|
+
if (config.placement === "auto") {
|
|
218
|
+
config.placement = "bottom";
|
|
219
|
+
config.middleware.unshift(
|
|
220
|
+
autoPlacement({
|
|
221
|
+
crossAxis: true,
|
|
222
|
+
autoAlignment: true,
|
|
223
|
+
}),
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return config;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* @private
|
|
232
|
+
* @param {object[]} modifiers
|
|
233
|
+
* @return {boolean}
|
|
234
|
+
*/
|
|
235
|
+
function normalizeEventListeners(modifiers) {
|
|
236
|
+
if (!isArray(modifiers)) {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
let result = true;
|
|
241
|
+
|
|
242
|
+
for (const entry of modifiers) {
|
|
243
|
+
if (entry?.name === "eventListeners") {
|
|
244
|
+
result = validateBoolean(entry.enabled);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return result;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* @private
|
|
253
|
+
* @param {object} config
|
|
254
|
+
* @return {Array}
|
|
255
|
+
*/
|
|
256
|
+
function normalizeMiddleware(config) {
|
|
257
|
+
const result = [];
|
|
258
|
+
const middleware = [];
|
|
259
|
+
|
|
260
|
+
if (isArray(config?.middleware)) {
|
|
261
|
+
middleware.push(...config.middleware);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (isArray(config?.modifiers)) {
|
|
265
|
+
middleware.push(...config.modifiers);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
for (const entry of middleware) {
|
|
269
|
+
if (isFunction(entry)) {
|
|
270
|
+
result.push(entry);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (isObject(entry) && isFunction(entry?.fn)) {
|
|
275
|
+
result.push(entry);
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (isObject(entry) && !isString(entry?.name)) {
|
|
280
|
+
result.push(entry);
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (!isObject(entry) || !isString(entry?.name)) {
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const normalizedEntry = normalizeModifier(entry);
|
|
289
|
+
if (normalizedEntry) {
|
|
290
|
+
result.push(normalizedEntry);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return result;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* @private
|
|
299
|
+
* @param {{name: string, options?: object, enabled?: boolean}} modifier
|
|
300
|
+
* @return {object|null}
|
|
301
|
+
*/
|
|
302
|
+
function normalizeModifier(modifier) {
|
|
303
|
+
if (modifier.enabled === false) {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
switch (modifier.name) {
|
|
308
|
+
case "arrow":
|
|
309
|
+
if (!isElement(modifier?.options?.element)) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
return arrow(modifier.options);
|
|
313
|
+
case "autoPlacement":
|
|
314
|
+
return autoPlacement(modifier.options);
|
|
315
|
+
case "eventListeners":
|
|
316
|
+
return null;
|
|
317
|
+
case "flip":
|
|
318
|
+
return flip(modifier.options);
|
|
319
|
+
case "hide":
|
|
320
|
+
return hide(modifier.options);
|
|
321
|
+
case "offset":
|
|
322
|
+
return offset(normalizeOffset(modifier.options?.offset));
|
|
323
|
+
case "preventOverflow":
|
|
324
|
+
return shift(modifier.options);
|
|
325
|
+
case "shift":
|
|
326
|
+
return shift(modifier.options);
|
|
327
|
+
case "size":
|
|
328
|
+
return size(modifier.options);
|
|
329
|
+
default:
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* @private
|
|
336
|
+
* @param {number|Array<number>} rawOffset
|
|
337
|
+
* @return {number|object}
|
|
338
|
+
*/
|
|
339
|
+
function normalizeOffset(rawOffset) {
|
|
340
|
+
if (isArray(rawOffset)) {
|
|
341
|
+
const [skidding = 0, distance = 0] = rawOffset;
|
|
342
|
+
return {
|
|
343
|
+
mainAxis: distance,
|
|
344
|
+
crossAxis: skidding,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (isNumber(rawOffset)) {
|
|
349
|
+
return rawOffset;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return 0;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* @private
|
|
357
|
+
* @param {number} value
|
|
358
|
+
* @return {number}
|
|
359
|
+
*/
|
|
360
|
+
function roundByDPR(value) {
|
|
361
|
+
const dpr = window.devicePixelRatio || 1;
|
|
362
|
+
return Math.round(value * dpr) / dpr;
|
|
55
363
|
}
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { instanceSymbol } from "../../constants.mjs";
|
|
16
|
-
import { createPopper } from "@popperjs/core";
|
|
17
16
|
import { extend } from "../../data/extend.mjs";
|
|
18
17
|
import { Pathfinder } from "../../data/pathfinder.mjs";
|
|
19
18
|
import {
|
|
@@ -56,6 +55,7 @@ import { TabsStyleSheet } from "./stylesheet/tabs.mjs";
|
|
|
56
55
|
import { loadAndAssignContent } from "../form/util/fetch.mjs";
|
|
57
56
|
import { ThemeStyleSheet } from "../stylesheet/theme.mjs";
|
|
58
57
|
import {
|
|
58
|
+
createFloatingPopper,
|
|
59
59
|
popperInstanceSymbol,
|
|
60
60
|
setEventListenersModifiers,
|
|
61
61
|
} from "../form/util/popper.mjs";
|
|
@@ -189,9 +189,9 @@ class Tabs extends CustomElement {
|
|
|
189
189
|
* @property {String} fetch.mode=same-origin
|
|
190
190
|
* @property {String} fetch.credentials=same-origin
|
|
191
191
|
* @property {Object} fetch.headers={"accept":"text/html"}}
|
|
192
|
-
* @property {Object} popper
|
|
193
|
-
* @property {string} popper.placement=bottom
|
|
194
|
-
* @property {Object[]} modifiers={name:offset}
|
|
192
|
+
* @property {Object} popper Popper configuration
|
|
193
|
+
* @property {string} popper.placement=bottom Popper placement
|
|
194
|
+
* @property {Object[]} popper.modifiers={name:offset} Placement middleware configuration
|
|
195
195
|
*/
|
|
196
196
|
get defaults() {
|
|
197
197
|
return Object.assign({}, super.defaults, {
|
|
@@ -473,6 +473,8 @@ class Tabs extends CustomElement {
|
|
|
473
473
|
for (const [, type] of Object.entries(["click", "touch"])) {
|
|
474
474
|
document.removeEventListener(type, this[closeEventHandler]);
|
|
475
475
|
}
|
|
476
|
+
|
|
477
|
+
this[popperInstanceSymbol]?.destroy();
|
|
476
478
|
}
|
|
477
479
|
}
|
|
478
480
|
|
|
@@ -668,14 +670,13 @@ function attachTabChangeObserver() {
|
|
|
668
670
|
/**
|
|
669
671
|
* @private
|
|
670
672
|
* @return {Select}
|
|
671
|
-
* @external "external:createPopper"
|
|
672
673
|
*/
|
|
673
674
|
function initPopper() {
|
|
674
675
|
const self = this;
|
|
675
676
|
|
|
676
677
|
const options = extend({}, self.getOption("popper"));
|
|
677
678
|
|
|
678
|
-
self[popperInstanceSymbol] =
|
|
679
|
+
self[popperInstanceSymbol] = createFloatingPopper(
|
|
679
680
|
self[switchElementSymbol],
|
|
680
681
|
self[popperElementSymbol],
|
|
681
682
|
options,
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { instanceSymbol } from "../../constants.mjs";
|
|
16
|
-
import { createPopper } from "@popperjs/core";
|
|
17
16
|
import { extend } from "../../data/extend.mjs";
|
|
18
17
|
import { Pathfinder } from "../../data/pathfinder.mjs";
|
|
19
18
|
import {
|
|
@@ -57,6 +56,7 @@ import { VerticalTabsStyleSheet } from "./stylesheet/vertical-tabs.mjs";
|
|
|
57
56
|
import { loadAndAssignContent } from "../form/util/fetch.mjs";
|
|
58
57
|
import { ThemeStyleSheet } from "../stylesheet/theme.mjs";
|
|
59
58
|
import {
|
|
59
|
+
createFloatingPopper,
|
|
60
60
|
popperInstanceSymbol,
|
|
61
61
|
setEventListenersModifiers,
|
|
62
62
|
} from "../form/util/popper.mjs";
|
|
@@ -190,9 +190,9 @@ class VerticalTabs extends CustomElement {
|
|
|
190
190
|
* @property {String} fetch.mode=same-origin
|
|
191
191
|
* @property {String} fetch.credentials=same-origin
|
|
192
192
|
* @property {Object} fetch.headers={"accept":"text/html"}}
|
|
193
|
-
* @property {Object} popper
|
|
194
|
-
* @property {string} popper.placement=
|
|
195
|
-
* @property {Object[]} modifiers={name:offset}
|
|
193
|
+
* @property {Object} popper Popper configuration
|
|
194
|
+
* @property {string} popper.placement=right-start Popper placement
|
|
195
|
+
* @property {Object[]} popper.modifiers={name:offset} Placement middleware configuration
|
|
196
196
|
*/
|
|
197
197
|
get defaults() {
|
|
198
198
|
return Object.assign({}, super.defaults, {
|
|
@@ -474,6 +474,8 @@ class VerticalTabs extends CustomElement {
|
|
|
474
474
|
for (const [, type] of Object.entries(["click", "touch"])) {
|
|
475
475
|
document.removeEventListener(type, this[closeEventHandler]);
|
|
476
476
|
}
|
|
477
|
+
|
|
478
|
+
this[popperInstanceSymbol]?.destroy();
|
|
477
479
|
}
|
|
478
480
|
}
|
|
479
481
|
|
|
@@ -669,14 +671,13 @@ function attachTabChangeObserver() {
|
|
|
669
671
|
/**
|
|
670
672
|
* @private
|
|
671
673
|
* @return {Select}
|
|
672
|
-
* @external "external:createPopper"
|
|
673
674
|
*/
|
|
674
675
|
function initPopper() {
|
|
675
676
|
const self = this;
|
|
676
677
|
|
|
677
678
|
const options = extend({}, self.getOption("popper"));
|
|
678
679
|
|
|
679
|
-
self[popperInstanceSymbol] =
|
|
680
|
+
self[popperInstanceSymbol] = createFloatingPopper(
|
|
680
681
|
self[switchElementSymbol],
|
|
681
682
|
self[popperElementSymbol],
|
|
682
683
|
options,
|
|
@@ -15,10 +15,11 @@ let html1, options, html2, ConfirmButton;
|
|
|
15
15
|
|
|
16
16
|
describe('ConfirmButton', function () {
|
|
17
17
|
|
|
18
|
-
before(function (
|
|
18
|
+
before(async function () {
|
|
19
|
+
|
|
20
|
+
await initJSDOM();
|
|
21
|
+
await import("element-internals-polyfill");
|
|
19
22
|
|
|
20
|
-
import("element-internals-polyfill").catch(e => done(e));
|
|
21
|
-
|
|
22
23
|
if(!global.ResizeObserver) {
|
|
23
24
|
global.ResizeObserver = ResizeObserverMock;
|
|
24
25
|
}
|
|
@@ -43,16 +44,8 @@ describe('ConfirmButton', function () {
|
|
|
43
44
|
</div>
|
|
44
45
|
`
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
import("../../../../source/components/form/confirm-button.mjs").then((m) => {
|
|
50
|
-
ConfirmButton = m['ConfirmButton'];
|
|
51
|
-
done()
|
|
52
|
-
}).catch(e => done(e))
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
});
|
|
47
|
+
const m = await import("../../../../source/components/form/confirm-button.mjs");
|
|
48
|
+
ConfirmButton = m['ConfirmButton'];
|
|
56
49
|
})
|
|
57
50
|
|
|
58
51
|
describe('new ConfirmButton', function () {
|
|
@@ -120,8 +113,31 @@ describe('ConfirmButton', function () {
|
|
|
120
113
|
}, 0)
|
|
121
114
|
|
|
122
115
|
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should use fixed positioning by default', function (done) {
|
|
119
|
+
|
|
120
|
+
let mocks = document.getElementById('mocks');
|
|
121
|
+
const button = document.createElement('monster-confirm-button');
|
|
122
|
+
mocks.appendChild(button);
|
|
123
|
+
|
|
124
|
+
setTimeout(() => {
|
|
125
|
+
try {
|
|
126
|
+
button.showDialog();
|
|
127
|
+
|
|
128
|
+
const popper = button.shadowRoot.querySelector('[data-monster-role="popper"]');
|
|
129
|
+
expect(popper).to.exist;
|
|
130
|
+
expect(popper.style.position).to.equal('fixed');
|
|
131
|
+
} catch (e) {
|
|
132
|
+
return done(e);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
done();
|
|
136
|
+
}, 0)
|
|
137
|
+
|
|
138
|
+
|
|
123
139
|
});
|
|
124
140
|
});
|
|
125
141
|
|
|
126
142
|
|
|
127
|
-
});
|
|
143
|
+
});
|
|
@@ -8,6 +8,8 @@ chai.use(chaiDom);
|
|
|
8
8
|
let Login;
|
|
9
9
|
|
|
10
10
|
describe("Login", function () {
|
|
11
|
+
this.timeout(10000);
|
|
12
|
+
|
|
11
13
|
before(function (done) {
|
|
12
14
|
initJSDOM().then(() => {
|
|
13
15
|
import("element-internals-polyfill")
|
|
@@ -32,21 +34,14 @@ describe("Login", function () {
|
|
|
32
34
|
expect(document.createElement("monster-login")).is.instanceof(Login);
|
|
33
35
|
});
|
|
34
36
|
|
|
35
|
-
it("should respect the native hidden attribute on the host", function (
|
|
37
|
+
it("should respect the native hidden attribute on the host", function () {
|
|
36
38
|
const login = document.createElement("monster-login");
|
|
37
39
|
login.setAttribute("hidden", "");
|
|
38
40
|
document.getElementById("mocks").appendChild(login);
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
expect(login.visible).to.be.false;
|
|
44
|
-
expect(login.isVisible).to.be.false;
|
|
45
|
-
done();
|
|
46
|
-
} catch (error) {
|
|
47
|
-
done(error);
|
|
48
|
-
}
|
|
49
|
-
}, 100);
|
|
42
|
+
expect(login.hidden).to.be.true;
|
|
43
|
+
expect(login.visible).to.be.false;
|
|
44
|
+
expect(login.isVisible).to.be.false;
|
|
50
45
|
});
|
|
51
46
|
|
|
52
47
|
it("should hide and show the host with the public visibility API", function (done) {
|
|
@@ -86,4 +86,25 @@ describe("PopperButton", function () {
|
|
|
86
86
|
}
|
|
87
87
|
}, 0);
|
|
88
88
|
});
|
|
89
|
+
|
|
90
|
+
it("should use absolute positioning by default", function (done) {
|
|
91
|
+
let mocks = document.getElementById("mocks");
|
|
92
|
+
const button = document.createElement("monster-popper-button");
|
|
93
|
+
mocks.appendChild(button);
|
|
94
|
+
|
|
95
|
+
setTimeout(() => {
|
|
96
|
+
try {
|
|
97
|
+
button.showDialog();
|
|
98
|
+
|
|
99
|
+
const popper = button.shadowRoot.querySelector(
|
|
100
|
+
'[data-monster-role="popper"]',
|
|
101
|
+
);
|
|
102
|
+
expect(popper).to.exist;
|
|
103
|
+
expect(popper.style.position).to.equal("absolute");
|
|
104
|
+
done();
|
|
105
|
+
} catch (e) {
|
|
106
|
+
done(e);
|
|
107
|
+
}
|
|
108
|
+
}, 0);
|
|
109
|
+
});
|
|
89
110
|
});
|
|
@@ -289,18 +289,19 @@ describe("DOM", function () {
|
|
|
289
289
|
firedDisconnected: 0,
|
|
290
290
|
},
|
|
291
291
|
};
|
|
292
|
+
static pendingCallbacks = [];
|
|
292
293
|
|
|
293
294
|
connectedCallback() {
|
|
294
295
|
const mode = this.getAttribute("data-mode") || "replace";
|
|
295
296
|
MonsterTestRaceItem.stats[mode].connected++;
|
|
296
297
|
|
|
297
|
-
|
|
298
|
+
MonsterTestRaceItem.pendingCallbacks.push(() => {
|
|
298
299
|
if (this.isConnected) {
|
|
299
300
|
MonsterTestRaceItem.stats[mode].firedConnected++;
|
|
300
301
|
} else {
|
|
301
302
|
MonsterTestRaceItem.stats[mode].firedDisconnected++;
|
|
302
303
|
}
|
|
303
|
-
}
|
|
304
|
+
});
|
|
304
305
|
}
|
|
305
306
|
|
|
306
307
|
disconnectedCallback() {
|
|
@@ -308,6 +309,14 @@ describe("DOM", function () {
|
|
|
308
309
|
MonsterTestRaceItem.stats[mode].disconnected++;
|
|
309
310
|
}
|
|
310
311
|
|
|
312
|
+
static flushPendingCallbacks() {
|
|
313
|
+
const pending = [...MonsterTestRaceItem.pendingCallbacks];
|
|
314
|
+
MonsterTestRaceItem.pendingCallbacks = [];
|
|
315
|
+
for (const callback of pending) {
|
|
316
|
+
callback();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
311
320
|
static resetStats() {
|
|
312
321
|
MonsterTestRaceItem.stats = {
|
|
313
322
|
replace: {
|
|
@@ -323,6 +332,7 @@ describe("DOM", function () {
|
|
|
323
332
|
firedDisconnected: 0,
|
|
324
333
|
},
|
|
325
334
|
};
|
|
335
|
+
MonsterTestRaceItem.pendingCallbacks = [];
|
|
326
336
|
}
|
|
327
337
|
}
|
|
328
338
|
|
|
@@ -671,8 +681,9 @@ describe("DOM", function () {
|
|
|
671
681
|
|
|
672
682
|
setTimeout(() => {
|
|
673
683
|
try {
|
|
674
|
-
const
|
|
675
|
-
|
|
684
|
+
const raceItem = customElements.get("monster-test-race-item");
|
|
685
|
+
raceItem.flushPendingCallbacks();
|
|
686
|
+
const raceStats = raceItem.stats;
|
|
676
687
|
expect(raceStats.patch.firedDisconnected).to.equal(0);
|
|
677
688
|
expect(raceStats.replace.firedDisconnected).to.be.greaterThan(
|
|
678
689
|
0,
|