Skip to content

Commit c073cda

Browse files
committed
add popovertarget mixin
1 parent 860a15f commit c073cda

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { LitElement } from 'lit';
2+
import { property } from 'lit/decorators.js';
3+
import { findAncestorByAttributeValue } from '../utils';
4+
5+
type Constructor<T = {}> = new (...args: any[]) => T;
6+
7+
export declare class PopoverTargetMixinInterface {
8+
/**
9+
* Set a popovertarget.
10+
* @type {string}
11+
* @attr
12+
* @default undefined
13+
*/
14+
public popoverContainerElement?: string;
15+
16+
/**
17+
* Toggle the popover.
18+
*/
19+
protected _togglePopover(): void;
20+
}
21+
22+
/**
23+
* This mixin provides popover target functionality to other components.
24+
*
25+
* @param {Object} superClass - superclass to be extended.
26+
* @mixin
27+
*/
28+
export const PopoverTargetMixin = <T extends Constructor<LitElement>>(
29+
superClass: T
30+
) => {
31+
/**
32+
* Popover target mixin class containing the popover target functionality.
33+
*/
34+
class PopoverTargetMixinClass extends superClass {
35+
/**
36+
* Set a popovertarget.
37+
* @type {string}
38+
* @attr
39+
* @default undefined
40+
*/
41+
@property({ type: String, attribute: 'popovertarget' })
42+
public popoverContainerElement?: string;
43+
44+
#popoverIsOpen = false;
45+
46+
constructor(...args: any[]) {
47+
super(...args);
48+
this.addEventListener('uui-popover-before-toggle', this.#popoverListener);
49+
}
50+
51+
protected _togglePopover = () => {
52+
if (!this.popoverContainerElement) return;
53+
54+
const popoverContainerElement = findAncestorByAttributeValue(
55+
this,
56+
'id',
57+
this.popoverContainerElement
58+
);
59+
if (!popoverContainerElement) return;
60+
61+
this.#popoverIsOpen
62+
? // @ts-ignore - This is part of the new popover API, but typescript doesn't recognize it yet.
63+
popoverContainerElement.hidePopover()
64+
: // @ts-ignore - This is part of the new popover API, but typescript doesn't recognize it yet.
65+
popoverContainerElement.showPopover();
66+
};
67+
68+
#popoverListener = (event: any) => {
69+
// Wait for the click event to finish before updating the popover state
70+
requestAnimationFrame(() => {
71+
this.#popoverIsOpen = event.detail.newState === 'open';
72+
});
73+
};
74+
}
75+
return PopoverTargetMixinClass as unknown as Constructor<PopoverTargetMixinInterface> &
76+
T;
77+
};

0 commit comments

Comments
 (0)