@schukai/monster 4.136.29 → 4.137.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/datatable/dataset.mjs +1 -1
- package/source/components/form/choice-cards.mjs +525 -0
- package/source/components/form/form.mjs +1 -1
- package/source/components/form/style/choice-cards.pcss +172 -0
- package/source/components/form/style/field-layout.pcss +8 -0
- package/source/components/form/stylesheet/choice-cards.mjs +31 -0
- package/source/components/form/stylesheet/field-layout.mjs +7 -14
- package/source/components/form/util/floating-ui.mjs +29 -5
- package/source/monster.mjs +1 -0
- package/test/cases/components/form/choice-cards.mjs +192 -0
- package/test/cases/components/form/floating-ui.mjs +63 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import * as chai from "chai";
|
|
2
|
+
import { chaiDom } from "../../../util/chai-dom.mjs";
|
|
3
|
+
import { initJSDOM } from "../../../util/jsdom.mjs";
|
|
4
|
+
|
|
5
|
+
let expect = chai.expect;
|
|
6
|
+
chai.use(chaiDom);
|
|
7
|
+
|
|
8
|
+
let ChoiceCards;
|
|
9
|
+
|
|
10
|
+
function waitForCondition(check, { timeout = 4000, interval = 25 } = {}) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const start = Date.now();
|
|
13
|
+
|
|
14
|
+
const poll = () => {
|
|
15
|
+
try {
|
|
16
|
+
if (check()) {
|
|
17
|
+
resolve();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
} catch (e) {
|
|
21
|
+
reject(e);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (Date.now() - start >= timeout) {
|
|
26
|
+
reject(new Error("Timed out while waiting for test condition."));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
setTimeout(poll, interval);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
poll();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe("ChoiceCards", function () {
|
|
38
|
+
before(function (done) {
|
|
39
|
+
initJSDOM()
|
|
40
|
+
.then(() => {
|
|
41
|
+
return import("element-internals-polyfill");
|
|
42
|
+
})
|
|
43
|
+
.then(() => {
|
|
44
|
+
return import("../../../../source/components/form/form.mjs");
|
|
45
|
+
})
|
|
46
|
+
.then(() => {
|
|
47
|
+
return import("../../../../source/components/form/choice-cards.mjs");
|
|
48
|
+
})
|
|
49
|
+
.then((m) => {
|
|
50
|
+
ChoiceCards = m["ChoiceCards"];
|
|
51
|
+
done();
|
|
52
|
+
})
|
|
53
|
+
.catch((e) => done(e));
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
document.getElementById("mocks").innerHTML = '<div id="test"></div>';
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
afterEach(() => {
|
|
61
|
+
document.getElementById("mocks").innerHTML = "";
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("creates a custom element instance", function () {
|
|
65
|
+
expect(document.createElement("monster-choice-cards")).is.instanceof(
|
|
66
|
+
ChoiceCards,
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("renders choice cards from items", function () {
|
|
71
|
+
const cards = document.createElement("monster-choice-cards");
|
|
72
|
+
cards.setItems([
|
|
73
|
+
{ value: "assets", label: "Project assets", icon: "project-assets" },
|
|
74
|
+
{ value: "api", label: "API collection", icon: "api-collection" },
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
document.getElementById("test").appendChild(cards);
|
|
78
|
+
|
|
79
|
+
const choices = cards.shadowRoot.querySelectorAll(
|
|
80
|
+
'[data-monster-role="choice"]',
|
|
81
|
+
);
|
|
82
|
+
expect(choices.length).is.equal(2);
|
|
83
|
+
expect(choices[0].textContent).contains("Project assets");
|
|
84
|
+
expect(choices[1].textContent).contains("API collection");
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("renders custom card content from slots", function () {
|
|
88
|
+
const cards = document.createElement("monster-choice-cards");
|
|
89
|
+
cards.setItems([
|
|
90
|
+
{ value: "assets", label: "Project assets", contentSlot: "assets-card" },
|
|
91
|
+
{ value: "api", label: "API collection", contentSlot: "api-card" },
|
|
92
|
+
{ value: "manual", label: "Manual", contentSlot: "manual-card" },
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
const assets = document.createElement("span");
|
|
96
|
+
assets.slot = "assets-card";
|
|
97
|
+
assets.textContent = "Custom assets content";
|
|
98
|
+
cards.appendChild(assets);
|
|
99
|
+
|
|
100
|
+
document.getElementById("test").appendChild(cards);
|
|
101
|
+
|
|
102
|
+
const choices = cards.shadowRoot.querySelectorAll(
|
|
103
|
+
'[data-monster-role="choice"]',
|
|
104
|
+
);
|
|
105
|
+
expect(choices.length).is.equal(3);
|
|
106
|
+
expect(
|
|
107
|
+
cards.shadowRoot
|
|
108
|
+
.querySelector('[data-choice-value="assets"] slot')
|
|
109
|
+
.getAttribute("name"),
|
|
110
|
+
).is.equal("assets-card");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("selects a card and emits change events", function (done) {
|
|
114
|
+
const cards = document.createElement("monster-choice-cards");
|
|
115
|
+
cards.setItems([
|
|
116
|
+
{ value: "assets", label: "Project assets" },
|
|
117
|
+
{ value: "api", label: "API collection" },
|
|
118
|
+
]);
|
|
119
|
+
|
|
120
|
+
cards.addEventListener("monster-change", (event) => {
|
|
121
|
+
expect(event.detail.value).is.equal("api");
|
|
122
|
+
expect(cards.value).is.equal("api");
|
|
123
|
+
expect(
|
|
124
|
+
cards.shadowRoot
|
|
125
|
+
.querySelector('[data-choice-value="api"]')
|
|
126
|
+
.getAttribute("aria-checked"),
|
|
127
|
+
).is.equal("true");
|
|
128
|
+
done();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
document.getElementById("test").appendChild(cards);
|
|
132
|
+
cards.shadowRoot.querySelector('[data-choice-value="api"]').click();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("reads from and writes back to a form datasource", async function () {
|
|
136
|
+
this.timeout(6000);
|
|
137
|
+
|
|
138
|
+
document.getElementById("test").innerHTML = `
|
|
139
|
+
<monster-datasource-dom id="choice-ds">
|
|
140
|
+
<script type="application/json">
|
|
141
|
+
[
|
|
142
|
+
{
|
|
143
|
+
"source": "assets"
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
</script>
|
|
147
|
+
</monster-datasource-dom>
|
|
148
|
+
<monster-form
|
|
149
|
+
id="choice-form"
|
|
150
|
+
data-monster-option-datasource-selector="#choice-ds"
|
|
151
|
+
data-monster-option-mapping-data=""
|
|
152
|
+
data-monster-option-mapping-index="0"
|
|
153
|
+
>
|
|
154
|
+
<monster-choice-cards
|
|
155
|
+
id="choice-source"
|
|
156
|
+
data-monster-attributes="value path:data.source"
|
|
157
|
+
data-monster-bind="path:data.source"
|
|
158
|
+
data-monster-options='{
|
|
159
|
+
"items": [
|
|
160
|
+
{ "value": "assets", "label": "Assets", "contentSlot": "assets-card" },
|
|
161
|
+
{ "value": "api", "label": "API", "contentSlot": "api-card" }
|
|
162
|
+
]
|
|
163
|
+
}'
|
|
164
|
+
>
|
|
165
|
+
<span slot="assets-card">Assets</span>
|
|
166
|
+
<span slot="api-card">API</span>
|
|
167
|
+
</monster-choice-cards>
|
|
168
|
+
</monster-form>
|
|
169
|
+
`;
|
|
170
|
+
|
|
171
|
+
const datasource = document.getElementById("choice-ds");
|
|
172
|
+
const cards = document.getElementById("choice-source");
|
|
173
|
+
|
|
174
|
+
await waitForCondition(() => cards.value === "assets");
|
|
175
|
+
|
|
176
|
+
cards.select("api");
|
|
177
|
+
await waitForCondition(() => datasource.data?.[0]?.source === "api");
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("does not select disabled items", function () {
|
|
181
|
+
const cards = document.createElement("monster-choice-cards");
|
|
182
|
+
cards.setItems([
|
|
183
|
+
{ value: "assets", label: "Project assets" },
|
|
184
|
+
{ value: "api", label: "API collection", disabled: true },
|
|
185
|
+
]);
|
|
186
|
+
|
|
187
|
+
document.getElementById("test").appendChild(cards);
|
|
188
|
+
cards.select("api");
|
|
189
|
+
|
|
190
|
+
expect(cards.value).is.equal(null);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
@@ -334,5 +334,68 @@ describe("form floating-ui boundary resolution", function () {
|
|
|
334
334
|
|
|
335
335
|
expect(content.style.overflowX).to.equal("auto");
|
|
336
336
|
expect(content.style.overflowY).to.equal("visible");
|
|
337
|
+
expect(content.style.height).to.equal("");
|
|
338
|
+
expect(content.style.maxHeight).to.equal("200px");
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it("should preserve declared nested scroll height when horizontal overlay content fits", function () {
|
|
342
|
+
const mocks = document.getElementById("mocks");
|
|
343
|
+
const popper = document.createElement("div");
|
|
344
|
+
const content = document.createElement("div");
|
|
345
|
+
const options = document.createElement("div");
|
|
346
|
+
|
|
347
|
+
content.setAttribute("part", "content");
|
|
348
|
+
content.setAttribute("data-monster-overflow-mode", "horizontal");
|
|
349
|
+
options.style.overflowY = "auto";
|
|
350
|
+
options.style.height = "72px";
|
|
351
|
+
options.style.maxHeight = "72px";
|
|
352
|
+
|
|
353
|
+
Object.defineProperty(content, "scrollHeight", {
|
|
354
|
+
configurable: true,
|
|
355
|
+
value: 120,
|
|
356
|
+
});
|
|
357
|
+
Object.defineProperty(options, "scrollHeight", {
|
|
358
|
+
configurable: true,
|
|
359
|
+
value: 72,
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
content.appendChild(options);
|
|
363
|
+
popper.appendChild(content);
|
|
364
|
+
mocks.appendChild(popper);
|
|
365
|
+
|
|
366
|
+
applyAdaptiveFloatingElementSize(popper, {
|
|
367
|
+
availableWidth: 240,
|
|
368
|
+
availableHeight: 200,
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
expect(options.style.height).to.equal("72px");
|
|
372
|
+
expect(options.style.maxHeight).to.equal("72px");
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it("should constrain horizontal overlay-aware content height only when it exceeds available height", function () {
|
|
376
|
+
const mocks = document.getElementById("mocks");
|
|
377
|
+
const popper = document.createElement("div");
|
|
378
|
+
const content = document.createElement("div");
|
|
379
|
+
|
|
380
|
+
content.setAttribute("part", "content");
|
|
381
|
+
content.setAttribute("data-monster-overflow-mode", "horizontal");
|
|
382
|
+
|
|
383
|
+
Object.defineProperty(content, "scrollHeight", {
|
|
384
|
+
configurable: true,
|
|
385
|
+
value: 320,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
popper.appendChild(content);
|
|
389
|
+
mocks.appendChild(popper);
|
|
390
|
+
|
|
391
|
+
applyAdaptiveFloatingElementSize(popper, {
|
|
392
|
+
availableWidth: 240,
|
|
393
|
+
availableHeight: 200,
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
expect(content.style.overflowX).to.equal("auto");
|
|
397
|
+
expect(content.style.overflowY).to.equal("auto");
|
|
398
|
+
expect(content.style.height).to.equal("200px");
|
|
399
|
+
expect(content.style.maxHeight).to.equal("200px");
|
|
337
400
|
});
|
|
338
401
|
});
|