@schukai/monster 4.93.0 → 4.94.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/CHANGELOG.md +8 -0
- package/package.json +1 -1
- package/source/components/datatable/columnbar.mjs +204 -0
- package/source/components/datatable/pagination.mjs +512 -11
- package/source/components/datatable/style/column-bar.pcss +17 -2
- package/source/components/datatable/style/embedded-pagination.pcss +65 -0
- package/source/components/datatable/style/pagination.pcss +57 -1
- package/source/components/datatable/stylesheet/column-bar.mjs +1 -1
- package/source/components/datatable/stylesheet/embedded-pagination.mjs +1 -1
- package/source/components/datatable/stylesheet/pagination.mjs +1 -1
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":"Volker Schukai","dependencies":{"@floating-ui/dom":"^1.7.4","@popperjs/core":"^2.11.8"},"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.4","@popperjs/core":"^2.11.8"},"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.94.0"}
|
|
@@ -65,6 +65,23 @@ const popperInstanceSymbol = Symbol("popperInstance");
|
|
|
65
65
|
*/
|
|
66
66
|
const closeEventHandlerSymbol = Symbol("closeEventHandler");
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* @private
|
|
70
|
+
* @type {symbol}
|
|
71
|
+
*/
|
|
72
|
+
const resizeObserverSymbol = Symbol("resizeObserver");
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @private
|
|
76
|
+
* @type {symbol}
|
|
77
|
+
*/
|
|
78
|
+
const dotsMutationObserverSymbol = Symbol("dotsMutationObserver");
|
|
79
|
+
/**
|
|
80
|
+
* @private
|
|
81
|
+
* @type {symbol}
|
|
82
|
+
*/
|
|
83
|
+
const dotsUpdateInProgressSymbol = Symbol("dotsUpdateInProgress");
|
|
84
|
+
|
|
68
85
|
/**
|
|
69
86
|
* A column bar for a datatable
|
|
70
87
|
*
|
|
@@ -102,6 +119,8 @@ class ColumnBar extends CustomElement {
|
|
|
102
119
|
* @property {string} templates.main Main template
|
|
103
120
|
* @property {object} labels Locale definitions
|
|
104
121
|
* @property {string} locale.settings The text for the settings button
|
|
122
|
+
* @property {object} dots Dots configuration
|
|
123
|
+
* @property {number} dots.maxVisible Max dots to show (0 disables limit)
|
|
105
124
|
*/
|
|
106
125
|
get defaults() {
|
|
107
126
|
return Object.assign({}, super.defaults, {
|
|
@@ -109,6 +128,9 @@ class ColumnBar extends CustomElement {
|
|
|
109
128
|
main: getTemplate(),
|
|
110
129
|
},
|
|
111
130
|
labels: getTranslations(),
|
|
131
|
+
dots: {
|
|
132
|
+
maxVisible: 15,
|
|
133
|
+
},
|
|
112
134
|
|
|
113
135
|
columns: [],
|
|
114
136
|
});
|
|
@@ -144,6 +166,11 @@ class ColumnBar extends CustomElement {
|
|
|
144
166
|
"touch",
|
|
145
167
|
this[closeEventHandlerSymbol],
|
|
146
168
|
);
|
|
169
|
+
|
|
170
|
+
queueMicrotask(() => {
|
|
171
|
+
initDotsObservers.call(this);
|
|
172
|
+
updateDotsVisibility.call(this);
|
|
173
|
+
});
|
|
147
174
|
}
|
|
148
175
|
|
|
149
176
|
/**
|
|
@@ -155,6 +182,16 @@ class ColumnBar extends CustomElement {
|
|
|
155
182
|
disconnectedCallback() {
|
|
156
183
|
super.disconnectedCallback();
|
|
157
184
|
|
|
185
|
+
if (this[resizeObserverSymbol] instanceof ResizeObserver) {
|
|
186
|
+
this[resizeObserverSymbol].disconnect();
|
|
187
|
+
this[resizeObserverSymbol] = null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (this[dotsMutationObserverSymbol] instanceof MutationObserver) {
|
|
191
|
+
this[dotsMutationObserverSymbol].disconnect();
|
|
192
|
+
this[dotsMutationObserverSymbol] = null;
|
|
193
|
+
}
|
|
194
|
+
|
|
158
195
|
if (this[closeEventHandlerSymbol]) {
|
|
159
196
|
getGlobalObject("document").removeEventListener(
|
|
160
197
|
"click",
|
|
@@ -367,6 +404,173 @@ function initEventHandler() {
|
|
|
367
404
|
});
|
|
368
405
|
}
|
|
369
406
|
|
|
407
|
+
/**
|
|
408
|
+
* @private
|
|
409
|
+
*/
|
|
410
|
+
function initDotsObservers() {
|
|
411
|
+
const controlElement = this.shadowRoot?.querySelector(
|
|
412
|
+
"[data-monster-role=control]",
|
|
413
|
+
);
|
|
414
|
+
const parentElement = this.parentElement;
|
|
415
|
+
|
|
416
|
+
if (controlElement && !this[resizeObserverSymbol]) {
|
|
417
|
+
this[resizeObserverSymbol] = new ResizeObserver(() => {
|
|
418
|
+
updateDotsVisibility.call(this);
|
|
419
|
+
});
|
|
420
|
+
this[resizeObserverSymbol].observe(controlElement);
|
|
421
|
+
if (parentElement) {
|
|
422
|
+
this[resizeObserverSymbol].observe(parentElement);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if (this[dotsContainerElementSymbol] && !this[dotsMutationObserverSymbol]) {
|
|
427
|
+
this[dotsMutationObserverSymbol] = new MutationObserver(() => {
|
|
428
|
+
if (this[dotsUpdateInProgressSymbol]) {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
requestAnimationFrame(() => updateDotsVisibility.call(this));
|
|
432
|
+
});
|
|
433
|
+
this[dotsMutationObserverSymbol].observe(this[dotsContainerElementSymbol], {
|
|
434
|
+
childList: true,
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* @private
|
|
441
|
+
*/
|
|
442
|
+
function updateDotsVisibility() {
|
|
443
|
+
if (this[dotsUpdateInProgressSymbol]) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (!this.shadowRoot || !this[dotsContainerElementSymbol]) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const controlElement = this.shadowRoot.querySelector(
|
|
452
|
+
"[data-monster-role=control]",
|
|
453
|
+
);
|
|
454
|
+
const settingsButton = this[settingsButtonElementSymbol];
|
|
455
|
+
const parentElement = this.parentElement;
|
|
456
|
+
|
|
457
|
+
if (!controlElement || !settingsButton) {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const dotsContainer = this[dotsContainerElementSymbol];
|
|
462
|
+
dotsContainer.classList.remove("dots-hidden");
|
|
463
|
+
|
|
464
|
+
this[dotsUpdateInProgressSymbol] = true;
|
|
465
|
+
try {
|
|
466
|
+
const dots = Array.from(dotsContainer.querySelectorAll("li"));
|
|
467
|
+
if (dots.length === 0) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
for (const dot of dots) {
|
|
472
|
+
dot.classList.remove("dots-overflow-hidden");
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const indicator = dotsContainer.querySelector(".dots-overflow-indicator");
|
|
476
|
+
if (indicator) {
|
|
477
|
+
indicator.remove();
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const controlWidth = controlElement.getBoundingClientRect().width;
|
|
481
|
+
const settingsWidth = settingsButton.getBoundingClientRect().width;
|
|
482
|
+
const availableWidth = Math.max(
|
|
483
|
+
0,
|
|
484
|
+
getAvailableWidth(parentElement, settingsWidth, this) ??
|
|
485
|
+
controlWidth - settingsWidth - 12,
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
const dotSlotWidth = getDotSlotWidth(dots[0]);
|
|
489
|
+
const maxDots =
|
|
490
|
+
dotSlotWidth > 0
|
|
491
|
+
? Math.floor(availableWidth / dotSlotWidth)
|
|
492
|
+
: dots.length;
|
|
493
|
+
const configuredMaxVisible = parseInt(
|
|
494
|
+
this.getOption("dots.maxVisible"),
|
|
495
|
+
10,
|
|
496
|
+
);
|
|
497
|
+
const enforceMaxVisible =
|
|
498
|
+
Number.isFinite(configuredMaxVisible) && configuredMaxVisible > 0;
|
|
499
|
+
|
|
500
|
+
if (maxDots <= 1) {
|
|
501
|
+
dotsContainer.classList.add("dots-hidden");
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
if (maxDots >= dots.length) {
|
|
506
|
+
if (!enforceMaxVisible) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
let visibleDots = Math.max(1, maxDots - 1);
|
|
512
|
+
if (enforceMaxVisible) {
|
|
513
|
+
visibleDots = Math.min(visibleDots, configuredMaxVisible);
|
|
514
|
+
}
|
|
515
|
+
for (let i = visibleDots; i < dots.length; i++) {
|
|
516
|
+
dots[i].classList.add("dots-overflow-hidden");
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const hiddenCount = dots.length - visibleDots;
|
|
520
|
+
const overflowIndicator = document.createElement("li");
|
|
521
|
+
overflowIndicator.className = "dots-overflow-indicator";
|
|
522
|
+
overflowIndicator.textContent = `+${hiddenCount}`;
|
|
523
|
+
dotsContainer.appendChild(overflowIndicator);
|
|
524
|
+
} finally {
|
|
525
|
+
this[dotsUpdateInProgressSymbol] = false;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* @private
|
|
531
|
+
* @param {HTMLElement} dot
|
|
532
|
+
* @return {number}
|
|
533
|
+
*/
|
|
534
|
+
function getDotSlotWidth(dot) {
|
|
535
|
+
if (!dot) return 0;
|
|
536
|
+
const styles = getComputedStyle(dot);
|
|
537
|
+
const marginRight = parseFloat(styles.marginRight || "0");
|
|
538
|
+
const marginLeft = parseFloat(styles.marginLeft || "0");
|
|
539
|
+
return dot.getBoundingClientRect().width + marginLeft + marginRight;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* @private
|
|
544
|
+
* @param {HTMLElement|null} parent
|
|
545
|
+
* @param {number} settingsWidth
|
|
546
|
+
* @return {number|null}
|
|
547
|
+
*/
|
|
548
|
+
function getAvailableWidth(parent, settingsWidth, hostElement) {
|
|
549
|
+
if (!parent) return null;
|
|
550
|
+
|
|
551
|
+
const parentWidth = parent.getBoundingClientRect().width;
|
|
552
|
+
if (!parentWidth) return null;
|
|
553
|
+
|
|
554
|
+
const styles = getComputedStyle(parent);
|
|
555
|
+
const gapValue = styles.columnGap || styles.gap || "0";
|
|
556
|
+
const gap = parseFloat(gapValue) || 0;
|
|
557
|
+
|
|
558
|
+
const siblings = Array.from(parent.children).filter(
|
|
559
|
+
(el) => el !== hostElement,
|
|
560
|
+
);
|
|
561
|
+
let siblingsWidth = 0;
|
|
562
|
+
for (const sibling of siblings) {
|
|
563
|
+
const siblingStyles = getComputedStyle(sibling);
|
|
564
|
+
if (siblingStyles.display === "none") {
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
siblingsWidth += sibling.getBoundingClientRect().width;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const gaps = siblings.length > 0 ? siblings.length : 0;
|
|
571
|
+
return Math.max(0, parentWidth - siblingsWidth - gap * gaps - settingsWidth);
|
|
572
|
+
}
|
|
573
|
+
|
|
370
574
|
/**
|
|
371
575
|
* @private
|
|
372
576
|
* @return {string}
|