UNPKG

@ribajs/bs5

Version:

Bootstrap 5 module for Riba.js

129 lines (103 loc) 3.13 kB
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; } }