@getflip/swirl-components 0.78.0 → 0.79.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/README.md +1 -1
- package/components.json +138 -20
- package/dist/cjs/file-manager.cjs.entry.js +2 -1
- package/dist/cjs/index-506fe4ea.js +2 -2
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/swirl-app-layout_7.cjs.entry.js +7 -4
- package/dist/cjs/swirl-button.cjs.entry.js +3 -1
- package/dist/cjs/swirl-components.cjs.js +1 -1
- package/dist/cjs/swirl-date-input.cjs.entry.js +1 -1
- package/dist/cjs/swirl-lightbox.cjs.entry.js +1 -1
- package/dist/cjs/swirl-pdf-reader.cjs.entry.js +2 -2
- package/dist/cjs/{swirl-popover.cjs.entry.js → swirl-popover_2.cjs.entry.js} +104 -18
- package/dist/cjs/swirl-select.cjs.entry.js +2 -2
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/swirl-button/swirl-button.js +37 -1
- package/dist/collection/components/swirl-date-input/swirl-date-input.js +1 -1
- package/dist/collection/components/swirl-date-input/swirl-date-input.spec.js +6 -4
- package/dist/collection/components/swirl-lightbox/swirl-lightbox.js +1 -1
- package/dist/collection/components/swirl-lightbox/swirl-lightbox.spec.js +6 -4
- package/dist/collection/components/swirl-menu/swirl-menu.spec.js +38 -14
- package/dist/collection/components/swirl-menu/swirl-menu.stories.js +35 -33
- package/dist/collection/components/swirl-pdf-reader/swirl-pdf-reader.js +2 -2
- package/dist/collection/components/swirl-pdf-reader/swirl-pdf-reader.spec.js +4 -2
- package/dist/collection/components/swirl-popover/swirl-popover.js +35 -39
- package/dist/collection/components/swirl-popover/swirl-popover.spec.js +20 -11
- package/dist/collection/components/swirl-popover/swirl-popover.stories.js +8 -25
- package/dist/collection/components/swirl-popover-trigger/swirl-popover-trigger.css +3 -0
- package/dist/collection/components/swirl-popover-trigger/swirl-popover-trigger.js +132 -0
- package/dist/collection/components/swirl-popover-trigger/swirl-popover-trigger.spec.js +26 -0
- package/dist/collection/components/swirl-popover-trigger/swirl-popover-trigger.stories.js +48 -0
- package/dist/collection/components/swirl-resource-list-item/swirl-resource-list-item.css +7 -0
- package/dist/collection/components/swirl-resource-list-item/swirl-resource-list-item.js +7 -3
- package/dist/collection/components/swirl-resource-list-item/swirl-resource-list-item.spec.js +1 -0
- package/dist/collection/components/swirl-resource-list-item/swirl-resource-list-item.stories.js +29 -29
- package/dist/collection/components/swirl-select/swirl-select.js +2 -2
- package/dist/collection/components/swirl-select/swirl-select.spec.js +4 -2
- package/dist/collection/prototypes/file-manager/file-manager.js +4 -2
- package/dist/components/file-manager.js +54 -46
- package/dist/components/swirl-button2.js +5 -1
- package/dist/components/swirl-date-input.js +13 -7
- package/dist/components/swirl-lightbox.js +21 -15
- package/dist/components/swirl-pdf-reader.js +48 -42
- package/dist/components/swirl-popover-trigger.d.ts +11 -0
- package/dist/components/swirl-popover-trigger.js +6 -0
- package/dist/components/swirl-popover-trigger2.js +99 -0
- package/dist/components/swirl-popover2.js +25 -19
- package/dist/components/swirl-resource-list-item2.js +19 -10
- package/dist/components/swirl-select.js +18 -12
- package/dist/esm/file-manager.entry.js +2 -1
- package/dist/esm/index-99d0060d.js +2 -2
- package/dist/esm/loader.js +1 -1
- package/dist/esm/swirl-app-layout_7.entry.js +7 -4
- package/dist/esm/swirl-button.entry.js +3 -1
- package/dist/esm/swirl-components.js +1 -1
- package/dist/esm/swirl-date-input.entry.js +1 -1
- package/dist/esm/swirl-lightbox.entry.js +1 -1
- package/dist/esm/swirl-pdf-reader.entry.js +2 -2
- package/dist/esm/{swirl-popover.entry.js → swirl-popover_2.entry.js} +104 -19
- package/dist/esm/swirl-select.entry.js +2 -2
- package/dist/swirl-components/p-0fce283f.entry.js +1 -0
- package/dist/swirl-components/p-2278aeae.entry.js +1 -0
- package/dist/swirl-components/p-251884ec.entry.js +1 -0
- package/dist/swirl-components/{p-a16a6381.entry.js → p-30ae7d5c.entry.js} +1 -1
- package/dist/swirl-components/p-3abcd491.entry.js +1 -0
- package/dist/swirl-components/p-794d25e2.entry.js +1 -0
- package/dist/swirl-components/p-ed921838.entry.js +1 -0
- package/dist/swirl-components/p-f9054b79.entry.js +1 -0
- package/dist/swirl-components/swirl-components.esm.js +1 -1
- package/dist/types/components/swirl-button/swirl-button.d.ts +2 -0
- package/dist/types/components/swirl-popover/swirl-popover.d.ts +3 -5
- package/dist/types/components/swirl-popover/swirl-popover.stories.d.ts +0 -3
- package/dist/types/components/swirl-popover-trigger/swirl-popover-trigger.d.ts +13 -0
- package/dist/types/components/swirl-popover-trigger/swirl-popover-trigger.stories.d.ts +22 -0
- package/dist/types/components/swirl-resource-list-item/swirl-resource-list-item.d.ts +1 -0
- package/dist/types/components/swirl-resource-list-item/swirl-resource-list-item.stories.d.ts +8 -3
- package/dist/types/components.d.ts +24 -5
- package/dist/types/prototypes/file-manager/file-manager.d.ts +1 -0
- package/dist/typings.d.ts +1 -0
- package/package.json +2 -2
- package/vscode-data.json +24 -3
- package/dist/swirl-components/p-8c507544.entry.js +0 -1
- package/dist/swirl-components/p-acd95936.entry.js +0 -1
- package/dist/swirl-components/p-b105d565.entry.js +0 -1
- package/dist/swirl-components/p-b28fadcf.entry.js +0 -1
- package/dist/swirl-components/p-d98edc75.entry.js +0 -1
- package/dist/swirl-components/p-ef50db1d.entry.js +0 -1
- package/dist/swirl-components/p-f990566c.entry.js +0 -1
|
@@ -48,7 +48,9 @@ describe("swirl-pdf-reader", () => {
|
|
|
48
48
|
</span>
|
|
49
49
|
</span>
|
|
50
50
|
<span class="pdf-reader__header-right">
|
|
51
|
-
<swirl-
|
|
51
|
+
<swirl-popover-trigger>
|
|
52
|
+
<swirl-button class="pdf-reader__menu-button" hidelabel="" icon="<swirl-icon-more-vertikal></swirl-icon-more-vertikal>" label="Open file menu"></swirl-button>
|
|
53
|
+
</swirl-popover-trigger>
|
|
52
54
|
</span>
|
|
53
55
|
<span class="pdf-reader__floating-tools">
|
|
54
56
|
<button aria-label="Toggle side by side view" class="pdf-reader__floating-tool-button" type="button">
|
|
@@ -75,7 +77,7 @@ describe("swirl-pdf-reader", () => {
|
|
|
75
77
|
</div>
|
|
76
78
|
</div>
|
|
77
79
|
</div>
|
|
78
|
-
<swirl-popover animation="scale-in-y" disablescrolllock="" label="File menu" placement="bottom-end"
|
|
80
|
+
<swirl-popover animation="scale-in-y" disablescrolllock="" id="menu" label="File menu" placement="bottom-end">
|
|
79
81
|
<swirl-stack>
|
|
80
82
|
<div class="pdf-reader__meta">
|
|
81
83
|
<div class="pdf-reader__file-icon">
|
|
@@ -55,7 +55,6 @@ export class SwirlPopover {
|
|
|
55
55
|
this.maxHeight = "22rem";
|
|
56
56
|
this.offset = 8;
|
|
57
57
|
this.placement = "bottom-start";
|
|
58
|
-
this.popoverId = undefined;
|
|
59
58
|
this.trigger = undefined;
|
|
60
59
|
this.triggerContainer = undefined;
|
|
61
60
|
this.useContainerWidth = undefined;
|
|
@@ -65,13 +64,16 @@ export class SwirlPopover {
|
|
|
65
64
|
}
|
|
66
65
|
componentDidLoad() {
|
|
67
66
|
this.connectTrigger();
|
|
68
|
-
this.updateFocusableChildren();
|
|
69
67
|
this.updateTriggerAttributes();
|
|
68
|
+
if (Boolean(this.trigger)) {
|
|
69
|
+
console.warn('[Swirl] The "trigger" prop of swirl-popover is deprecated and will be removed with the next major release. Please use the swirl-popover-trigger component instead. https://swirl-storybook.flip-app.dev/?path=/docs/components-swirlpopovertrigger--docs');
|
|
70
|
+
}
|
|
70
71
|
}
|
|
71
72
|
disconnectedCallback() {
|
|
72
73
|
this.unlockBodyScroll();
|
|
73
74
|
}
|
|
74
75
|
onWindowFocusIn(event) {
|
|
76
|
+
var _a;
|
|
75
77
|
if (!this.active) {
|
|
76
78
|
return;
|
|
77
79
|
}
|
|
@@ -82,7 +84,7 @@ export class SwirlPopover {
|
|
|
82
84
|
const popoverLostFocus = !this.el.contains(target) &&
|
|
83
85
|
!this.el.contains(activeElement) &&
|
|
84
86
|
target !== this.triggerEl &&
|
|
85
|
-
!this.triggerEl.contains(target) &&
|
|
87
|
+
!((_a = this.triggerEl) === null || _a === void 0 ? void 0 : _a.contains(target)) &&
|
|
86
88
|
(!isSafari ||
|
|
87
89
|
(isSafari &&
|
|
88
90
|
!this.el.contains(relatedTarget || target) &&
|
|
@@ -102,7 +104,7 @@ export class SwirlPopover {
|
|
|
102
104
|
.some((el) => Boolean(el) && el instanceof Node
|
|
103
105
|
? this.el.contains(el)
|
|
104
106
|
: false);
|
|
105
|
-
const clickedTrigger =
|
|
107
|
+
const clickedTrigger = target === this.triggerEl;
|
|
106
108
|
if (!clickedChild && !clickedShadowChild && !clickedTrigger) {
|
|
107
109
|
this.close();
|
|
108
110
|
}
|
|
@@ -133,19 +135,20 @@ export class SwirlPopover {
|
|
|
133
135
|
* Open the popover.
|
|
134
136
|
* @returns
|
|
135
137
|
*/
|
|
136
|
-
async open() {
|
|
137
|
-
|
|
138
|
+
async open(triggerEl) {
|
|
139
|
+
this.triggerEl = triggerEl || this.triggerEl;
|
|
140
|
+
if (this.active || !Boolean(this.triggerEl)) {
|
|
138
141
|
return;
|
|
139
142
|
}
|
|
140
143
|
this.adjustWidth();
|
|
141
144
|
this.active = true;
|
|
142
|
-
this.updateFocusableChildren();
|
|
143
145
|
this.updateTriggerAttributes();
|
|
146
|
+
const focusableChildren = this.getFocusableChildren();
|
|
144
147
|
requestAnimationFrame(async () => {
|
|
145
148
|
await this.reposition();
|
|
146
149
|
this.popoverOpen.emit({ position: this.position });
|
|
147
|
-
if (
|
|
148
|
-
|
|
150
|
+
if (focusableChildren.length > 0) {
|
|
151
|
+
focusableChildren[0].focus();
|
|
149
152
|
}
|
|
150
153
|
else {
|
|
151
154
|
this.contentContainer.focus();
|
|
@@ -153,12 +156,16 @@ export class SwirlPopover {
|
|
|
153
156
|
if (this.disableAutoUpdate) {
|
|
154
157
|
this.disableAutoUpdate();
|
|
155
158
|
}
|
|
156
|
-
this.disableAutoUpdate = autoUpdate(this.triggerEl, this.contentContainer, this.reposition);
|
|
159
|
+
this.disableAutoUpdate = autoUpdate(this.triggerEl, this.contentContainer, () => this.reposition());
|
|
157
160
|
this.scrollContainer.scrollTop = 0;
|
|
158
161
|
this.lockBodyScroll();
|
|
159
162
|
});
|
|
160
163
|
}
|
|
161
164
|
connectTrigger() {
|
|
165
|
+
if (!Boolean(this.trigger)) {
|
|
166
|
+
this.triggerEl = undefined;
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
162
169
|
this.triggerEl =
|
|
163
170
|
typeof this.trigger === "string"
|
|
164
171
|
? querySelectorAllDeep(this.triggerContainer || document.body, `#${this.trigger}`)[0]
|
|
@@ -171,10 +178,10 @@ export class SwirlPopover {
|
|
|
171
178
|
});
|
|
172
179
|
}
|
|
173
180
|
getNativeTriggerElement() {
|
|
174
|
-
var _a, _b, _c;
|
|
175
|
-
return this.triggerEl.tagName.startsWith("SWIRL-")
|
|
176
|
-
? (((
|
|
177
|
-
((
|
|
181
|
+
var _a, _b, _c, _d;
|
|
182
|
+
return ((_a = this.triggerEl) === null || _a === void 0 ? void 0 : _a.tagName.startsWith("SWIRL-"))
|
|
183
|
+
? (((_b = this.triggerEl) === null || _b === void 0 ? void 0 : _b.children[0]) ||
|
|
184
|
+
((_d = (_c = this.triggerEl) === null || _c === void 0 ? void 0 : _c.shadowRoot) === null || _d === void 0 ? void 0 : _d.children[0]) ||
|
|
178
185
|
this.triggerEl)
|
|
179
186
|
: this.triggerEl;
|
|
180
187
|
}
|
|
@@ -183,12 +190,12 @@ export class SwirlPopover {
|
|
|
183
190
|
return;
|
|
184
191
|
}
|
|
185
192
|
const nativeTriggerEl = this.getNativeTriggerElement();
|
|
186
|
-
nativeTriggerEl.setAttribute("aria-controls", this.
|
|
193
|
+
nativeTriggerEl.setAttribute("aria-controls", this.el.id);
|
|
187
194
|
nativeTriggerEl.setAttribute("aria-expanded", String(this.active));
|
|
188
195
|
nativeTriggerEl.setAttribute("aria-haspopup", "dialog");
|
|
189
196
|
}
|
|
190
|
-
|
|
191
|
-
|
|
197
|
+
getFocusableChildren() {
|
|
198
|
+
return querySelectorAllDeep(this.el, '[role="menuitem"], [role="listbox"]');
|
|
192
199
|
}
|
|
193
200
|
adjustWidth() {
|
|
194
201
|
let useContainerWidth = this.useContainerWidth;
|
|
@@ -235,7 +242,7 @@ export class SwirlPopover {
|
|
|
235
242
|
"popover--fullscreen-bottom-sheet": this.fullscreenBottomSheet,
|
|
236
243
|
"popover--inactive": !this.active,
|
|
237
244
|
});
|
|
238
|
-
return (h(Host,
|
|
245
|
+
return (h(Host, null, h("div", { class: className, onKeyDown: this.onKeydown }, h("div", { "aria-hidden": !this.active ? "true" : "false", "aria-label": this.label, class: "popover__content", part: "popover__content", role: "dialog", ref: (el) => (this.contentContainer = el), style: {
|
|
239
246
|
top: Boolean(this.position) ? `${(_b = this.position) === null || _b === void 0 ? void 0 : _b.y}px` : "",
|
|
240
247
|
left: Boolean(this.position) ? `${(_c = this.position) === null || _c === void 0 ? void 0 : _c.x}px` : "",
|
|
241
248
|
}, tabindex: "-1" }, h("span", { class: "popover__handle" }), h("div", { class: "popover__scroll-container", ref: (el) => (this.scrollContainer = el), style: {
|
|
@@ -409,23 +416,6 @@ export class SwirlPopover {
|
|
|
409
416
|
"reflect": false,
|
|
410
417
|
"defaultValue": "\"bottom-start\""
|
|
411
418
|
},
|
|
412
|
-
"popoverId": {
|
|
413
|
-
"type": "string",
|
|
414
|
-
"mutable": false,
|
|
415
|
-
"complexType": {
|
|
416
|
-
"original": "string",
|
|
417
|
-
"resolved": "string",
|
|
418
|
-
"references": {}
|
|
419
|
-
},
|
|
420
|
-
"required": true,
|
|
421
|
-
"optional": false,
|
|
422
|
-
"docs": {
|
|
423
|
-
"tags": [],
|
|
424
|
-
"text": ""
|
|
425
|
-
},
|
|
426
|
-
"attribute": "popover-id",
|
|
427
|
-
"reflect": false
|
|
428
|
-
},
|
|
429
419
|
"trigger": {
|
|
430
420
|
"type": "string",
|
|
431
421
|
"mutable": false,
|
|
@@ -438,8 +428,8 @@ export class SwirlPopover {
|
|
|
438
428
|
}
|
|
439
429
|
}
|
|
440
430
|
},
|
|
441
|
-
"required":
|
|
442
|
-
"optional":
|
|
431
|
+
"required": false,
|
|
432
|
+
"optional": true,
|
|
443
433
|
"docs": {
|
|
444
434
|
"tags": [],
|
|
445
435
|
"text": ""
|
|
@@ -553,11 +543,17 @@ export class SwirlPopover {
|
|
|
553
543
|
},
|
|
554
544
|
"open": {
|
|
555
545
|
"complexType": {
|
|
556
|
-
"signature": "() => Promise<void>",
|
|
557
|
-
"parameters": [
|
|
546
|
+
"signature": "(triggerEl?: HTMLElement) => Promise<void>",
|
|
547
|
+
"parameters": [{
|
|
548
|
+
"tags": [],
|
|
549
|
+
"text": ""
|
|
550
|
+
}],
|
|
558
551
|
"references": {
|
|
559
552
|
"Promise": {
|
|
560
553
|
"location": "global"
|
|
554
|
+
},
|
|
555
|
+
"HTMLElement": {
|
|
556
|
+
"location": "global"
|
|
561
557
|
}
|
|
562
558
|
},
|
|
563
559
|
"return": "Promise<void>"
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { newSpecPage } from "@stencil/core/testing";
|
|
2
2
|
import { SwirlPopover } from "./swirl-popover";
|
|
3
|
+
import { SwirlPopoverTrigger } from "../swirl-popover-trigger/swirl-popover-trigger";
|
|
3
4
|
describe("swirl-popover", () => {
|
|
4
5
|
const template = `
|
|
5
6
|
<div>
|
|
6
|
-
<
|
|
7
|
-
|
|
7
|
+
<swirl-popover-trigger popover="popover">
|
|
8
|
+
<button id="trigger">Trigger popover</button>
|
|
9
|
+
</swirl-popover-trigger>
|
|
10
|
+
<swirl-popover label="Popover" id="popover">
|
|
8
11
|
<div>Content</div>
|
|
9
12
|
</swirl-popover>
|
|
10
13
|
</div>
|
|
@@ -19,13 +22,15 @@ describe("swirl-popover", () => {
|
|
|
19
22
|
});
|
|
20
23
|
it("renders the trigger and content", async () => {
|
|
21
24
|
const page = await newSpecPage({
|
|
22
|
-
components: [SwirlPopover],
|
|
25
|
+
components: [SwirlPopover, SwirlPopoverTrigger],
|
|
23
26
|
html: template,
|
|
24
27
|
});
|
|
25
28
|
expect(page.body).toEqualHtml(`
|
|
26
29
|
<div>
|
|
27
|
-
<
|
|
28
|
-
|
|
30
|
+
<swirl-popover-trigger popover="popover">
|
|
31
|
+
<button aria-controls="popover" aria-expanded="false" aria-haspopup="dialog" id="trigger">Trigger popover</button>
|
|
32
|
+
</swirl-popover-trigger>
|
|
33
|
+
<swirl-popover id="popover" label="Popover">
|
|
29
34
|
<mock:shadow-root>
|
|
30
35
|
<div class="popover popover--animation-scale-in-xy popover--inactive popover--placement-undefined">
|
|
31
36
|
<div aria-hidden="true" aria-label="Popover" class="popover__content" part="popover__content" role="dialog" tabindex="-1">
|
|
@@ -45,18 +50,20 @@ describe("swirl-popover", () => {
|
|
|
45
50
|
});
|
|
46
51
|
it("opens on click and closes on blur/esc", async () => {
|
|
47
52
|
const page = await newSpecPage({
|
|
48
|
-
components: [SwirlPopover],
|
|
53
|
+
components: [SwirlPopover, SwirlPopoverTrigger],
|
|
49
54
|
html: template,
|
|
50
55
|
});
|
|
51
56
|
function isOpen() {
|
|
52
|
-
return !page.
|
|
53
|
-
.querySelector("
|
|
57
|
+
return !page.doc
|
|
58
|
+
.querySelector("swirl-popover")
|
|
59
|
+
.shadowRoot.querySelector(".popover")
|
|
54
60
|
.classList.contains("popover--inactive");
|
|
55
61
|
}
|
|
56
62
|
expect(isOpen()).toBeFalsy();
|
|
57
63
|
// click trigger
|
|
58
|
-
const trigger = page.
|
|
64
|
+
const trigger = page.root;
|
|
59
65
|
trigger.click();
|
|
66
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
60
67
|
await page.waitForChanges();
|
|
61
68
|
expect(isOpen()).toBeTruthy();
|
|
62
69
|
// blur popover
|
|
@@ -66,11 +73,13 @@ describe("swirl-popover", () => {
|
|
|
66
73
|
expect(isOpen()).toBeFalsy();
|
|
67
74
|
// re-open popover
|
|
68
75
|
trigger.click();
|
|
76
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
69
77
|
await page.waitForChanges();
|
|
70
78
|
expect(isOpen()).toBeTruthy();
|
|
71
79
|
// close via escape key
|
|
72
|
-
page.
|
|
73
|
-
.querySelector("
|
|
80
|
+
page.doc
|
|
81
|
+
.querySelector("swirl-popover")
|
|
82
|
+
.shadowRoot.querySelector(".popover")
|
|
74
83
|
.dispatchEvent(new KeyboardEvent("keydown", { code: "Escape" }));
|
|
75
84
|
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
76
85
|
await page.waitForChanges();
|
|
@@ -13,7 +13,7 @@ export default {
|
|
|
13
13
|
},
|
|
14
14
|
},
|
|
15
15
|
trigger: {
|
|
16
|
-
description: "ID of the trigger element or the trigger DOM element.",
|
|
16
|
+
description: "**Deprecated! Please use the swirl-popover-trigger component instead.** ID of the trigger element or the trigger DOM element.",
|
|
17
17
|
control: {
|
|
18
18
|
type: "text",
|
|
19
19
|
},
|
|
@@ -31,34 +31,18 @@ export default {
|
|
|
31
31
|
parameters: {
|
|
32
32
|
docs: {
|
|
33
33
|
page: Docs,
|
|
34
|
-
source: {
|
|
35
|
-
code: `<swirl-button id="trigger" label="Trigger"></swirl-button>
|
|
36
|
-
|
|
37
|
-
<swirl-popover label="Popover" popover-id="popover" trigger="trigger">
|
|
38
|
-
<swirl-action-list>
|
|
39
|
-
<swirl-action-list-section label="Section 1">
|
|
40
|
-
<swirl-action-list-item icon="<swirl-icon-mention></swirl-icon-mention>" label="Action item 1"></swirl-action-list-item>
|
|
41
|
-
<swirl-action-list-item icon="<swirl-icon-mention></swirl-icon-mention>" label="Action item 2"></swirl-action-list-item>
|
|
42
|
-
<swirl-action-list-item icon="<swirl-icon-mention></swirl-icon-mention>" label="Action item 3"></swirl-action-list-item>
|
|
43
|
-
</swirl-action-list-section>
|
|
44
|
-
<swirl-action-list-section label="Section 2">
|
|
45
|
-
<swirl-action-list-item icon="<swirl-icon-mention></swirl-icon-mention>" label="Action item 1"></swirl-action-list-item>
|
|
46
|
-
<swirl-action-list-item icon="<swirl-icon-mention></swirl-icon-mention>" label="Action item 2"></swirl-action-list-item>
|
|
47
|
-
<swirl-action-list-item icon="<swirl-icon-mention></swirl-icon-mention>" label="Action item 3"></swirl-action-list-item>
|
|
48
|
-
</swirl-action-list-section>
|
|
49
|
-
</swirl-action-list>
|
|
50
|
-
</swirl-popover>`,
|
|
51
|
-
},
|
|
52
34
|
},
|
|
53
35
|
},
|
|
54
36
|
title: "Components/SwirlPopover",
|
|
55
37
|
};
|
|
56
38
|
const Template = (args) => {
|
|
57
39
|
const container = document.createElement("div");
|
|
58
|
-
const trigger = document.createElement("swirl-
|
|
40
|
+
const trigger = document.createElement("swirl-popover-trigger");
|
|
59
41
|
const element = generateStoryElement("swirl-popover", args);
|
|
60
|
-
trigger.
|
|
61
|
-
trigger.
|
|
42
|
+
trigger.setAttribute("popover", "popover");
|
|
43
|
+
trigger.innerHTML = `
|
|
44
|
+
<swirl-button label="Trigger popover"></swirl-button>
|
|
45
|
+
`;
|
|
62
46
|
element.innerHTML = `
|
|
63
47
|
<swirl-action-list>
|
|
64
48
|
<swirl-action-list-section label="Section 1">
|
|
@@ -73,7 +57,7 @@ const Template = (args) => {
|
|
|
73
57
|
</swirl-action-list-section>
|
|
74
58
|
</swirl-action-list>
|
|
75
59
|
`;
|
|
76
|
-
container.append(trigger, element);
|
|
60
|
+
container.append("\n ", trigger, "\n ", element);
|
|
77
61
|
element.addEventListener("click", (event) => {
|
|
78
62
|
const target = event.target;
|
|
79
63
|
if ((target === null || target === void 0 ? void 0 : target.tagName) === "SWIRL-ACTION-LIST-ITEM") {
|
|
@@ -84,7 +68,6 @@ const Template = (args) => {
|
|
|
84
68
|
};
|
|
85
69
|
export const SwirlPopover = Template.bind({});
|
|
86
70
|
SwirlPopover.args = {
|
|
71
|
+
id: "popover",
|
|
87
72
|
label: "Popover",
|
|
88
|
-
popoverId: "popover",
|
|
89
|
-
trigger: "trigger",
|
|
90
73
|
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { h, Host } from "@stencil/core";
|
|
2
|
+
export class SwirlPopoverTrigger {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.popoverOpen = false;
|
|
5
|
+
this.onClick = (event) => {
|
|
6
|
+
event.stopPropagation();
|
|
7
|
+
const popoverEl = this.getPopoverEl();
|
|
8
|
+
if (!Boolean(popoverEl)) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (this.popoverOpen) {
|
|
12
|
+
popoverEl.close();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const triggerEl = this.getTriggerEl();
|
|
16
|
+
if (!Boolean(triggerEl)) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
popoverEl.open(triggerEl);
|
|
20
|
+
popoverEl.addEventListener("popoverOpen", () => {
|
|
21
|
+
this.popoverOpen = true;
|
|
22
|
+
this.updateTriggerElAriaAttributes(true);
|
|
23
|
+
}, { once: true });
|
|
24
|
+
popoverEl.addEventListener("popoverClose", () => {
|
|
25
|
+
this.popoverOpen = false;
|
|
26
|
+
this.updateTriggerElAriaAttributes(false);
|
|
27
|
+
}, { once: true });
|
|
28
|
+
};
|
|
29
|
+
this.updateTriggerElAriaAttributes = (open) => {
|
|
30
|
+
var _a;
|
|
31
|
+
if (!this.setAriaAttributes) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const triggerEl = this.getTriggerEl();
|
|
35
|
+
const popoverId = typeof this.popover === "string" ? this.popover : (_a = this.popover) === null || _a === void 0 ? void 0 : _a.id;
|
|
36
|
+
if (triggerEl.tagName.startsWith("SWIRL-")) {
|
|
37
|
+
triggerEl.setAttribute("swirl-aria-controls", popoverId);
|
|
38
|
+
triggerEl.setAttribute("swirl-aria-expanded", String(open || "false"));
|
|
39
|
+
triggerEl.setAttribute("swirl-aria-haspopup", "dialog");
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
triggerEl.setAttribute("aria-controls", popoverId);
|
|
43
|
+
triggerEl.setAttribute("aria-expanded", String(open || "false"));
|
|
44
|
+
triggerEl.setAttribute("aria-haspopup", "dialog");
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
this.popover = undefined;
|
|
48
|
+
this.setAriaAttributes = true;
|
|
49
|
+
}
|
|
50
|
+
componentDidLoad() {
|
|
51
|
+
this.updateTriggerElAriaAttributes();
|
|
52
|
+
}
|
|
53
|
+
watchPopover() {
|
|
54
|
+
this.updateTriggerElAriaAttributes();
|
|
55
|
+
}
|
|
56
|
+
getPopoverEl() {
|
|
57
|
+
return typeof this.popover === "string"
|
|
58
|
+
? document.querySelector(`#${this.popover}`)
|
|
59
|
+
: this.popover;
|
|
60
|
+
}
|
|
61
|
+
getTriggerEl() {
|
|
62
|
+
if (this.el.children.length !== 1) {
|
|
63
|
+
console.warn('[Swirl] The "swirl-popover-trigger" component expects exactly one child element.');
|
|
64
|
+
}
|
|
65
|
+
return this.el.children[0];
|
|
66
|
+
}
|
|
67
|
+
render() {
|
|
68
|
+
return (h(Host, { onClick: this.onClick }, h("slot", null)));
|
|
69
|
+
}
|
|
70
|
+
static get is() { return "swirl-popover-trigger"; }
|
|
71
|
+
static get encapsulation() { return "scoped"; }
|
|
72
|
+
static get originalStyleUrls() {
|
|
73
|
+
return {
|
|
74
|
+
"$": ["swirl-popover-trigger.css"]
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
static get styleUrls() {
|
|
78
|
+
return {
|
|
79
|
+
"$": ["swirl-popover-trigger.css"]
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
static get properties() {
|
|
83
|
+
return {
|
|
84
|
+
"popover": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"mutable": false,
|
|
87
|
+
"complexType": {
|
|
88
|
+
"original": "string | HTMLSwirlPopoverElement",
|
|
89
|
+
"resolved": "HTMLSwirlPopoverElement | string",
|
|
90
|
+
"references": {
|
|
91
|
+
"HTMLSwirlPopoverElement": {
|
|
92
|
+
"location": "global"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"required": true,
|
|
97
|
+
"optional": false,
|
|
98
|
+
"docs": {
|
|
99
|
+
"tags": [],
|
|
100
|
+
"text": ""
|
|
101
|
+
},
|
|
102
|
+
"attribute": "popover",
|
|
103
|
+
"reflect": false
|
|
104
|
+
},
|
|
105
|
+
"setAriaAttributes": {
|
|
106
|
+
"type": "boolean",
|
|
107
|
+
"mutable": false,
|
|
108
|
+
"complexType": {
|
|
109
|
+
"original": "boolean",
|
|
110
|
+
"resolved": "boolean",
|
|
111
|
+
"references": {}
|
|
112
|
+
},
|
|
113
|
+
"required": false,
|
|
114
|
+
"optional": true,
|
|
115
|
+
"docs": {
|
|
116
|
+
"tags": [],
|
|
117
|
+
"text": ""
|
|
118
|
+
},
|
|
119
|
+
"attribute": "set-aria-attributes",
|
|
120
|
+
"reflect": false,
|
|
121
|
+
"defaultValue": "true"
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
static get elementRef() { return "el"; }
|
|
126
|
+
static get watchers() {
|
|
127
|
+
return [{
|
|
128
|
+
"propName": "popover",
|
|
129
|
+
"methodName": "watchPopover"
|
|
130
|
+
}];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { newSpecPage } from "@stencil/core/testing";
|
|
2
|
+
import { SwirlPopoverTrigger } from "./swirl-popover-trigger";
|
|
3
|
+
import { SwirlButton } from "../swirl-button/swirl-button";
|
|
4
|
+
describe("swirl-popover-trigger", () => {
|
|
5
|
+
it("renders its trigger element and adds aria attributes", async () => {
|
|
6
|
+
const page = await newSpecPage({
|
|
7
|
+
components: [SwirlPopoverTrigger, SwirlButton],
|
|
8
|
+
html: `
|
|
9
|
+
<swirl-popover-trigger popover="popover">
|
|
10
|
+
<swirl-button label="trigger"></swirl-button>
|
|
11
|
+
</swirl-popover-trigger>
|
|
12
|
+
`,
|
|
13
|
+
});
|
|
14
|
+
expect(page.root).toEqualHtml(`
|
|
15
|
+
<swirl-popover-trigger popover="popover">
|
|
16
|
+
<swirl-button label="trigger" swirl-aria-controls="popover" swirl-aria-expanded="false" swirl-aria-haspopup="dialog">
|
|
17
|
+
<button aria-controls="popover" aria-expanded="false" aria-haspopup="dialog" class="button button--icon-position-start button--intent-default button--size-m button--variant-ghost" type="button">
|
|
18
|
+
<span class="button__label">
|
|
19
|
+
trigger
|
|
20
|
+
</span>
|
|
21
|
+
</button>
|
|
22
|
+
</swirl-button>
|
|
23
|
+
</swirl-popover-trigger>
|
|
24
|
+
`);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { generateStoryElement } from "../../utils";
|
|
2
|
+
import Docs from "./swirl-popover-trigger.mdx";
|
|
3
|
+
export default {
|
|
4
|
+
argTypes: {
|
|
5
|
+
popover: {
|
|
6
|
+
description: "ID of a popover element or a reference to a DOM element of type HTMLSwirlPopoverElement.",
|
|
7
|
+
control: {
|
|
8
|
+
type: "text",
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
component: "swirl-popover-trigger",
|
|
13
|
+
tags: ["autodocs"],
|
|
14
|
+
parameters: {
|
|
15
|
+
docs: {
|
|
16
|
+
page: Docs,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
title: "Components/SwirlPopoverTrigger",
|
|
20
|
+
};
|
|
21
|
+
const Template = (args) => {
|
|
22
|
+
const container = document.createElement("swirl-stack");
|
|
23
|
+
const element = generateStoryElement("swirl-popover-trigger", args);
|
|
24
|
+
const secondTrigger = generateStoryElement("swirl-popover-trigger", args);
|
|
25
|
+
const popover = document.createElement("swirl-popover");
|
|
26
|
+
container.orientation = "horizontal";
|
|
27
|
+
container.spacing = "16";
|
|
28
|
+
popover.label = "Popover";
|
|
29
|
+
popover.id = "popover";
|
|
30
|
+
popover.placement = "bottom-start";
|
|
31
|
+
popover.innerHTML = `
|
|
32
|
+
<swirl-box padding="12">
|
|
33
|
+
<swirl-text size="sm">Popover</swirl-text>
|
|
34
|
+
</swirl-box>
|
|
35
|
+
`;
|
|
36
|
+
element.innerHTML = `
|
|
37
|
+
<swirl-button label="Trigger element" variant="flat"></swirl-button>
|
|
38
|
+
`;
|
|
39
|
+
secondTrigger.innerHTML = `
|
|
40
|
+
<swirl-button label="Second trigger, same popover" variant="flat"></swirl-button>
|
|
41
|
+
`;
|
|
42
|
+
container.append("\n ", element, "\n ", secondTrigger, "\n ", popover, "\n");
|
|
43
|
+
return container;
|
|
44
|
+
};
|
|
45
|
+
export const SwirlPopoverTrigger = Template.bind({});
|
|
46
|
+
SwirlPopoverTrigger.args = {
|
|
47
|
+
popover: "popover",
|
|
48
|
+
};
|
|
@@ -223,6 +223,13 @@
|
|
|
223
223
|
transform: translateY(-50%);
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
+
.resource-list-item__control {
|
|
227
|
+
position: absolute;
|
|
228
|
+
top: 50%;
|
|
229
|
+
right: var(--s-space-16);
|
|
230
|
+
transform: translateY(-50%);
|
|
231
|
+
}
|
|
232
|
+
|
|
226
233
|
.resource-list-item__checkbox {
|
|
227
234
|
position: absolute;
|
|
228
235
|
top: 50%;
|
|
@@ -2,6 +2,7 @@ import { h, Host, } from "@stencil/core";
|
|
|
2
2
|
import classnames from "classnames";
|
|
3
3
|
import { getDesktopMediaQuery } from "../../utils";
|
|
4
4
|
/**
|
|
5
|
+
* @slot control - Used to add a menu button to the item
|
|
5
6
|
* @slot media - Media displayed inside the item (e.g. swirl-avatar)
|
|
6
7
|
*/
|
|
7
8
|
export class SwirlResourceListItem {
|
|
@@ -56,6 +57,9 @@ export class SwirlResourceListItem {
|
|
|
56
57
|
this.forceIconProps(this.desktopMediaQuery.matches);
|
|
57
58
|
this.updateIconSize(this.desktopMediaQuery.matches);
|
|
58
59
|
this.desktopMediaQuery.onchange = this.desktopMediaQueryHandler;
|
|
60
|
+
if (Boolean(this.menuTriggerId)) {
|
|
61
|
+
console.warn('[Swirl] The "menu-trigger-id" prop of swirl-resource-list-item is deprecated and will be removed with the next major release. Please use the "control" slot to add a menu button instead. https://swirl-storybook.flip-app.dev/?path=/docs/components-swirlresourcelistitem--docs');
|
|
62
|
+
}
|
|
59
63
|
}
|
|
60
64
|
disconnectedCallback() {
|
|
61
65
|
var _a, _b;
|
|
@@ -83,9 +87,9 @@ export class SwirlResourceListItem {
|
|
|
83
87
|
? "a"
|
|
84
88
|
: "button";
|
|
85
89
|
const disabled = this.disabled && !Boolean(this.href);
|
|
86
|
-
const hasMenu = Boolean(this.menuTriggerId);
|
|
90
|
+
const hasMenu = Boolean(this.menuTriggerId) || this.el.querySelector("[slot='control']");
|
|
87
91
|
const href = this.interactive && Boolean(this.href) ? this.href : undefined;
|
|
88
|
-
const showMenu =
|
|
92
|
+
const showMenu = Boolean(this.menuTriggerId) && !Boolean(this.meta) && !this.selectable;
|
|
89
93
|
const showMeta = Boolean(this.meta) && !this.selectable;
|
|
90
94
|
const ariaChecked = this.selectable ? String(this.checked) : undefined;
|
|
91
95
|
const role = this.interactive && this.selectable ? "checkbox" : undefined;
|
|
@@ -99,7 +103,7 @@ export class SwirlResourceListItem {
|
|
|
99
103
|
"resource-list-item--interactive": this.interactive || this.selectable,
|
|
100
104
|
"resource-list-item--selectable": this.selectable,
|
|
101
105
|
});
|
|
102
|
-
return (h(Host, { role: "row" }, h("div", { class: className, role: "gridcell" }, h(Tag, { "aria-checked": ariaChecked, "aria-disabled": disabled ? "true" : undefined, "aria-labelledby": "label", class: "resource-list-item__content", href: href, disabled: disabled, onClick: this.onClick, part: "resource-list-item__content", role: role, tabIndex: 0 }, this.hasMedia && (h("span", { class: "resource-list-item__media" }, h("slot", { name: "media" }))), h("span", { class: "resource-list-item__label-container" }, h("span", { class: "resource-list-item__label", id: "label", innerHTML: this.label }), this.description && (h("span", { class: "resource-list-item__description" }, this.description)))), this.selectable && (h("span", { "aria-hidden": "true", class: "resource-list-item__checkbox" }, h("span", { class: "resource-list-item__checkbox-icon" }, this.checked && (h("swirl-icon-check-strong", null))))), showMeta && (h("span", { class: "resource-list-item__meta" }, this.meta)), showMenu && (h("swirl-button", { "aria-disabled": disabled ? "true" : undefined, class: "resource-list-item__menu-trigger", disabled: disabled, hideLabel: true, icon: "<swirl-icon-more-horizontal></swirl-icon-more-horizontal>",
|
|
106
|
+
return (h(Host, { role: "row" }, h("div", { class: className, role: "gridcell" }, h(Tag, { "aria-checked": ariaChecked, "aria-disabled": disabled ? "true" : undefined, "aria-labelledby": "label", class: "resource-list-item__content", href: href, disabled: disabled, onClick: this.onClick, part: "resource-list-item__content", role: role, tabIndex: 0 }, this.hasMedia && (h("span", { class: "resource-list-item__media" }, h("slot", { name: "media" }))), h("span", { class: "resource-list-item__label-container" }, h("span", { class: "resource-list-item__label", id: "label", innerHTML: this.label }), this.description && (h("span", { class: "resource-list-item__description" }, this.description)))), this.selectable && (h("span", { "aria-hidden": "true", class: "resource-list-item__checkbox" }, h("span", { class: "resource-list-item__checkbox-icon" }, this.checked && (h("swirl-icon-check-strong", null))))), showMeta && (h("span", { class: "resource-list-item__meta" }, this.meta)), h("span", { class: "resource-list-item__control" }, h("slot", { name: "control" })), showMenu && (h("swirl-popover-trigger", { popover: this.menuTriggerId }, h("swirl-button", { "aria-disabled": disabled ? "true" : undefined, class: "resource-list-item__menu-trigger", disabled: disabled, hideLabel: true, icon: "<swirl-icon-more-horizontal></swirl-icon-more-horizontal>", intent: "primary", label: this.menuTriggerLabel, onClick: this.onMenuTriggerClick })))), this.allowDrag && (h("button", { "aria-describedby": this.dragHandleDescription, "aria-label": `${this.dragHandleLabel} "${this.label}"`, class: "resource-list-item__drag-handle", onKeyDown: this.onDragHandleKeyDown, type: "button" }, h("swirl-icon-drag-handle", { size: this.iconSize })))));
|
|
103
107
|
}
|
|
104
108
|
static get is() { return "swirl-resource-list-item"; }
|
|
105
109
|
static get encapsulation() { return "scoped"; }
|