@schukai/monster 4.143.7 → 4.143.9
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
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.143.
|
|
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.143.9"}
|
|
@@ -1393,16 +1393,29 @@ function getVisualBorderElement(element, side) {
|
|
|
1393
1393
|
"textarea",
|
|
1394
1394
|
"monster-input-group",
|
|
1395
1395
|
"monster-select",
|
|
1396
|
+
"monster-button",
|
|
1397
|
+
"monster-state-button",
|
|
1398
|
+
"monster-message-state-button",
|
|
1399
|
+
"monster-action-button",
|
|
1400
|
+
"monster-api-button",
|
|
1401
|
+
"monster-confirm-button",
|
|
1402
|
+
"monster-popper-button",
|
|
1396
1403
|
"[data-monster-role=control]",
|
|
1397
1404
|
].join(",");
|
|
1398
1405
|
if (element.shadowRoot instanceof ShadowRoot) {
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
element.shadowRoot.querySelector(
|
|
1402
|
-
"monster-input-group,monster-select,[data-monster-role=control]",
|
|
1403
|
-
) ||
|
|
1404
|
-
element
|
|
1406
|
+
const primaryControl = element.shadowRoot.querySelector(
|
|
1407
|
+
"[data-monster-role=button],button,input,select,textarea",
|
|
1405
1408
|
);
|
|
1409
|
+
if (primaryControl instanceof HTMLElement && primaryControl !== element) {
|
|
1410
|
+
return getVisualBorderElement.call(this, primaryControl, side);
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
const control = element.shadowRoot.querySelector(selector);
|
|
1414
|
+
if (control instanceof HTMLElement && control !== element) {
|
|
1415
|
+
return getVisualBorderElement.call(this, control, side);
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
return element;
|
|
1406
1419
|
}
|
|
1407
1420
|
|
|
1408
1421
|
const candidates = Array.from(element.querySelectorAll(selector)).filter(
|
|
@@ -1413,10 +1426,14 @@ function getVisualBorderElement(element, side) {
|
|
|
1413
1426
|
}
|
|
1414
1427
|
|
|
1415
1428
|
if (side === "right" || side === "bottom") {
|
|
1416
|
-
return
|
|
1429
|
+
return getVisualBorderElement.call(
|
|
1430
|
+
this,
|
|
1431
|
+
candidates[candidates.length - 1],
|
|
1432
|
+
side,
|
|
1433
|
+
);
|
|
1417
1434
|
}
|
|
1418
1435
|
|
|
1419
|
-
return candidates[0];
|
|
1436
|
+
return getVisualBorderElement.call(this, candidates[0], side);
|
|
1420
1437
|
}
|
|
1421
1438
|
|
|
1422
1439
|
/**
|
|
@@ -299,6 +299,7 @@ const optionsMapSymbol = Symbol("optionsMap");
|
|
|
299
299
|
const optionsMapVersionSnapshotSymbol = Symbol("optionsMapVersionSnapshot");
|
|
300
300
|
const selectionVersionSymbol = Symbol("selectionVersion");
|
|
301
301
|
const closeOnSelectAutoSymbol = Symbol("closeOnSelectAuto");
|
|
302
|
+
const lastFilterValueSymbol = Symbol("lastFilterValue");
|
|
302
303
|
|
|
303
304
|
/**
|
|
304
305
|
* @private
|
|
@@ -3893,22 +3894,28 @@ function handleFilterKeyboardEvents(event) {
|
|
|
3893
3894
|
) {
|
|
3894
3895
|
this.click();
|
|
3895
3896
|
}
|
|
3896
|
-
|
|
3897
|
-
handleFilterKeyEvents.call(this);
|
|
3898
3897
|
}
|
|
3899
3898
|
}
|
|
3900
3899
|
|
|
3901
3900
|
/**
|
|
3902
|
-
* Method
|
|
3901
|
+
* Method handleFilterInputEvents is used to handle filter input events.
|
|
3903
3902
|
* Debounce is used to prevent multiple calls.
|
|
3904
3903
|
*
|
|
3905
3904
|
* @function
|
|
3906
|
-
* @name
|
|
3905
|
+
* @name handleFilterInputEvents
|
|
3907
3906
|
*
|
|
3908
3907
|
* @private
|
|
3909
3908
|
* @return {void} This method does not return anything.
|
|
3910
3909
|
*/
|
|
3911
|
-
function
|
|
3910
|
+
function handleFilterInputEvents() {
|
|
3911
|
+
const filterValue = getCurrentFilterInputValue.call(this);
|
|
3912
|
+
|
|
3913
|
+
if (filterValue === this[lastFilterValueSymbol]) {
|
|
3914
|
+
return;
|
|
3915
|
+
}
|
|
3916
|
+
|
|
3917
|
+
this[lastFilterValueSymbol] = filterValue;
|
|
3918
|
+
|
|
3912
3919
|
if (this[keyFilterEventSymbol] instanceof DeadMansSwitch) {
|
|
3913
3920
|
try {
|
|
3914
3921
|
this[keyFilterEventSymbol].touch();
|
|
@@ -3934,6 +3941,27 @@ function handleFilterKeyEvents() {
|
|
|
3934
3941
|
});
|
|
3935
3942
|
}
|
|
3936
3943
|
|
|
3944
|
+
/**
|
|
3945
|
+
* @private
|
|
3946
|
+
* @returns {string|undefined}
|
|
3947
|
+
*/
|
|
3948
|
+
function getCurrentFilterInputValue() {
|
|
3949
|
+
switch (this.getOption("filter.position")) {
|
|
3950
|
+
case FILTER_POSITION_INLINE:
|
|
3951
|
+
if (this[inlineFilterElementSymbol] instanceof HTMLInputElement) {
|
|
3952
|
+
return this[inlineFilterElementSymbol].value.toLowerCase();
|
|
3953
|
+
}
|
|
3954
|
+
break;
|
|
3955
|
+
case FILTER_POSITION_POPPER:
|
|
3956
|
+
default:
|
|
3957
|
+
if (this[popperFilterElementSymbol] instanceof HTMLInputElement) {
|
|
3958
|
+
return this[popperFilterElementSymbol].value.toLowerCase();
|
|
3959
|
+
}
|
|
3960
|
+
}
|
|
3961
|
+
|
|
3962
|
+
return undefined;
|
|
3963
|
+
}
|
|
3964
|
+
|
|
3937
3965
|
/**
|
|
3938
3966
|
* @private
|
|
3939
3967
|
*/
|
|
@@ -5336,6 +5364,7 @@ function initEventHandler() {
|
|
|
5336
5364
|
element.hasAttribute(ATTRIBUTE_ROLE) &&
|
|
5337
5365
|
element.getAttribute(ATTRIBUTE_ROLE) === "filter"
|
|
5338
5366
|
) {
|
|
5367
|
+
handleFilterInputEvents.call(self);
|
|
5339
5368
|
}
|
|
5340
5369
|
}
|
|
5341
5370
|
};
|
|
@@ -32,6 +32,8 @@ describe("ControlBar", function () {
|
|
|
32
32
|
import("../../../../source/components/form/control-bar-spacer.mjs"),
|
|
33
33
|
import("../../../../source/components/form/button.mjs"),
|
|
34
34
|
import("../../../../source/components/form/popper-button.mjs"),
|
|
35
|
+
import("../../../../source/components/form/message-state-button.mjs"),
|
|
36
|
+
import("../../../../source/components/form/confirm-button.mjs"),
|
|
35
37
|
])
|
|
36
38
|
.then((m) => {
|
|
37
39
|
ControlBar = m[0].ControlBar;
|
|
@@ -506,6 +508,105 @@ describe("ControlBar", function () {
|
|
|
506
508
|
}
|
|
507
509
|
});
|
|
508
510
|
|
|
511
|
+
it("should join borders between message state and confirm buttons", async function () {
|
|
512
|
+
const originalRequestAnimationFrame = window.requestAnimationFrame;
|
|
513
|
+
const originalGlobalRequestAnimationFrame = globalThis.requestAnimationFrame;
|
|
514
|
+
|
|
515
|
+
const scheduledCallbacks = [];
|
|
516
|
+
const flushFrames = async () => {
|
|
517
|
+
while (scheduledCallbacks.length > 0) {
|
|
518
|
+
scheduledCallbacks.shift()();
|
|
519
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
try {
|
|
524
|
+
window.requestAnimationFrame = (callback) => {
|
|
525
|
+
scheduledCallbacks.push(callback);
|
|
526
|
+
return scheduledCallbacks.length;
|
|
527
|
+
};
|
|
528
|
+
globalThis.requestAnimationFrame = window.requestAnimationFrame;
|
|
529
|
+
|
|
530
|
+
const mocks = document.getElementById("mocks");
|
|
531
|
+
mocks.innerHTML = `
|
|
532
|
+
<div id="workflow-border-bar-wrapper">
|
|
533
|
+
<monster-control-bar
|
|
534
|
+
id="workflow-border-bar"
|
|
535
|
+
data-nucleus-role="workflow-lifecycle-integrity-actions"
|
|
536
|
+
>
|
|
537
|
+
<monster-message-state-button
|
|
538
|
+
id="workflow-border-copy"
|
|
539
|
+
data-nucleus-role="workflow-lifecycle-integrity-copy"
|
|
540
|
+
>Diagnose kopieren</monster-message-state-button>
|
|
541
|
+
<monster-confirm-button
|
|
542
|
+
id="workflow-border-repair"
|
|
543
|
+
data-nucleus-role="workflow-lifecycle-integrity-repair"
|
|
544
|
+
>
|
|
545
|
+
<div>
|
|
546
|
+
<p>Workflow-Lifecycle für diese Variante jetzt reparieren?</p>
|
|
547
|
+
</div>
|
|
548
|
+
<div slot="confirm">Ja</div>
|
|
549
|
+
<div slot="cancel">Nein</div>
|
|
550
|
+
<div slot="button">Lifecycle reparieren</div>
|
|
551
|
+
</monster-confirm-button>
|
|
552
|
+
</monster-control-bar>
|
|
553
|
+
</div>
|
|
554
|
+
`;
|
|
555
|
+
|
|
556
|
+
const wrapper = document.getElementById("workflow-border-bar-wrapper");
|
|
557
|
+
const copy = document.getElementById("workflow-border-copy");
|
|
558
|
+
const repair = document.getElementById("workflow-border-repair");
|
|
559
|
+
|
|
560
|
+
wrapper.style.boxSizing = "border-box";
|
|
561
|
+
wrapper.style.width = "400px";
|
|
562
|
+
Object.defineProperty(wrapper, "clientWidth", {
|
|
563
|
+
configurable: true,
|
|
564
|
+
value: 400,
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
for (const control of [copy, repair]) {
|
|
568
|
+
Object.defineProperty(control, "offsetWidth", {
|
|
569
|
+
configurable: true,
|
|
570
|
+
value: 120,
|
|
571
|
+
});
|
|
572
|
+
Object.defineProperty(control, "offsetHeight", {
|
|
573
|
+
configurable: true,
|
|
574
|
+
value: 30,
|
|
575
|
+
});
|
|
576
|
+
control.getBoundingClientRect = () => ({
|
|
577
|
+
width: 120,
|
|
578
|
+
height: 30,
|
|
579
|
+
top: 0,
|
|
580
|
+
right: 120,
|
|
581
|
+
bottom: 30,
|
|
582
|
+
left: 0,
|
|
583
|
+
x: 0,
|
|
584
|
+
y: 0,
|
|
585
|
+
toJSON: () => {},
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
const copyInnerButton = copy.shadowRoot
|
|
590
|
+
?.querySelector('[data-monster-role="button"]')
|
|
591
|
+
?.shadowRoot?.querySelector("button");
|
|
592
|
+
const repairInnerButton = repair.shadowRoot?.querySelector(
|
|
593
|
+
'[data-monster-role="button"]',
|
|
594
|
+
);
|
|
595
|
+
|
|
596
|
+
copyInnerButton.style.borderRightWidth = "3px";
|
|
597
|
+
repairInnerButton.style.borderLeftWidth = "3px";
|
|
598
|
+
|
|
599
|
+
await flushFrames();
|
|
600
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
601
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
602
|
+
|
|
603
|
+
expect(repair.style.marginLeft).to.equal("-3px");
|
|
604
|
+
} finally {
|
|
605
|
+
window.requestAnimationFrame = originalRequestAnimationFrame;
|
|
606
|
+
globalThis.requestAnimationFrame = originalGlobalRequestAnimationFrame;
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
|
|
509
610
|
it("should size inline spacer lines from adjacent border widths", async function () {
|
|
510
611
|
const originalRequestAnimationFrame = window.requestAnimationFrame;
|
|
511
612
|
const originalGlobalRequestAnimationFrame = globalThis.requestAnimationFrame;
|
|
@@ -2283,12 +2283,10 @@ describe('Select', function () {
|
|
|
2283
2283
|
select.setOption('mapping.objectsPerPage', 'pagination.perPage');
|
|
2284
2284
|
mocks.appendChild(select);
|
|
2285
2285
|
|
|
2286
|
-
const
|
|
2287
|
-
input.dispatchEvent(new
|
|
2286
|
+
const dispatchFilterInput = (input) => {
|
|
2287
|
+
input.dispatchEvent(new Event('input', {
|
|
2288
2288
|
bubbles: true,
|
|
2289
|
-
composed: true
|
|
2290
|
-
code,
|
|
2291
|
-
key
|
|
2289
|
+
composed: true
|
|
2292
2290
|
}));
|
|
2293
2291
|
};
|
|
2294
2292
|
|
|
@@ -2304,12 +2302,12 @@ describe('Select', function () {
|
|
|
2304
2302
|
expect(requests[0]).to.equal('https://example.com/defaults?page=1');
|
|
2305
2303
|
|
|
2306
2304
|
filterInput.value = 'alpha';
|
|
2307
|
-
|
|
2305
|
+
dispatchFilterInput(filterInput);
|
|
2308
2306
|
await waitForCondition(() => requests.length >= 2);
|
|
2309
2307
|
expect(requests[1]).to.equal('https://example.com/items?filter=alpha&page=1');
|
|
2310
2308
|
|
|
2311
2309
|
filterInput.value = '';
|
|
2312
|
-
|
|
2310
|
+
dispatchFilterInput(filterInput);
|
|
2313
2311
|
await waitForCondition(() => requests.length >= 3);
|
|
2314
2312
|
expect(requests[2]).to.equal('https://example.com/defaults?page=1');
|
|
2315
2313
|
|
|
@@ -2321,6 +2319,129 @@ describe('Select', function () {
|
|
|
2321
2319
|
expect(requests[3]).to.equal('https://example.com/defaults?page=1');
|
|
2322
2320
|
});
|
|
2323
2321
|
|
|
2322
|
+
it('should not search when filter cursor keys do not change the value', async function () {
|
|
2323
|
+
this.timeout(5000);
|
|
2324
|
+
|
|
2325
|
+
let mocks = document.getElementById('mocks');
|
|
2326
|
+
const requests = [];
|
|
2327
|
+
|
|
2328
|
+
global['fetch'] = function (url) {
|
|
2329
|
+
requests.push(String(url));
|
|
2330
|
+
|
|
2331
|
+
return createJsonResponse({
|
|
2332
|
+
items: [
|
|
2333
|
+
{id: 'alpha', name: 'Alpha'}
|
|
2334
|
+
],
|
|
2335
|
+
pagination: {
|
|
2336
|
+
total: 1,
|
|
2337
|
+
page: 1,
|
|
2338
|
+
perPage: 1
|
|
2339
|
+
}
|
|
2340
|
+
});
|
|
2341
|
+
};
|
|
2342
|
+
|
|
2343
|
+
const select = document.createElement('monster-select');
|
|
2344
|
+
select.setOption('url', 'https://example.com/items?filter={filter}&page={page}');
|
|
2345
|
+
select.setOption('filter.mode', 'remote');
|
|
2346
|
+
select.setOption('filter.position', 'popper');
|
|
2347
|
+
select.setOption('mapping.selector', 'items.*');
|
|
2348
|
+
select.setOption('mapping.labelTemplate', '${name}');
|
|
2349
|
+
select.setOption('mapping.valueTemplate', '${id}');
|
|
2350
|
+
select.setOption('mapping.total', 'pagination.total');
|
|
2351
|
+
select.setOption('mapping.currentPage', 'pagination.page');
|
|
2352
|
+
select.setOption('mapping.objectsPerPage', 'pagination.perPage');
|
|
2353
|
+
mocks.appendChild(select);
|
|
2354
|
+
|
|
2355
|
+
await waitForCondition(() => {
|
|
2356
|
+
return select.shadowRoot.querySelector('[data-monster-role=filter][name="popper-filter"]') instanceof HTMLInputElement;
|
|
2357
|
+
});
|
|
2358
|
+
|
|
2359
|
+
const filterInput = select.shadowRoot.querySelector('[data-monster-role=filter][name="popper-filter"]');
|
|
2360
|
+
filterInput.value = 'alpha';
|
|
2361
|
+
|
|
2362
|
+
filterInput.dispatchEvent(new KeyboardEvent('keydown', {
|
|
2363
|
+
bubbles: true,
|
|
2364
|
+
composed: true,
|
|
2365
|
+
code: 'ArrowLeft',
|
|
2366
|
+
key: 'ArrowLeft'
|
|
2367
|
+
}));
|
|
2368
|
+
filterInput.dispatchEvent(new KeyboardEvent('keydown', {
|
|
2369
|
+
bubbles: true,
|
|
2370
|
+
composed: true,
|
|
2371
|
+
code: 'ArrowRight',
|
|
2372
|
+
key: 'ArrowRight'
|
|
2373
|
+
}));
|
|
2374
|
+
|
|
2375
|
+
await new Promise((resolve) => setTimeout(resolve, 260));
|
|
2376
|
+
expect(requests).to.have.length(0);
|
|
2377
|
+
|
|
2378
|
+
filterInput.dispatchEvent(new Event('input', {
|
|
2379
|
+
bubbles: true,
|
|
2380
|
+
composed: true
|
|
2381
|
+
}));
|
|
2382
|
+
|
|
2383
|
+
await waitForCondition(() => requests.length === 1);
|
|
2384
|
+
expect(requests[0]).to.equal('https://example.com/items?filter=alpha&page=1');
|
|
2385
|
+
});
|
|
2386
|
+
|
|
2387
|
+
it('should debounce repeated remote filter input events', async function () {
|
|
2388
|
+
this.timeout(5000);
|
|
2389
|
+
|
|
2390
|
+
let mocks = document.getElementById('mocks');
|
|
2391
|
+
const requests = [];
|
|
2392
|
+
|
|
2393
|
+
global['fetch'] = function (url) {
|
|
2394
|
+
requests.push(String(url));
|
|
2395
|
+
|
|
2396
|
+
return createJsonResponse({
|
|
2397
|
+
items: [
|
|
2398
|
+
{id: 'alpha', name: 'Alpha'}
|
|
2399
|
+
],
|
|
2400
|
+
pagination: {
|
|
2401
|
+
total: 1,
|
|
2402
|
+
page: 1,
|
|
2403
|
+
perPage: 1
|
|
2404
|
+
}
|
|
2405
|
+
});
|
|
2406
|
+
};
|
|
2407
|
+
|
|
2408
|
+
const select = document.createElement('monster-select');
|
|
2409
|
+
select.setOption('url', 'https://example.com/items?filter={filter}&page={page}');
|
|
2410
|
+
select.setOption('filter.mode', 'remote');
|
|
2411
|
+
select.setOption('filter.position', 'popper');
|
|
2412
|
+
select.setOption('mapping.selector', 'items.*');
|
|
2413
|
+
select.setOption('mapping.labelTemplate', '${name}');
|
|
2414
|
+
select.setOption('mapping.valueTemplate', '${id}');
|
|
2415
|
+
select.setOption('mapping.total', 'pagination.total');
|
|
2416
|
+
select.setOption('mapping.currentPage', 'pagination.page');
|
|
2417
|
+
select.setOption('mapping.objectsPerPage', 'pagination.perPage');
|
|
2418
|
+
mocks.appendChild(select);
|
|
2419
|
+
|
|
2420
|
+
await waitForCondition(() => {
|
|
2421
|
+
return select.shadowRoot.querySelector('[data-monster-role=filter][name="popper-filter"]') instanceof HTMLInputElement;
|
|
2422
|
+
});
|
|
2423
|
+
|
|
2424
|
+
const filterInput = select.shadowRoot.querySelector('[data-monster-role=filter][name="popper-filter"]');
|
|
2425
|
+
const dispatchInput = (value) => {
|
|
2426
|
+
filterInput.value = value;
|
|
2427
|
+
filterInput.dispatchEvent(new Event('input', {
|
|
2428
|
+
bubbles: true,
|
|
2429
|
+
composed: true
|
|
2430
|
+
}));
|
|
2431
|
+
};
|
|
2432
|
+
|
|
2433
|
+
dispatchInput('a');
|
|
2434
|
+
dispatchInput('al');
|
|
2435
|
+
dispatchInput('alp');
|
|
2436
|
+
dispatchInput('alpha');
|
|
2437
|
+
|
|
2438
|
+
await waitForCondition(() => requests.length === 1);
|
|
2439
|
+
expect(requests[0]).to.equal('https://example.com/items?filter=alpha&page=1');
|
|
2440
|
+
|
|
2441
|
+
await new Promise((resolve) => setTimeout(resolve, 260));
|
|
2442
|
+
expect(requests).to.have.length(1);
|
|
2443
|
+
});
|
|
2444
|
+
|
|
2324
2445
|
it('should keep unresolved lookup values visible and mark their badge', function (done) {
|
|
2325
2446
|
this.timeout(3000);
|
|
2326
2447
|
|