@schukai/monster 4.148.9 → 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/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
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { expect } from "chai";
|
|
2
|
+
import { initJSDOM } from "../../../util/jsdom.mjs";
|
|
3
|
+
|
|
4
|
+
const waitForUpdates = () => new Promise((resolve) => setTimeout(resolve, 250));
|
|
5
|
+
|
|
6
|
+
function createFixture() {
|
|
7
|
+
const datasource = document.createElement("monster-datasource-dom");
|
|
8
|
+
datasource.id = "selection-datasource";
|
|
9
|
+
datasource.innerHTML = `
|
|
10
|
+
<script type="application/json">
|
|
11
|
+
{
|
|
12
|
+
"dataset": [
|
|
13
|
+
{ "id": "first", "name": "Alpha" },
|
|
14
|
+
{ "id": "second", "name": "Beta" },
|
|
15
|
+
{ "id": "third", "name": "Gamma" }
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
</script>
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
const datatable = document.createElement("monster-datatable");
|
|
22
|
+
datatable.id = "selection-table";
|
|
23
|
+
datatable.setAttribute(
|
|
24
|
+
"data-monster-datasource-selector",
|
|
25
|
+
"#selection-datasource",
|
|
26
|
+
);
|
|
27
|
+
datatable.setOption("datasource.selector", "#selection-datasource");
|
|
28
|
+
datatable.innerHTML = `
|
|
29
|
+
<template id="selection-table-row">
|
|
30
|
+
<div
|
|
31
|
+
data-monster-features="select"
|
|
32
|
+
data-monster-mode="fixed"
|
|
33
|
+
></div>
|
|
34
|
+
<div
|
|
35
|
+
data-monster-head="Name"
|
|
36
|
+
data-monster-replace="path:selection-table-row.name"
|
|
37
|
+
></div>
|
|
38
|
+
</template>
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
document.getElementById("mocks").append(datasource, datatable);
|
|
42
|
+
return datatable;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
describe("Datatable row selection", function () {
|
|
46
|
+
before(async function () {
|
|
47
|
+
await initJSDOM();
|
|
48
|
+
await import("element-internals-polyfill").catch(() => {});
|
|
49
|
+
await import("../../../../source/components/datatable/datatable.mjs");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
document.getElementById("mocks").innerHTML = "";
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("renders selectable rows from a populated DOM datasource", async function () {
|
|
57
|
+
const datatable = createFixture();
|
|
58
|
+
await waitForUpdates();
|
|
59
|
+
|
|
60
|
+
const rowCheckboxes = datatable.shadowRoot.querySelectorAll(
|
|
61
|
+
'[data-monster-role="select-row"]',
|
|
62
|
+
);
|
|
63
|
+
const selectAll = datatable.shadowRoot.querySelector(
|
|
64
|
+
'[data-monster-role="select-all"]',
|
|
65
|
+
);
|
|
66
|
+
const firstRowCells = datatable.shadowRoot.querySelectorAll(
|
|
67
|
+
'[data-monster-insert-reference="selection-table-row-0"]',
|
|
68
|
+
);
|
|
69
|
+
expect(rowCheckboxes).to.have.length(3);
|
|
70
|
+
expect(rowCheckboxes[0].getAttribute("aria-label")).to.equal("Select row");
|
|
71
|
+
expect(selectAll.getAttribute("aria-label")).to.equal("Select all rows");
|
|
72
|
+
expect(
|
|
73
|
+
firstRowCells[0].hasAttribute("data-monster-datatable-row-start"),
|
|
74
|
+
).to.equal(true);
|
|
75
|
+
expect(
|
|
76
|
+
firstRowCells[firstRowCells.length - 1].hasAttribute(
|
|
77
|
+
"data-monster-datatable-row-end",
|
|
78
|
+
),
|
|
79
|
+
).to.equal(true);
|
|
80
|
+
expect(datatable.getSelectedRows()).to.deep.equal([]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("synchronizes row, select-all, and mixed selection states", async function () {
|
|
84
|
+
const datatable = createFixture();
|
|
85
|
+
const events = [];
|
|
86
|
+
for (const type of [
|
|
87
|
+
"monster-datatable-row-selected",
|
|
88
|
+
"monster-datatable-all-rows-selected",
|
|
89
|
+
"monster-datatable-all-rows-deselected",
|
|
90
|
+
"monster-datatable-selection-changed",
|
|
91
|
+
]) {
|
|
92
|
+
datatable.addEventListener(type, () => events.push(type));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
await waitForUpdates();
|
|
96
|
+
|
|
97
|
+
const rowCheckboxes = [
|
|
98
|
+
...datatable.shadowRoot.querySelectorAll(
|
|
99
|
+
'[data-monster-role="select-row"]',
|
|
100
|
+
),
|
|
101
|
+
];
|
|
102
|
+
const selectAll = datatable.shadowRoot.querySelector(
|
|
103
|
+
'[data-monster-role="select-all"]',
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
rowCheckboxes[0].click();
|
|
107
|
+
|
|
108
|
+
expect(datatable.getSelectedRows()).to.deep.equal([0]);
|
|
109
|
+
expect(selectAll.checked).to.equal(false);
|
|
110
|
+
expect(selectAll.indeterminate).to.equal(true);
|
|
111
|
+
expect(
|
|
112
|
+
datatable.shadowRoot.querySelectorAll(
|
|
113
|
+
'[data-monster-role="datatable"] > .selected',
|
|
114
|
+
),
|
|
115
|
+
).to.have.length(2);
|
|
116
|
+
|
|
117
|
+
selectAll.click();
|
|
118
|
+
|
|
119
|
+
expect(datatable.getSelectedRows()).to.deep.equal([0, 1, 2]);
|
|
120
|
+
expect(rowCheckboxes.every((checkbox) => checkbox.checked)).to.equal(true);
|
|
121
|
+
expect(selectAll.checked).to.equal(true);
|
|
122
|
+
expect(selectAll.indeterminate).to.equal(false);
|
|
123
|
+
expect(
|
|
124
|
+
datatable.shadowRoot.querySelectorAll(
|
|
125
|
+
'[data-monster-role="datatable"] > .selected',
|
|
126
|
+
),
|
|
127
|
+
).to.have.length(6);
|
|
128
|
+
|
|
129
|
+
selectAll.click();
|
|
130
|
+
|
|
131
|
+
expect(datatable.getSelectedRows()).to.deep.equal([]);
|
|
132
|
+
expect(rowCheckboxes.every((checkbox) => !checkbox.checked)).to.equal(true);
|
|
133
|
+
expect(selectAll.checked).to.equal(false);
|
|
134
|
+
expect(selectAll.indeterminate).to.equal(false);
|
|
135
|
+
expect(
|
|
136
|
+
datatable.shadowRoot.querySelectorAll(
|
|
137
|
+
'[data-monster-role="datatable"] > .selected',
|
|
138
|
+
),
|
|
139
|
+
).to.have.length(0);
|
|
140
|
+
expect(events).to.deep.equal([
|
|
141
|
+
"monster-datatable-row-selected",
|
|
142
|
+
"monster-datatable-selection-changed",
|
|
143
|
+
"monster-datatable-all-rows-selected",
|
|
144
|
+
"monster-datatable-selection-changed",
|
|
145
|
+
"monster-datatable-all-rows-deselected",
|
|
146
|
+
"monster-datatable-selection-changed",
|
|
147
|
+
]);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { expect } from "chai";
|
|
3
|
+
|
|
4
|
+
const actionButtonSource = readFileSync(
|
|
5
|
+
new URL(
|
|
6
|
+
"../../../../source/components/form/style/action-button.pcss",
|
|
7
|
+
import.meta.url,
|
|
8
|
+
),
|
|
9
|
+
"utf8",
|
|
10
|
+
);
|
|
11
|
+
const actionButtonStyleSheet = readFileSync(
|
|
12
|
+
new URL(
|
|
13
|
+
"../../../../source/components/form/stylesheet/action-button.mjs",
|
|
14
|
+
import.meta.url,
|
|
15
|
+
),
|
|
16
|
+
"utf8",
|
|
17
|
+
);
|
|
18
|
+
const actionButtonComponent = readFileSync(
|
|
19
|
+
new URL(
|
|
20
|
+
"../../../../source/components/form/action-button.mjs",
|
|
21
|
+
import.meta.url,
|
|
22
|
+
),
|
|
23
|
+
"utf8",
|
|
24
|
+
);
|
|
25
|
+
const stateButtonSource = readFileSync(
|
|
26
|
+
new URL(
|
|
27
|
+
"../../../../source/components/form/style/state-button.pcss",
|
|
28
|
+
import.meta.url,
|
|
29
|
+
),
|
|
30
|
+
"utf8",
|
|
31
|
+
);
|
|
32
|
+
const stateButtonStyleSheet = readFileSync(
|
|
33
|
+
new URL(
|
|
34
|
+
"../../../../source/components/form/stylesheet/state-button.mjs",
|
|
35
|
+
import.meta.url,
|
|
36
|
+
),
|
|
37
|
+
"utf8",
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
describe("ActionButton styles", () => {
|
|
41
|
+
it("provides theme hooks for a coherent action menu", () => {
|
|
42
|
+
for (const token of [
|
|
43
|
+
"--monster-action-menu-padding",
|
|
44
|
+
"--monster-action-menu-item-padding",
|
|
45
|
+
"--monster-action-button-popper-padding",
|
|
46
|
+
"--monster-action-button-popper-border-color",
|
|
47
|
+
"--monster-action-button-menu-min-inline-size",
|
|
48
|
+
"--monster-action-button-item-background-color",
|
|
49
|
+
"--monster-action-button-item-hover-background-color",
|
|
50
|
+
"--monster-action-button-item-focus-outline-offset",
|
|
51
|
+
]) {
|
|
52
|
+
expect(actionButtonSource, token).to.include(token);
|
|
53
|
+
expect(actionButtonStyleSheet, token).to.include(token);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("keeps the existing action appearance as the token fallback", () => {
|
|
58
|
+
expect(actionButtonSource).to.include(
|
|
59
|
+
"--monster-action-menu-item-background-color",
|
|
60
|
+
);
|
|
61
|
+
expect(actionButtonSource).to.include(
|
|
62
|
+
"--monster-action-button-item-margin, 2px",
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("allows menu labels to align independently from regular state buttons", () => {
|
|
67
|
+
const declaration =
|
|
68
|
+
"var(--monster-state-button-label-justify-content, center)";
|
|
69
|
+
const buttonDeclaration = "--monster-state-button-justify-content";
|
|
70
|
+
|
|
71
|
+
expect(stateButtonSource).to.include(declaration);
|
|
72
|
+
expect(stateButtonSource).to.include(buttonDeclaration);
|
|
73
|
+
expect(stateButtonStyleSheet).to.include(
|
|
74
|
+
"var(--monster-state-button-label-justify-content,center)",
|
|
75
|
+
);
|
|
76
|
+
expect(stateButtonStyleSheet).to.include(buttonDeclaration);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("forwards the public accessible name to the native menu trigger", () => {
|
|
80
|
+
expect(actionButtonComponent).to.include(
|
|
81
|
+
'data-monster-attributes="aria-label path:aria.label, class path:classes.button"',
|
|
82
|
+
);
|
|
83
|
+
expect(actionButtonComponent).to.include('aria-haspopup="menu"');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -85,6 +85,38 @@ describe("ButtonBar", function () {
|
|
|
85
85
|
expect(bar.toggleDialog).to.be.a("function");
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
+
it("should name and expose the state of the overflow switch", async function () {
|
|
89
|
+
const bar = document.getElementById("bar");
|
|
90
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
91
|
+
const switchButton = bar.shadowRoot.querySelector(
|
|
92
|
+
'[data-monster-role="switch"]',
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
expect(switchButton.getAttribute("aria-label")).to.equal("More actions");
|
|
96
|
+
expect(switchButton.getAttribute("aria-expanded")).to.equal("false");
|
|
97
|
+
expect(switchButton.getAttribute("aria-controls")).to.equal(
|
|
98
|
+
"monster-button-bar-popper",
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
bar.setOption("labels.moreActions", "Weitere Aktionen");
|
|
102
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
103
|
+
expect(switchButton.getAttribute("aria-label")).to.equal(
|
|
104
|
+
"Weitere Aktionen",
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
bar.showDialog();
|
|
108
|
+
expect(switchButton.getAttribute("aria-expanded")).to.equal("true");
|
|
109
|
+
switchButton.dispatchEvent(
|
|
110
|
+
new KeyboardEvent("keydown", {
|
|
111
|
+
key: "Escape",
|
|
112
|
+
bubbles: true,
|
|
113
|
+
composed: true,
|
|
114
|
+
}),
|
|
115
|
+
);
|
|
116
|
+
expect(switchButton.getAttribute("aria-expanded")).to.equal("false");
|
|
117
|
+
expect(bar.shadowRoot.activeElement).to.equal(switchButton);
|
|
118
|
+
});
|
|
119
|
+
|
|
88
120
|
it("should keep the popper switch hidden when no buttons are slotted", function (done) {
|
|
89
121
|
const bar = document.getElementById("bar");
|
|
90
122
|
|
|
@@ -245,6 +277,99 @@ describe("ButtonBar", function () {
|
|
|
245
277
|
}
|
|
246
278
|
});
|
|
247
279
|
|
|
280
|
+
it("should use the host content box when reserving overflow switch space", async function () {
|
|
281
|
+
const originalRequestAnimationFrame = window.requestAnimationFrame;
|
|
282
|
+
const originalGlobalRequestAnimationFrame = globalThis.requestAnimationFrame;
|
|
283
|
+
const scheduledCallbacks = [];
|
|
284
|
+
const flushFrames = async () => {
|
|
285
|
+
while (scheduledCallbacks.length > 0) {
|
|
286
|
+
scheduledCallbacks.shift()();
|
|
287
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
window.requestAnimationFrame = (callback) => {
|
|
293
|
+
scheduledCallbacks.push(callback);
|
|
294
|
+
return scheduledCallbacks.length;
|
|
295
|
+
};
|
|
296
|
+
globalThis.requestAnimationFrame = window.requestAnimationFrame;
|
|
297
|
+
|
|
298
|
+
const mocks = document.getElementById("mocks");
|
|
299
|
+
mocks.innerHTML = `
|
|
300
|
+
<div id="content-box-wrapper">
|
|
301
|
+
<monster-button-bar
|
|
302
|
+
id="content-box-button-bar"
|
|
303
|
+
style="box-sizing: border-box; padding-left: 20px; padding-right: 20px"
|
|
304
|
+
>
|
|
305
|
+
<button id="content-box-a" type="button">One</button>
|
|
306
|
+
<button id="content-box-b" type="button">Two</button>
|
|
307
|
+
</monster-button-bar>
|
|
308
|
+
</div>
|
|
309
|
+
`;
|
|
310
|
+
const wrapper = document.getElementById("content-box-wrapper");
|
|
311
|
+
const bar = document.getElementById("content-box-button-bar");
|
|
312
|
+
const buttons = [
|
|
313
|
+
document.getElementById("content-box-a"),
|
|
314
|
+
document.getElementById("content-box-b"),
|
|
315
|
+
];
|
|
316
|
+
const switchButton = bar.shadowRoot.querySelector(
|
|
317
|
+
'[data-monster-role="switch"]',
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
wrapper.style.boxSizing = "border-box";
|
|
321
|
+
Object.defineProperty(wrapper, "clientWidth", {
|
|
322
|
+
configurable: true,
|
|
323
|
+
value: 120,
|
|
324
|
+
});
|
|
325
|
+
Object.defineProperty(bar, "clientWidth", {
|
|
326
|
+
configurable: true,
|
|
327
|
+
value: 60,
|
|
328
|
+
});
|
|
329
|
+
Object.defineProperty(switchButton, "offsetWidth", {
|
|
330
|
+
configurable: true,
|
|
331
|
+
value: 20,
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
for (const button of buttons) {
|
|
335
|
+
Object.defineProperty(button, "offsetWidth", {
|
|
336
|
+
configurable: true,
|
|
337
|
+
value: 48,
|
|
338
|
+
});
|
|
339
|
+
Object.defineProperty(button, "offsetHeight", {
|
|
340
|
+
configurable: true,
|
|
341
|
+
value: 30,
|
|
342
|
+
});
|
|
343
|
+
button.getBoundingClientRect = () => ({
|
|
344
|
+
width: 48,
|
|
345
|
+
height: 30,
|
|
346
|
+
top: 0,
|
|
347
|
+
right: 48,
|
|
348
|
+
bottom: 30,
|
|
349
|
+
left: 0,
|
|
350
|
+
x: 0,
|
|
351
|
+
y: 0,
|
|
352
|
+
toJSON: () => {},
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
await flushFrames();
|
|
357
|
+
await waitForCondition(() => {
|
|
358
|
+
return buttons.every(
|
|
359
|
+
(button) => button.getAttribute("slot") === "popper",
|
|
360
|
+
);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
expect(
|
|
364
|
+
buttons.every((button) => button.getAttribute("slot") === "popper"),
|
|
365
|
+
).to.be.true;
|
|
366
|
+
expect(switchButton.hasAttribute("hidden")).to.be.false;
|
|
367
|
+
} finally {
|
|
368
|
+
window.requestAnimationFrame = originalRequestAnimationFrame;
|
|
369
|
+
globalThis.requestAnimationFrame = originalGlobalRequestAnimationFrame;
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
|
|
248
373
|
it("should default the button bar layout alignment to left", function () {
|
|
249
374
|
const bar = document.getElementById("bar");
|
|
250
375
|
const buttonBar = bar.shadowRoot.querySelector(
|
|
@@ -275,7 +400,7 @@ describe("ButtonBar", function () {
|
|
|
275
400
|
}, 50);
|
|
276
401
|
});
|
|
277
402
|
|
|
278
|
-
it("should
|
|
403
|
+
it("should allow themes to space main and overflow button groups", function () {
|
|
279
404
|
const cssText = ButtonBar.getCSSStyleSheet()
|
|
280
405
|
.flatMap((styleSheet) => Array.from(styleSheet.cssRules))
|
|
281
406
|
.map((rule) => rule.cssText)
|
|
@@ -283,9 +408,103 @@ describe("ButtonBar", function () {
|
|
|
283
408
|
|
|
284
409
|
expect(cssText).to.contain("slot[name=popper]");
|
|
285
410
|
expect(cssText).to.contain("align-items: stretch");
|
|
286
|
-
expect(cssText).to.contain("gap
|
|
411
|
+
expect(cssText).to.contain("var(--monster-button-bar-gap,0)");
|
|
412
|
+
expect(cssText).to.contain("--monster-button-bar-popper-gap");
|
|
413
|
+
expect(cssText).to.contain("--monster-action-menu-gap");
|
|
287
414
|
expect(cssText).to.contain("margin-top");
|
|
288
|
-
expect(cssText).to.contain("
|
|
415
|
+
expect(cssText).to.contain("--monster-button-bar-item-spacing");
|
|
416
|
+
expect(cssText).to.contain("--monster-button-bar-popper-item-spacing");
|
|
417
|
+
expect(cssText).to.match(/--monster-button-bar-item-spacing,\s*0/u);
|
|
418
|
+
expect(cssText).to.match(/--monster-button-bar-popper-item-spacing,\s*0/u);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it("should clear joined-border offsets when a button gap is configured", async function () {
|
|
422
|
+
const originalRequestAnimationFrame = window.requestAnimationFrame;
|
|
423
|
+
const originalGlobalRequestAnimationFrame = globalThis.requestAnimationFrame;
|
|
424
|
+
const scheduledCallbacks = [];
|
|
425
|
+
const flushFrames = async () => {
|
|
426
|
+
while (scheduledCallbacks.length > 0) {
|
|
427
|
+
scheduledCallbacks.shift()();
|
|
428
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
try {
|
|
433
|
+
window.requestAnimationFrame = (callback) => {
|
|
434
|
+
scheduledCallbacks.push(callback);
|
|
435
|
+
return scheduledCallbacks.length;
|
|
436
|
+
};
|
|
437
|
+
globalThis.requestAnimationFrame = window.requestAnimationFrame;
|
|
438
|
+
|
|
439
|
+
const mocks = document.getElementById("mocks");
|
|
440
|
+
mocks.innerHTML = `
|
|
441
|
+
<div id="spaced-button-bar-wrapper">
|
|
442
|
+
<monster-button-bar
|
|
443
|
+
id="spaced-button-bar"
|
|
444
|
+
style="--monster-button-bar-gap: 8px"
|
|
445
|
+
>
|
|
446
|
+
<button id="spaced-button-a" type="button">One</button>
|
|
447
|
+
<button id="spaced-button-b" type="button">Two</button>
|
|
448
|
+
</monster-button-bar>
|
|
449
|
+
</div>
|
|
450
|
+
`;
|
|
451
|
+
const wrapper = document.getElementById("spaced-button-bar-wrapper");
|
|
452
|
+
const bar = document.getElementById("spaced-button-bar");
|
|
453
|
+
const buttons = [
|
|
454
|
+
document.getElementById("spaced-button-a"),
|
|
455
|
+
document.getElementById("spaced-button-b"),
|
|
456
|
+
];
|
|
457
|
+
|
|
458
|
+
Object.defineProperty(wrapper, "clientWidth", {
|
|
459
|
+
configurable: true,
|
|
460
|
+
value: 200,
|
|
461
|
+
});
|
|
462
|
+
for (const button of buttons) {
|
|
463
|
+
button.style.border = "1px solid";
|
|
464
|
+
button.style.borderRadius = "8px";
|
|
465
|
+
Object.defineProperty(button, "offsetWidth", {
|
|
466
|
+
configurable: true,
|
|
467
|
+
value: 48,
|
|
468
|
+
});
|
|
469
|
+
Object.defineProperty(button, "offsetHeight", {
|
|
470
|
+
configurable: true,
|
|
471
|
+
value: 40,
|
|
472
|
+
});
|
|
473
|
+
button.getBoundingClientRect = () => ({
|
|
474
|
+
width: 48,
|
|
475
|
+
height: 40,
|
|
476
|
+
top: 0,
|
|
477
|
+
right: 48,
|
|
478
|
+
bottom: 40,
|
|
479
|
+
left: 0,
|
|
480
|
+
x: 0,
|
|
481
|
+
y: 0,
|
|
482
|
+
toJSON: () => {},
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
buttons[1].style.marginLeft = "-1px";
|
|
486
|
+
|
|
487
|
+
const switchButton = bar.shadowRoot.querySelector(
|
|
488
|
+
'[data-monster-role="switch"]',
|
|
489
|
+
);
|
|
490
|
+
Object.defineProperty(switchButton, "offsetWidth", {
|
|
491
|
+
configurable: true,
|
|
492
|
+
value: 20,
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
await flushFrames();
|
|
496
|
+
|
|
497
|
+
expect(buttons[1].style.marginLeft).to.equal("");
|
|
498
|
+
expect(buttons[0].style.borderRadius).to.equal("8px");
|
|
499
|
+
expect(buttons[0].style.borderTopRightRadius).to.equal("");
|
|
500
|
+
expect(buttons[0].style.borderBottomRightRadius).to.equal("");
|
|
501
|
+
expect(buttons[1].style.borderRadius).to.equal("8px");
|
|
502
|
+
expect(buttons[1].style.borderTopLeftRadius).to.equal("");
|
|
503
|
+
expect(buttons[1].style.borderBottomLeftRadius).to.equal("");
|
|
504
|
+
} finally {
|
|
505
|
+
window.requestAnimationFrame = originalRequestAnimationFrame;
|
|
506
|
+
globalThis.requestAnimationFrame = originalGlobalRequestAnimationFrame;
|
|
507
|
+
}
|
|
289
508
|
});
|
|
290
509
|
|
|
291
510
|
it("should coalesce resize layouts and avoid unchanged layout writes", async function () {
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
const contextThemeClasses = new Map([
|
|
7
|
+
["monster-context-help", "monster-theme-primary-1"],
|
|
8
|
+
["monster-context-hint", "monster-theme-tertiary-2"],
|
|
9
|
+
["monster-context-info", "monster-theme-primary-2"],
|
|
10
|
+
["monster-context-note", "monster-theme-secondary-2"],
|
|
11
|
+
["monster-context-success", "monster-theme-success-2"],
|
|
12
|
+
["monster-context-warning", "monster-theme-warning-2"],
|
|
13
|
+
["monster-context-error", "monster-theme-error-2"],
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
describe("Context component theme colors", () => {
|
|
17
|
+
before(async () => {
|
|
18
|
+
await initJSDOM();
|
|
19
|
+
await import("element-internals-polyfill");
|
|
20
|
+
|
|
21
|
+
const global = getGlobal();
|
|
22
|
+
if (!global.ResizeObserver) {
|
|
23
|
+
global.ResizeObserver = ResizeObserverMock;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
await Promise.all([
|
|
27
|
+
import("../../../../source/components/form/context-help.mjs"),
|
|
28
|
+
import("../../../../source/components/form/context-hint.mjs"),
|
|
29
|
+
import("../../../../source/components/form/context-info.mjs"),
|
|
30
|
+
import("../../../../source/components/form/context-note.mjs"),
|
|
31
|
+
import("../../../../source/components/form/context-success.mjs"),
|
|
32
|
+
import("../../../../source/components/form/context-warning.mjs"),
|
|
33
|
+
import("../../../../source/components/form/context-error.mjs"),
|
|
34
|
+
]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterEach(() => {
|
|
38
|
+
document.getElementById("mocks").replaceChildren();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
for (const [tag, themeClass] of contextThemeClasses) {
|
|
42
|
+
it(`${tag} keeps its semantic pair while inheriting the control background`, async () => {
|
|
43
|
+
const element = document.createElement(tag);
|
|
44
|
+
element.textContent = "Accessible context";
|
|
45
|
+
document.getElementById("mocks").append(element);
|
|
46
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
47
|
+
|
|
48
|
+
const button = element.shadowRoot.querySelector(
|
|
49
|
+
'[data-monster-role="button"]',
|
|
50
|
+
);
|
|
51
|
+
const icon = button.querySelector("svg");
|
|
52
|
+
|
|
53
|
+
assert.ok(button.classList.contains(themeClass));
|
|
54
|
+
assert.ok(button.classList.contains("monster-theme-background-inherit"));
|
|
55
|
+
assert.equal(icon.getAttribute("fill"), "currentColor");
|
|
56
|
+
assert.equal(icon.querySelector("[fill]"), null);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
});
|