@ribajs/bs5
Version:
Bootstrap 5 module for Riba.js
129 lines (103 loc) • 3.13 kB
text/typescript
import { Component, TemplateFunction } from "@ribajs/core";
import { Dropdown } from "../../services/dropdown.js";
import { Dropdown as BSDropdown } from "bootstrap";
import { JsxBs5DropdownProps } from "../../types/jsx/jsx-dropdown-props.js";
interface Scope extends Partial<BSDropdown.Options> {
toggle: Bs5DropdownComponent["toggle"];
show: Bs5DropdownComponent["show"];
hide: Bs5DropdownComponent["hide"];
update: Bs5DropdownComponent["update"];
isShown: boolean;
}
export class Bs5DropdownComponent extends Component {
public static tagName = "bs5-dropdown";
public scope: Scope = {
toggle: this.toggle,
show: this.show,
hide: this.hide,
update: this.update,
isShown: false,
};
public dropdown?: Dropdown;
protected toggler: HTMLElement | Bs5DropdownComponent | null = null;
static get observedAttributes(): (keyof JsxBs5DropdownProps)[] {
return [
"offset",
"boundary",
"reference",
"display",
"popper-config",
"auto-close",
];
}
constructor() {
super();
}
public isShown() {
// TODO: Do not access private methods
return (this.dropdown as any)?._isShown() || false;
}
public toggle(event: Event, ctx: Scope, el: any) {
if (!this.dropdown) {
throw new Error("Dropdown not ready!");
}
// Only call toggle if this is not called by the dropdown service itself which is the case on the toggler element
if (el !== this.toggler) {
this.dropdown.toggle();
}
}
public show() {
if (!this.dropdown) {
throw new Error("Dropdown not ready!");
}
this.dropdown.show();
}
public hide() {
if (!this.dropdown) {
throw new Error("Dropdown not ready!");
}
this.dropdown.hide();
}
public update() {
if (!this.dropdown) {
throw new Error("Dropdown not ready!");
}
this.dropdown.update();
}
protected connectedCallback() {
super.connectedCallback();
this.init(Bs5DropdownComponent.observedAttributes);
}
async afterBind() {
this.initDropdown();
this.addEventListeners();
await super.afterBind();
}
protected initDropdown() {
this.toggler = this.classList.contains("dropdown-toggle")
? this
: this.querySelector<HTMLElement>(".dropdown-toggle") || this;
// To detect this element as an dropdown by the bootstrap logic
this.toggler.dataset.bsToggle = "dropdown";
this.dropdown = new Dropdown(this.toggler, this.scope);
this.dropdown.hide();
this.scope.isShown = this.isShown();
}
protected _onShown() {
console.debug("onShown");
this.scope.isShown = this.isShown();
}
protected onShown = this._onShown.bind(this);
protected _onHidden() {
console.debug("onHidden");
this.scope.isShown = this.isShown();
}
protected onHidden = this._onHidden.bind(this);
protected addEventListeners() {
this.toggler?.addEventListener(Dropdown.EVENT_SHOWN, this.onShown);
this.toggler?.addEventListener(Dropdown.EVENT_HIDDEN, this.onHidden);
}
protected template(): ReturnType<TemplateFunction> {
return null;
}
}