UNPKG

@angular-mdc/web

Version:
566 lines (562 loc) 17 kB
/** * @license * Copyright (c) Dominic Carretto * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/trimox/angular-mdc-web/blob/master/LICENSE */ import { forwardRef, EventEmitter, Component, ViewEncapsulation, ChangeDetectionStrategy, NgZone, ChangeDetectorRef, ElementRef, Optional, Input, Output, ViewChild, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { MdcFormFieldControl, MdcFormField, MdcFormFieldModule } from '@angular-mdc/web/form-field'; import { __awaiter } from 'tslib'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { supportsPassiveEventListeners, Platform } from '@angular/cdk/platform'; import { Subject, fromEvent } from 'rxjs'; import { takeUntil, filter } from 'rxjs/operators'; import { matches } from '@angular-mdc/web/dom'; import { MDCRippleFoundation } from '@material/ripple'; import { MDCCheckboxFoundation } from '@material/checkbox'; import { MDCComponent } from '@angular-mdc/web/base'; import { MdcRipple } from '@angular-mdc/web/ripple'; /** * @fileoverview added by tsickle * Generated from: checkbox/checkbox.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ let nextUniqueId = 0; /** * Change event object emitted by MdcCheckbox. */ class MdcCheckboxChange { /** * @param {?} source * @param {?} checked */ constructor(source, checked) { this.source = source; this.checked = checked; } } /** @type {?} */ const MDC_CHECKBOX_CONTROL_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((/** * @return {?} */ () => MdcCheckbox)), multi: true }; class MdcCheckbox extends MDCComponent { /** * @param {?} _platform * @param {?} _ngZone * @param {?} _changeDetectorRef * @param {?} elementRef * @param {?} ripple * @param {?} _parentFormField */ constructor(_platform, _ngZone, _changeDetectorRef, elementRef, ripple, _parentFormField) { super(elementRef); this._platform = _platform; this._ngZone = _ngZone; this._changeDetectorRef = _changeDetectorRef; this.elementRef = elementRef; this.ripple = ripple; this._parentFormField = _parentFormField; /** * Emits whenever the component is destroyed. */ this._destroy = new Subject(); this._initialized = false; this._uniqueId = `mdc-checkbox-${++nextUniqueId}`; this.id = this._uniqueId; this.name = null; this._checked = false; this._touch = false; this._disabled = false; /** * The value attribute of the native input element */ this.value = null; this._indeterminate = false; this._indeterminateToChecked = true; this._disableRipple = false; this.tabIndex = 0; this.ariaLabel = ''; this.ariaLabelledby = null; /** * Fired when checkbox is checked or unchecked, but not when set * indeterminate. Sends the state of [checked]. */ this.change = new EventEmitter(); /** * Fired when checkbox goes in and out of indeterminate state, but not when * set to checked. Sends the state of [indeterminate]; */ this.indeterminateChange = new EventEmitter(); /** * View to model callback called when value changes */ this._onChange = (/** * @return {?} */ () => { }); /** * View to model callback called when component has been touched */ this._onTouched = (/** * @return {?} */ () => { }); this._root = this.elementRef.nativeElement; if (this._parentFormField) { _parentFormField.elementRef.nativeElement.classList.add('mdc-form-field'); } } /** * Returns the unique id for the visual hidden input. * @return {?} */ get inputId() { return `${this.id || this._uniqueId}-input`; } /** * @return {?} */ get checked() { return this._checked; } /** * @param {?} value * @return {?} */ set checked(value) { if (value !== this.checked) { this._checked = coerceBooleanProperty(value); this._changeDetectorRef.markForCheck(); } } /** * @return {?} */ get touch() { return this._touch; } /** * @param {?} value * @return {?} */ set touch(value) { this._touch = coerceBooleanProperty(value); } /** * @return {?} */ get disabled() { return this._disabled; } /** * @param {?} value * @return {?} */ set disabled(value) { this.setDisabledState(value); } /** * Alternative state of the checkbox, not user set-able state. Between * [checked] and [indeterminate], only one can be true, though both can be * false. * `true` is INDETERMINATE and `false` is not. * @return {?} */ get indeterminate() { return this._indeterminate; } /** * @param {?} value * @return {?} */ set indeterminate(value) { var _a; if (this.disabled) { return; } /** @type {?} */ const newValue = coerceBooleanProperty(value); if (newValue !== this._indeterminate) { this._indeterminate = newValue; if (newValue) { this.checked = false; } this.indeterminateChange.emit({ source: this, indeterminate: this._indeterminate }); this._changeDetectorRef.markForCheck(); (_a = this._foundation) === null || _a === void 0 ? void 0 : _a.handleChange(); } } /** * Determines the state to go into when [indeterminate] state is toggled. * `true` will go to checked and `false` will go to unchecked. * @return {?} */ get indeterminateToChecked() { return this._indeterminateToChecked; } /** * @param {?} value * @return {?} */ set indeterminateToChecked(value) { this._indeterminateToChecked = coerceBooleanProperty(value); this._changeDetectorRef.markForCheck(); } /** * Whether the ripple ink is disabled. * @return {?} */ get disableRipple() { return this._disableRipple; } /** * @param {?} value * @return {?} */ set disableRipple(value) { this._disableRipple = coerceBooleanProperty(value); } /** * @return {?} */ getDefaultFoundation() { // Do not initialize foundation until ngAfterViewInit runs if (!this._initialized) { return undefined; } /** @type {?} */ const adapter = { addClass: (/** * @param {?} className * @return {?} */ (className) => this._root.classList.add(className)), removeClass: (/** * @param {?} className * @return {?} */ (className) => this._root.classList.remove(className)), setNativeControlAttr: (/** * @param {?} attr * @param {?} value * @return {?} */ (attr, value) => this._inputElement.nativeElement.setAttribute(attr, value)), removeNativeControlAttr: (/** * @param {?} attr * @return {?} */ (attr) => this._inputElement.nativeElement.removeAttribute(attr)), isIndeterminate: (/** * @return {?} */ () => this.indeterminate), isChecked: (/** * @return {?} */ () => this.checked), hasNativeControl: (/** * @return {?} */ () => true), setNativeControlDisabled: (/** * @param {?} disabled * @return {?} */ (disabled) => this._inputElement.nativeElement.disabled = disabled), forceLayout: (/** * @return {?} */ () => ((/** @type {?} */ (this._root))).offsetWidth), isAttachedToDOM: (/** * @return {?} */ () => true) }; return new MDCCheckboxFoundation(adapter); } /** * @return {?} */ _asyncBuildFoundation() { return __awaiter(this, void 0, void 0, function* () { this._foundation = this.getDefaultFoundation(); }); } /** * @return {?} */ ngAfterViewInit() { this._initialized = true; this._asyncBuildFoundation() .then((/** * @return {?} */ () => { this._foundation.init(); this.setDisabledState(this._inputElement.nativeElement.disabled); this.ripple = this._createRipple(); this.ripple.init(); })); this._loadListeners(); } /** * @return {?} */ ngOnDestroy() { this._destroy.next(); this._destroy.complete(); this.ripple.destroy(); this._foundation.destroy(); } /** * @param {?} value * @return {?} */ writeValue(value) { this.checked = !!value; } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this._onChange = fn; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this._onTouched = fn; } /** * Focuses the checkbox. * @return {?} */ focus() { if (!this.disabled) { this._inputElement.nativeElement.focus(); } } /** * @param {?=} checked * @return {?} */ toggle(checked) { this._setState(checked); } /** * @param {?} evt * @return {?} */ _onInteraction(evt) { // We have to stop propagation for click events on the visual hidden input element. // Preventing bubbling for the second event will solve that issue. evt.stopPropagation(); this._setState(); this._onChange(this.checked); this._changeDetectorRef.markForCheck(); this.change.emit(new MdcCheckboxChange(this, this.checked)); } /** * @param {?} evt * @return {?} */ _onInputClick(evt) { evt.stopPropagation(); } /** * @param {?} disabled * @return {?} */ setDisabledState(disabled) { var _a; /** @type {?} */ const newValue = coerceBooleanProperty(disabled); if (newValue !== this._disabled) { this._disabled = newValue; (_a = this._foundation) === null || _a === void 0 ? void 0 : _a.setDisabled(newValue); this._changeDetectorRef.markForCheck(); } } /** * @private * @param {?=} checked * @return {?} */ _setState(checked) { if (this.disabled) { return; } if (this.indeterminate) { this._checked = this.indeterminateToChecked; this.indeterminate = false; } else { this.checked = checked || !this.checked; } // Reset native input when clicked with noop. The native checkbox becomes checked after // click, reset it to be align with `checked` value of `mdc-checkbox`. this._inputElement.nativeElement.checked = this.checked; this._ngZone.runOutsideAngular((/** * @return {?} */ () => requestAnimationFrame((/** * @return {?} */ () => this._foundation.handleChange())))); } /** * @private * @return {?} */ _createRipple() { /** @type {?} */ const adapter = Object.assign(Object.assign({}, MdcRipple.createAdapter(this)), { isSurfaceActive: (/** * @return {?} */ () => matches(this._inputElement.nativeElement, ':active')), isUnbounded: (/** * @return {?} */ () => true), isSurfaceDisabled: (/** * @return {?} */ () => this.disableRipple), deregisterInteractionHandler: (/** * @param {?} evtType * @param {?} handler * @return {?} */ (evtType, handler) => this._inputElement.nativeElement.removeEventListener(evtType, handler, supportsPassiveEventListeners())), registerInteractionHandler: (/** * @param {?} evtType * @param {?} handler * @return {?} */ (evtType, handler) => this._inputElement.nativeElement.addEventListener(evtType, handler, supportsPassiveEventListeners())) }); return new MdcRipple(this.elementRef, new MDCRippleFoundation(adapter)); } /** * @private * @return {?} */ _loadListeners() { if (!this._platform.isBrowser) { return; } this._ngZone.runOutsideAngular((/** * @return {?} */ () => fromEvent(this._root, 'animationend') .pipe(takeUntil(this._destroy), filter((/** * @param {?} e * @return {?} */ (e) => e.target === this._root))) .subscribe((/** * @return {?} */ () => this._ngZone.run((/** * @return {?} */ () => this._foundation.handleAnimationEnd())))))); } } MdcCheckbox.decorators = [ { type: Component, args: [{selector: 'mdc-checkbox', exportAs: 'mdcCheckbox', host: { '[id]': 'id', 'class': 'mdc-checkbox', '[class.mdc-checkbox--touch]': 'touch', }, template: ` <input type="checkbox" #input class="mdc-checkbox__native-control" [id]="inputId" [attr.name]="name" [tabIndex]="tabIndex" [attr.aria-label]="ariaLabel || null" [attr.aria-labelledby]="ariaLabelledby" [disabled]="disabled" [checked]="checked" [attr.value]="value" [indeterminate]="indeterminate" (change)="_onInteraction($event)" (click)="_onInputClick($event)"/> <div class="mdc-checkbox__background"> <svg class="mdc-checkbox__checkmark" viewBox="0 0 24 24" focusable="false"> <path class="mdc-checkbox__checkmark-path" fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59"/> </svg> <div class="mdc-checkbox__mixedmark"></div> </div> <div *ngIf="!disableRipple && !disabled" class="mdc-checkbox__ripple"></div> `, providers: [ MDC_CHECKBOX_CONTROL_VALUE_ACCESSOR, MdcRipple, { provide: MdcFormFieldControl, useExisting: MdcCheckbox } ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush },] }, ]; /** @nocollapse */ MdcCheckbox.ctorParameters = () => [ { type: Platform }, { type: NgZone }, { type: ChangeDetectorRef }, { type: ElementRef }, { type: MdcRipple }, { type: MdcFormField, decorators: [{ type: Optional }] } ]; MdcCheckbox.propDecorators = { id: [{ type: Input }], name: [{ type: Input }], checked: [{ type: Input }], touch: [{ type: Input }], disabled: [{ type: Input }], value: [{ type: Input }], indeterminate: [{ type: Input }], indeterminateToChecked: [{ type: Input }], disableRipple: [{ type: Input }], tabIndex: [{ type: Input }], ariaLabel: [{ type: Input, args: ['aria-label',] }], ariaLabelledby: [{ type: Input, args: ['aria-labelledby',] }], change: [{ type: Output }], indeterminateChange: [{ type: Output }], _inputElement: [{ type: ViewChild, args: ['input', { static: true },] }] }; /** * @fileoverview added by tsickle * Generated from: checkbox/module.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class MdcCheckboxModule { } MdcCheckboxModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule, MdcFormFieldModule], exports: [ MdcFormFieldModule, MdcCheckbox ], declarations: [MdcCheckbox] },] }, ]; export { MDC_CHECKBOX_CONTROL_VALUE_ACCESSOR, MdcCheckbox, MdcCheckboxChange, MdcCheckboxModule }; //# sourceMappingURL=checkbox.js.map