@schukai/monster 4.148.8 → 4.149.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/accessibility/stylesheet/locale-picker.mjs +61 -1
- package/source/components/content/image-editor.mjs +79 -11
- package/source/components/content/style/copy.pcss +1 -1
- package/source/components/content/stylesheet/camera-capture.mjs +1 -1
- package/source/components/content/stylesheet/copy.mjs +1 -1
- package/source/components/content/stylesheet/fetch-box.mjs +1 -1
- package/source/components/content/stylesheet/viewer.mjs +61 -1
- package/source/components/data/kpi-tile.mjs +5 -3
- package/source/components/data/metric-graph.mjs +22 -20
- package/source/components/data/metric.mjs +20 -18
- package/source/components/data/style/kpi-tile.pcss +65 -43
- package/source/components/data/style/metric-graph.pcss +35 -18
- package/source/components/data/style/metric.pcss +35 -28
- package/source/components/data/stylesheet/kpi-tile.mjs +61 -1
- package/source/components/data/stylesheet/metric-graph.mjs +61 -1
- package/source/components/data/stylesheet/metric.mjs +61 -1
- package/source/components/datatable/columnbar.mjs +4 -2
- package/source/components/datatable/datatable.mjs +73 -15
- package/source/components/datatable/filter/date-range.mjs +61 -61
- package/source/components/datatable/filter/date-time.mjs +5 -1
- package/source/components/datatable/filter/range.mjs +3 -3
- package/source/components/datatable/filter/select-operator.mjs +7 -1
- package/source/components/datatable/filter/text-operator.mjs +11 -3
- package/source/components/datatable/filter.mjs +16 -0
- package/source/components/datatable/pagination.mjs +2 -2
- package/source/components/datatable/style/column-bar.pcss +115 -23
- package/source/components/datatable/style/datatable.pcss +257 -29
- package/source/components/datatable/style/embedded-pagination.pcss +63 -34
- package/source/components/datatable/style/filter-button.pcss +1 -1
- package/source/components/datatable/style/filter-controls-defaults.pcss +49 -3
- package/source/components/datatable/style/filter-select.pcss +4 -1
- package/source/components/datatable/style/filter.pcss +18 -1
- package/source/components/datatable/stylesheet/change-button.mjs +61 -1
- package/source/components/datatable/stylesheet/column-bar.mjs +69 -1
- package/source/components/datatable/stylesheet/dataset.mjs +61 -1
- package/source/components/datatable/stylesheet/datatable.mjs +71 -1
- package/source/components/datatable/stylesheet/embedded-pagination.mjs +1 -1
- package/source/components/datatable/stylesheet/filter-button.mjs +1 -1
- package/source/components/datatable/stylesheet/filter-controls-defaults.mjs +1 -1
- package/source/components/datatable/stylesheet/filter-select.mjs +61 -1
- package/source/components/datatable/stylesheet/filter.mjs +61 -1
- package/source/components/datatable/stylesheet/pagination.mjs +67 -1
- package/source/components/datatable/stylesheet/save-button.mjs +61 -1
- package/source/components/datatable/stylesheet/status.mjs +61 -1
- package/source/components/form/action-button.mjs +2 -1
- package/source/components/form/button-bar.mjs +7 -2
- package/source/components/form/context-error.mjs +4 -3
- package/source/components/form/context-help.mjs +10 -4
- package/source/components/form/context-hint.mjs +1 -1
- package/source/components/form/context-info.mjs +1 -1
- package/source/components/form/context-note.mjs +1 -1
- package/source/components/form/context-success.mjs +1 -1
- package/source/components/form/context-warning.mjs +1 -1
- package/source/components/form/control-bar.mjs +300 -14
- package/source/components/form/credential-button.mjs +4 -2
- package/source/components/form/digits.mjs +28 -1
- package/source/components/form/field-set.mjs +30 -0
- package/source/components/form/login.mjs +13 -10
- package/source/components/form/password.mjs +6 -0
- package/source/components/form/popper-button.mjs +1 -1
- package/source/components/form/quantity.mjs +14 -6
- package/source/components/form/register-wizard.mjs +46 -26
- package/source/components/form/select.mjs +17 -10
- package/source/components/form/sheet.mjs +13 -2
- package/source/components/form/style/action-button.pcss +131 -5
- package/source/components/form/style/button-bar.pcss +204 -3
- package/source/components/form/style/control-bar.pcss +254 -26
- package/source/components/form/style/digits.pcss +7 -6
- package/source/components/form/style/input-group.pcss +65 -1
- package/source/components/form/style/login.pcss +1 -1
- package/source/components/form/style/mixin/field-set-layout.pcss +8 -0
- package/source/components/form/style/password.pcss +25 -1
- package/source/components/form/style/popper-button.pcss +1 -0
- package/source/components/form/style/quantity.pcss +11 -20
- package/source/components/form/style/select.pcss +52 -7
- package/source/components/form/style/sheet.pcss +70 -1
- package/source/components/form/style/state-button.pcss +5 -2
- package/source/components/form/style/toggle-switch.pcss +7 -4
- package/source/components/form/stylesheet/action-button.mjs +63 -1
- package/source/components/form/stylesheet/button-bar.mjs +153 -1
- package/source/components/form/stylesheet/button.mjs +61 -1
- package/source/components/form/stylesheet/control-bar.mjs +163 -1
- package/source/components/form/stylesheet/digits.mjs +1 -1
- package/source/components/form/stylesheet/field-layout.mjs +1 -1
- package/source/components/form/stylesheet/field-set.mjs +1 -1
- package/source/components/form/stylesheet/form.mjs +1 -1
- package/source/components/form/stylesheet/input-group.mjs +15 -1
- package/source/components/form/stylesheet/login.mjs +1 -1
- package/source/components/form/stylesheet/password.mjs +7 -1
- package/source/components/form/stylesheet/popper-button.mjs +61 -1
- package/source/components/form/stylesheet/quantity.mjs +1 -1
- package/source/components/form/stylesheet/register-wizard.mjs +1 -1
- package/source/components/form/stylesheet/select.mjs +3 -1
- package/source/components/form/stylesheet/sheet.mjs +1 -1
- package/source/components/form/stylesheet/state-button.mjs +3 -1
- package/source/components/form/stylesheet/toggle-switch.mjs +1 -1
- package/source/components/form/stylesheet/wizard.mjs +1 -1
- package/source/components/form/util/floating-ui.mjs +35 -7
- package/source/components/host/call-button.mjs +3 -1
- package/source/components/host/stylesheet/call-button.mjs +61 -1
- package/source/components/host/stylesheet/host.mjs +1 -1
- package/source/components/host/stylesheet/toggle-button.mjs +61 -1
- package/source/components/layout/full-screen.mjs +31 -23
- package/source/components/layout/iframe.mjs +5 -1
- package/source/components/layout/popper.mjs +34 -4
- package/source/components/layout/style/full-screen.pcss +94 -23
- package/source/components/layout/style/split-panel.pcss +57 -5
- package/source/components/layout/style/tabs.pcss +277 -47
- package/source/components/layout/style/vertical-tabs.pcss +147 -0
- package/source/components/layout/stylesheet/collapse.mjs +61 -1
- package/source/components/layout/stylesheet/details.mjs +61 -1
- package/source/components/layout/stylesheet/full-screen.mjs +23 -1
- package/source/components/layout/stylesheet/overlay.mjs +1 -1
- package/source/components/layout/stylesheet/panel.mjs +1 -1
- package/source/components/layout/stylesheet/slider.mjs +1 -1
- package/source/components/layout/stylesheet/split-panel.mjs +17 -1
- package/source/components/layout/stylesheet/tabs.mjs +97 -1
- package/source/components/layout/stylesheet/vertical-tabs.mjs +33 -95
- package/source/components/layout/tabs.mjs +63 -0
- package/source/components/layout/vertical-tabs.mjs +63 -0
- package/source/components/navigation/stylesheet/site-navigation.mjs +1 -1
- package/source/components/navigation/stylesheet/table-of-content.mjs +1 -1
- package/source/components/navigation/stylesheet/wizard-navigation.mjs +1 -1
- package/source/components/navigation/table-of-content.mjs +13 -0
- package/source/components/notify/style/notify.pcss +1 -2
- package/source/components/notify/stylesheet/message.mjs +1 -1
- package/source/components/notify/stylesheet/notify.mjs +1 -1
- package/source/components/state/style/log.pcss +1 -0
- package/source/components/state/style/state.pcss +5 -1
- package/source/components/state/stylesheet/log.mjs +1 -1
- package/source/components/state/stylesheet/state.mjs +7 -1
- package/source/components/style/button.css +61 -205
- package/source/components/style/button.pcss +78 -34
- package/source/components/style/common.css +1 -170
- package/source/components/style/common.pcss +5 -9
- package/source/components/style/form.css +1 -49
- package/source/components/style/form.pcss +24 -6
- package/source/components/style/link.css +1 -39
- package/source/components/style/link.pcss +8 -16
- package/source/components/style/mixin/button.pcss +19 -10
- package/source/components/style/mixin/property.pcss +8 -0
- package/source/components/style/mixin/skeleton.pcss +11 -5
- package/source/components/style/normalize.css +1 -144
- package/source/components/style/normalize.pcss +5 -5
- package/source/components/style/property.css +1 -387
- package/source/components/style/skeleton.css +1 -198
- package/source/components/style/skeleton.pcss +8 -2
- package/source/components/style/theme-modern.css +74 -0
- package/source/components/style/theme-modern.pcss +498 -0
- package/source/components/stylesheet/button.mjs +61 -1
- package/source/components/stylesheet/common.mjs +1 -1
- package/source/components/stylesheet/form.mjs +1 -1
- package/source/components/stylesheet/link.mjs +1 -1
- package/source/components/stylesheet/normalize.mjs +1 -1
- package/source/components/stylesheet/property.mjs +1 -1
- package/source/components/stylesheet/skeleton.mjs +1 -1
- package/source/components/stylesheet/theme-modern.mjs +110 -0
- package/source/components/time/stylesheet/day.mjs +61 -1
- package/source/components/time/stylesheet/month-calendar.mjs +61 -1
- package/source/components/time/timeline/stylesheet/appointment.mjs +61 -1
- package/source/components/time/timeline/stylesheet/segment.mjs +61 -1
- package/source/components/tree-menu/style/tree-menu.pcss +26 -37
- package/source/components/tree-menu/stylesheet/tree-menu.mjs +1 -1
- package/source/dom/customelement.mjs +105 -40
- package/source/dom/updater.mjs +381 -119
- package/test/cases/components/content/image-editor.mjs +19 -0
- package/test/cases/components/datatable/accessibility-defaults.mjs +112 -0
- package/test/cases/components/datatable/filter-availability.mjs +37 -0
- package/test/cases/components/datatable/filter-date-range-layout.mjs +40 -0
- package/test/cases/components/datatable/filter-select-operator.mjs +118 -0
- package/test/cases/components/datatable/mobile-layout.mjs +203 -0
- package/test/cases/components/datatable/responsive-breakpoint.mjs +41 -0
- package/test/cases/components/datatable/selection.mjs +149 -0
- package/test/cases/components/form/action-button-style.mjs +85 -0
- package/test/cases/components/form/button-bar.mjs +222 -3
- package/test/cases/components/form/context-theme-colors.mjs +59 -0
- package/test/cases/components/form/control-bar.mjs +228 -3
- package/test/cases/components/form/control-heights.mjs +103 -0
- package/test/cases/components/form/digits-accessibility.mjs +65 -0
- package/test/cases/components/form/field-set.mjs +54 -0
- package/test/cases/components/form/floating-ui.mjs +74 -0
- package/test/cases/components/form/input-group.mjs +61 -28
- package/test/cases/components/form/login.mjs +47 -0
- package/test/cases/components/form/password.mjs +63 -0
- package/test/cases/components/form/popper-button.mjs +30 -15
- package/test/cases/components/form/quantity-accessibility.mjs +46 -0
- package/test/cases/components/form/register-wizard.mjs +79 -0
- package/test/cases/components/form/select.mjs +94 -2
- package/test/cases/components/form/sheet.mjs +56 -2
- package/test/cases/components/host/toggle-button.mjs +50 -0
- package/test/cases/components/layout/full-screen.mjs +60 -0
- package/test/cases/components/layout/iframe-accessibility.mjs +44 -0
- package/test/cases/components/layout/popper.mjs +128 -0
- package/test/cases/components/layout/slit-panel.mjs +30 -1
- package/test/cases/components/layout/tabs.mjs +93 -0
- package/test/cases/components/navigation/table-of-content.mjs +18 -0
- package/test/cases/components/state/state-style.mjs +31 -0
- package/test/cases/components/style/action-menu.mjs +74 -0
- package/test/cases/components/style/form-controls.mjs +37 -0
- package/test/cases/components/style/kpi-tile.mjs +60 -0
- package/test/cases/components/style/legacy-theme-compatibility.mjs +137 -0
- package/test/cases/components/style/metric-layout.mjs +94 -0
- package/test/cases/components/style/skeleton.mjs +69 -0
- package/test/cases/components/style/theme-component-catalog.mjs +853 -0
- package/test/cases/components/style/theme-modern.mjs +439 -0
- package/test/cases/components/style/theme-review-regressions.mjs +41 -0
- package/test/cases/dom/customelement.mjs +136 -1
- package/test/cases/dom/updater.mjs +174 -0
|
@@ -2,36 +2,69 @@ import * as chai from "chai";
|
|
|
2
2
|
import { chaiDom } from "../../../util/chai-dom.mjs";
|
|
3
3
|
import { initJSDOM } from "../../../util/jsdom.mjs";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const expect = chai.expect;
|
|
6
6
|
chai.use(chaiDom);
|
|
7
7
|
|
|
8
8
|
let InputGroup;
|
|
9
9
|
|
|
10
|
-
describe("InputGroup",
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
10
|
+
describe("InputGroup", () => {
|
|
11
|
+
before((done) => {
|
|
12
|
+
initJSDOM()
|
|
13
|
+
.then(() => import("../../../../source/components/form/input-group.mjs"))
|
|
14
|
+
.then((m) => {
|
|
15
|
+
InputGroup = m.InputGroup;
|
|
16
|
+
done();
|
|
17
|
+
})
|
|
18
|
+
.catch((e) => done(e));
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should create an input group element", () => {
|
|
22
|
+
const inputGroup = document.createElement("monster-input-group");
|
|
23
|
+
|
|
24
|
+
expect(inputGroup).to.be.instanceof(InputGroup);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should allow the input group to stretch within constrained controls", () => {
|
|
28
|
+
const cssText = InputGroup.getCSSStyleSheet()
|
|
29
|
+
.flatMap((styleSheet) => Array.from(styleSheet.cssRules))
|
|
30
|
+
.map((rule) => rule.cssText)
|
|
31
|
+
.join("\n");
|
|
32
|
+
|
|
33
|
+
expect(cssText).to.contain("display: flex");
|
|
34
|
+
expect(cssText).to.contain("box-sizing: border-box");
|
|
35
|
+
expect(cssText).to.contain("height: 100%");
|
|
36
|
+
expect(cssText).to.contain(
|
|
37
|
+
"min-block-size: var(--monster-control-min-block-size",
|
|
38
|
+
);
|
|
39
|
+
expect(cssText).to.contain("min-block-size: 0");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("should draw one focus ring around the complete composed control", () => {
|
|
43
|
+
const cssText = InputGroup.getCSSStyleSheet()
|
|
44
|
+
.flatMap((styleSheet) => Array.from(styleSheet.cssRules))
|
|
45
|
+
.map((rule) => rule.cssText)
|
|
46
|
+
.join("\n");
|
|
47
|
+
|
|
48
|
+
expect(cssText).to.contain(":host(:focus-within)");
|
|
49
|
+
expect(cssText).to.contain("var(--monster-focus-ring-width");
|
|
50
|
+
expect(cssText).to.contain("var(--monster-focus-ring-offset");
|
|
51
|
+
expect(cssText).to.contain("::slotted(input:focus-visible)");
|
|
52
|
+
expect(cssText).to.contain("outline: none !important");
|
|
53
|
+
expect(cssText).to.contain("box-sizing: content-box !important");
|
|
54
|
+
expect(cssText).to.contain("height: 1.1rem");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should keep hover feedback on the complete composed control", () => {
|
|
58
|
+
const cssText = InputGroup.getCSSStyleSheet()
|
|
59
|
+
.flatMap((styleSheet) => Array.from(styleSheet.cssRules))
|
|
60
|
+
.map((rule) => rule.cssText)
|
|
61
|
+
.join("\n");
|
|
62
|
+
|
|
63
|
+
expect(cssText).to.contain(":host(:hover)");
|
|
64
|
+
expect(cssText).to.contain("--monster-input-group-hover-background-color");
|
|
65
|
+
expect(cssText).to.contain("--monster-input-group-hover-border-color");
|
|
66
|
+
expect(cssText).to.contain("::slotted(input:hover)");
|
|
67
|
+
expect(cssText).to.contain("box-shadow: none !important");
|
|
68
|
+
expect(cssText).to.contain("transition: none !important");
|
|
69
|
+
});
|
|
37
70
|
});
|
|
@@ -34,6 +34,53 @@ describe("Login", function () {
|
|
|
34
34
|
expect(document.createElement("monster-login")).is.instanceof(Login);
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
+
it("should associate visible labels and pass them to nested controls", async function () {
|
|
38
|
+
const login = document.createElement("monster-login");
|
|
39
|
+
document.getElementById("mocks").appendChild(login);
|
|
40
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
41
|
+
|
|
42
|
+
const username = login.shadowRoot.querySelector("input[name='username']");
|
|
43
|
+
const usernameLabel = login.shadowRoot.querySelector(
|
|
44
|
+
'label[for="monster-login-username"]',
|
|
45
|
+
);
|
|
46
|
+
const email = login.shadowRoot.querySelector("input[name='email']");
|
|
47
|
+
const emailLabel = login.shadowRoot.querySelector(
|
|
48
|
+
'label[for="monster-login-email"]',
|
|
49
|
+
);
|
|
50
|
+
const password = login.shadowRoot.querySelector("monster-password");
|
|
51
|
+
const digits = login.shadowRoot.querySelector(
|
|
52
|
+
'[data-monster-role="digits-collapse"] monster-digits',
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
expect(usernameLabel).to.not.equal(null);
|
|
56
|
+
expect(usernameLabel.htmlFor).to.equal(username.id);
|
|
57
|
+
expect(emailLabel).to.not.equal(null);
|
|
58
|
+
expect(emailLabel.htmlFor).to.equal(email.id);
|
|
59
|
+
expect(password.getOption("labels.input")).to.equal(
|
|
60
|
+
login.getOption("labels.password"),
|
|
61
|
+
);
|
|
62
|
+
expect(digits.getOption("labels.group")).to.equal(
|
|
63
|
+
login.getOption("labels.digits"),
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("keeps validation markers from shifting later grid rows", function () {
|
|
68
|
+
const login = document.createElement("monster-login");
|
|
69
|
+
document.getElementById("mocks").appendChild(login);
|
|
70
|
+
|
|
71
|
+
const validationMarkers = [
|
|
72
|
+
...login.shadowRoot.querySelectorAll(
|
|
73
|
+
'div[style*="grid-column: 1 / -1"]',
|
|
74
|
+
),
|
|
75
|
+
];
|
|
76
|
+
expect(validationMarkers).to.have.length.greaterThan(0);
|
|
77
|
+
expect(
|
|
78
|
+
validationMarkers.every(
|
|
79
|
+
(element) => element.style.gridColumn === "1 / -1",
|
|
80
|
+
),
|
|
81
|
+
).to.be.true;
|
|
82
|
+
});
|
|
83
|
+
|
|
37
84
|
it("should respect the native hidden attribute on the host", function () {
|
|
38
85
|
const login = document.createElement("monster-login");
|
|
39
86
|
login.setAttribute("hidden", "");
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as chai from "chai";
|
|
2
|
+
import { chaiDom } from "../../../util/chai-dom.mjs";
|
|
3
|
+
import { initJSDOM } from "../../../util/jsdom.mjs";
|
|
4
|
+
|
|
5
|
+
const { expect } = chai;
|
|
6
|
+
chai.use(chaiDom);
|
|
7
|
+
const nextTask = () => new Promise((resolve) => setTimeout(resolve, 0));
|
|
8
|
+
|
|
9
|
+
let Password;
|
|
10
|
+
|
|
11
|
+
describe("Password", function () {
|
|
12
|
+
before(function (done) {
|
|
13
|
+
initJSDOM()
|
|
14
|
+
.then(() => import("../../../../source/components/form/password.mjs"))
|
|
15
|
+
.then((module) => {
|
|
16
|
+
Password = module.Password;
|
|
17
|
+
done();
|
|
18
|
+
})
|
|
19
|
+
.catch((error) => done(error));
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
document.getElementById("mocks").replaceChildren();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("should name its native input from the public label option", async function () {
|
|
27
|
+
const password = document.createElement("monster-password");
|
|
28
|
+
document.getElementById("mocks").append(password);
|
|
29
|
+
await nextTask();
|
|
30
|
+
const input = password.shadowRoot.querySelector(
|
|
31
|
+
'[data-monster-role="input"]',
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
expect(input.getAttribute("aria-label")).to.equal("Password");
|
|
35
|
+
password.setOption("labels.input", "Passwort");
|
|
36
|
+
await nextTask();
|
|
37
|
+
expect(input.getAttribute("aria-label")).to.equal("Passwort");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should preserve the input-group radius around the reveal control", function () {
|
|
41
|
+
const cssText = Password.getCSSStyleSheet()
|
|
42
|
+
.flatMap((styleSheet) => Array.from(styleSheet.cssRules))
|
|
43
|
+
.map((rule) => rule.cssText)
|
|
44
|
+
.join("\n");
|
|
45
|
+
|
|
46
|
+
expect(cssText).to.contain("monster-input-group");
|
|
47
|
+
expect(cssText).to.contain("--monster-theme-control-bg-color");
|
|
48
|
+
expect(cssText).to.contain("overflow: hidden");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should vertically center the input and reveal icon in the shared control height", function () {
|
|
52
|
+
const cssText = Password.getCSSStyleSheet()
|
|
53
|
+
.flatMap((styleSheet) => Array.from(styleSheet.cssRules))
|
|
54
|
+
.map((rule) => rule.cssText)
|
|
55
|
+
.join("\n");
|
|
56
|
+
|
|
57
|
+
expect(cssText).to.contain("--monster-password-control-block-size");
|
|
58
|
+
expect(cssText).to.contain("var(--monster-control-min-block-size,2.5rem)");
|
|
59
|
+
expect(cssText).to.contain("[data-monster-role=control]");
|
|
60
|
+
expect(cssText).to.contain("monster-input-group");
|
|
61
|
+
expect(cssText).to.contain("block-size: 100%");
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -31,6 +31,23 @@ describe("PopperButton", function () {
|
|
|
31
31
|
);
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
+
it("should style native form controls inside popper content", function () {
|
|
35
|
+
const cssText = PopperButton.getCSSStyleSheet()
|
|
36
|
+
.flatMap((styleSheet) => Array.from(styleSheet.cssRules))
|
|
37
|
+
.map((rule) => rule.cssText)
|
|
38
|
+
.join("\n")
|
|
39
|
+
.replaceAll(/\s+/g, "");
|
|
40
|
+
|
|
41
|
+
expect(cssText).to.contain(
|
|
42
|
+
"input:not([type=checkbox]):not([type=radio]),select,textarea{min-height:var(--monster-control-min-block-size,auto)",
|
|
43
|
+
);
|
|
44
|
+
expect(cssText).to.contain(
|
|
45
|
+
"input:is([type=checkbox],[type=radio]){block-size:1rem;inline-size:1rem",
|
|
46
|
+
);
|
|
47
|
+
expect(cssText).to.contain("font-size:100%");
|
|
48
|
+
expect(cssText).to.contain("textarea{resize:vertical;min-height:6rem");
|
|
49
|
+
});
|
|
50
|
+
|
|
34
51
|
it("should apply content overflow mode to the rendered content wrapper", function (done) {
|
|
35
52
|
let mocks = document.getElementById("mocks");
|
|
36
53
|
const button = document.createElement("monster-popper-button");
|
|
@@ -48,9 +65,9 @@ describe("PopperButton", function () {
|
|
|
48
65
|
|
|
49
66
|
setTimeout(() => {
|
|
50
67
|
try {
|
|
51
|
-
expect(
|
|
52
|
-
|
|
53
|
-
)
|
|
68
|
+
expect(content.getAttribute("data-monster-overflow-mode")).to.equal(
|
|
69
|
+
"horizontal",
|
|
70
|
+
);
|
|
54
71
|
done();
|
|
55
72
|
} catch (e) {
|
|
56
73
|
done(e);
|
|
@@ -79,9 +96,9 @@ describe("PopperButton", function () {
|
|
|
79
96
|
|
|
80
97
|
setTimeout(() => {
|
|
81
98
|
try {
|
|
82
|
-
expect(
|
|
83
|
-
|
|
84
|
-
)
|
|
99
|
+
expect(content.getAttribute("data-monster-overflow-mode")).to.equal(
|
|
100
|
+
"horizontal",
|
|
101
|
+
);
|
|
85
102
|
done();
|
|
86
103
|
} catch (e) {
|
|
87
104
|
done(e);
|
|
@@ -107,12 +124,12 @@ describe("PopperButton", function () {
|
|
|
107
124
|
|
|
108
125
|
setTimeout(() => {
|
|
109
126
|
try {
|
|
110
|
-
expect(
|
|
111
|
-
|
|
112
|
-
)
|
|
113
|
-
expect(
|
|
114
|
-
|
|
115
|
-
)
|
|
127
|
+
expect(button.getOption("popper.contentOverflow")).to.equal(
|
|
128
|
+
"visible",
|
|
129
|
+
);
|
|
130
|
+
expect(content.getAttribute("data-monster-overflow-mode")).to.equal(
|
|
131
|
+
"visible",
|
|
132
|
+
);
|
|
116
133
|
done();
|
|
117
134
|
} catch (e) {
|
|
118
135
|
done(e);
|
|
@@ -161,9 +178,7 @@ describe("PopperButton", function () {
|
|
|
161
178
|
try {
|
|
162
179
|
const button = mocks.querySelector("monster-popper-button");
|
|
163
180
|
const content = button.shadowRoot.querySelector('[part="content"]');
|
|
164
|
-
expect(button.getOption("popper.contentOverflow")).to.equal(
|
|
165
|
-
"visible",
|
|
166
|
-
);
|
|
181
|
+
expect(button.getOption("popper.contentOverflow")).to.equal("visible");
|
|
167
182
|
expect(content.getAttribute("data-monster-overflow-mode")).to.equal(
|
|
168
183
|
"visible",
|
|
169
184
|
);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as chai from "chai";
|
|
2
|
+
import { initJSDOM } from "../../../util/jsdom.mjs";
|
|
3
|
+
|
|
4
|
+
const { expect } = chai;
|
|
5
|
+
const nextTask = () => new Promise((resolve) => setTimeout(resolve, 0));
|
|
6
|
+
|
|
7
|
+
describe("Quantity accessibility", function () {
|
|
8
|
+
before(async () => {
|
|
9
|
+
await initJSDOM();
|
|
10
|
+
await import("element-internals-polyfill");
|
|
11
|
+
await import("../../../../source/components/form/quantity.mjs");
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
document.getElementById("mocks").replaceChildren();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should name every native control from configurable labels", async function () {
|
|
19
|
+
const quantity = document.createElement("monster-quantity");
|
|
20
|
+
quantity.setOptions({
|
|
21
|
+
labels: {
|
|
22
|
+
input: "Seats",
|
|
23
|
+
decrement: "Remove one seat",
|
|
24
|
+
increment: "Add one seat",
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
document.getElementById("mocks").append(quantity);
|
|
28
|
+
await nextTask();
|
|
29
|
+
|
|
30
|
+
expect(
|
|
31
|
+
quantity.shadowRoot
|
|
32
|
+
.querySelector('[data-monster-role="input"]')
|
|
33
|
+
.getAttribute("aria-label"),
|
|
34
|
+
).to.equal("Seats");
|
|
35
|
+
expect(
|
|
36
|
+
quantity.shadowRoot
|
|
37
|
+
.querySelector('[data-monster-role="decrement"]')
|
|
38
|
+
.getAttribute("aria-label"),
|
|
39
|
+
).to.equal("Remove one seat");
|
|
40
|
+
expect(
|
|
41
|
+
quantity.shadowRoot
|
|
42
|
+
.querySelector('[data-monster-role="increment"]')
|
|
43
|
+
.getAttribute("aria-label"),
|
|
44
|
+
).to.equal("Add one seat");
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { strict as assert } from "node:assert";
|
|
2
|
+
import { getGlobal } from "../../../../source/types/global.mjs";
|
|
3
|
+
import { initJSDOM } from "../../../util/jsdom.mjs";
|
|
4
|
+
import { ResizeObserverMock } from "../../../util/resize-observer.mjs";
|
|
5
|
+
|
|
6
|
+
describe("RegisterWizard", () => {
|
|
7
|
+
before(async () => {
|
|
8
|
+
await initJSDOM();
|
|
9
|
+
await import("element-internals-polyfill");
|
|
10
|
+
|
|
11
|
+
const global = getGlobal();
|
|
12
|
+
if (!global.ResizeObserver) {
|
|
13
|
+
global.ResizeObserver = ResizeObserverMock;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
await import("../../../../source/components/form/register-wizard.mjs");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
document.getElementById("mocks").replaceChildren();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("keeps explicit labels inside nested field sets", async () => {
|
|
24
|
+
const element = document.createElement("monster-register-wizard");
|
|
25
|
+
element.setOptions({
|
|
26
|
+
labels: {
|
|
27
|
+
email: "Email address",
|
|
28
|
+
password: "Password",
|
|
29
|
+
passwordConfirm: "Confirm password",
|
|
30
|
+
firstName: "First name",
|
|
31
|
+
lastName: "Last name",
|
|
32
|
+
consentsTitle: "Consents",
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
document.getElementById("mocks").append(element);
|
|
36
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
37
|
+
|
|
38
|
+
const labels = new Map([
|
|
39
|
+
["email-label", "Email address"],
|
|
40
|
+
["password-label", "Password"],
|
|
41
|
+
["password-confirm-label", "Confirm password"],
|
|
42
|
+
["first-name-label", "First name"],
|
|
43
|
+
["last-name-label", "Last name"],
|
|
44
|
+
["consents-title", "Consents"],
|
|
45
|
+
]);
|
|
46
|
+
for (const [role, expected] of labels) {
|
|
47
|
+
const label = element.shadowRoot.querySelector(
|
|
48
|
+
`[data-monster-role~="${role}"]`,
|
|
49
|
+
);
|
|
50
|
+
assert.equal(label.textContent.trim(), expected, role);
|
|
51
|
+
}
|
|
52
|
+
const email = element.shadowRoot.querySelector(
|
|
53
|
+
'[data-monster-role="email-input"]',
|
|
54
|
+
);
|
|
55
|
+
assert.equal(
|
|
56
|
+
email.getAttribute("aria-label"),
|
|
57
|
+
element.getOption("labels.emailAria"),
|
|
58
|
+
);
|
|
59
|
+
assert.equal(
|
|
60
|
+
email.getAttribute("placeholder"),
|
|
61
|
+
element.getOption("labels.emailPlaceholder"),
|
|
62
|
+
);
|
|
63
|
+
assert.equal(
|
|
64
|
+
email.getAttribute("autocomplete"),
|
|
65
|
+
element.getOption("autocomplete.email"),
|
|
66
|
+
);
|
|
67
|
+
const password = element.shadowRoot.querySelector(
|
|
68
|
+
'[data-monster-role="password-input"]',
|
|
69
|
+
);
|
|
70
|
+
assert.equal(password.hasAttribute("aria-label"), false);
|
|
71
|
+
assert.equal(
|
|
72
|
+
password.shadowRoot
|
|
73
|
+
.querySelector('[data-monster-role="input"]')
|
|
74
|
+
.getAttribute("aria-label"),
|
|
75
|
+
element.getOption("labels.passwordAria"),
|
|
76
|
+
);
|
|
77
|
+
assert.equal(element.shadowRoot.textContent.includes("undefined"), false);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -187,9 +187,29 @@ describe('Select', function () {
|
|
|
187
187
|
expect(cssText).to.contain("--monster-select-container-align-self");
|
|
188
188
|
expect(cssText).to.contain("--monster-select-container-block-size");
|
|
189
189
|
expect(cssText).to.contain("--monster-select-control-padding");
|
|
190
|
+
expect(cssText).to.contain("--monster-select-control-min-block-size");
|
|
191
|
+
expect(cssText).to.contain("--monster-select-option-padding");
|
|
192
|
+
expect(cssText).to.contain("--monster-select-option-control-size");
|
|
190
193
|
expect(cssText).to.contain("--monster-select-selection-margin");
|
|
191
194
|
expect(cssText).to.contain("--monster-select-selection-flex-wrap");
|
|
192
|
-
expect(cssText.replace(/\s+/g, '')).to.contain(
|
|
195
|
+
expect(cssText.replace(/\s+/g, '')).to.contain(
|
|
196
|
+
'div[data-monster-role=popper]{z-index:var(--monster-z-index-popover);}'
|
|
197
|
+
);
|
|
198
|
+
expect(cssText.replace(/\s+/g, '')).to.contain(
|
|
199
|
+
'min-block-size:var(--monster-select-control-min-block-size,var(--monster-control-min-block-size,2.5rem))'
|
|
200
|
+
);
|
|
201
|
+
expect(cssText.replace(/\s+/g, '')).to.contain(
|
|
202
|
+
'margin:var(--monster-select-selection-margin,05px)'
|
|
203
|
+
);
|
|
204
|
+
expect(cssText.replace(/\s+/g, '')).to.contain(
|
|
205
|
+
'padding:var(--monster-select-option-padding,2px6px)'
|
|
206
|
+
);
|
|
207
|
+
expect(cssText.replace(/\s+/g, '')).to.contain(
|
|
208
|
+
'min-block-size:var(--monster-select-option-control-size,1rem)'
|
|
209
|
+
);
|
|
210
|
+
expect(cssText.replace(/\s+/g, '')).to.match(
|
|
211
|
+
/@media\(prefers-color-scheme:light\)\{\[data-monster-role=control\]\{[^}]*border-color:var\(--monster-theme-control-border-color\)/u
|
|
212
|
+
);
|
|
193
213
|
});
|
|
194
214
|
|
|
195
215
|
it('should render select pagination in the compact arrow mode immediately', async function () {
|
|
@@ -1532,6 +1552,7 @@ describe('Select', function () {
|
|
|
1532
1552
|
const result = getDefaultSelectPopperPositionProfile();
|
|
1533
1553
|
|
|
1534
1554
|
expect(result.placement).to.equal('bottom-start');
|
|
1555
|
+
expect(result.strategy).to.equal('fixed');
|
|
1535
1556
|
expect(result.middleware).to.deep.equal([
|
|
1536
1557
|
'flip',
|
|
1537
1558
|
'offset:4',
|
|
@@ -2122,6 +2143,71 @@ describe('Select', function () {
|
|
|
2122
2143
|
mocks.innerHTML = "";
|
|
2123
2144
|
})
|
|
2124
2145
|
|
|
2146
|
+
it('should prevent automatic popper filter focus from scrolling the page', async function () {
|
|
2147
|
+
const mocks = document.getElementById('mocks');
|
|
2148
|
+
const select = document.createElement('monster-select');
|
|
2149
|
+
select.setOption('filter.mode', 'options');
|
|
2150
|
+
select.setOption('filter.position', 'popper');
|
|
2151
|
+
select.setOption('options', [
|
|
2152
|
+
{label: 'Alpha', value: 'alpha'},
|
|
2153
|
+
{label: 'Beta', value: 'beta'}
|
|
2154
|
+
]);
|
|
2155
|
+
mocks.appendChild(select);
|
|
2156
|
+
|
|
2157
|
+
await waitForCondition(() => {
|
|
2158
|
+
return select.shadowRoot.querySelector(
|
|
2159
|
+
'[data-monster-role=filter][name="popper-filter"]'
|
|
2160
|
+
) instanceof HTMLInputElement;
|
|
2161
|
+
});
|
|
2162
|
+
await new Promise(resolve => setTimeout(resolve, 150));
|
|
2163
|
+
|
|
2164
|
+
const filterInput = select.shadowRoot.querySelector(
|
|
2165
|
+
'[data-monster-role=filter][name="popper-filter"]'
|
|
2166
|
+
);
|
|
2167
|
+
const focusCalls = [];
|
|
2168
|
+
filterInput.focus = (...args) => {
|
|
2169
|
+
focusCalls.push(args);
|
|
2170
|
+
};
|
|
2171
|
+
|
|
2172
|
+
select.shadowRoot.querySelector('[data-monster-role=container]').click();
|
|
2173
|
+
|
|
2174
|
+
await waitForCondition(() => focusCalls.length > 0);
|
|
2175
|
+
|
|
2176
|
+
expect(focusCalls.every(([options]) => {
|
|
2177
|
+
return options?.preventScroll === true;
|
|
2178
|
+
})).to.equal(true);
|
|
2179
|
+
});
|
|
2180
|
+
|
|
2181
|
+
it('should reveal a searchable popper after opening', async function () {
|
|
2182
|
+
this.timeout(5000);
|
|
2183
|
+
|
|
2184
|
+
const mocks = document.getElementById('mocks');
|
|
2185
|
+
const select = document.createElement('monster-select');
|
|
2186
|
+
select.setOption('filter.mode', 'options');
|
|
2187
|
+
select.setOption('filter.position', 'popper');
|
|
2188
|
+
select.setOption('options', [
|
|
2189
|
+
{label: 'Alpha', value: 'alpha'},
|
|
2190
|
+
{label: 'Beta', value: 'beta'}
|
|
2191
|
+
]);
|
|
2192
|
+
mocks.appendChild(select);
|
|
2193
|
+
|
|
2194
|
+
await waitForCondition(() => {
|
|
2195
|
+
return select.shadowRoot.querySelector(
|
|
2196
|
+
'[data-monster-role=container]'
|
|
2197
|
+
) instanceof HTMLElement;
|
|
2198
|
+
});
|
|
2199
|
+
|
|
2200
|
+
const popper = select.shadowRoot.querySelector(
|
|
2201
|
+
'[data-monster-role=popper]'
|
|
2202
|
+
);
|
|
2203
|
+
select.shadowRoot.querySelector('[data-monster-role=container]').click();
|
|
2204
|
+
|
|
2205
|
+
await waitForCondition(() => popper.style.display === 'block');
|
|
2206
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
2207
|
+
|
|
2208
|
+
expect(popper.style.visibility).to.equal('');
|
|
2209
|
+
});
|
|
2210
|
+
|
|
2125
2211
|
it('should have no options', function (done) {
|
|
2126
2212
|
|
|
2127
2213
|
let mocks = document.getElementById('mocks');
|
|
@@ -2147,7 +2233,7 @@ describe('Select', function () {
|
|
|
2147
2233
|
|
|
2148
2234
|
});
|
|
2149
2235
|
|
|
2150
|
-
it('should expose styling parts for container, filter messages and pagination', function (done) {
|
|
2236
|
+
it('should expose styling parts for container, filter messages and the compact pagination footer', function (done) {
|
|
2151
2237
|
|
|
2152
2238
|
let mocks = document.getElementById('mocks');
|
|
2153
2239
|
const select = document.createElement('monster-select');
|
|
@@ -2158,10 +2244,16 @@ describe('Select', function () {
|
|
|
2158
2244
|
try {
|
|
2159
2245
|
const container = select.shadowRoot.querySelector('[data-monster-role=container]');
|
|
2160
2246
|
const selectionMessages = select.shadowRoot.querySelector('[data-monster-role=selection-messages]');
|
|
2247
|
+
const paginationFooter = select.shadowRoot.querySelector('[data-monster-role=pagination-footer]');
|
|
2248
|
+
const remoteInfo = select.shadowRoot.querySelector('[data-monster-role=remote-info]');
|
|
2161
2249
|
const pagination = select.shadowRoot.querySelector('[data-monster-role=pagination]');
|
|
2162
2250
|
|
|
2163
2251
|
expect(container.getAttribute('part')).to.equal('container');
|
|
2164
2252
|
expect(selectionMessages.getAttribute('part')).to.equal('selection-messages');
|
|
2253
|
+
expect(paginationFooter.getAttribute('part')).to.equal('pagination-footer');
|
|
2254
|
+
expect(paginationFooter.firstElementChild).to.equal(remoteInfo);
|
|
2255
|
+
expect(remoteInfo.getAttribute('part')).to.equal('remote-info');
|
|
2256
|
+
expect(remoteInfo.nextElementSibling).to.equal(pagination);
|
|
2165
2257
|
expect(pagination.getAttribute('part')).to.equal('pagination');
|
|
2166
2258
|
} catch (e) {
|
|
2167
2259
|
return done(e);
|
|
@@ -27,9 +27,62 @@ describe("Sheet", function () {
|
|
|
27
27
|
expect(document.createElement("monster-sheet")).to.be.instanceof(Sheet);
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
+
it("should name editable cells from their row and column labels", function () {
|
|
31
|
+
const sheet = document.createElement("monster-sheet");
|
|
32
|
+
sheet.setOptions({
|
|
33
|
+
columns: [{ id: "project", label: "Project" }],
|
|
34
|
+
rows: [{ id: "first", label: "First row" }],
|
|
35
|
+
labels: { cell: "{column} / {row}" },
|
|
36
|
+
});
|
|
37
|
+
document.getElementById("mocks").appendChild(sheet);
|
|
38
|
+
|
|
39
|
+
const input = sheet.shadowRoot.querySelector(
|
|
40
|
+
'[data-monster-role="cell-input"]',
|
|
41
|
+
);
|
|
42
|
+
expect(input.getAttribute("aria-label")).to.equal("Project / First row");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("should position and expose its context menu on right click", function () {
|
|
46
|
+
const sheet = document.createElement("monster-sheet");
|
|
47
|
+
document.getElementById("mocks").appendChild(sheet);
|
|
48
|
+
|
|
49
|
+
const input = sheet.shadowRoot.querySelector(
|
|
50
|
+
'[data-monster-role="cell-input"]',
|
|
51
|
+
);
|
|
52
|
+
const menu = sheet.shadowRoot.querySelector(
|
|
53
|
+
'[data-monster-role="context-menu"]',
|
|
54
|
+
);
|
|
55
|
+
const event = new window.MouseEvent("contextmenu", {
|
|
56
|
+
bubbles: true,
|
|
57
|
+
cancelable: true,
|
|
58
|
+
clientX: 120,
|
|
59
|
+
clientY: 80,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
input.dispatchEvent(event);
|
|
63
|
+
|
|
64
|
+
expect(event.defaultPrevented).to.equal(true);
|
|
65
|
+
expect(menu.hidden).to.equal(false);
|
|
66
|
+
expect(menu.style.display).to.equal("flex");
|
|
67
|
+
expect(menu.style.left).to.equal("0px");
|
|
68
|
+
expect(menu.style.top).to.equal("0px");
|
|
69
|
+
expect(menu.querySelectorAll('[role="menuitem"]')).to.have.length(3);
|
|
70
|
+
|
|
71
|
+
const cssText = Sheet.getCSSStyleSheet()
|
|
72
|
+
.flatMap((styleSheet) => Array.from(styleSheet.cssRules || []))
|
|
73
|
+
.map((rule) => rule.cssText)
|
|
74
|
+
.join("\n")
|
|
75
|
+
.replace(/\s+/g, "");
|
|
76
|
+
expect(cssText).to.contain("[part=context-menu]{position:absolute");
|
|
77
|
+
expect(cssText).to.contain(
|
|
78
|
+
"min-block-size:var(--monster-action-menu-item-min-block-size,44px)",
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
30
82
|
it("should coalesce column resize pointer moves", function (done) {
|
|
31
83
|
const originalRequestAnimationFrame = window.requestAnimationFrame;
|
|
32
|
-
const originalGlobalRequestAnimationFrame =
|
|
84
|
+
const originalGlobalRequestAnimationFrame =
|
|
85
|
+
globalThis.requestAnimationFrame;
|
|
33
86
|
const originalCancelAnimationFrame = window.cancelAnimationFrame;
|
|
34
87
|
const originalGlobalCancelAnimationFrame = globalThis.cancelAnimationFrame;
|
|
35
88
|
const scheduledCallbacks = [];
|
|
@@ -110,7 +163,8 @@ describe("Sheet", function () {
|
|
|
110
163
|
done(e);
|
|
111
164
|
} finally {
|
|
112
165
|
window.requestAnimationFrame = originalRequestAnimationFrame;
|
|
113
|
-
globalThis.requestAnimationFrame =
|
|
166
|
+
globalThis.requestAnimationFrame =
|
|
167
|
+
originalGlobalRequestAnimationFrame;
|
|
114
168
|
window.cancelAnimationFrame = originalCancelAnimationFrame;
|
|
115
169
|
globalThis.cancelAnimationFrame = originalGlobalCancelAnimationFrame;
|
|
116
170
|
}
|