Repository URL to install this package:
|
Version:
1.0.0-next.0 ▾
|
/**
* @license
* FOURBURNER CONFIDENTIAL
* Unpublished Copyright (C) 2021 FourBurner Technologies, Inc. All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of FOURBURNER TECHNOLOGIES,
* INC. The intellectual and technical concepts contained herein are proprietary to FOURBURNER
* TECHNOLOGIES, INC. and may be covered by U.S. and Foreign Patents, patents in process, and are
* protected by trade secret or copyright law. Dissemination of this information or reproduction of
* this material is strictly forbidden unless prior written permission is obtained from FOURBURNER
* TECHNOLOGIES, INC. Access to the source code contained herein is hereby forbidden to anyone
* except current FOURBURNER TECHNOLOGIES, INC. employees, managers or contractors who have executed
* Confidentiality and Non-disclosure agreements explicitly covering such access.
*
* The copyright notice above does not evidence any actual or intended publication or disclosure of
* this source code, which includes information that is confidential and/or proprietary, and is a
* trade secret, of FOURBURNER TECHNOLOGIES, INC. ANY REPRODUCTION, MODIFICATION, DISTRIBUTION,
* PUBLIC PERFORMANCE, OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT THE EXPRESS
* WRITTEN CONSENT OF FOURBURNER TECHNOLOGIES, INC. IS STRICTLY PROHIBITED, AND IN VIOLATION OF
* APPLICABLE LAWS AND INTERNATIONAL TREATIES. THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR
* RELATED INFORMATION DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS
* CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN PART.
*/
import {FocusMonitor, FocusableOption, FocusOrigin} from '@angular/cdk/a11y';
import {
ChangeDetectionStrategy,
Component,
ElementRef,
OnDestroy,
ViewChild,
ViewEncapsulation,
Optional,
Inject,
Input,
AfterViewInit,
} from '@angular/core';
import {
CanColor,
CanDisable,
CanDisableRipple,
TWNDRipple,
mixinColor,
mixinDisabled,
mixinDisableRipple,
} from '@twnd/ux/core';
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
/** Default color palette for round buttons (twnd-fab and twnd-mini-fab) */
const DEFAULT_ROUND_BUTTON_COLOR = 'accent';
/**
* List of classes to add to TWNDButton instances based on host attributes to
* style as different variants.
*/
const BUTTON_HOST_ATTRIBUTES = [
'twnd-button',
'twnd-flat-button',
'twnd-icon-button',
'twnd-raised-button',
'twnd-stroked-button',
'twnd-mini-fab',
'twnd-fab',
];
// Boilerplate for applying mixins to TWNDButton.
const _TWNDButtonBase = mixinColor(
mixinDisabled(
mixinDisableRipple(
class {
constructor(public _elementRef: ElementRef) {}
},
),
),
);
/**
* TWND UX design button.
*/
/* clang-format off */
@Component({
selector : `button[twnd-button], button[twnd-raised-button], button[twnd-icon-button],
button[twnd-fab], button[twnd-mini-fab], button[twnd-stroked-button],
button[twnd-flat-button]`,
exportAs : 'twndButton',
host : {
'[attr.disabled]' : 'disabled || null',
'[class._twnd-animation-noopable]' : '_animationMode === "NoopAnimations"',
// Add a class for disabled button styling instead of the using attribute
// selector or pseudo-selector. This allows users to create focusabled
// disabled buttons without recreating the styles.
'[class.twnd-button-disabled]' : 'disabled',
'class' : 'twnd-focus-indicator',
},
templateUrl : 'button.html',
inputs : [ 'disabled', 'disableRipple', 'color' ],
encapsulation : ViewEncapsulation.None,
changeDetection : ChangeDetectionStrategy.OnPush,
})
/* clang-format on */
export class TWNDButton extends _TWNDButtonBase implements AfterViewInit, OnDestroy, CanDisable,
CanColor, CanDisableRipple,
FocusableOption
{
/** Whether the button is round. */
readonly isRoundButton: boolean = this._hasHostAttributes('twnd-fab', 'twnd-mini-fab');
/** Whether the button is icon button. */
readonly isIconButton: boolean = this._hasHostAttributes('twnd-icon-button');
/** Reference to the TWNDRipple instance of the button. */
@ViewChild(TWNDRipple) ripple: TWNDRipple;
constructor(
elementRef: ElementRef,
private _focusMonitor: FocusMonitor,
@Optional() @Inject(ANIMATION_MODULE_TYPE) public _animationMode: string,
)
{
super(elementRef);
// For each of the variant selectors that is present in the button's host
// attributes, add the correct corresponding class.
for (const attr of BUTTON_HOST_ATTRIBUTES) {
if (this._hasHostAttributes(attr)) {
(this._getHostElement() as HTMLElement).classList.add(attr);
}
}
// Add a class that applies to all buttons. This makes it easier to target if somebody
// wants to target all TWND UX buttons. We do it here rather than `host` to ensure that
// the class is applied to derived classes.
elementRef.nativeElement.classList.add('twnd-button-base');
if (this.isRoundButton) {
this.color = DEFAULT_ROUND_BUTTON_COLOR;
}
}
ngAfterViewInit()
{
this._focusMonitor.monitor(this._elementRef, true);
}
ngOnDestroy()
{
this._focusMonitor.stopMonitoring(this._elementRef);
}
/** Focuses the button. */
focus(origin?: FocusOrigin, options?: FocusOptions): void
{
if (origin) {
this._focusMonitor.focusVia(this._getHostElement(), origin, options);
} else {
this._getHostElement().focus(options);
}
}
_getHostElement()
{
return this._elementRef.nativeElement;
}
_isRippleDisabled()
{
return this.disableRipple || this.disabled;
}
/** Gets whether the button has one of the given attributes. */
_hasHostAttributes(...attributes: string[])
{
return attributes.some(attribute => this._getHostElement().hasAttribute(attribute));
}
}
/**
* TWND UX anchor button.
*/
@Component({
/* clang-format off */
selector : `a[twnd-button], a[twnd-raised-button], a[twnd-icon-button], a[twnd-fab],
a[twnd-mini-fab], a[twnd-stroked-button], a[twnd-flat-button]`,
exportAs : 'twndButton, twndAnchor',
host : {
// Note that we ignore the user-specified tabindex when it's disabled for
// consistency with the `twnd-button` applied on native buttons where even
// though they have an index, they're not tabbable.
'[attr.tabindex]' : 'disabled ? -1 : (tabIndex || 0)',
'[attr.disabled]' : 'disabled || null',
'[attr.aria-disabled]' : 'disabled.toString()',
'(click)' : '_haltDisabledEvents($event)',
'[class._twnd-animation-noopable]' : '_animationMode === "NoopAnimations"',
'[class.twnd-button-disabled]' : 'disabled',
'class' : 'twnd-focus-indicator',
},
inputs : [ 'disabled', 'disableRipple', 'color' ],
templateUrl : 'button.html',
encapsulation : ViewEncapsulation.None,
changeDetection : ChangeDetectionStrategy.OnPush,
/* clang-format on */
})
export class TWNDAnchor extends TWNDButton
{
/** Tabindex of the button. */
@Input() tabIndex: number;
constructor(
focusMonitor: FocusMonitor,
elementRef: ElementRef,
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode: string,
)
{
super(elementRef, focusMonitor, animationMode);
}
_haltDisabledEvents(event: Event)
{
// A disabled button shouldn't apply any actions
if (this.disabled) {
event.preventDefault();
event.stopImmediatePropagation();
}
}
}