@schukai/monster 4.134.0 → 4.136.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 +1 -1
- package/source/components/form/message-state-button.mjs +6 -0
- package/source/components/form/select.mjs +13 -0
- package/source/components/form/util/floating-ui.mjs +298 -19
- package/source/data/datasource/server/restapi.mjs +7 -1
- package/source/data/datasource/server/webconnect.mjs +7 -1
- package/source/data/datasource/server.mjs +7 -1
- package/source/data/datasource/storage.mjs +6 -0
- package/source/data/datasource.mjs +6 -0
- package/source/dom/assembler.mjs +3 -0
- package/source/dom/customcontrol.mjs +5 -0
- package/source/dom/customelement.mjs +5 -0
- package/source/dom/focusmanager.mjs +3 -0
- package/source/dom/resource/link/stylesheet.mjs +4 -1
- package/source/dom/resource/link.mjs +4 -1
- package/source/dom/resource/script.mjs +4 -1
- package/source/dom/resource.mjs +4 -1
- package/source/dom/resourcemanager.mjs +7 -1
- package/source/dom/template.mjs +6 -0
- package/source/dom/updater.mjs +9 -0
- package/source/i18n/formatter.mjs +3 -0
- package/source/i18n/provider.mjs +6 -0
- package/source/i18n/translations.mjs +4 -0
- package/source/logging/handler.mjs +6 -0
- package/source/logging/logger.mjs +6 -0
- package/source/net/webconnect/message.mjs +6 -0
- package/source/net/webconnect.mjs +6 -0
- package/source/types/observablequeue.mjs +4 -1
- package/source/types/observer.mjs +4 -0
- package/test/cases/components/form/floating-ui.mjs +77 -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.
|
|
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.0"}
|
|
@@ -466,6 +466,11 @@ function initControlReferences() {
|
|
|
466
466
|
this[messageElementSymbol] = this.shadowRoot.querySelector(
|
|
467
467
|
`[${ATTRIBUTE_ROLE}=message]`,
|
|
468
468
|
);
|
|
469
|
+
if (this[popperElementSymbol] instanceof HTMLElement) {
|
|
470
|
+
this[popperElementSymbol].monsterBeforeFloatingUpdate = () => {
|
|
471
|
+
applyMeasuredMessageWidth.call(this);
|
|
472
|
+
};
|
|
473
|
+
}
|
|
469
474
|
applyResolvedMessagePresentation.call(this);
|
|
470
475
|
}
|
|
471
476
|
|
|
@@ -868,6 +873,7 @@ function applyMeasuredMessageWidth() {
|
|
|
868
873
|
Math.min(measuredWidth || minWidth, maxWidth),
|
|
869
874
|
);
|
|
870
875
|
|
|
876
|
+
popper.dataset.monsterPreferredMaxWidth = `${maxWidth}`;
|
|
871
877
|
popper.style.width = `${targetWidth}px`;
|
|
872
878
|
popper.style.minWidth = `${minWidth}px`;
|
|
873
879
|
popper.style.maxWidth = `${maxWidth}px`;
|
|
@@ -2453,6 +2453,7 @@ function getOptionElements() {
|
|
|
2453
2453
|
function calcAndSetOptionsDimension() {
|
|
2454
2454
|
const options = getOptionElements.call(this);
|
|
2455
2455
|
const container = this[optionsElementSymbol];
|
|
2456
|
+
const content = this[popperElementSymbol]?.querySelector?.('[part="content"]');
|
|
2456
2457
|
if (!(container instanceof HTMLElement && options instanceof NodeList)) {
|
|
2457
2458
|
return;
|
|
2458
2459
|
}
|
|
@@ -2541,8 +2542,17 @@ function calcAndSetOptionsDimension() {
|
|
|
2541
2542
|
|
|
2542
2543
|
const domRect = this[controlElementSymbol].getBoundingClientRect();
|
|
2543
2544
|
|
|
2545
|
+
this[popperElementSymbol].dataset.monsterPreferredWidth = `${Math.ceil(
|
|
2546
|
+
domRect.width,
|
|
2547
|
+
)}`;
|
|
2544
2548
|
this[popperElementSymbol].style.width = `${domRect.width}px`;
|
|
2549
|
+
this[popperElementSymbol].style.minWidth = `${domRect.width}px`;
|
|
2545
2550
|
container.style.overflowX = "auto";
|
|
2551
|
+
|
|
2552
|
+
if (content instanceof HTMLElement) {
|
|
2553
|
+
content.style.overflowX = "hidden";
|
|
2554
|
+
content.style.overflowY = "hidden";
|
|
2555
|
+
}
|
|
2546
2556
|
}
|
|
2547
2557
|
|
|
2548
2558
|
/**
|
|
@@ -4429,6 +4439,9 @@ function initControlReferences() {
|
|
|
4429
4439
|
this[popperElementSymbol] = this.shadowRoot.querySelector(
|
|
4430
4440
|
`[${ATTRIBUTE_ROLE}=popper]`,
|
|
4431
4441
|
);
|
|
4442
|
+
this[popperElementSymbol].monsterBeforeFloatingUpdate = () => {
|
|
4443
|
+
calcAndSetOptionsDimension.call(this);
|
|
4444
|
+
};
|
|
4432
4445
|
this[inlineFilterElementSymbol] = this.shadowRoot.querySelector(
|
|
4433
4446
|
`[${ATTRIBUTE_ROLE}=filter][name="inline-filter"]`,
|
|
4434
4447
|
);
|
|
@@ -27,6 +27,7 @@ import { isArray, isFunction, isObject, isString } from "../../../types/is.mjs";
|
|
|
27
27
|
import { Processing } from "../../../util/processing.mjs";
|
|
28
28
|
|
|
29
29
|
export {
|
|
30
|
+
applyAdaptiveFloatingElementSize,
|
|
30
31
|
closePositionedPopper,
|
|
31
32
|
resolveClippingBoundaryElement,
|
|
32
33
|
isPositionedPopperOpen,
|
|
@@ -35,6 +36,8 @@ export {
|
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
const autoUpdateCleanupMap = new WeakMap();
|
|
39
|
+
const settlingFrameMap = new WeakMap();
|
|
40
|
+
const floatingResizeObserverMap = new WeakMap();
|
|
38
41
|
|
|
39
42
|
/**
|
|
40
43
|
* @private
|
|
@@ -67,16 +70,26 @@ function enableFloatingPositioning(controlElement, popperElement, config) {
|
|
|
67
70
|
popperElement.style.removeProperty("visibility");
|
|
68
71
|
popperElement.style.display = "block";
|
|
69
72
|
|
|
73
|
+
startFloatingResizeObserver(controlElement, popperElement, config);
|
|
70
74
|
startAutoUpdate(controlElement, popperElement, () => {
|
|
75
|
+
runFloatingUpdateHook(popperElement);
|
|
71
76
|
syncFloatingPopover(controlElement, popperElement, config);
|
|
72
77
|
});
|
|
78
|
+
runFloatingUpdateHook(popperElement);
|
|
73
79
|
syncFloatingPopover(controlElement, popperElement, config);
|
|
74
80
|
}
|
|
75
81
|
|
|
76
|
-
function syncFloatingPopover(
|
|
82
|
+
function syncFloatingPopover(
|
|
83
|
+
controlElement,
|
|
84
|
+
popperElement,
|
|
85
|
+
config,
|
|
86
|
+
allowSettlingPass = true,
|
|
87
|
+
) {
|
|
77
88
|
const arrowElement = popperElement.querySelector("[data-monster-role=arrow]");
|
|
78
89
|
const floatingMiddleware = [...config.floatingMiddleware];
|
|
79
90
|
|
|
91
|
+
resetAdaptiveFloatingElementSize(popperElement);
|
|
92
|
+
|
|
80
93
|
if (
|
|
81
94
|
arrowElement instanceof HTMLElement &&
|
|
82
95
|
config.middlewareTokens.includes("arrow")
|
|
@@ -101,6 +114,10 @@ function syncFloatingPopover(controlElement, popperElement, config) {
|
|
|
101
114
|
if (middlewareData.arrow) {
|
|
102
115
|
applyFloatingArrowStyles(arrowElement, placement, middlewareData.arrow);
|
|
103
116
|
}
|
|
117
|
+
|
|
118
|
+
if (allowSettlingPass) {
|
|
119
|
+
scheduleSettlingPass(controlElement, popperElement, config);
|
|
120
|
+
}
|
|
104
121
|
});
|
|
105
122
|
}
|
|
106
123
|
|
|
@@ -253,30 +270,249 @@ function createAdaptiveSizeMiddleware(detectOverflowOptions, popperElement) {
|
|
|
253
270
|
return;
|
|
254
271
|
}
|
|
255
272
|
|
|
256
|
-
|
|
273
|
+
applyAdaptiveFloatingElementSize(floatingElement, {
|
|
257
274
|
availableWidth,
|
|
258
|
-
readMaxDimension(floatingElement, "maxWidth"),
|
|
259
|
-
);
|
|
260
|
-
const maxHeight = clampAvailableDimension(
|
|
261
275
|
availableHeight,
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
276
|
+
});
|
|
277
|
+
},
|
|
278
|
+
}),
|
|
279
|
+
);
|
|
280
|
+
}
|
|
267
281
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
282
|
+
function applyAdaptiveFloatingElementSize(
|
|
283
|
+
floatingElement,
|
|
284
|
+
{ availableWidth, availableHeight },
|
|
285
|
+
) {
|
|
286
|
+
const maxWidth = clampAvailableDimension(
|
|
287
|
+
availableWidth,
|
|
288
|
+
readMaxDimension(floatingElement, "maxWidth"),
|
|
289
|
+
);
|
|
290
|
+
const maxHeight = clampAvailableDimension(
|
|
291
|
+
availableHeight,
|
|
292
|
+
readMaxDimension(floatingElement, "maxHeight"),
|
|
293
|
+
);
|
|
294
|
+
const nextStyle = {
|
|
295
|
+
boxSizing: "border-box",
|
|
296
|
+
};
|
|
271
297
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
298
|
+
if (Number.isFinite(maxWidth) && maxWidth > 0) {
|
|
299
|
+
nextStyle.maxWidth = `${maxWidth}px`;
|
|
300
|
+
} else {
|
|
301
|
+
nextStyle.maxWidth = "";
|
|
302
|
+
}
|
|
275
303
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
304
|
+
if (Number.isFinite(maxHeight) && maxHeight > 0) {
|
|
305
|
+
nextStyle.maxHeight = `${maxHeight}px`;
|
|
306
|
+
} else {
|
|
307
|
+
nextStyle.maxHeight = "";
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
Object.assign(floatingElement.style, nextStyle);
|
|
311
|
+
|
|
312
|
+
syncPreferredFloatingWidth(floatingElement, maxWidth);
|
|
313
|
+
syncPreferredFloatingMaxWidth(floatingElement, maxWidth);
|
|
314
|
+
applyAdaptiveFloatingContentSize(floatingElement, maxHeight);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function applyAdaptiveFloatingContentSize(floatingElement, maxHeight) {
|
|
318
|
+
const contentElement = getFloatingContentElement(floatingElement);
|
|
319
|
+
if (!(contentElement instanceof HTMLElement)) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (contentElement.dataset.monsterOverflowMode === "visible") {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const reservedHeight = getReservedFloatingHeight(
|
|
328
|
+
floatingElement,
|
|
329
|
+
contentElement,
|
|
330
|
+
);
|
|
331
|
+
const contentMaxHeight = clampAvailableDimension(
|
|
332
|
+
Number.isFinite(maxHeight) ? maxHeight - reservedHeight : null,
|
|
333
|
+
readMaxDimension(contentElement, "maxHeight"),
|
|
279
334
|
);
|
|
335
|
+
|
|
336
|
+
if (Number.isFinite(contentMaxHeight) && contentMaxHeight > 0) {
|
|
337
|
+
contentElement.style.maxHeight = `${contentMaxHeight}px`;
|
|
338
|
+
} else {
|
|
339
|
+
contentElement.style.maxHeight = "";
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
syncNestedScrollContainerHeight(contentElement, contentMaxHeight);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function getFloatingContentElement(floatingElement) {
|
|
346
|
+
for (const child of floatingElement.children) {
|
|
347
|
+
if (!(child instanceof HTMLElement)) {
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const part = child.getAttribute("part");
|
|
352
|
+
if (
|
|
353
|
+
isString(part) &&
|
|
354
|
+
part
|
|
355
|
+
.split(/\s+/)
|
|
356
|
+
.filter((token) => token.length > 0)
|
|
357
|
+
.includes("content")
|
|
358
|
+
) {
|
|
359
|
+
return child;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function getReservedFloatingHeight(floatingElement, contentElement) {
|
|
367
|
+
const floatingStyle = getComputedStyle(floatingElement);
|
|
368
|
+
let reservedHeight = 0;
|
|
369
|
+
|
|
370
|
+
reservedHeight += readBoxDimension(floatingStyle.paddingTop);
|
|
371
|
+
reservedHeight += readBoxDimension(floatingStyle.paddingBottom);
|
|
372
|
+
reservedHeight += readBoxDimension(floatingStyle.borderTopWidth);
|
|
373
|
+
reservedHeight += readBoxDimension(floatingStyle.borderBottomWidth);
|
|
374
|
+
|
|
375
|
+
for (const child of floatingElement.children) {
|
|
376
|
+
if (!(child instanceof HTMLElement) || child === contentElement) {
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const childStyle = getComputedStyle(child);
|
|
381
|
+
reservedHeight += child.getBoundingClientRect().height;
|
|
382
|
+
reservedHeight += readBoxDimension(childStyle.marginTop);
|
|
383
|
+
reservedHeight += readBoxDimension(childStyle.marginBottom);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return Math.max(0, reservedHeight);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function readBoxDimension(rawValue) {
|
|
390
|
+
const value = Number.parseFloat(rawValue);
|
|
391
|
+
return Number.isFinite(value) ? value : 0;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function syncNestedScrollContainerHeight(contentElement, contentMaxHeight) {
|
|
395
|
+
const nestedScrollableElement = getNestedScrollableElement(contentElement);
|
|
396
|
+
if (!(nestedScrollableElement instanceof HTMLElement)) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (Number.isFinite(contentMaxHeight) && contentMaxHeight > 0) {
|
|
401
|
+
nestedScrollableElement.style.height = `${contentMaxHeight}px`;
|
|
402
|
+
nestedScrollableElement.style.maxHeight = `${contentMaxHeight}px`;
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
nestedScrollableElement.style.height = "";
|
|
407
|
+
nestedScrollableElement.style.maxHeight = "";
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function syncPreferredFloatingWidth(floatingElement, maxWidth) {
|
|
411
|
+
const preferredWidth = Number.parseFloat(
|
|
412
|
+
floatingElement.dataset.monsterPreferredWidth || "",
|
|
413
|
+
);
|
|
414
|
+
if (!Number.isFinite(preferredWidth) || preferredWidth <= 0) {
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const contentElement = getFloatingContentElement(floatingElement);
|
|
419
|
+
if (!(contentElement instanceof HTMLElement)) {
|
|
420
|
+
floatingElement.style.width = `${preferredWidth}px`;
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const floatingRect = floatingElement.getBoundingClientRect();
|
|
425
|
+
const contentRect = contentElement.getBoundingClientRect();
|
|
426
|
+
const reservedWidth = Math.max(0, floatingRect.width - contentRect.width);
|
|
427
|
+
const contentRequiredWidth = getRequiredContentWidth(contentElement);
|
|
428
|
+
const preferredFloatingWidth = preferredWidth;
|
|
429
|
+
const requiredFloatingWidth = Math.max(
|
|
430
|
+
preferredFloatingWidth,
|
|
431
|
+
contentRequiredWidth + reservedWidth,
|
|
432
|
+
);
|
|
433
|
+
const nextFloatingWidth = clampAvailableDimension(
|
|
434
|
+
requiredFloatingWidth,
|
|
435
|
+
Number.isFinite(maxWidth) ? maxWidth : Infinity,
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
if (Number.isFinite(nextFloatingWidth) && nextFloatingWidth > 0) {
|
|
439
|
+
floatingElement.style.width = `${nextFloatingWidth}px`;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function syncPreferredFloatingMaxWidth(floatingElement, maxWidth) {
|
|
444
|
+
const preferredMaxWidth = Number.parseFloat(
|
|
445
|
+
floatingElement.dataset.monsterPreferredMaxWidth || "",
|
|
446
|
+
);
|
|
447
|
+
if (!Number.isFinite(preferredMaxWidth) || preferredMaxWidth <= 0) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const nextFloatingMaxWidth = clampAvailableDimension(
|
|
452
|
+
preferredMaxWidth,
|
|
453
|
+
Number.isFinite(maxWidth) ? maxWidth : Infinity,
|
|
454
|
+
);
|
|
455
|
+
if (Number.isFinite(nextFloatingMaxWidth) && nextFloatingMaxWidth > 0) {
|
|
456
|
+
floatingElement.style.maxWidth = `${nextFloatingMaxWidth}px`;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function resetAdaptiveFloatingElementSize(floatingElement) {
|
|
461
|
+
if (!(floatingElement instanceof HTMLElement)) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
floatingElement.style.removeProperty("maxHeight");
|
|
466
|
+
|
|
467
|
+
const contentElement = getFloatingContentElement(floatingElement);
|
|
468
|
+
if (!(contentElement instanceof HTMLElement)) {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
contentElement.style.removeProperty("maxHeight");
|
|
473
|
+
|
|
474
|
+
const nestedScrollableElement = getNestedScrollableElement(contentElement);
|
|
475
|
+
if (!(nestedScrollableElement instanceof HTMLElement)) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
nestedScrollableElement.style.removeProperty("height");
|
|
480
|
+
nestedScrollableElement.style.removeProperty("maxHeight");
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function runFloatingUpdateHook(popperElement) {
|
|
484
|
+
const hook = popperElement?.monsterBeforeFloatingUpdate;
|
|
485
|
+
if (typeof hook === "function") {
|
|
486
|
+
hook();
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function getRequiredContentWidth(contentElement) {
|
|
491
|
+
const nestedScrollableElement = getNestedScrollableElement(contentElement);
|
|
492
|
+
if (nestedScrollableElement instanceof HTMLElement) {
|
|
493
|
+
return Math.max(
|
|
494
|
+
contentElement.scrollWidth,
|
|
495
|
+
nestedScrollableElement.scrollWidth,
|
|
496
|
+
contentElement.clientWidth,
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return Math.max(contentElement.scrollWidth, contentElement.clientWidth);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function getNestedScrollableElement(contentElement) {
|
|
504
|
+
for (const child of contentElement.children) {
|
|
505
|
+
if (!(child instanceof HTMLElement)) {
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const style = getComputedStyle(child);
|
|
510
|
+
if (["auto", "scroll"].includes(style.overflowY)) {
|
|
511
|
+
return child;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
return null;
|
|
280
516
|
}
|
|
281
517
|
|
|
282
518
|
function buildDetectOverflowOptions(boundaryElement) {
|
|
@@ -418,6 +654,8 @@ function startAutoUpdate(controlElement, popperElement, callback) {
|
|
|
418
654
|
}
|
|
419
655
|
|
|
420
656
|
function stopAutoUpdate(popperElement) {
|
|
657
|
+
cancelSettlingPass(popperElement);
|
|
658
|
+
stopFloatingResizeObserver(popperElement);
|
|
421
659
|
const cleanup = autoUpdateCleanupMap.get(popperElement);
|
|
422
660
|
if (typeof cleanup === "function") {
|
|
423
661
|
cleanup();
|
|
@@ -425,6 +663,47 @@ function stopAutoUpdate(popperElement) {
|
|
|
425
663
|
autoUpdateCleanupMap.delete(popperElement);
|
|
426
664
|
}
|
|
427
665
|
|
|
666
|
+
function startFloatingResizeObserver(controlElement, popperElement, config) {
|
|
667
|
+
stopFloatingResizeObserver(popperElement);
|
|
668
|
+
|
|
669
|
+
const observer = new ResizeObserver(() => {
|
|
670
|
+
scheduleSettlingPass(controlElement, popperElement, config);
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
observer.observe(popperElement);
|
|
674
|
+
floatingResizeObserverMap.set(popperElement, observer);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
function stopFloatingResizeObserver(popperElement) {
|
|
678
|
+
const observer = floatingResizeObserverMap.get(popperElement);
|
|
679
|
+
if (observer instanceof ResizeObserver) {
|
|
680
|
+
observer.disconnect();
|
|
681
|
+
}
|
|
682
|
+
floatingResizeObserverMap.delete(popperElement);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
function scheduleSettlingPass(controlElement, popperElement, config) {
|
|
686
|
+
if (settlingFrameMap.has(popperElement)) {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const frameId = requestAnimationFrame(() => {
|
|
691
|
+
settlingFrameMap.delete(popperElement);
|
|
692
|
+
runFloatingUpdateHook(popperElement);
|
|
693
|
+
syncFloatingPopover(controlElement, popperElement, config, false);
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
settlingFrameMap.set(popperElement, frameId);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
function cancelSettlingPass(popperElement) {
|
|
700
|
+
const frameId = settlingFrameMap.get(popperElement);
|
|
701
|
+
if (typeof frameId === "number") {
|
|
702
|
+
cancelAnimationFrame(frameId);
|
|
703
|
+
}
|
|
704
|
+
settlingFrameMap.delete(popperElement);
|
|
705
|
+
}
|
|
706
|
+
|
|
428
707
|
function applyFloatingArrowStyles(arrowElement, placement, arrowData) {
|
|
429
708
|
if (!(arrowElement instanceof HTMLElement)) {
|
|
430
709
|
return;
|
|
@@ -35,11 +35,17 @@ const rawDataSymbol = Symbol.for(
|
|
|
35
35
|
/**
|
|
36
36
|
* The RestAPI is a class that enables a REST API server.
|
|
37
37
|
*
|
|
38
|
+
* @fragments /fragments/libraries/data/datasource/server/restapi/
|
|
39
|
+
*
|
|
38
40
|
* @externalExample ../../../../example/data/datasource/server/restapi.mjs
|
|
41
|
+
* @example /examples/libraries/data/datasource/server/restapi/simple/ Configure read and write endpoints
|
|
42
|
+
* @example /examples/libraries/data/datasource/server/restapi/response-callback/ Replace the default read callback with a custom assignment flow
|
|
43
|
+
* @example /examples/libraries/data/datasource/server/restapi/partial-write/ Patch only changed fields before sending a write request
|
|
44
|
+
* @example /examples/libraries/data/datasource/server/restapi/report-path/ Read validation reports from a nested response path
|
|
39
45
|
* @license AGPLv3
|
|
40
46
|
* @since 1.22.0
|
|
41
47
|
* @copyright Volker Schukai
|
|
42
|
-
* @summary
|
|
48
|
+
* @summary A REST-backed datasource for reading and writing application state over HTTP.
|
|
43
49
|
*/
|
|
44
50
|
class RestAPI extends Server {
|
|
45
51
|
/**
|
|
@@ -31,11 +31,17 @@ const webConnectSymbol = Symbol("connection");
|
|
|
31
31
|
/**
|
|
32
32
|
* The RestAPI is a class that enables a REST API server.
|
|
33
33
|
*
|
|
34
|
+
* @fragments /fragments/libraries/data/datasource/server/webconnect/
|
|
35
|
+
*
|
|
34
36
|
* @externalExample ../../../../example/data/datasource/server/webconnect.mjs
|
|
37
|
+
* @example /examples/libraries/data/datasource/server/webconnect/simple/ Configure a realtime datasource bridge
|
|
38
|
+
* @example /examples/libraries/data/datasource/server/webconnect/message-queue/ Read queued realtime messages through the datasource API
|
|
39
|
+
* @example /examples/libraries/data/datasource/server/webconnect/transformed-read/ Apply read mapping to incoming socket payloads
|
|
40
|
+
* @example /examples/libraries/data/datasource/server/webconnect/write-envelope/ Prepare outgoing socket writes with sheathing options
|
|
35
41
|
* @license AGPLv3
|
|
36
42
|
* @since 3.1.0
|
|
37
43
|
* @copyright Volker Schukai
|
|
38
|
-
* @summary
|
|
44
|
+
* @summary A realtime datasource that bridges WebConnect messages into the datasource API.
|
|
39
45
|
*/
|
|
40
46
|
class WebConnect extends Server {
|
|
41
47
|
/**
|
|
@@ -30,10 +30,16 @@ const serverVersionSymbol = Symbol("serverVersion");
|
|
|
30
30
|
/**
|
|
31
31
|
* Base class for all server data sources
|
|
32
32
|
*
|
|
33
|
+
* @fragments /fragments/libraries/data/datasource/server/
|
|
34
|
+
*
|
|
35
|
+
* @example /examples/libraries/data/datasource/server/simple/ Transform and prepare server payloads
|
|
36
|
+
* @example /examples/libraries/data/datasource/server/transformer-callbacks/ Combine transformer expressions with mapping callbacks
|
|
37
|
+
* @example /examples/libraries/data/datasource/server/partial-diff/ Reduce write payloads through the partial diff callback
|
|
38
|
+
* @example /examples/libraries/data/datasource/server/sheathing-object/ Wrap outgoing payloads into a server-side envelope
|
|
33
39
|
* @license AGPLv3
|
|
34
40
|
* @since 3.4.0
|
|
35
41
|
* @copyright Volker Schukai
|
|
36
|
-
* @summary
|
|
42
|
+
* @summary A base datasource layer for reading, transforming and writing structured server payloads.
|
|
37
43
|
*/
|
|
38
44
|
class Server extends Datasource {
|
|
39
45
|
/**
|
|
@@ -29,6 +29,12 @@ const storageObjectSymbol = Symbol.for(
|
|
|
29
29
|
/**
|
|
30
30
|
* The class represents a record.
|
|
31
31
|
*
|
|
32
|
+
* @fragments /fragments/libraries/data/datasource/storage/
|
|
33
|
+
*
|
|
34
|
+
* @example /examples/libraries/data/datasource/storage/simple/ Read and write JSON through Web Storage
|
|
35
|
+
* @example /examples/libraries/data/datasource/storage/session-draft/ Persist draft state in session storage
|
|
36
|
+
* @example /examples/libraries/data/datasource/storage/local-preferences/ Persist user preferences in local storage
|
|
37
|
+
* @example /examples/libraries/data/datasource/storage/remove-on-undefined/ Remove the storage entry when the datasource becomes undefined
|
|
32
38
|
* @license AGPLv3
|
|
33
39
|
* @since 1.22.0
|
|
34
40
|
* @copyright Volker Schukai
|
|
@@ -48,6 +48,12 @@ const internalDataSymbol = Symbol.for(
|
|
|
48
48
|
* The datasource class is the basis for dealing with different data sources.
|
|
49
49
|
* It provides a unified interface for accessing data
|
|
50
50
|
* @externalExample ../../example/data/datasource.mjs
|
|
51
|
+
* @fragments /fragments/libraries/data/datasource/
|
|
52
|
+
* @example /examples/libraries/data/datasource/basic-read-write/ Implement a small in memory datasource with read and write
|
|
53
|
+
* @example /examples/libraries/data/datasource/observer-log/ Attach observers and react to subject changes
|
|
54
|
+
* @example /examples/libraries/data/datasource/skip-noop-events/ Compare skipNoopEvents with repeated writes
|
|
55
|
+
* @example /examples/libraries/data/datasource/render-list/ Drive a small UI list from datasource updates
|
|
56
|
+
* @example /examples/libraries/data/datasource/async-options/ Use datasource options to control async reads
|
|
51
57
|
* @license AGPLv3
|
|
52
58
|
* @since 1.22.0
|
|
53
59
|
* @copyright Volker Schukai
|
package/source/dom/assembler.mjs
CHANGED
|
@@ -29,6 +29,9 @@ const ATTRIBUTEPREFIX = "data-monster-";
|
|
|
29
29
|
/**
|
|
30
30
|
* Assembler class
|
|
31
31
|
*
|
|
32
|
+
* @fragments /fragments/libraries/dom/assembler/
|
|
33
|
+
*
|
|
34
|
+
* @example /examples/libraries/dom/assembler/simple/ Basic assembly flow
|
|
32
35
|
* @license AGPLv3
|
|
33
36
|
* @since 1.6.0
|
|
34
37
|
* @copyright Volker Schukai
|
|
@@ -50,6 +50,11 @@ const attachedInternalSymbol = Symbol("attachedInternal");
|
|
|
50
50
|
* Read the HTML specification for Custom Element Reactions: {@link https://html.spec.whatwg.org/dev/custom-elements.html#custom-element-reactions|Custom Element Reactions}.
|
|
51
51
|
*
|
|
52
52
|
* @fragments /fragments/libraries/dom/customcontrol/
|
|
53
|
+
* @example /examples/libraries/dom/customcontrol/text-input/ Build a minimal form associated text control
|
|
54
|
+
* @example /examples/libraries/dom/customcontrol/validation/ Add validation and reportValidity behaviour
|
|
55
|
+
* @example /examples/libraries/dom/customcontrol/formdata-submit/ Submit structured FormData from a custom control
|
|
56
|
+
* @example /examples/libraries/dom/customcontrol/reset-behaviour/ Restore the control state on form reset
|
|
57
|
+
* @example /examples/libraries/dom/customcontrol/disabled-sync/ Sync disabled state from form containers into the control
|
|
53
58
|
*
|
|
54
59
|
* @summary A form-oriented base class for Monster controls with value handling, validation and control semantics.
|
|
55
60
|
* @license AGPLv3
|
|
@@ -190,6 +190,11 @@ let hostVisibilityStyleSheet = null;
|
|
|
190
190
|
* And in the [HTML Standard](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements) or in the [WHATWG Wiki](https://wiki.whatwg.org/wiki/Custom_Elements).
|
|
191
191
|
*
|
|
192
192
|
* @fragments /fragments/libraries/dom/customelement/
|
|
193
|
+
* @example /examples/libraries/dom/customelement/simple-card/ Register a minimal element with inline template and stylesheet
|
|
194
|
+
* @example /examples/libraries/dom/customelement/options-from-attributes/ Read declarative options from data-monster-options
|
|
195
|
+
* @example /examples/libraries/dom/customelement/runtime-option-updates/ Update component state via setOption and setOptions
|
|
196
|
+
* @example /examples/libraries/dom/customelement/document-template/ Resolve the template from the surrounding document
|
|
197
|
+
* @example /examples/libraries/dom/customelement/visibility-events/ React to show hide and visibility events
|
|
193
198
|
*
|
|
194
199
|
* @license AGPLv3
|
|
195
200
|
* @since 1.7.0
|
|
@@ -42,6 +42,9 @@ const stackSymbol = Symbol("stack");
|
|
|
42
42
|
/**
|
|
43
43
|
* With the focus manager the focus can be stored in a document, recalled and moved.
|
|
44
44
|
*
|
|
45
|
+
* @fragments /fragments/libraries/dom/focusmanager/
|
|
46
|
+
*
|
|
47
|
+
* @example /examples/libraries/dom/focusmanager/simple/ Store and restore focus inside a dialog flow
|
|
45
48
|
* @license AGPLv3
|
|
46
49
|
* @since 1.25.0
|
|
47
50
|
* @copyright Volker Schukai
|
|
@@ -20,10 +20,13 @@ export { Stylesheet };
|
|
|
20
20
|
/**
|
|
21
21
|
* This class is used by the resource manager to embed external resources.
|
|
22
22
|
*
|
|
23
|
+
* @fragments /fragments/libraries/dom/resource/link/stylesheet/
|
|
24
|
+
*
|
|
25
|
+
* @example /examples/libraries/dom/resource/link/stylesheet/simple/ Configure a stylesheet resource
|
|
23
26
|
* @license AGPLv3
|
|
24
27
|
* @since 1.25.0
|
|
25
28
|
* @copyright Volker Schukai
|
|
26
|
-
* @summary A
|
|
29
|
+
* @summary A link resource specialized for loading external stylesheets.
|
|
27
30
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link
|
|
28
31
|
*/
|
|
29
32
|
class Stylesheet extends Link {
|
|
@@ -30,10 +30,13 @@ export { Link };
|
|
|
30
30
|
/**
|
|
31
31
|
* This class is used by the resource manager to embed external resources.
|
|
32
32
|
*
|
|
33
|
+
* @fragments /fragments/libraries/dom/resource/link/
|
|
34
|
+
*
|
|
35
|
+
* @example /examples/libraries/dom/resource/link/simple/ Create and connect a link resource
|
|
33
36
|
* @license AGPLv3
|
|
34
37
|
* @since 1.25.0
|
|
35
38
|
* @copyright Volker Schukai
|
|
36
|
-
* @summary A
|
|
39
|
+
* @summary A link resource for attaching external link-based assets such as stylesheets or preloads.
|
|
37
40
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link
|
|
38
41
|
*/
|
|
39
42
|
class Link extends Resource {
|
|
@@ -29,10 +29,13 @@ export { Script };
|
|
|
29
29
|
/**
|
|
30
30
|
* This class is used by the resource manager to embed scripts.
|
|
31
31
|
*
|
|
32
|
+
* @fragments /fragments/libraries/dom/resource/script/
|
|
33
|
+
*
|
|
34
|
+
* @example /examples/libraries/dom/resource/script/simple/ Create and connect a script resource
|
|
32
35
|
* @license AGPLv3
|
|
33
36
|
* @since 1.25.0
|
|
34
37
|
* @copyright Volker Schukai
|
|
35
|
-
* @summary A
|
|
38
|
+
* @summary A script resource for inserting external JavaScript files into the document.
|
|
36
39
|
*/
|
|
37
40
|
class Script extends Resource {
|
|
38
41
|
/**
|
package/source/dom/resource.mjs
CHANGED
|
@@ -56,10 +56,13 @@ const referenceSymbol = Symbol("reference");
|
|
|
56
56
|
/**
|
|
57
57
|
* This class is the base class for all resources to be loaded.
|
|
58
58
|
*
|
|
59
|
+
* @fragments /fragments/libraries/dom/resource/
|
|
60
|
+
*
|
|
61
|
+
* @example /examples/libraries/dom/resource/simple/ Create and connect a DOM resource
|
|
59
62
|
* @license AGPLv3
|
|
60
63
|
* @since 1.25.0
|
|
61
64
|
* @copyright Volker Schukai
|
|
62
|
-
* @summary A
|
|
65
|
+
* @summary A base resource abstraction for creating, connecting and observing DOM-loaded assets.
|
|
63
66
|
*/
|
|
64
67
|
class Resource extends BaseWithOptions {
|
|
65
68
|
/**
|
|
@@ -28,10 +28,16 @@ export { ResourceManager };
|
|
|
28
28
|
/**
|
|
29
29
|
* The ResourceManager is a singleton that manages all resources.
|
|
30
30
|
*
|
|
31
|
+
* @fragments /fragments/libraries/dom/resourcemanager/
|
|
32
|
+
*
|
|
33
|
+
* @example /examples/libraries/dom/resourcemanager/simple/ Register and connect multiple resources
|
|
34
|
+
* @example /examples/libraries/dom/resourcemanager/data-url-bundle/ Connect script stylesheet and data resources from inline urls
|
|
35
|
+
* @example /examples/libraries/dom/resourcemanager/separate-registration/ Register resources in separate steps and inspect the internal groups
|
|
36
|
+
* @example /examples/libraries/dom/resourcemanager/availability-check/ Wait for registered resources to report availability
|
|
31
37
|
* @license AGPLv3
|
|
32
38
|
* @since 1.25.0
|
|
33
39
|
* @copyright Volker Schukai
|
|
34
|
-
* @summary A
|
|
40
|
+
* @summary A resource coordinator for registering and connecting scripts, stylesheets and data assets.
|
|
35
41
|
*/
|
|
36
42
|
class ResourceManager extends Base {
|
|
37
43
|
/**
|
package/source/dom/template.mjs
CHANGED
|
@@ -25,6 +25,12 @@ export { Template };
|
|
|
25
25
|
/**
|
|
26
26
|
* The template class provides methods for creating templates.
|
|
27
27
|
*
|
|
28
|
+
* @fragments /fragments/libraries/dom/template/
|
|
29
|
+
*
|
|
30
|
+
* @example /examples/libraries/dom/template/simple/ Clone a named template fragment
|
|
31
|
+
* @example /examples/libraries/dom/template/theme-specific/ Resolve theme specific templates by id suffix
|
|
32
|
+
* @example /examples/libraries/dom/template/prefixed-lookup/ Resolve prefixed templates near the current node
|
|
33
|
+
* @example /examples/libraries/dom/template/repeated-clones/ Clone the same template multiple times without mutating the source
|
|
28
34
|
* @license AGPLv3
|
|
29
35
|
* @since 1.6.0
|
|
30
36
|
* @copyright Volker Schukai
|
package/source/dom/updater.mjs
CHANGED
|
@@ -105,6 +105,15 @@ const queuedSnapshotSymbol = Symbol("queuedSnapshot");
|
|
|
105
105
|
* @fragments /fragments/libraries/dom/updater/
|
|
106
106
|
*
|
|
107
107
|
* @example /examples/libraries/dom/updater/simple/ Simple example
|
|
108
|
+
* @example /examples/libraries/dom/updater/properties-and-patch/ Properties, patching and keyed list rendering
|
|
109
|
+
* @example /examples/libraries/dom/updater/attributes-and-aria/ Attribute and ARIA mapping
|
|
110
|
+
* @example /examples/libraries/dom/updater/bind-types/ Bound value casting
|
|
111
|
+
* @example /examples/libraries/dom/updater/retrieve-once/ One-time retrieval without live events
|
|
112
|
+
* @example /examples/libraries/dom/updater/insert-template-list/ Template insertion for iterable data
|
|
113
|
+
* @example /examples/libraries/dom/updater/custom-callbacks/ Custom pipe callbacks
|
|
114
|
+
* @example /examples/libraries/dom/updater/batch-updates/ Batched update processing
|
|
115
|
+
* @example /examples/libraries/dom/updater/control-properties/ Property updates on native controls
|
|
116
|
+
* @example /examples/libraries/dom/updater/select-multiple-array/ Multi-select array binding
|
|
108
117
|
*
|
|
109
118
|
* @license AGPLv3
|
|
110
119
|
* @since 1.8.0
|
|
@@ -31,6 +31,9 @@ const internalTranslationSymbol = Symbol("internalTranslation");
|
|
|
31
31
|
* The Formatter extends the Text.Formatter with the possibility to replace the key by a translation.
|
|
32
32
|
*
|
|
33
33
|
* @fragments /fragments/libraries/i18n/formatter/
|
|
34
|
+
* @example /examples/libraries/i18n/formatter/basic-translation/ Resolve one translation key through the i18n marker
|
|
35
|
+
* @example /examples/libraries/i18n/formatter/parameterized-text/ Combine translated text with formatter parameters
|
|
36
|
+
* @example /examples/libraries/i18n/formatter/custom-markers/ Configure custom formatter markers for translated strings
|
|
34
37
|
*
|
|
35
38
|
* @license AGPLv3
|
|
36
39
|
* @since 1.26.0
|
package/source/i18n/provider.mjs
CHANGED
|
@@ -38,6 +38,12 @@ const translationsLinkSymbol = Symbol.for(
|
|
|
38
38
|
/**
|
|
39
39
|
* A provider makes a translation object available.
|
|
40
40
|
*
|
|
41
|
+
* @fragments /fragments/libraries/i18n/provider/
|
|
42
|
+
*
|
|
43
|
+
* @example /examples/libraries/i18n/provider/simple/ Assign translations to a document
|
|
44
|
+
* @example /examples/libraries/i18n/provider/merge-existing/ Merge a second translation payload into an already linked element
|
|
45
|
+
* @example /examples/libraries/i18n/provider/subtree-assignment/ Attach translations to a dedicated subtree instead of the whole document
|
|
46
|
+
* @example /examples/libraries/i18n/provider/locale-switch/ Resolve different translation objects for different locales
|
|
41
47
|
* @license AGPLv3
|
|
42
48
|
* @since 1.13.0
|
|
43
49
|
* @copyright Volker Schukai
|
|
@@ -36,6 +36,10 @@ export { Translations, getDocumentTranslations };
|
|
|
36
36
|
* @fragments /fragments/libraries/i18n/translations/
|
|
37
37
|
*
|
|
38
38
|
* @externalExample ../../example/i18n/translations.mjs
|
|
39
|
+
* @example /examples/libraries/i18n/translations/simple/ Resolve singular and plural translations
|
|
40
|
+
* @example /examples/libraries/i18n/translations/bulk-assignment/ Load multiple translation keys from plain objects
|
|
41
|
+
* @example /examples/libraries/i18n/translations/fallbacks/ Use explicit default text when a key is missing
|
|
42
|
+
* @example /examples/libraries/i18n/translations/plural-keywords/ Resolve plural texts with explicit plural rule keywords
|
|
39
43
|
* @license AGPLv3
|
|
40
44
|
* @since 1.13.0
|
|
41
45
|
* @copyright Volker Schukai
|
|
@@ -22,6 +22,12 @@ export { Handler };
|
|
|
22
22
|
/**
|
|
23
23
|
* The log handler is the interface between the log entries and the log listeners.
|
|
24
24
|
*
|
|
25
|
+
* @fragments /fragments/libraries/logging/handler/
|
|
26
|
+
*
|
|
27
|
+
* @example /examples/libraries/logging/handler/simple/ Filter log entries before forwarding them
|
|
28
|
+
* @example /examples/libraries/logging/handler/level-switch/ Switch handler thresholds with the convenience methods
|
|
29
|
+
* @example /examples/libraries/logging/handler/structured-output/ Forward structured log entry data into a custom buffer
|
|
30
|
+
* @example /examples/libraries/logging/handler/off-state/ Disable a handler completely with the off level
|
|
25
31
|
* @license AGPLv3
|
|
26
32
|
* @since 1.5.0
|
|
27
33
|
* @copyright Volker Schukai
|
|
@@ -68,6 +68,12 @@ const OFF = 0;
|
|
|
68
68
|
/**
|
|
69
69
|
* The logger is a class that takes care of logging.
|
|
70
70
|
*
|
|
71
|
+
* @fragments /fragments/libraries/logging/logger/
|
|
72
|
+
*
|
|
73
|
+
* @example /examples/libraries/logging/logger/simple/ Write entries through a console handler
|
|
74
|
+
* @example /examples/libraries/logging/logger/multiple-handlers/ Route the same log entry through multiple handlers
|
|
75
|
+
* @example /examples/libraries/logging/logger/level-filtering/ Filter log output through handler log levels
|
|
76
|
+
* @example /examples/libraries/logging/logger/remove-handler/ Remove a handler and verify that it no longer receives entries
|
|
71
77
|
* @license AGPLv3
|
|
72
78
|
* @since 1.5.0
|
|
73
79
|
* @copyright Volker Schukai
|
|
@@ -22,6 +22,12 @@ const dataSymbol = Symbol("@@data");
|
|
|
22
22
|
/**
|
|
23
23
|
* This class represents a WebSocket message.
|
|
24
24
|
*
|
|
25
|
+
* @fragments /fragments/libraries/net/webconnect/message/
|
|
26
|
+
*
|
|
27
|
+
* @example /examples/libraries/net/webconnect/message/simple/ Serialize and restore a structured message
|
|
28
|
+
* @example /examples/libraries/net/webconnect/message/nested-payload/ Keep nested payload data intact through serialization
|
|
29
|
+
* @example /examples/libraries/net/webconnect/message/queue-ready-shape/ Use a message shape that is ready for queue inspection and logging
|
|
30
|
+
* @example /examples/libraries/net/webconnect/message/object-access/ Access raw message data through getData and toJSON
|
|
25
31
|
* @license AGPLv3
|
|
26
32
|
* @since 3.4.0
|
|
27
33
|
* @copyright Volker Schukai
|
|
@@ -209,7 +209,13 @@ function connectServer(resolve, reject) {
|
|
|
209
209
|
/**
|
|
210
210
|
* The RestAPI is a class that enables a REST API server.
|
|
211
211
|
*
|
|
212
|
+
* @fragments /fragments/libraries/net/webconnect/
|
|
213
|
+
*
|
|
212
214
|
* @externalExample ../../example/net/webconnect.mjs
|
|
215
|
+
* @example /examples/libraries/net/webconnect/simple/ Connect and consume structured messages
|
|
216
|
+
* @example /examples/libraries/net/webconnect/send-and-close/ Send structured messages and close the connection manually
|
|
217
|
+
* @example /examples/libraries/net/webconnect/observer-queue/ Observe incoming queue updates through the receive queue observer API
|
|
218
|
+
* @example /examples/libraries/net/webconnect/reconnect-options/ Configure reconnect and timeout options for resilient connections
|
|
213
219
|
* @license AGPLv3
|
|
214
220
|
* @since 3.1.0
|
|
215
221
|
* @copyright Volker Schukai
|
|
@@ -23,9 +23,12 @@ export { ObservableQueue };
|
|
|
23
23
|
*
|
|
24
24
|
* `Queue.add()` and `Queue.clear()` notify all observers.
|
|
25
25
|
*
|
|
26
|
+
* @fragments /fragments/libraries/types/observablequeue/
|
|
27
|
+
*
|
|
28
|
+
* @example /examples/libraries/types/observablequeue/simple/ Observe queue changes while items are added
|
|
26
29
|
* @since 3.3.0
|
|
27
30
|
* @copyright Volker Schukai
|
|
28
|
-
* @summary
|
|
31
|
+
* @summary A FIFO queue that notifies observers whenever its contents change.
|
|
29
32
|
*/
|
|
30
33
|
class ObservableQueue extends Queue {
|
|
31
34
|
/**
|
|
@@ -40,8 +40,12 @@ export { Observer };
|
|
|
40
40
|
* observer.update(mySubject);
|
|
41
41
|
* greeter.update(mySubject);
|
|
42
42
|
*
|
|
43
|
+
* @fragments /fragments/libraries/types/observer/
|
|
44
|
+
*
|
|
45
|
+
* @example /examples/libraries/types/observer/simple/ Schedule a deduplicated observer update
|
|
43
46
|
* @license AGPLv3
|
|
44
47
|
* @since 1.0.0
|
|
48
|
+
* @summary An asynchronous observer that batches updates per subject and callback.
|
|
45
49
|
*/
|
|
46
50
|
class Observer extends Base {
|
|
47
51
|
/**
|
|
@@ -4,6 +4,7 @@ import { initJSDOM } from "../../../util/jsdom.mjs";
|
|
|
4
4
|
let expect = chai.expect;
|
|
5
5
|
|
|
6
6
|
let resolveClippingBoundaryElement;
|
|
7
|
+
let applyAdaptiveFloatingElementSize;
|
|
7
8
|
|
|
8
9
|
describe("form floating-ui boundary resolution", function () {
|
|
9
10
|
before(function (done) {
|
|
@@ -15,6 +16,7 @@ describe("form floating-ui boundary resolution", function () {
|
|
|
15
16
|
})
|
|
16
17
|
.then((m) => {
|
|
17
18
|
resolveClippingBoundaryElement = m.resolveClippingBoundaryElement;
|
|
19
|
+
applyAdaptiveFloatingElementSize = m.applyAdaptiveFloatingElementSize;
|
|
18
20
|
done();
|
|
19
21
|
})
|
|
20
22
|
.catch((e) => done(e));
|
|
@@ -58,4 +60,79 @@ describe("form floating-ui boundary resolution", function () {
|
|
|
58
60
|
|
|
59
61
|
expect(resolveClippingBoundaryElement(control, popper)).to.equal(wrapper);
|
|
60
62
|
});
|
|
63
|
+
|
|
64
|
+
it("should adapt the content max height to the available popper height", function () {
|
|
65
|
+
const mocks = document.getElementById("mocks");
|
|
66
|
+
const popper = document.createElement("div");
|
|
67
|
+
const header = document.createElement("div");
|
|
68
|
+
const content = document.createElement("div");
|
|
69
|
+
const footer = document.createElement("div");
|
|
70
|
+
|
|
71
|
+
popper.style.maxHeight = "300px";
|
|
72
|
+
content.style.maxHeight = "240px";
|
|
73
|
+
content.setAttribute("part", "content");
|
|
74
|
+
|
|
75
|
+
popper.appendChild(header);
|
|
76
|
+
popper.appendChild(content);
|
|
77
|
+
popper.appendChild(footer);
|
|
78
|
+
mocks.appendChild(popper);
|
|
79
|
+
|
|
80
|
+
header.getBoundingClientRect = () => {
|
|
81
|
+
return {
|
|
82
|
+
width: 180,
|
|
83
|
+
height: 30,
|
|
84
|
+
top: 0,
|
|
85
|
+
left: 0,
|
|
86
|
+
right: 180,
|
|
87
|
+
bottom: 30,
|
|
88
|
+
x: 0,
|
|
89
|
+
y: 0,
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
popper.getBoundingClientRect = () => {
|
|
93
|
+
return {
|
|
94
|
+
width: 220,
|
|
95
|
+
height: 200,
|
|
96
|
+
top: 0,
|
|
97
|
+
left: 0,
|
|
98
|
+
right: 220,
|
|
99
|
+
bottom: 200,
|
|
100
|
+
x: 0,
|
|
101
|
+
y: 0,
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
footer.getBoundingClientRect = () => {
|
|
105
|
+
return {
|
|
106
|
+
width: 180,
|
|
107
|
+
height: 30,
|
|
108
|
+
top: 0,
|
|
109
|
+
left: 0,
|
|
110
|
+
right: 180,
|
|
111
|
+
bottom: 30,
|
|
112
|
+
x: 0,
|
|
113
|
+
y: 0,
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
content.getBoundingClientRect = () => {
|
|
117
|
+
return {
|
|
118
|
+
width: 180,
|
|
119
|
+
height: 140,
|
|
120
|
+
top: 0,
|
|
121
|
+
left: 0,
|
|
122
|
+
right: 180,
|
|
123
|
+
bottom: 140,
|
|
124
|
+
x: 0,
|
|
125
|
+
y: 0,
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
applyAdaptiveFloatingElementSize(popper, {
|
|
130
|
+
availableWidth: 220,
|
|
131
|
+
availableHeight: 160,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect(popper.style.maxHeight).to.equal("160px");
|
|
135
|
+
expect(content.style.maxWidth).to.equal("");
|
|
136
|
+
expect(content.style.maxHeight).to.equal("100px");
|
|
137
|
+
});
|
|
61
138
|
});
|