UNPKG

@angular-mdc/web

Version:
627 lines (623 loc) 18.8 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, ChangeDetectionStrategy, ViewEncapsulation, NgZone, ChangeDetectorRef, ElementRef, Attribute, Input, Output, ViewChild, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { __awaiter } from 'tslib'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion'; import { Platform, supportsPassiveEventListeners } from '@angular/cdk/platform'; import { Subject, fromEvent } from 'rxjs'; import { auditTime, takeUntil } from 'rxjs/operators'; import { MDCComponent } from '@angular-mdc/web/base'; import { MDCSliderFoundation } from '@material/slider'; /** * @fileoverview added by tsickle * Generated from: slider/slider.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const MDC_SLIDER_CONTROL_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef((/** * @return {?} */ () => MdcSlider)), multi: true }; class MdcSliderChange { /** * @param {?} source * @param {?} value */ constructor(source, value) { this.source = source; this.value = value; } } class MdcSlider extends MDCComponent { /** * @param {?} _platform * @param {?} _ngZone * @param {?} _changeDetectorRef * @param {?} elementRef * @param {?} tabIndex */ constructor(_platform, _ngZone, _changeDetectorRef, elementRef, tabIndex) { super(elementRef); this._platform = _platform; this._ngZone = _ngZone; this._changeDetectorRef = _changeDetectorRef; this.elementRef = elementRef; /** * Emits whenever the component is destroyed. */ this._destroyed = new Subject(); this._initialized = false; this.tabIndex = 0; this._discrete = false; this._markers = false; this._min = 0; this._max = 100; this._step = 1; this._value = null; this._disabled = false; this.change = new EventEmitter(); this.input = new EventEmitter(); /** * Emits when the raw value of the slider changes. This is here primarily * to facilitate the two-way binding for the `value` input. */ this.valueChange = new EventEmitter(); /** * Function when touched */ this._onTouched = (/** * @return {?} */ () => { }); /** * Function when changed */ this._controlValueAccessorChangeFn = (/** * @return {?} */ () => { }); this.tabIndex = parseInt(tabIndex, 10) || 0; this._root = this.elementRef.nativeElement; } /** * @return {?} */ get discrete() { return this._discrete; } /** * @param {?} value * @return {?} */ set discrete(value) { this._discrete = coerceBooleanProperty(value); } /** * @return {?} */ get markers() { return this._markers; } /** * @param {?} value * @return {?} */ set markers(value) { this._markers = coerceBooleanProperty(value); } /** * @return {?} */ get min() { return this._min; } /** * @param {?} value * @return {?} */ set min(value) { /** @type {?} */ const min = coerceNumberProperty(value); if (min !== this._min) { this._min = min; } } /** * @return {?} */ get max() { return this._max; } /** * @param {?} value * @return {?} */ set max(value) { /** @type {?} */ const max = coerceNumberProperty(value); if (max !== this._max) { this._max = max; } } /** * @return {?} */ get step() { return this._step; } /** * @param {?} value * @return {?} */ set step(value) { /** @type {?} */ const step = coerceNumberProperty(value, this._step); if (step !== this._step) { this._step = step; } } /** * @return {?} */ get value() { if (this._value === null) { this.value = this.min; } return this._value; } /** * @param {?} newValue * @return {?} */ set value(newValue) { this._value = coerceNumberProperty(newValue, null); } /** * @return {?} */ get disabled() { return this._disabled; } /** * @param {?} value * @return {?} */ set disabled(value) { this.setDisabledState(value); } /** * @return {?} */ getDefaultFoundation() { /** @type {?} */ const adapter = { hasClass: (/** * @param {?} className * @return {?} */ (className) => this._root.classList.contains(className)), addClass: (/** * @param {?} className * @return {?} */ (className) => this._root.classList.add(className)), removeClass: (/** * @param {?} className * @return {?} */ (className) => this._root.classList.remove(className)), getAttribute: (/** * @param {?} name * @return {?} */ (name) => this._root.getAttribute(name)), setAttribute: (/** * @param {?} name * @param {?} value * @return {?} */ (name, value) => this._root.setAttribute(name, value)), removeAttribute: (/** * @param {?} name * @return {?} */ (name) => this._root.removeAttribute(name)), computeBoundingRect: (/** * @return {?} */ () => this._root.getBoundingClientRect()), getTabIndex: (/** * @return {?} */ () => ((/** @type {?} */ (this._root))).tabIndex), registerInteractionHandler: (/** * @template K * @param {?} evtType * @param {?} handler * @return {?} */ (evtType, handler) => ((/** @type {?} */ (this._root))).addEventListener(evtType, handler)), deregisterInteractionHandler: (/** * @template K * @param {?} evtType * @param {?} handler * @return {?} */ (evtType, handler) => ((/** @type {?} */ (this._root))).removeEventListener(evtType, handler)), registerThumbContainerInteractionHandler: (/** * @template K * @param {?} evtType * @param {?} handler * @return {?} */ (evtType, handler) => { this._ngZone.runOutsideAngular((/** * @return {?} */ () => { this.thumbContainer.nativeElement.addEventListener(evtType, handler, supportsPassiveEventListeners()); })); }), deregisterThumbContainerInteractionHandler: (/** * @template K * @param {?} evtType * @param {?} handler * @return {?} */ (evtType, handler) => this.thumbContainer.nativeElement.removeEventListener(evtType, handler, supportsPassiveEventListeners())), registerBodyInteractionHandler: (/** * @template K * @param {?} evtType * @param {?} handler * @return {?} */ (evtType, handler) => document.body.addEventListener(evtType, handler)), deregisterBodyInteractionHandler: (/** * @template K * @param {?} evtType * @param {?} handler * @return {?} */ (evtType, handler) => document.body.removeEventListener(evtType, handler)), registerResizeHandler: (/** * @return {?} */ () => { }), deregisterResizeHandler: (/** * @return {?} */ () => { }), notifyInput: (/** * @return {?} */ () => { /** @type {?} */ const newValue = this._foundation.getValue(); if (newValue !== this.value) { this.value = newValue; this.input.emit(this._createChangeEvent(newValue)); } }), notifyChange: (/** * @return {?} */ () => { this.value = this._foundation.getValue(); this._emitChangeEvent((/** @type {?} */ (this.value))); }), setThumbContainerStyleProperty: (/** * @param {?} propertyName * @param {?} value * @return {?} */ (propertyName, value) => this.thumbContainer.nativeElement.style.setProperty(propertyName, value)), setTrackStyleProperty: (/** * @param {?} propertyName * @param {?} value * @return {?} */ (propertyName, value) => this.track.nativeElement.style.setProperty(propertyName, value)), setMarkerValue: (/** * @param {?} value * @return {?} */ (value) => { this._changeDetectorRef.markForCheck(); (/** @type {?} */ (this.pinValueMarker)).nativeElement.innerText = value !== null ? value.toString() : null; }), setTrackMarkers: (/** * @param {?} step * @param {?} max * @param {?} min * @return {?} */ (step, max, min) => (/** @type {?} */ (this.trackMarkerContainer)).nativeElement.style.setProperty('background', this._getTrackMarkersBackground(step, min, max))), isRTL: (/** * @return {?} */ () => this._platform.isBrowser ? window.getComputedStyle(this._root).getPropertyValue('direction') === 'rtl' : false), }; return new MDCSliderFoundation(adapter); } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { if (!this._initialized) { return; } if (changes['step']) { this._syncStepWithFoundation(); } if (changes['max']) { this._syncMaxWithFoundation(); } if (changes['min']) { this._syncMinWithFoundation(); } if (changes['value']) { this._syncValueWithFoundation(); } if (changes['markers'] || changes['discrete']) { this._refreshTrackMarkers(); } } /** * @return {?} */ _asyncInitializeFoundation() { return __awaiter(this, void 0, void 0, function* () { this._foundation.init(); }); } /** * @return {?} */ ngAfterViewInit() { if (this._platform.isBrowser) { this._initialized = true; this._asyncInitializeFoundation() .then((/** * @return {?} */ () => { this._syncStepWithFoundation(); this._syncMaxWithFoundation(); this._syncMinWithFoundation(); this._syncValueWithFoundation(); this._foundation.setupTrackMarker(); this._loadListeners(); this._changeDetectorRef.markForCheck(); })); } } /** * @return {?} */ ngOnDestroy() { this._destroyed.next(); this._destroyed.complete(); this.destroy(); } /** * @param {?} value * @return {?} */ writeValue(value) { this.value = value; this._syncValueWithFoundation(); } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this._controlValueAccessorChangeFn = fn; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this._onTouched = fn; } /** * @param {?} disabled * @return {?} */ setDisabledState(disabled) { this._disabled = coerceBooleanProperty(disabled); this._foundation.setDisabled(disabled); this._changeDetectorRef.markForCheck(); } /** * @return {?} */ layout() { this._foundation.layout(); } /** * @private * @return {?} */ _loadListeners() { this._ngZone.runOutsideAngular((/** * @return {?} */ () => fromEvent(window, 'resize') .pipe(auditTime(16), takeUntil(this._destroyed)) .subscribe((/** * @return {?} */ () => this.layout())))); } /** * @private * @return {?} */ _syncValueWithFoundation() { this._foundation.setValue((/** @type {?} */ (this.value))); } /** * @private * @return {?} */ _syncStepWithFoundation() { this._foundation.setStep(this.step); } /** * @private * @return {?} */ _syncMinWithFoundation() { this._foundation.setMin(this.min); } /** * @private * @return {?} */ _syncMaxWithFoundation() { this._foundation.setMax(this.max); } /** * @private * @param {?} newValue * @return {?} */ _createChangeEvent(newValue) { return new MdcSliderChange(this, newValue); } /** * @private * @param {?} newValue * @return {?} */ _emitChangeEvent(newValue) { this._controlValueAccessorChangeFn(newValue); this.valueChange.emit(newValue); this.change.emit(this._createChangeEvent(newValue)); } /** * Keep calculation in css for better rounding/subpixel behavior. * @private * @param {?} step * @param {?} min * @param {?} max * @return {?} */ _getTrackMarkersBackground(step, min, max) { /** @type {?} */ const stepStr = step.toLocaleString(); /** @type {?} */ const maxStr = max.toLocaleString(); /** @type {?} */ const minStr = min.toLocaleString(); /** @type {?} */ const markerAmount = `((${maxStr} - ${minStr}) / ${stepStr})`; /** @type {?} */ const markerWidth = `2px`; /** @type {?} */ const markerBkgdImage = `linear-gradient(to right, currentColor ${markerWidth}, transparent 0)`; /** @type {?} */ const markerBkgdLayout = `0 center / calc((100% - ${markerWidth}) / ${markerAmount}) 100% repeat-x`; return `${markerBkgdImage} ${markerBkgdLayout}`; } /** * Method that ensures that track markers are refreshed. * @private * @return {?} */ _refreshTrackMarkers() { ((/** @type {?} */ (this._foundation))).hasTrackMarker_ = this.markers; this._foundation.setupTrackMarker(); } } MdcSlider.decorators = [ { type: Component, args: [{selector: 'mdc-slider', exportAs: 'mdcSlider', host: { 'role': 'slider', 'aria-orientation': 'horizontal', '[attr.tabindex]': 'tabIndex || 0', 'class': 'mdc-slider', '[class.mdc-slider--discrete]': 'discrete', '[class.mdc-slider--display-markers]': 'markers && discrete', '(blur)': '_onTouched()', }, template: ` <div class="mdc-slider__track-container"> <div #track class="mdc-slider__track"></div> <div #markercontainer *ngIf="markers" class="mdc-slider__track-marker-container"></div> </div> <div #thumbcontainer class="mdc-slider__thumb-container"> <div *ngIf="discrete" class="mdc-slider__pin"> <span #pin class="mdc-slider__pin-value-marker"></span> </div> <svg #sliderThumb class="mdc-slider__thumb" width="21" height="21" focusable="false"> <circle cx="10.5" cy="10.5" r="7.875"></circle> </svg> <div class="mdc-slider__focus-ring"></div> </div>`, providers: [MDC_SLIDER_CONTROL_VALUE_ACCESSOR], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None },] }, ]; /** @nocollapse */ MdcSlider.ctorParameters = () => [ { type: Platform }, { type: NgZone }, { type: ChangeDetectorRef }, { type: ElementRef }, { type: String, decorators: [{ type: Attribute, args: ['tabindex',] }] } ]; MdcSlider.propDecorators = { tabIndex: [{ type: Input }], discrete: [{ type: Input }], markers: [{ type: Input }], min: [{ type: Input }], max: [{ type: Input }], step: [{ type: Input }], value: [{ type: Input }], disabled: [{ type: Input }], change: [{ type: Output }], input: [{ type: Output }], valueChange: [{ type: Output }], thumbContainer: [{ type: ViewChild, args: ['thumbcontainer', { static: false },] }], _sliderThumb: [{ type: ViewChild, args: ['sliderThumb', { static: false },] }], track: [{ type: ViewChild, args: ['track', { static: false },] }], pinValueMarker: [{ type: ViewChild, args: ['pin', { static: false },] }], trackMarkerContainer: [{ type: ViewChild, args: ['markercontainer', { static: false },] }] }; /** * @fileoverview added by tsickle * Generated from: slider/module.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class MdcSliderModule { } MdcSliderModule.decorators = [ { type: NgModule, args: [{ imports: [CommonModule], exports: [MdcSlider], declarations: [MdcSlider] },] }, ]; export { MDC_SLIDER_CONTROL_VALUE_ACCESSOR, MdcSlider, MdcSliderChange, MdcSliderModule }; //# sourceMappingURL=slider.js.map