UNPKG

gd-bs

Version:

Bootstrap JavaScript, TypeScript and Web Components library.

262 lines (224 loc) 8.77 kB
import { IButton, IButtonProps } from "./types"; import { Base } from "../base"; import { Badge, BadgeTypes } from "../badge"; import { ClassNames } from "../classNames"; import { Spinner } from "../spinner"; import { HTML, HTMLBlock, HTMLLink } from "./templates"; /** * Button Types */ export enum ButtonTypes { Danger = 1, Dark = 2, Info = 3, Light = 4, Link = 5, Primary = 6, Secondary = 7, Success = 8, Warning = 9, OutlineDanger = 10, OutlineDark = 11, OutlineInfo = 12, OutlineLight = 13, OutlineLink = 14, OutlinePrimary = 15, OutlineSecondary = 16, OutlineSuccess = 17, OutlineWarning = 18 } /** * Button Classes */ export const ButtonClassNames = new ClassNames([ "btn-danger", "btn-dark", "btn-info", "btn-light", "btn-link", "btn-primary", "btn-secondary", "btn-success", "btn-warning", "btn-outline-danger", "btn-outline-dark", "btn-outline-info", "btn-outline-light", "btn-outline-link", "btn-outline-primary", "btn-outline-secondary", "btn-outline-success", "btn-outline-warning" ]); /** * Button * @param props The button properties. */ class _Button extends Base<IButtonProps> implements IButton { // Constructor constructor(props: IButtonProps, template: string = props.isBlock ? HTMLBlock : (props.href || props.isLink ? HTMLLink : HTML)) { super(template, props); // Configure the button this.configure(); // Configure the events this.configureEvents(); // Configure the parent this.configureParent(); } // Configure the button private configure() { // Add the class names this.props.isLarge ? this.el.classList.add("btn-lg") : null; this.props.isSmall ? this.el.classList.add("btn-sm") : null; // Set the default type this.setType(this.props.type || ButtonTypes.Primary) // Set the aria label/description this.props.description ? this.el.setAttribute("aria-description", this.props.description) : null; this.el.setAttribute("aria-label", this.props.label || this.props.text); // Set the attributes this.props.dismiss ? this.el.setAttribute("data-bs-dismiss", this.props.dismiss) : null; this.props.href ? this.el.href = this.props.href : null; this.props.id ? this.el.id = this.props.id : null; this.props.isDisabled ? this.el.setAttribute("disabled", "disabled") : null; this.props.tabIndex != null ? this.el.setAttribute("tabindex", this.props.tabIndex) : null; this.props.target ? this.el.setAttribute("data-bs-target", this.props.target) : null; this.props.title ? this.el.title = this.props.title : null; this.props.toggle ? this.el.setAttribute("data-bs-toggle", this.props.toggle) : null; this.props.trigger ? this.el.setAttribute("data-bs-trigger", this.props.trigger) : null; typeof (this.props.isExpanded) === "boolean" ? this.el.setAttribute("aria-expanded", this.props.isExpanded ? "true" : "false") : null; // See if controls are defined if (this.props.controls) { // See if this is a string if (typeof (this.props.controls) === "string") { // Set the controls this.el.setAttribute("aria-controls", this.props.controls); } else { // Set the controls this.el.setAttribute("aria-controls", this.props.controls.join(' ')); } } // Set the text this.setText(this.props.text); // Set the icon if it exists if (this.props.iconType) { // Update the styling of the button this.el.classList.add("btn-icon"); if (typeof (this.props.iconType) === "function") { // Append the icon this.el.prepend((this.props.iconType as Function)(this.props.iconSize, this.props.iconSize, this.props.iconClassName)); } // Else, it's an element else if (typeof (this.props.iconType) === "object") { // Append the icon this.el.prepend(this.props.iconType); } } // See if this is a spinner if (this.props.spinnerProps) { // Set the element to render to this.props.spinnerProps.el = this.el; // Render the spinner Spinner(this.props.spinnerProps); } // See if there is a badge if (this.props.badge) { // Default the type this.props.badge.type = this.props.badge.type || BadgeTypes.Light; // Render the badge this.el.appendChild(Badge(this.props.badge).el); } } // Configure the events private configureEvents() { // See if there is a click event if (this.props.onClick) { // Add a click event this.el.addEventListener("click", ev => { // Call the click event this.props.onClick(this.props, ev); }); } // See if we are toggling anything if (this.props.toggleObj) { // Add a click event this.el.addEventListener("click", ev => { // See if it's a function if (typeof (this.props.toggleObj.toggle) === "function") { // Toggle the object this.props.toggleObj.toggle(); } else { let objToggle: any = window[this.props.toggleObj]; if (typeof (objToggle?.toggle) === "function") { // Toggle the object objToggle.toggle(); } } }); } } /** * Public Properties */ // Disables the button disable() { (this.el as HTMLButtonElement).disabled = true; } // Enables the button enable() { (this.el as HTMLButtonElement).disabled = false; } // Sets the icon setIcon(iconType: Function, iconSize: number = 16, iconClassName?: string) { let elButton = this.el as HTMLButtonElement; // Parse the child nodes for (var i = 0; i < elButton.childNodes.length; i++) { // See if this is the icon if (elButton.childNodes[i].nodeName == "svg") { // Insert the icon elButton.insertBefore(iconType(iconSize, iconSize, iconClassName), elButton.childNodes[i]); // Remove the existing icon elButton.removeChild((this.el as HTMLButtonElement).childNodes[i]); // Update the styling of the button elButton.classList.add("btn-icon"); // Break from the loop break; } } } // Sets the button text setText(btnText?: string) { let elButton = this.el as HTMLButtonElement; let existsFl = false; // Parse the child nodes for (var i = 0; i < elButton.childNodes.length; i++) { // See if this is the text element if (elButton.childNodes[i].nodeName == "#text") { // Set the flag existsFl = true; // Set the value elButton.childNodes[i].nodeValue = btnText || ""; // Break from the loop break; } } // See if it doesn't exist if (!existsFl) { // Add the text node elButton.appendChild(document.createTextNode(btnText == null ? "" : btnText)) } } // Sets the button type setType(buttonType: number) { // Parse the class names ButtonClassNames.parse(className => { // Remove the class names this.el.classList.remove(className); }); // Set the class name let className = ButtonClassNames.getByType(buttonType) || ButtonClassNames.getByType(ButtonTypes.Primary); this.el.classList.add(className); } // Toggles the button toggle() { let btn = this.el as HTMLButtonElement; // Toggle the element btn.classList.contains("active") ? btn.classList.remove("active") : btn.classList.add("active"); } } export const Button = (props: IButtonProps, template?: string): IButton => { return new _Button(props, template); }