@fluid-topics/ft-popover 2.0.37 → 2.1.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 CHANGED
@@ -12,8 +12,8 @@ yarn add @fluid-topics/ft-popover
12
12
  ### ft-popover
13
13
 
14
14
  ```typescript
15
- import { html } from "lit"
16
- import "@fluid-topics/ft-link"
15
+ import {html} from "lit"
16
+ import "@fluid-topics/ftds-link"
17
17
  import "@fluid-topics/ft-popover"
18
18
 
19
19
  function render() {
@@ -25,35 +25,3 @@ function render() {
25
25
  }
26
26
 
27
27
  ```
28
-
29
- ### ftds-popover
30
-
31
- ```typescript
32
- import { html } from "lit"
33
- import "@fluid-topics/ft-link"
34
- import "@fluid-topics/ft-popover"
35
-
36
- function render() {
37
- return html`
38
- <ftds-popover heading="Popover heading">
39
- Exemple popover content
40
- <ftds-link slot="link" href="" variant="body-2-medium" family="brand" underlined>Example popover link</ftds-link>
41
- </ftds-popover>
42
- `
43
- }
44
-
45
- function render() {
46
- return html`
47
- <ftds-popover>
48
- <ftds-popover-section slot="sections" heading="Popover section heading">
49
- Example popover section content
50
- <ftds-link slot="link">Example popover section link</ftds-link>
51
- </ftds-popover-section>
52
- <ftds-popover-section slot="sections">
53
- Other example popover section content
54
- </ftds-popover-section>
55
- </ftds-popover>
56
- `
57
- }
58
-
59
- ```
@@ -1,9 +1,5 @@
1
- import { FtdsPopover } from "./ftds-popover";
2
- import { FtdsPopoverSection } from "./ftds-popover-section";
3
1
  import { FtPopover } from "./ft-popover";
4
2
  declare const _default: {
5
3
  "ft-popover": typeof FtPopover;
6
- "ftds-popover": typeof FtdsPopover;
7
- "ftds-popover-section": typeof FtdsPopoverSection;
8
4
  };
9
5
  export default _default;
@@ -1,8 +1,4 @@
1
- import { FtdsPopover } from "./ftds-popover";
2
- import { FtdsPopoverSection } from "./ftds-popover-section";
3
1
  import { FtPopover } from "./ft-popover";
4
2
  export default {
5
3
  "ft-popover": FtPopover,
6
- "ftds-popover": FtdsPopover,
7
- "ftds-popover-section": FtdsPopoverSection,
8
4
  };
@@ -1,18 +1,40 @@
1
- import { FtBasePopover } from "./ft-base-popover";
1
+ import { Position } from "@fluid-topics/ft-tooltip";
2
+ import { ElementDefinitionsMap, FtLitElement } from "@fluid-topics/ft-wc-utils";
3
+ import { FtIcons } from "@fluid-topics/ft-icon";
4
+ import { nothing, PropertyValues } from "lit";
2
5
  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;
6
+ export declare class FtPopover extends FtLitElement implements FtPopoverProperties {
8
7
  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;
8
+ static styles: import("lit").CSSResult;
9
+ heading: string;
10
+ opened: boolean;
11
+ hidden: boolean;
12
+ closeButtonLabel: string;
13
+ openButtonLabel: string;
14
+ openButtonIcon: FtIcons;
15
+ openButtonTooltipPosition: Position;
16
+ private isTriggerSlotAssigned;
17
+ private openingButton?;
18
+ private closingButton?;
19
+ private popoverWrapper?;
20
+ private triggerSlot?;
21
+ private wrapperId;
22
+ private headingId;
23
+ private contentId;
24
+ protected maxWidth: import("@fluid-topics/design-system-variables").FtCssVariable;
25
+ private renderOpeningButton;
26
+ private renderClosingButton;
27
+ private renderFullContent;
28
+ get openingElement(): HTMLElement | undefined;
29
+ protected render(): typeof nothing | import("lit-html").TemplateResult<1>;
30
+ protected renderPopover(): typeof nothing | import("lit-html").TemplateResult<1>;
31
+ updated(properties: PropertyValues<FtPopover>): void;
32
+ close(): void;
33
+ open(): void;
34
+ protected closeAndFocusOpeningButton(): void;
35
+ private onTriggerSlotChange;
36
+ private onTriggerKeydown;
37
+ private watchFocusIn;
38
+ private watchEscapeKey;
39
+ private positionWrapper;
18
40
  }
@@ -4,26 +4,60 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
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
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
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";
7
+ import { computeOffsetAutoPosition, FtLitElement, } from "@fluid-topics/ft-wc-utils";
8
+ import { property, query, state, } from "lit/decorators.js";
12
9
  import { FtIcons } from "@fluid-topics/ft-icon";
