/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Platform} from '@angular/cdk/platform';
import {ElementRef, NgZone, ViewChild} from '@angular/core';
import {
CanColor,
CanColorCtor,
CanDisable,
CanDisableCtor,
CanDisableRipple,
CanDisableRippleCtor,
MatRipple,
mixinColor,
mixinDisabled,
mixinDisableRipple,
RippleAnimationConfig
} from '@angular/material/core';
import {numbers} from '@material/ripple';
/** Inputs common to all buttons. */
export const MAT_BUTTON_INPUTS = ['disabled', 'disableRipple', 'color'];
/** Shared host configuration for all buttons */
export const MAT_BUTTON_HOST = {
'[attr.disabled]': 'disabled || null',
'[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"',
// MDC automatically applies the primary theme color to the button, but we want to support
// an unthemed version. If color is undefined, apply a CSS class that makes it easy to
// select and style this "theme".
'[class.mat-unthemed]': '!color',
};
/** List of classes to add to buttons instances based on host attribute selector. */
const HOST_SELECTOR_MDC_CLASS_PAIR: {selector: string, mdcClasses: string[]}[] = [
{
selector: 'mat-button',
mdcClasses: ['mdc-button', 'mat-mdc-button'],
},
{
selector: 'mat-flat-button',
mdcClasses: ['mdc-button', 'mdc-button--unelevated', 'mat-mdc-unelevated-button'],
},
{
selector: 'mat-raised-button',
mdcClasses: ['mdc-button', 'mdc-button--raised', 'mat-mdc-raised-button'],
},
{
selector: 'mat-stroked-button',
mdcClasses: ['mdc-button', 'mdc-button--outlined', 'mat-mdc-outlined-button'],
},
{
selector: 'mat-fab',
mdcClasses: ['mdc-fab', 'mat-mdc-fab'],
},
{
selector: 'mat-mini-fab',
mdcClasses: ['mdc-fab', 'mdc-fab--mini', 'mat-mdc-mini-fab'],
},
{
selector: 'mat-icon-button',
mdcClasses: ['mdc-icon-button', 'mat-mdc-icon-button'],
}
];
// Boilerplate for applying mixins to MatButton.
/** @docs-private */
export class MatButtonMixinCore {
constructor(public _elementRef: ElementRef) {}
}
export const _MatButtonBaseMixin: CanDisableRippleCtor&CanDisableCtor&CanColorCtor&
typeof MatButtonMixinCore = mixinColor(mixinDisabled(mixinDisableRipple(MatButtonMixinCore)));
/** Base class for all buttons. */
export class MatButtonBase extends _MatButtonBaseMixin implements CanDisable, CanColor,
CanDisableRipple {
/** The ripple animation configuration to use for the buttons. */
_rippleAnimation: RippleAnimationConfig = {
enterDuration: numbers.DEACTIVATION_TIMEOUT_MS,
exitDuration: numbers.FG_DEACTIVATION_MS
};
/** Whether the ripple is centered on the button. */
_isRippleCentered = false;
/** Reference to the MatRipple instance of the button. */
@ViewChild(MatRipple, {static: false}) ripple: MatRipple;
constructor(
elementRef: ElementRef, public _platform: Platform, public _ngZone: NgZone,
public _animationMode?: string) {
super(elementRef);
// For each of the variant selectors that is present in the button's host
// attributes, add the correct corresponding MDC classes.
for (const pair of HOST_SELECTOR_MDC_CLASS_PAIR) {
if (this._hasHostAttributes(pair.selector)) {
(elementRef.nativeElement as HTMLElement).classList.add(...pair.mdcClasses);
}
}
}
/** Focuses the button. */
focus(): void {
this._elementRef.nativeElement.focus();
}
/** Gets whether the button has one of the given attributes. */
private _hasHostAttributes(...attributes: string[]) {
return attributes.some(attribute => this._elementRef.nativeElement.hasAttribute(attribute));
}
_isRippleDisabled() {
return this.disableRipple || this.disabled;
}
}
/** Shared inputs by buttons using the `` tag */
export const MAT_ANCHOR_INPUTS = ['disabled', 'disableRipple', 'color', 'tabIndex'];
/** Shared host configuration for buttons using the `` tag. */
export const MAT_ANCHOR_HOST = {
'[attr.disabled]': 'disabled || null',
'[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"',
// Note that we ignore the user-specified tabindex when it's disabled for
// consistency with the `mat-button` applied on native buttons where even
// though they have an index, they're not tabbable.
'[attr.tabindex]': 'disabled ? -1 : (tabIndex || 0)',
'[attr.aria-disabled]': 'disabled.toString()',
'(click)': '_haltDisabledEvents($event)',
// MDC automatically applies the primary theme color to the button, but we want to support
// an unthemed version. If color is undefined, apply a CSS class that makes it easy to
// select and style this "theme".
'[class.mat-unthemed]': '!color',
};
/**
* Anchor button base.
*/
export class MatAnchorBase extends MatButtonBase {
tabIndex: number;
constructor(elementRef: ElementRef, platform: Platform, ngZone: NgZone, animationMode?: string) {
super(elementRef, platform, ngZone, animationMode);
}
_haltDisabledEvents(event: Event) {
// A disabled button shouldn't apply any actions
if (this.disabled) {
event.preventDefault();
event.stopImmediatePropagation();
}
}
}