UNPKG

primeng

Version:

[![npm version](https://badge.fury.io/js/primeng.svg)](https://badge.fury.io/js/primeng) [![npm downloads](https://img.shields.io/npm/dm/primeng.svg)](https://www.npmjs.com/package/primeng) [![Actions CI](https://github.com/primefaces/primeng/workflows/No

657 lines (653 loc) 25.7 kB
import { DOCUMENT, NgIf, NgTemplateOutlet, NgStyle, NgClass } from '@angular/common'; import * as i0 from '@angular/core'; import { booleanAttribute, Directive, Inject, Input, EventEmitter, numberAttribute, Component, ChangeDetectionStrategy, ViewEncapsulation, Output, ContentChildren, NgModule } from '@angular/core'; import { PrimeTemplate, SharedModule } from 'primeng/api'; import { AutoFocus } from 'primeng/autofocus'; import { DomHandler } from 'primeng/dom'; import { SpinnerIcon } from 'primeng/icons/spinner'; import { Ripple } from 'primeng/ripple'; import { ObjectUtils } from 'primeng/utils'; const INTERNAL_BUTTON_CLASSES = { button: 'p-button', component: 'p-component', iconOnly: 'p-button-icon-only', disabled: 'p-disabled', loading: 'p-button-loading', labelOnly: 'p-button-loading-label-only' }; /** * Button directive is an extension to button component. * @group Components */ class ButtonDirective { el; document; /** * Position of the icon. * @group Props */ iconPos = 'left'; /** * Uses to pass attributes to the loading icon's DOM element. * @group Props */ loadingIcon; /** * Text of the button. * @group Props */ get label() { return this._label; } set label(val) { this._label = val; if (this.initialized) { this.updateLabel(); this.updateIcon(); this.setStyleClass(); } } /** * Name of the icon. * @group Props */ get icon() { return this._icon; } set icon(val) { this._icon = val; if (this.initialized) { this.updateIcon(); this.setStyleClass(); } } /** * Whether the button is in loading state. * @group Props */ get loading() { return this._loading; } set loading(val) { this._loading = val; if (this.initialized) { this.updateIcon(); this.setStyleClass(); } } /** * Defines the style of the button. * @group Props */ severity; /** * Add a shadow to indicate elevation. * @group Props */ raised = false; /** * Add a circular border radius to the button. * @group Props */ rounded = false; /** * Add a textual class to the button without a background initially. * @group Props */ text = false; /** * Add a border class without a background initially. * @group Props */ outlined = false; /** * Defines the size of the button. * @group Props */ size = null; /** * Add a plain textual class to the button without a background initially. * @group Props */ plain = false; _label; _icon; _loading = false; initialized; get htmlElement() { return this.el.nativeElement; } _internalClasses = Object.values(INTERNAL_BUTTON_CLASSES); constructor(el, document) { this.el = el; this.document = document; } ngAfterViewInit() { DomHandler.addMultipleClasses(this.htmlElement, this.getStyleClass().join(' ')); this.createIcon(); this.createLabel(); this.initialized = true; } getStyleClass() { const styleClass = [INTERNAL_BUTTON_CLASSES.button, INTERNAL_BUTTON_CLASSES.component]; if (this.icon && !this.label && ObjectUtils.isEmpty(this.htmlElement.textContent)) { styleClass.push(INTERNAL_BUTTON_CLASSES.iconOnly); } if (this.loading) { styleClass.push(INTERNAL_BUTTON_CLASSES.disabled, INTERNAL_BUTTON_CLASSES.loading); if (!this.icon && this.label) { styleClass.push(INTERNAL_BUTTON_CLASSES.labelOnly); } if (this.icon && !this.label && !ObjectUtils.isEmpty(this.htmlElement.textContent)) { styleClass.push(INTERNAL_BUTTON_CLASSES.iconOnly); } } if (this.text) { styleClass.push('p-button-text'); } if (this.severity) { styleClass.push(`p-button-${this.severity}`); } if (this.plain) { styleClass.push('p-button-plain'); } if (this.raised) { styleClass.push('p-button-raised'); } if (this.size) { styleClass.push(`p-button-${this.size}`); } if (this.outlined) { styleClass.push('p-button-outlined'); } if (this.rounded) { styleClass.push('p-button-rounded'); } if (this.size === 'small') { styleClass.push('p-button-sm'); } if (this.size === 'large') { styleClass.push('p-button-lg'); } return styleClass; } setStyleClass() { const styleClass = this.getStyleClass(); this.htmlElement.classList.remove(...this._internalClasses); this.htmlElement.classList.add(...styleClass); } createLabel() { const created = DomHandler.findSingle(this.htmlElement, '.p-button-label'); if (!created && this.label) { let labelElement = this.document.createElement('span'); if (this.icon && !this.label) { labelElement.setAttribute('aria-hidden', 'true'); } labelElement.className = 'p-button-label'; labelElement.appendChild(this.document.createTextNode(this.label)); this.htmlElement.appendChild(labelElement); } } createIcon() { const created = DomHandler.findSingle(this.htmlElement, '.p-button-icon'); if (!created && (this.icon || this.loading)) { let iconElement = this.document.createElement('span'); iconElement.className = 'p-button-icon'; iconElement.setAttribute('aria-hidden', 'true'); let iconPosClass = this.label ? 'p-button-icon-' + this.iconPos : null; if (iconPosClass) { DomHandler.addClass(iconElement, iconPosClass); } let iconClass = this.getIconClass(); if (iconClass) { DomHandler.addMultipleClasses(iconElement, iconClass); } this.htmlElement.insertBefore(iconElement, this.htmlElement.firstChild); } } updateLabel() { let labelElement = DomHandler.findSingle(this.htmlElement, '.p-button-label'); if (!this.label) { labelElement && this.htmlElement.removeChild(labelElement); return; } labelElement ? (labelElement.textContent = this.label) : this.createLabel(); } updateIcon() { let iconElement = DomHandler.findSingle(this.htmlElement, '.p-button-icon'); let labelElement = DomHandler.findSingle(this.htmlElement, '.p-button-label'); if (iconElement) { if (this.iconPos) { iconElement.className = 'p-button-icon ' + (labelElement ? 'p-button-icon-' + this.iconPos : '') + ' ' + this.getIconClass(); } else { iconElement.className = 'p-button-icon ' + this.getIconClass(); } } else { this.createIcon(); } } getIconClass() { return this.loading ? 'p-button-loading-icon pi-spin ' + (this.loadingIcon ?? 'pi pi-spinner') : this.icon || 'p-hidden'; } ngOnDestroy() { this.initialized = false; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: ButtonDirective, deps: [{ token: i0.ElementRef }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "18.0.1", type: ButtonDirective, isStandalone: true, selector: "[pButton]", inputs: { iconPos: "iconPos", loadingIcon: "loadingIcon", label: "label", icon: "icon", loading: "loading", severity: "severity", raised: ["raised", "raised", booleanAttribute], rounded: ["rounded", "rounded", booleanAttribute], text: ["text", "text", booleanAttribute], outlined: ["outlined", "outlined", booleanAttribute], size: "size", plain: ["plain", "plain", booleanAttribute] }, host: { classAttribute: "p-element" }, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: ButtonDirective, decorators: [{ type: Directive, args: [{ selector: '[pButton]', standalone: true, host: { class: 'p-element' } }] }], ctorParameters: () => [{ type: i0.ElementRef }, { type: Document, decorators: [{ type: Inject, args: [DOCUMENT] }] }], propDecorators: { iconPos: [{ type: Input }], loadingIcon: [{ type: Input }], label: [{ type: Input }], icon: [{ type: Input }], loading: [{ type: Input }], severity: [{ type: Input }], raised: [{ type: Input, args: [{ transform: booleanAttribute }] }], rounded: [{ type: Input, args: [{ transform: booleanAttribute }] }], text: [{ type: Input, args: [{ transform: booleanAttribute }] }], outlined: [{ type: Input, args: [{ transform: booleanAttribute }] }], size: [{ type: Input }], plain: [{ type: Input, args: [{ transform: booleanAttribute }] }] } }); /** * Button is an extension to standard button element with icons and theming. * @group Components */ class Button { el; /** * Type of the button. * @group Props */ type = 'button'; /** * Position of the icon. * @group Props */ iconPos = 'left'; /** * Name of the icon. * @group Props */ icon; /** * Value of the badge. * @group Props */ badge; /** * Uses to pass attributes to the label's DOM element. * @group Props */ label; /** * When present, it specifies that the component should be disabled. * @group Props */ disabled; /** * Whether the button is in loading state. * @group Props */ loading = false; /** * Icon to display in loading state. * @group Props */ loadingIcon; /** * Add a shadow to indicate elevation. * @group Props */ raised = false; /** * Add a circular border radius to the button. * @group Props */ rounded = false; /** * Add a textual class to the button without a background initially. * @group Props */ text = false; /** * Add a plain textual class to the button without a background initially. * @group Props */ plain = false; /** * Defines the style of the button. * @group Props */ severity; /** * Add a border class without a background initially. * @group Props */ outlined = false; /** * Add a link style to the button. * @group Props */ link = false; /** * Add a tabindex to the button. * @group Props */ tabindex; /** * Defines the size of the button. * @group Props */ size; /** * Inline style of the element. * @group Props */ style; /** * Class of the element. * @group Props */ styleClass; /** * Style class of the badge. * @group Props */ badgeClass; /** * Used to define a string that autocomplete attribute the current element. * @group Props */ ariaLabel; /** * When present, it specifies that the component should automatically get focus on load. * @group Props */ autofocus; /** * Callback to execute when button is clicked. * This event is intended to be used with the <p-button> component. Using a regular <button> element, use (click). * @param {MouseEvent} event - Mouse event. * @group Emits */ onClick = new EventEmitter(); /** * Callback to execute when button is focused. * This event is intended to be used with the <p-button> component. Using a regular <button> element, use (focus). * @param {FocusEvent} event - Focus event. * @group Emits */ onFocus = new EventEmitter(); /** * Callback to execute when button loses focus. * This event is intended to be used with the <p-button> component. Using a regular <button> element, use (blur). * @param {FocusEvent} event - Focus event. * @group Emits */ onBlur = new EventEmitter(); contentTemplate; loadingIconTemplate; iconTemplate; templates; constructor(el) { this.el = el; } spinnerIconClass() { return Object.entries(this.iconClass()) .filter(([, value]) => !!value) .reduce((acc, [key]) => acc + ` ${key}`, 'p-button-loading-icon'); } iconClass() { const iconClasses = { 'p-button-icon': true, 'p-button-icon-left': this.iconPos === 'left' && this.label, 'p-button-icon-right': this.iconPos === 'right' && this.label, 'p-button-icon-top': this.iconPos === 'top' && this.label, 'p-button-icon-bottom': this.iconPos === 'bottom' && this.label }; if (this.loading) { iconClasses[`p-button-loading-icon pi-spin ${this.loadingIcon ?? ''}`] = true; } else if (this.icon) { iconClasses[this.icon] = true; } return iconClasses; } get buttonClass() { return { 'p-button p-component': true, 'p-button-icon-only': (this.icon || this.iconTemplate || this.loadingIcon || this.loadingIconTemplate) && !this.label, 'p-button-vertical': (this.iconPos === 'top' || this.iconPos === 'bottom') && this.label, 'p-button-loading': this.loading, 'p-button-loading-label-only': this.loading && !this.icon && this.label && !this.loadingIcon && this.iconPos === 'left', 'p-button-link': this.link, [`p-button-${this.severity}`]: this.severity, 'p-button-raised': this.raised, 'p-button-rounded': this.rounded, 'p-button-text': this.text, 'p-button-outlined': this.outlined, 'p-button-sm': this.size === 'small', 'p-button-lg': this.size === 'large', 'p-button-plain': this.plain, [`${this.styleClass}`]: this.styleClass }; } ngAfterContentInit() { this.templates?.forEach((item) => { switch (item.getType()) { case 'content': this.contentTemplate = item.template; break; case 'icon': this.iconTemplate = item.template; break; case 'loadingicon': this.loadingIconTemplate = item.template; break; default: this.contentTemplate = item.template; break; } }); } badgeStyleClass() { return { 'p-badge p-component': true, 'p-badge-no-gutter': this.badge && String(this.badge).length === 1 }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: Button, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "18.0.1", type: Button, isStandalone: true, selector: "p-button", inputs: { type: "type", iconPos: "iconPos", icon: "icon", badge: "badge", label: "label", disabled: ["disabled", "disabled", booleanAttribute], loading: ["loading", "loading", booleanAttribute], loadingIcon: "loadingIcon", raised: ["raised", "raised", booleanAttribute], rounded: ["rounded", "rounded", booleanAttribute], text: ["text", "text", booleanAttribute], plain: ["plain", "plain", booleanAttribute], severity: "severity", outlined: ["outlined", "outlined", booleanAttribute], link: ["link", "link", booleanAttribute], tabindex: ["tabindex", "tabindex", numberAttribute], size: "size", style: "style", styleClass: "styleClass", badgeClass: "badgeClass", ariaLabel: "ariaLabel", autofocus: ["autofocus", "autofocus", booleanAttribute] }, outputs: { onClick: "onClick", onFocus: "onFocus", onBlur: "onBlur" }, host: { properties: { "class.p-disabled": "disabled" }, classAttribute: "p-element" }, queries: [{ propertyName: "templates", predicate: PrimeTemplate }], ngImport: i0, template: ` <button [attr.type]="type" [attr.aria-label]="ariaLabel" [ngStyle]="style" [disabled]="disabled || loading" [ngClass]="buttonClass" (click)="onClick.emit($event)" (focus)="onFocus.emit($event)" (blur)="onBlur.emit($event)" pRipple [attr.data-pc-name]="'button'" [attr.data-pc-section]="'root'" [attr.tabindex]="tabindex" pAutoFocus [autofocus]="autofocus" > <ng-content></ng-content> <ng-container *ngTemplateOutlet="contentTemplate"></ng-container> <ng-container *ngIf="loading"> <ng-container *ngIf="!loadingIconTemplate"> <span *ngIf="loadingIcon" [ngClass]="iconClass()" [attr.aria-hidden]="true" [attr.data-pc-section]="'loadingicon'"></span> <SpinnerIcon *ngIf="!loadingIcon" [styleClass]="spinnerIconClass()" [spin]="true" [attr.aria-hidden]="true" [attr.data-pc-section]="'loadingicon'" /> </ng-container> <ng-template [ngIf]="loadingIconTemplate" *ngTemplateOutlet="loadingIconTemplate; context: { class: iconClass() }"></ng-template> </ng-container> <ng-container *ngIf="!loading"> <span *ngIf="icon && !iconTemplate" [ngClass]="iconClass()" [attr.data-pc-section]="'icon'"></span> <ng-template [ngIf]="!icon && iconTemplate" *ngTemplateOutlet="iconTemplate; context: { class: iconClass() }"></ng-template> </ng-container> <span class="p-button-label" [attr.aria-hidden]="icon && !label" *ngIf="!contentTemplate && label" [attr.data-pc-section]="'label'">{{ label }}</span> <span [ngClass]="badgeStyleClass()" [class]="badgeClass" *ngIf="!contentTemplate && badge" [attr.data-pc-section]="'badge'">{{ badge }}</span> </button> `, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: Ripple, selector: "[pRipple]" }, { kind: "directive", type: AutoFocus, selector: "[pAutoFocus]", inputs: ["autofocus"] }, { kind: "component", type: SpinnerIcon, selector: "SpinnerIcon" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: Button, decorators: [{ type: Component, args: [{ selector: 'p-button', standalone: true, imports: [NgIf, NgTemplateOutlet, NgStyle, NgClass, Ripple, AutoFocus, SpinnerIcon], template: ` <button [attr.type]="type" [attr.aria-label]="ariaLabel" [ngStyle]="style" [disabled]="disabled || loading" [ngClass]="buttonClass" (click)="onClick.emit($event)" (focus)="onFocus.emit($event)" (blur)="onBlur.emit($event)" pRipple [attr.data-pc-name]="'button'" [attr.data-pc-section]="'root'" [attr.tabindex]="tabindex" pAutoFocus [autofocus]="autofocus" > <ng-content></ng-content> <ng-container *ngTemplateOutlet="contentTemplate"></ng-container> <ng-container *ngIf="loading"> <ng-container *ngIf="!loadingIconTemplate"> <span *ngIf="loadingIcon" [ngClass]="iconClass()" [attr.aria-hidden]="true" [attr.data-pc-section]="'loadingicon'"></span> <SpinnerIcon *ngIf="!loadingIcon" [styleClass]="spinnerIconClass()" [spin]="true" [attr.aria-hidden]="true" [attr.data-pc-section]="'loadingicon'" /> </ng-container> <ng-template [ngIf]="loadingIconTemplate" *ngTemplateOutlet="loadingIconTemplate; context: { class: iconClass() }"></ng-template> </ng-container> <ng-container *ngIf="!loading"> <span *ngIf="icon && !iconTemplate" [ngClass]="iconClass()" [attr.data-pc-section]="'icon'"></span> <ng-template [ngIf]="!icon && iconTemplate" *ngTemplateOutlet="iconTemplate; context: { class: iconClass() }"></ng-template> </ng-container> <span class="p-button-label" [attr.aria-hidden]="icon && !label" *ngIf="!contentTemplate && label" [attr.data-pc-section]="'label'">{{ label }}</span> <span [ngClass]="badgeStyleClass()" [class]="badgeClass" *ngIf="!contentTemplate && badge" [attr.data-pc-section]="'badge'">{{ badge }}</span> </button> `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { class: 'p-element', '[class.p-disabled]': 'disabled' || 'loading' } }] }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { type: [{ type: Input }], iconPos: [{ type: Input }], icon: [{ type: Input }], badge: [{ type: Input }], label: [{ type: Input }], disabled: [{ type: Input, args: [{ transform: booleanAttribute }] }], loading: [{ type: Input, args: [{ transform: booleanAttribute }] }], loadingIcon: [{ type: Input }], raised: [{ type: Input, args: [{ transform: booleanAttribute }] }], rounded: [{ type: Input, args: [{ transform: booleanAttribute }] }], text: [{ type: Input, args: [{ transform: booleanAttribute }] }], plain: [{ type: Input, args: [{ transform: booleanAttribute }] }], severity: [{ type: Input }], outlined: [{ type: Input, args: [{ transform: booleanAttribute }] }], link: [{ type: Input, args: [{ transform: booleanAttribute }] }], tabindex: [{ type: Input, args: [{ transform: numberAttribute }] }], size: [{ type: Input }], style: [{ type: Input }], styleClass: [{ type: Input }], badgeClass: [{ type: Input }], ariaLabel: [{ type: Input }], autofocus: [{ type: Input, args: [{ transform: booleanAttribute }] }], onClick: [{ type: Output }], onFocus: [{ type: Output }], onBlur: [{ type: Output }], templates: [{ type: ContentChildren, args: [PrimeTemplate] }] } }); class ButtonModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: ButtonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.0.1", ngImport: i0, type: ButtonModule, imports: [ButtonDirective, Button], exports: [ButtonDirective, Button, SharedModule] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: ButtonModule, imports: [Button, SharedModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.1", ngImport: i0, type: ButtonModule, decorators: [{ type: NgModule, args: [{ imports: [ButtonDirective, Button], exports: [ButtonDirective, Button, SharedModule] }] }] }); /** * Generated bundle index. Do not edit. */ export { Button, ButtonDirective, ButtonModule }; //# sourceMappingURL=primeng-button.mjs.map