10
+ import { html, nothing, } from "lit";
11
+ import { classMap } from "lit/directives/class-map.js";
12
+ import { ifDefined } from "lit/directives/if-defined.js";
13
+ import { FtCssVariableFactory } from "@fluid-topics/design-system-variables/build/FtCssVariables";
14
+ import { FtButton } from "@fluid-topics/ft-button";
13
15
  import { ftPopoverStyles } from "./ft-popover.styles";
14
- export class FtPopover extends FtBasePopover {
16
+ import { FtTypography, FtTypographyVariants, } from "@fluid-topics/ft-typography";
17
+ export class FtPopover extends FtLitElement {
15
18
  constructor() {
16
19
  super(...arguments);
20
+ this.heading = "";
21
+ this.opened = false;
22
+ this.hidden = false;
23
+ this.closeButtonLabel = "close info";
24
+ this.openButtonLabel = "more info";
25
+ this.openButtonIcon = FtIcons.CIRCLE_QUESTION;
26
+ this.openButtonTooltipPosition = "bottom";
27
+ this.isTriggerSlotAssigned = false;
17
28
  this.wrapperId = "ft-popover-wrapper";
18
29
  this.headingId = "ft-popover-heading";
19
30
  this.contentId = "ft-popover-content";
31
+ this.maxWidth = FtCssVariableFactory.create("--ft-popover-max-width", "", "SIZE", "464px");
32
+ this.onTriggerSlotChange = () => {
33
+ var _a, _b;
34
+ const assignedTrigger = (_b = (_a = this.triggerSlot) === null || _a === void 0 ? void 0 : _a.assignedElements()) !== null && _b !== void 0 ? _b : [];
35
+ this.isTriggerSlotAssigned = assignedTrigger.length > 0;
36
+ };
37
+ this.onTriggerKeydown = (event) => {
38
+ if (event.key === "Enter" || event.key === " ") {
39
+ event.preventDefault();
40
+ this.open();
41
+ }
42
+ };
43
+ this.watchFocusIn = (event) => {
44
+ if (this.popoverWrapper && !event.composedPath().includes(this.popoverWrapper)) {
45
+ this.close();
46
+ }
47
+ };
48
+ this.watchEscapeKey = (event) => {
49
+ var _a;
50
+ if (event.key === "Escape") {
51
+ this.close();
52
+ (_a = this.openingElement) === null || _a === void 0 ? void 0 : _a.focus();
53
+ }
54
+ };
20
55
  }
21
56
  renderOpeningButton() {
22
57
  return html `
23
58
  <ft-button @focusin=${this.close}
24
59
  part="opening-button"
25
60
  icon="${this.openButtonIcon}"
26
- size="${this.openButtonSize}"
27
61
  label="${this.openButtonLabel}"
28
62
  tooltipposition="${this.openButtonTooltipPosition}"
29
63
  aria-haspopup="true" aria-expanded="${this.opened}"
@@ -50,17 +84,146 @@ export class FtPopover extends FtBasePopover {
50
84
  </div>
51
85
  `;
52
86
  }
53
- hideUnusedSlots() {
87
+ get openingElement() {
88
+ var _a;
89
+ const assignedTrigger = (_a = this.triggerSlot) === null || _a === void 0 ? void 0 : _a.assignedElements();
90
+ if ((assignedTrigger === null || assignedTrigger === void 0 ? void 0 : assignedTrigger.length) && assignedTrigger[0] instanceof HTMLElement) {
91
+ return assignedTrigger[0];
92
+ }
93
+ return this.openingButton;
94
+ }
95
+ render() {
96
+ const classes = {
97
+ opened: this.opened,
98
+ };
99
+ return this.hidden ? nothing : html `
100
+ <div part="root-container" class="${classMap(classes)}">
101
+ <slot name="trigger"
102
+ @slotchange=${this.onTriggerSlotChange}
103
+ @click=${this.open}
104
+ @keydown=${this.onTriggerKeydown}
105
+ @focusin=${this.close}
106
+ ></slot>
107
+ ${this.isTriggerSlotAssigned ? nothing : this.renderOpeningButton()}
108
+ ${this.renderPopover()}
109
+ </div>
110
+ `;
111
+ }
112
+ renderPopover() {
113
+ return this.opened ? html `
114
+ <div part="popover-container">
115
+ <div part="overlay" @click=${this.close}></div>
116
+ <div id="${this.wrapperId}" part="wrapper" role="dialog"
117
+ aria-labelledby="${ifDefined(this.heading ? `${this.headingId}` : undefined)}"
118
+ aria-describedby="${this.contentId}">
119
+ <div part="closing-button-container">
120
+ ${this.renderClosingButton()}
121
+ </div>
122
+ ${this.renderFullContent()}
123
+ </div>
124
+ </div>
125
+ ` : nothing;
126
+ }
127
+ updated(properties) {
128
+ super.updated(properties);
129
+ if (properties.has("opened")) {
130
+ if (this.opened) {
131
+ setTimeout(() => {
132
+ this.positionWrapper();
133
+ document.addEventListener("keydown", this.watchEscapeKey);
134
+ document.addEventListener("focusin", this.watchFocusIn);
135
+ }, 0);
136
+ }
137
+ else {
138
+ document.removeEventListener("keydown", this.watchEscapeKey);
139
+ document.removeEventListener("focusin", this.watchFocusIn);
140
+ }
141
+ }
142
+ }
143
+ close() {
144
+ this.opened = false;
145
+ this.dispatchEvent(new CustomEvent("opened-changed", { detail: { opened: false } }));
146
+ }
147
+ open() {
148
+ this.opened = true;
149
+ this.dispatchEvent(new CustomEvent("opened-changed", { detail: { opened: true } }));
150
+ }
151
+ closeAndFocusOpeningButton() {
152
+ var _a;
153
+ this.close();
154
+ (_a = this.openingElement) === null || _a === void 0 ? void 0 : _a.focus();
155
+ if (window.FluidTopicsA11yHints.isKeyboardNavigation) {
156
+ if (this.openingElement instanceof FtButton) {
157
+ this.openingElement.showTooltip();
158
+ }
159
+ }
160
+ }
161
+ async positionWrapper() {
162
+ var _a, _b;
163
+ if (this.popoverWrapper) {
164
+ this.popoverWrapper.classList.remove("positioned");
165
+ this.popoverWrapper.style.left = "";
166
+ this.popoverWrapper.style.top = "";
167
+ if (this.openingElement) {
168
+ const allowedPlacements = [
169
+ "bottom-start",
170
+ "right-start",
171
+ "bottom-end",
172
+ "right-end",
173
+ "left-start",
174
+ "left-end",
175
+ "top-start",
176
+ "top-end",
177
+ ];
178
+ const defaultPlacement = "bottom-start";
179
+ const options = { placement: defaultPlacement, allowedPlacements: allowedPlacements, maxWidthCssVariable: this.maxWidth };
180
+ const { x, y } = await computeOffsetAutoPosition(this.openingElement, this.popoverWrapper, options);
181
+ this.popoverWrapper.style.left = `${x}px`;
182
+ this.popoverWrapper.style.top = `${y}px`;
183
+ }
184
+ this.popoverWrapper.classList.add("positioned");
185
+ }
186
+ (_a = this.closingButton) === null || _a === void 0 ? void 0 : _a.focus();
187
+ if (window.FluidTopicsA11yHints.isKeyboardNavigation) {
188
+ (_b = this.closingButton) === null || _b === void 0 ? void 0 : _b.showTooltip();
189
+ }
54
190
  }
55
191
  }
56
- FtPopover.styles = ftPopoverStyles;
57
192
  FtPopover.elementDefinitions = {
58
193
  "ft-typography": FtTypography,
59
194
  "ft-button": FtButton,
60
195
  };
196
+ FtPopover.styles = ftPopoverStyles;
197
+ __decorate([
198
+ property({ type: Boolean })
199
+ ], FtPopover.prototype, "opened", void 0);
200
+ __decorate([
201
+ property({ type: Boolean })
202
+ ], FtPopover.prototype, "hidden", void 0);
203
+ __decorate([
204
+ property()
205
+ ], FtPopover.prototype, "closeButtonLabel", void 0);
206
+ __decorate([
207
+ property()
208
+ ], FtPopover.prototype, "openButtonLabel", void 0);
209
+ __decorate([
210
+ property()
211
+ ], FtPopover.prototype, "openButtonIcon", void 0);
212
+ __decorate([
213
+ property()
214
+ ], FtPopover.prototype, "openButtonTooltipPosition", void 0);
215
+ __decorate([
216
+ state()
217
+ ], FtPopover.prototype, "isTriggerSlotAssigned", void 0);
61
218
  __decorate([
62
219
  query(`[part="opening-button"]`)
63
220
  ], FtPopover.prototype, "openingButton", void 0);
64
221
  __decorate([
65
222
  query(`[part="closing-button"]`)
66
223
  ], FtPopover.prototype, "closingButton", void 0);
224
+ __decorate([
225
+ query(`[part="wrapper"]`)
226
+ ], FtPopover.prototype, "popoverWrapper", void 0);
227
+ __decorate([
228
+ query(`slot[name="trigger"]`)
229
+ ], FtPopover.prototype, "triggerSlot", void 0);