gd-bs
Version:
Bootstrap JavaScript, TypeScript and Web Components library.
173 lines (147 loc) • 5.55 kB
text/typescript
import { IFloatingUI } from "../floating-ui/types";
import { Button } from "../button";
import { Base } from "../base";
import { appendContent, setClassNames } from "../common";
import { FloatingUI, FloatingUIPlacements } from "../floating-ui";
import { IPopover, IPopoverProps } from "./types";
/**
* Popover Types
*/
export enum PopoverTypes {
Danger = 1,
Dark = 2,
Info = 3,
Light = 4,
LightBorder = 5,
Material = 6,
Primary = 7,
Secondary = 8,
Success = 9,
Translucent = 10,
Warning = 11
}
/**
* Popover Placements
*/
export { FloatingUIPlacements as PopoverPlacements }
/**
* Popover
*/
class _Popover extends Base<IPopoverProps> implements IPopover {
private _elContent: HTMLDivElement = null;
private _floatingUI: IFloatingUI = null;
// Constructor
constructor(props: IPopoverProps, template: string = "") {
super(template, props);
// Configure the collapse
this.configure();
// Configure the parent, if the target wasn't specified
this.props.target ? null : this.configureParent();
}
// Configure the card group
private configure() {
// See if we are targeting an element
let elPopover: HTMLElement = null;
if (this.props.target) {
// Set the popover to the target element
elPopover = this.props.target as HTMLElement;
// Ensure the attributes are set in the target element
elPopover.setAttribute("tabindex", "0");
// Update this element
this.el = elPopover as any;
} else {
// Create the button
let btnProps = this.props.btnProps || {};
btnProps.isLink = this.props.isDismissible ? true : false;
btnProps.tabIndex = btnProps.tabIndex || 0;
this.el = Button(btnProps).el;
}
// Create the content element
this._elContent = document.createElement("div");
this._elContent.classList.add("popover");
setClassNames(this._elContent, this.props.className);
this._elContent.innerHTML = '<div class="popover-header"></div><div class="popover-body"></div>';
appendContent(this._elContent.querySelector(".popover-header"), this.props.title);
setClassNames(this._elContent.querySelector(".popover-header"), this.props.classNameHeader);
appendContent(this._elContent.querySelector(".popover-body"), this.props.options?.content);
setClassNames(this._elContent.querySelector(".popover-body"), this.props.classNameBody);
// Create the floating ui
this._floatingUI = FloatingUI({
elContent: this._elContent,
elTarget: this.el,
options: {
...{ arrow: true, flip: true, shift: { padding: 5 }, trigger: "mouse" },
...this.props.options
},
placement: this.props.placement || FloatingUIPlacements.Top,
show: this.props.show,
theme: this.props.type
});
}
/**
* Public Interface
*/
// Disables the popover
disable() {
// Disable the target element
(this.el as HTMLButtonElement).disabled = true;
}
// Enables the popover
enable() {
// Enable the target element
(this.el as HTMLButtonElement).disabled = false;
}
// Hides the popover
hide() { this._floatingUI.hide(); }
// Determines if the popover is visible
get isVisible(): boolean { return this._floatingUI.isVisible; }
// The floating ui instand
get floatingUI() { return this._floatingUI; }
// Sets the popover body element
setBody(content: string | Element) {
let elBody: HTMLElement = this._elContent.querySelector(".popover-body");
if (elBody) {
// Clear the content
while (elBody.firstChild) { elBody.removeChild(elBody.firstChild); }
// Update the content
appendContent(elBody, content);
}
}
// Sets the tippy content
setContent(content: string | Element) {
// See if this is a string
if (typeof (content) === "string") {
// Set the content
this._elContent.innerHTML = content;
} else {
// Clear the content
while (this._elContent.firstChild) { this._elContent.removeChild(this._elContent.firstChild); }
// Append the content
appendContent(this._elContent, content);
}
}
// Sets the popover header element
setHeader(content: string | Element) {
let elHeader: HTMLElement = this._elContent.querySelector(".popover-header");
if (elHeader) {
// Clear the content
while (elHeader.firstChild) { elHeader.removeChild(elHeader.firstChild); }
// Update the content
appendContent(elHeader, content);
}
}
// Shows the popover
show() { this._floatingUI.show(); }
// Toggles the popover
toggle() {
// Toggle the element
if (this.isVisible) {
// Hide the element
this.hide();
} else {
// Show the element
this.show();
}
}
}
export const Popover = (props: IPopoverProps, template?: string): IPopover => { return new _Popover(props, template); }