@fluid-topics/ft-popover 2.0.6 → 2.0.7
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 +21 -2
- package/build/define.js +2 -0
- package/build/ft-base-popover.d.ts +44 -0
- package/build/ft-base-popover.js +157 -0
- package/build/ft-popover.d.ts +18 -0
- package/build/ft-popover.js +67 -0
- package/build/ft-popover.light.js +326 -234
- package/build/ft-popover.min.js +352 -260
- package/build/ft-popover.properties.d.ts +3 -0
- package/build/ft-popover.properties.js +1 -0
- package/build/ft-popover.styles.d.ts +1 -0
- package/build/ft-popover.styles.js +65 -0
- package/build/ftds-popover.d.ts +17 -29
- package/build/ftds-popover.js +60 -167
- package/build/ftds-popover.properties.d.ts +2 -7
- package/build/index.d.ts +3 -0
- package/build/index.js +3 -0
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -3,12 +3,31 @@ A popover component.
|
|
|
3
3
|
## Install
|
|
4
4
|
|
|
5
5
|
```shell
|
|
6
|
-
npm install @fluid-topics/
|
|
7
|
-
yarn add @fluid-topics/
|
|
6
|
+
npm install @fluid-topics/ft-popover
|
|
7
|
+
yarn add @fluid-topics/ft-popover
|
|
8
8
|
```
|
|
9
9
|
|
|
10
10
|
## Usage
|
|
11
11
|
|
|
12
|
+
### ft-popover
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
import { html } from "lit"
|
|
16
|
+
import "@fluid-topics/ft-link"
|
|
17
|
+
import "@fluid-topics/ft-popover"
|
|
18
|
+
|
|
19
|
+
function render() {
|
|
20
|
+
return html`
|
|
21
|
+
<ft-popover>
|
|
22
|
+
Example popover content
|
|
23
|
+
</ft-popover>
|
|
24
|
+
`
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### ftds-popover
|
|
30
|
+
|
|
12
31
|
```typescript
|
|
13
32
|
import { html } from "lit"
|
|
14
33
|
import "@fluid-topics/ft-link"
|
package/build/define.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { customElement } from "@fluid-topics/ft-wc-utils";
|
|
2
2
|
import { FtdsPopover } from "./ftds-popover";
|
|
3
3
|
import { FtdsPopoverSection } from "./ftds-popover-section";
|
|
4
|
+
import { FtPopover } from "./ft-popover";
|
|
5
|
+
customElement("ft-popover")(FtPopover);
|
|
4
6
|
customElement("ftds-popover")(FtdsPopover);
|
|
5
7
|
customElement("ftds-popover-section")(FtdsPopoverSection);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Position } from "@fluid-topics/ft-tooltip";
|
|
2
|
+
import { FtLitElement } from "@fluid-topics/ft-wc-utils";
|
|
3
|
+
import { FtIcons } from "@fluid-topics/ft-icon";
|
|
4
|
+
import { DesignSystemFamily, DesignSystemSize } from "@fluid-topics/design-system-variables";
|
|
5
|
+
import { nothing, PropertyValues, TemplateResult } from "lit";
|
|
6
|
+
import { FtBaseButton } from "@fluid-topics/ft-button/build/ft-base-button";
|
|
7
|
+
export interface FtBasePopoverProperties {
|
|
8
|
+
opened?: boolean;
|
|
9
|
+
hidden?: boolean;
|
|
10
|
+
closeButtonLabel?: string;
|
|
11
|
+
openButtonLabel?: string;
|
|
12
|
+
openButtonTooltipPosition?: Position;
|
|
13
|
+
}
|
|
14
|
+
export declare abstract class FtBasePopover extends FtLitElement implements FtBasePopoverProperties {
|
|
15
|
+
heading: string;
|
|
16
|
+
closeButtonLabel: string;
|
|
17
|
+
openButtonIcon: FtIcons;
|
|
18
|
+
openButtonLabel: string;
|
|
19
|
+
openButtonTooltipPosition: Position;
|
|
20
|
+
opened: boolean;
|
|
21
|
+
hidden: boolean;
|
|
22
|
+
openButtonSize: DesignSystemSize;
|
|
23
|
+
openButtonFamily: DesignSystemFamily;
|
|
24
|
+
protected abstract openingButton?: FtBaseButton;
|
|
25
|
+
protected abstract closingButton?: FtBaseButton;
|
|
26
|
+
private popoverWrapper?;
|
|
27
|
+
protected abstract wrapperId: string;
|
|
28
|
+
protected abstract headingId: string;
|
|
29
|
+
protected abstract contentId: string;
|
|
30
|
+
protected maxWidth: import("@fluid-topics/ft-wc-utils").FtCssVariable;
|
|
31
|
+
protected abstract renderOpeningButton(): TemplateResult;
|
|
32
|
+
protected abstract renderClosingButton(): TemplateResult;
|
|
33
|
+
protected abstract renderFullContent(): TemplateResult;
|
|
34
|
+
protected abstract hideUnusedSlots(): void;
|
|
35
|
+
protected render(): typeof nothing | TemplateResult<1>;
|
|
36
|
+
protected renderPopover(): typeof nothing | TemplateResult<1>;
|
|
37
|
+
updated(properties: PropertyValues<FtBasePopover>): void;
|
|
38
|
+
close(): void;
|
|
39
|
+
open(): void;
|
|
40
|
+
protected closeAndFocusOpeningButton(): void;
|
|
41
|
+
private watchFocusIn;
|
|
42
|
+
private watchEscapeKey;
|
|
43
|
+
private positionWrapper;
|
|
44
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { computeOffsetAutoPosition, FtLitElement } from "@fluid-topics/ft-wc-utils";
|
|
8
|
+
import { property, query } from "lit/decorators.js";
|
|
9
|
+
import { FtIcons } from "@fluid-topics/ft-icon";
|
|
10
|
+
import { DesignSystemFamily, DesignSystemSize, } from "@fluid-topics/design-system-variables";
|
|
11
|
+
import { html, nothing } from "lit";
|
|
12
|
+
import { classMap } from "lit/directives/class-map.js";
|
|
13
|
+
import { ifDefined } from "lit/directives/if-defined.js";
|
|
14
|
+
import { FtCssVariableFactory } from "@fluid-topics/design-system-variables/build/FtCssVariables";
|
|
15
|
+
export class FtBasePopover extends FtLitElement {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(...arguments);
|
|
18
|
+
this.heading = "";
|
|
19
|
+
this.closeButtonLabel = "close info";
|
|
20
|
+
this.openButtonIcon = FtIcons.CIRCLE_QUESTION;
|
|
21
|
+
this.openButtonLabel = "more info";
|
|
22
|
+
this.openButtonTooltipPosition = "bottom";
|
|
23
|
+
this.opened = false;
|
|
24
|
+
this.hidden = false;
|
|
25
|
+
this.openButtonSize = DesignSystemSize.medium;
|
|
26
|
+
this.openButtonFamily = DesignSystemFamily.info;
|
|
27
|
+
this.maxWidth = FtCssVariableFactory.create("--ft-popover-max-width", "", "SIZE", "464px");
|
|
28
|
+
this.watchFocusIn = (event) => {
|
|
29
|
+
if (this.popoverWrapper && !event.composedPath().includes(this.popoverWrapper)) {
|
|
30
|
+
this.close();
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
this.watchEscapeKey = (event) => {
|
|
34
|
+
var _a;
|
|
35
|
+
if (event.key === "Escape") {
|
|
36
|
+
this.close();
|
|
37
|
+
(_a = this.openingButton) === null || _a === void 0 ? void 0 : _a.focus();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
render() {
|
|
42
|
+
const classes = {
|
|
43
|
+
opened: this.opened,
|
|
44
|
+
};
|
|
45
|
+
return this.hidden ? nothing : html `
|
|
46
|
+
<div part="root-container" class="${classMap(classes)}">
|
|
47
|
+
${this.renderOpeningButton()}
|
|
48
|
+
${this.renderPopover()}
|
|
49
|
+
</div>
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
renderPopover() {
|
|
53
|
+
return this.opened ? html `
|
|
54
|
+
<div part="popover-container">
|
|
55
|
+
<div part="overlay" @click=${this.close}></div>
|
|
56
|
+
<div id="${this.wrapperId}" part="wrapper" role="dialog"
|
|
57
|
+
aria-labelledby="${ifDefined(this.heading ? `${this.headingId}` : undefined)}"
|
|
58
|
+
aria-describedby="${this.contentId}">
|
|
59
|
+
<div part="closing-button-container">
|
|
60
|
+
${this.renderClosingButton()}
|
|
61
|
+
</div>
|
|
62
|
+
${this.renderFullContent()}
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
` : nothing;
|
|
66
|
+
}
|
|
67
|
+
updated(properties) {
|
|
68
|
+
super.updated(properties);
|
|
69
|
+
if (properties.has("opened")) {
|
|
70
|
+
if (this.opened) {
|
|
71
|
+
setTimeout(() => {
|
|
72
|
+
this.positionWrapper();
|
|
73
|
+
document.addEventListener("keydown", this.watchEscapeKey);
|
|
74
|
+
document.addEventListener("focusin", this.watchFocusIn);
|
|
75
|
+
}, 0);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
document.removeEventListener("keydown", this.watchEscapeKey);
|
|
79
|
+
document.removeEventListener("focusin", this.watchFocusIn);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
close() {
|
|
84
|
+
this.opened = false;
|
|
85
|
+
this.dispatchEvent(new CustomEvent("opened-changed", { detail: { opened: false } }));
|
|
86
|
+
}
|
|
87
|
+
open() {
|
|
88
|
+
this.opened = true;
|
|
89
|
+
this.dispatchEvent(new CustomEvent("opened-changed", { detail: { opened: true } }));
|
|
90
|
+
}
|
|
91
|
+
closeAndFocusOpeningButton() {
|
|
92
|
+
var _a, _b;
|
|
93
|
+
this.close();
|
|
94
|
+
(_a = this.openingButton) === null || _a === void 0 ? void 0 : _a.focus();
|
|
95
|
+
if (window.FluidTopicsA11yHints.isKeyboardNavigation) {
|
|
96
|
+
(_b = this.openingButton) === null || _b === void 0 ? void 0 : _b.showTooltip();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async positionWrapper() {
|
|
100
|
+
var _a, _b;
|
|
101
|
+
if (this.popoverWrapper) {
|
|
102
|
+
this.popoverWrapper.classList.remove("positioned");
|
|
103
|
+
this.popoverWrapper.style.left = "";
|
|
104
|
+
this.popoverWrapper.style.top = "";
|
|
105
|
+
if (this.openingButton) {
|
|
106
|
+
const allowedPlacements = [
|
|
107
|
+
"bottom-start",
|
|
108
|
+
"right-start",
|
|
109
|
+
"bottom-end",
|
|
110
|
+
"right-end",
|
|
111
|
+
"left-start",
|
|
112
|
+
"left-end",
|
|
113
|
+
"top-start",
|
|
114
|
+
"top-end"
|
|
115
|
+
];
|
|
116
|
+
const defaultPlacement = "bottom-start";
|
|
117
|
+
const options = { placement: defaultPlacement, allowedPlacements: allowedPlacements, maxWidthCssVariable: this.maxWidth };
|
|
118
|
+
const { x, y } = await computeOffsetAutoPosition(this.openingButton, this.popoverWrapper, options);
|
|
119
|
+
this.popoverWrapper.style.left = `${x}px`;
|
|
120
|
+
this.popoverWrapper.style.top = `${y}px`;
|
|
121
|
+
}
|
|
122
|
+
this.popoverWrapper.classList.add("positioned");
|
|
123
|
+
}
|
|
124
|
+
this.hideUnusedSlots();
|
|
125
|
+
(_a = this.closingButton) === null || _a === void 0 ? void 0 : _a.focus();
|
|
126
|
+
if (window.FluidTopicsA11yHints.isKeyboardNavigation) {
|
|
127
|
+
(_b = this.closingButton) === null || _b === void 0 ? void 0 : _b.showTooltip();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
__decorate([
|
|
132
|
+
property()
|
|
133
|
+
], FtBasePopover.prototype, "closeButtonLabel", void 0);
|
|
134
|
+
__decorate([
|
|
135
|
+
property()
|
|
136
|
+
], FtBasePopover.prototype, "openButtonIcon", void 0);
|
|
137
|
+
__decorate([
|
|
138
|
+
property()
|
|
139
|
+
], FtBasePopover.prototype, "openButtonLabel", void 0);
|
|
140
|
+
__decorate([
|
|
141
|
+
property()
|
|
142
|
+
], FtBasePopover.prototype, "openButtonTooltipPosition", void 0);
|
|
143
|
+
__decorate([
|
|
144
|
+
property({ type: Boolean })
|
|
145
|
+
], FtBasePopover.prototype, "opened", void 0);
|
|
146
|
+
__decorate([
|
|
147
|
+
property({ type: Boolean })
|
|
148
|
+
], FtBasePopover.prototype, "hidden", void 0);
|
|
149
|
+
__decorate([
|
|
150
|
+
property({ type: DesignSystemSize })
|
|
151
|
+
], FtBasePopover.prototype, "openButtonSize", void 0);
|
|
152
|
+
__decorate([
|
|
153
|
+
property({ type: DesignSystemFamily })
|
|
154
|
+
], FtBasePopover.prototype, "openButtonFamily", void 0);
|
|
155
|
+
__decorate([
|
|
156
|
+
query(`[part="wrapper"]`)
|
|
157
|
+
], FtBasePopover.prototype, "popoverWrapper", void 0);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FtBasePopover } from "./ft-base-popover";
|
|
2
|
+
import { FtPopoverProperties } from "./ft-popover.properties";
|
|
3
|
+
import { TemplateResult } from "lit";
|
|
4
|
+
import { ElementDefinitionsMap } from "@fluid-topics/ft-wc-utils";
|
|
5
|
+
import { FtButton } from "@fluid-topics/ft-button";
|
|
6
|
+
export declare class FtPopover extends FtBasePopover implements FtPopoverProperties {
|
|
7
|
+
static styles: import("lit").CSSResult;
|
|
8
|
+
static elementDefinitions: ElementDefinitionsMap;
|
|
9
|
+
protected openingButton?: FtButton;
|
|
10
|
+
protected closingButton?: FtButton;
|
|
11
|
+
protected wrapperId: string;
|
|
12
|
+
protected headingId: string;
|
|
13
|
+
protected contentId: string;
|
|
14
|
+
protected renderOpeningButton(): TemplateResult;
|
|
15
|
+
protected renderClosingButton(): TemplateResult;
|
|
16
|
+
protected renderFullContent(): TemplateResult;
|
|
17
|
+
protected hideUnusedSlots(): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { FtBasePopover } from "./ft-base-popover";
|
|
8
|
+
import { html } from "lit";
|
|
9
|
+
import { FtTypography, FtTypographyVariants } from "@fluid-topics/ft-typography";
|
|
10
|
+
import { FtButton } from "@fluid-topics/ft-button";
|
|
11
|
+
import { query } from "lit/decorators.js";
|
|
12
|
+
import { FtIcons } from "@fluid-topics/ft-icon";
|
|
13
|
+
import { ftPopoverStyles } from "./ft-popover.styles";
|
|
14
|
+
class FtPopover extends FtBasePopover {
|
|
15
|
+
constructor() {
|
|
16
|
+
super(...arguments);
|
|
17
|
+
this.wrapperId = "ft-popover-wrapper";
|
|
18
|
+
this.headingId = "ft-popover-heading";
|
|
19
|
+
this.contentId = "ft-popover-content";
|
|
20
|
+
}
|
|
21
|
+
renderOpeningButton() {
|
|
22
|
+
return html `
|
|
23
|
+
<ft-button @focusin=${this.close}
|
|
24
|
+
part="opening-button"
|
|
25
|
+
icon="${this.openButtonIcon}"
|
|
26
|
+
size="${this.openButtonSize}"
|
|
27
|
+
label="${this.openButtonLabel}"
|
|
28
|
+
tooltipposition="${this.openButtonTooltipPosition}"
|
|
29
|
+
aria-haspopup="true" aria-expanded="${this.opened}"
|
|
30
|
+
aria-controls="${this.wrapperId}"
|
|
31
|
+
@click=${this.open}>
|
|
32
|
+
</ft-button>
|
|
33
|
+
`;
|
|
34
|
+
}
|
|
35
|
+
renderClosingButton() {
|
|
36
|
+
return html `
|
|
37
|
+
<ft-button part="closing-button"
|
|
38
|
+
icon="${FtIcons.CLOSE}"
|
|
39
|
+
label="${this.closeButtonLabel}"
|
|
40
|
+
@click=${this.closeAndFocusOpeningButton}>
|
|
41
|
+
</ft-button>
|
|
42
|
+
`;
|
|
43
|
+
}
|
|
44
|
+
renderFullContent() {
|
|
45
|
+
return html `
|
|
46
|
+
<div id="ft-popover-content" part="content">
|
|
47
|
+
<ft-typography variant="${FtTypographyVariants.body2}">
|
|
48
|
+
<slot part="popover-content-slot"></slot>
|
|
49
|
+
</ft-typography>
|
|
50
|
+
</div>
|
|
51
|
+
`;
|
|
52
|
+
}
|
|
53
|
+
hideUnusedSlots() {
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
FtPopover.styles = ftPopoverStyles;
|
|
57
|
+
FtPopover.elementDefinitions = {
|
|
58
|
+
"ft-typography": FtTypography,
|
|
59
|
+
"ft-button": FtButton,
|
|
60
|
+
};
|
|
61
|
+
__decorate([
|
|
62
|
+
query(`[part="opening-button"]`)
|
|
63
|
+
], FtPopover.prototype, "openingButton", void 0);
|
|
64
|
+
__decorate([
|
|
65
|
+
query(`[part="closing-button"]`)
|
|
66
|
+
], FtPopover.prototype, "closingButton", void 0);
|
|
67
|
+
export { FtPopover };
|