UNPKG

@ribajs/bs5

Version:

Bootstrap 5 module for Riba.js

182 lines (159 loc) 4.74 kB
/** * This components is used to trigger a toggle event used in other components or parts of your project. This site itself uses the bs5-toggle-button to open or close the sidebar. * @attribute "target-id" (Required) The id with which the toggle event is triggered * @method toggle Triggeres the toggle event * @property state Can be 'hidden' or something else * @property isClosed Is true if the state is 'hidden' * @property targetId Passed attribute value, see `target-id` attribute */ import { Component, TemplateFunction, ScopeBase } from "@ribajs/core"; import { EventDispatcher } from "@ribajs/events"; import { hasChildNodesTrim } from "@ribajs/utils/src/dom.js"; import { JsxBs5ToggleButtonProps } from "../../types/index.js"; import { TOGGLE_BUTTON } from "../../constants/index.js"; type State = | "undefined" | "overlay-left" | "overlay-right" | "side-left" | "side-right" | "hidden" | "added" | "removed"; interface Scope extends ScopeBase { targetId?: string; toggle: Bs5ToggleButtonComponent["toggle"]; state: State; isActive: boolean; /** @deprecated use !isActive instead */ isClosed: boolean; } // TODO extend from Bs5ButtonComponent export class Bs5ToggleButtonComponent extends Component { static get observedAttributes(): (keyof JsxBs5ToggleButtonProps)[] { return ["target-id"]; } protected requiredAttributes(): (keyof JsxBs5ToggleButtonProps)[] { return ["target-id"]; } public static tagName = "bs5-toggle-button"; protected autobind = true; public _debug = false; protected eventDispatcher?: EventDispatcher; protected lifecycleEvents = EventDispatcher.getInstance("lifecycle"); public scope: Scope = { targetId: undefined, toggle: this.toggle, state: "undefined", isActive: true, isClosed: false, }; constructor() { super(); this.lifecycleEvents.once( "ComponentLifecycle:allBound", this.onAllComponentsReady, this, ); } public toggle() { this.debug("toggle", this.eventDispatcher); if (this.eventDispatcher) { this.eventDispatcher.trigger( TOGGLE_BUTTON.eventNames.toggle, this.scope.targetId, ); } } protected onAllComponentsReady() { this.debug("onAllComponentsReady"); // Trigger init to trigger there current state of all the components that are connected to this component this.eventDispatcher?.trigger( TOGGLE_BUTTON.eventNames.init, this.scope.targetId, ); } protected async afterBind() { await super.afterBind(); } protected connectedCallback() { super.connectedCallback(); this.init(Bs5ToggleButtonComponent.observedAttributes); } protected onToggledEvent(state: State) { this.scope.state = state; this.scope.isActive = state !== "hidden" && state !== "removed"; this.scope.isClosed = !this.scope.isActive; } protected initEventDispatcher(id: string) { if (this.eventDispatcher) { this.eventDispatcher.off( TOGGLE_BUTTON.eventNames.toggled, this.onToggledEvent, this, ); } const namespace = TOGGLE_BUTTON.nsPrefix + id; this.debug(`Init event dispatcher for namespace ${namespace}`); this.eventDispatcher = new EventDispatcher(namespace); this.eventDispatcher.on( TOGGLE_BUTTON.eventNames.toggled, this.onToggledEvent, this, ); // Triggered state triggered by `..trigger('init', ...` this.eventDispatcher.on( TOGGLE_BUTTON.eventNames.state, this.onToggledEvent, this, ); } protected async attributeChangedCallback( attributeName: string, oldValue: any, newValue: any, namespace: string | null, ) { super.attributeChangedCallback( attributeName, oldValue, newValue, namespace, ); } protected parsedAttributeChangedCallback( attributeName: string, oldValue: any, newValue: any, namespace: string | null, ) { super.parsedAttributeChangedCallback( attributeName, oldValue, newValue, namespace, ); if (attributeName === "targetId" && newValue) { this.initEventDispatcher(newValue); } } // deconstruction protected disconnectedCallback() { super.disconnectedCallback(); if (this.eventDispatcher) { this.eventDispatcher.off( TOGGLE_BUTTON.eventNames.toggled, this.onToggledEvent, this, ); } } protected template(): ReturnType<TemplateFunction> { if (!hasChildNodesTrim(this)) { console.warn( "No child elements found, this component as no template so you need to define your own as child of this component.", ); } return null; } }