UNPKG

@duoduo-oba/ng-devui

Version:

DevUI components based on Angular

606 lines (600 loc) 19.1 kB
import { forwardRef, Component, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, Input, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import { fromEvent } from 'rxjs'; import { tap, pluck, map, distinctUntilChanged, takeUntil } from 'rxjs/operators'; import { CommonModule } from '@angular/common'; import { PopoverModule } from '@duoduo-oba/ng-devui/popover'; /** * @fileoverview added by tsickle * Generated from: slider.component.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const SLIDER_CONTROL_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, // tslint:disable-next-line useExisting: forwardRef((/** * @return {?} */ () => SliderComponent)), multi: true }; class SliderComponent { /** * @param {?} cdr */ constructor(cdr) { this.cdr = cdr; this.isDragging = false; this.isHovering = false; this.showValuePopover = false; this.max = 100; this.min = 0; this.step = 1; this.disabled = false; this.tipsRenderer = (/** * @param {?} value * @return {?} */ (value) => `${value}`); this.onTouchedCallback = (/** * @param {?} v * @return {?} */ (v) => { }); this.onChangeCallback = (/** * @param {?} v * @return {?} */ (v) => { }); } /** * @return {?} */ ngOnInit() { this.checkRangeValues(this.min, this.max); this.checkStepValue(); this.toggleDisabled(this.disabled); if (this.value === null) { this.setValue(this.ensureValueInRange(null)); } } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { if (changes.hasOwnProperty('min') || changes.hasOwnProperty('max') || changes.hasOwnProperty('step')) { this.checkRangeValues(this.min, this.max); this.checkStepValue(); } } /** * @return {?} */ ngAfterViewInit() { this.registerMouseEventsListeners(); this.registerHandleHoverPopoverListener(); this.toggleDisabled(this.disabled); } /** * @param {?} fn * @return {?} */ registerOnChange(fn) { this.onChangeCallback = fn; } /** * @param {?} fn * @return {?} */ registerOnTouched(fn) { this.onTouchedCallback = fn; } /** * @param {?} isDisabled * @return {?} */ setDisabledState(isDisabled) { this.disabled = isDisabled; this.toggleDisabled(isDisabled); } /** * @param {?} newValue * @return {?} */ writeValue(newValue) { this.setValue(this.ensureValueInRange(newValue)); } /** * @private * @param {?} minValue * @param {?} maxValue * @return {?} */ checkRangeValues(minValue, maxValue) { if (maxValue <= minValue) { throw new Error(`max value must be greater than min value`); } } /** * @private * @return {?} */ checkStepValue() { if (this.step < 0 || !!!this.step) { throw new Error('step value must be greater than 0.'); } else if ((this.max - this.min) % this.step) { throw new Error('(max - min) must be divisible by step.'); } } /** * @private * @param {?} ratio * @param {?} min * @param {?} max * @param {?} step * @return {?} */ ratioToValue(ratio, min, max, step) { /** @type {?} */ let value = (max - min) * ratio + min; if (step > 0) { value = Math.round(value / step) * step; } return this.clamp(min, value, max); } /** * @private * @param {?} handleX * @param {?} startX * @param {?} totalLength * @return {?} */ convertHandlePositionToRatio(handleX, startX, totalLength) { return this.clamp(0, (handleX - startX) / totalLength, 1); } /** * @private * @param {?} min * @param {?} n * @param {?} max * @return {?} */ clamp(min, n, max) { return Math.max(min, Math.min(n, max)); } /** * @private * @param {?} percentage * @return {?} */ updateStyle(percentage) { percentage = Math.min(1, Math.max(0, percentage)); this.sliderTrack.nativeElement.style.width = `${percentage * 100}%`; this.sliderHandle.nativeElement.style.left = `${percentage * 100}%`; } /** * @private * @return {?} */ registerMouseEventsListeners() { this.dragStartListener = fromEvent(this.slider.nativeElement, 'mousedown').pipe(tap((/** * @param {?} e * @return {?} */ (e) => { e.stopPropagation(); e.preventDefault(); })), pluck('pageX'), map((/** * @param {?} position * @return {?} */ (position) => this.mousePositionToAdaptiveValue(position)))); this.dragEndListener = fromEvent(document, 'mouseup'); this.dragMoveListener = fromEvent(document, 'mousemove').pipe(tap((/** * @param {?} e * @return {?} */ (e) => { e.stopPropagation(); e.preventDefault(); })), pluck('pageX'), distinctUntilChanged(), map((/** * @param {?} position * @return {?} */ (position) => this.mousePositionToAdaptiveValue(position))), distinctUntilChanged(), takeUntil(this.dragEndListener)); } /** * @private * @return {?} */ getSliderPagePosition() { /** @type {?} */ const rect = this.slider.nativeElement.getBoundingClientRect(); /** @type {?} */ const window = this.slider.nativeElement.ownerDocument.defaultView; return rect.left + window.pageXOffset; } /** * @private * @return {?} */ getRailLength() { return this.sliderRail.nativeElement.clientWidth; } /** * @private * @param {?} handleX * @return {?} */ mousePositionToAdaptiveValue(handleX) { /** @type {?} */ const sliderStartX = this.getSliderPagePosition(); /** @type {?} */ const sliderLength = this.getRailLength(); /** @type {?} */ const ratio = this.convertHandlePositionToRatio(handleX, sliderStartX, sliderLength); /** @type {?} */ const value = this.ratioToValue(ratio, this.min, this.max, this.step); return parseFloat(value.toFixed(this.getDecimals(this.step))); } /** * @private * @param {?} value * @return {?} */ getDecimals(value) { /** @type {?} */ const valueString = value.toString(); /** @type {?} */ const integerLength = valueString.indexOf('.') + 1; return integerLength >= 0 ? valueString.length - integerLength : 0; } /** * @private * @param {?} value * @return {?} */ mouseStartMoving(value) { this.handleController(true); this.setValue(value); } /** * @private * @param {?} value * @return {?} */ mouseMoving(value) { this.setValue(value); this.cdr.markForCheck(); } /** * @private * @return {?} */ mouseStopMoving() { this.handleController(false); this.cdr.markForCheck(); } /** * @private * @param {?=} mouseActions * @return {?} */ subscribeMouseActions(mouseActions = ['start', 'move', 'end']) { if (mouseActions.indexOf('start') !== -1 && this.dragStartListener && !this.dragStartHandler) { this.dragStartHandler = this.dragStartListener.subscribe(this.mouseStartMoving.bind(this)); } if (mouseActions.indexOf('move') !== -1 && this.dragMoveListener && !this.dragMoveHandler) { this.dragMoveHandler = this.dragMoveListener.subscribe(this.mouseMoving.bind(this)); } if (mouseActions.indexOf('end') !== -1 && this.dragEndListener && !this.dragEndHandler) { this.dragEndHandler = this.dragEndListener.subscribe(this.mouseStopMoving.bind(this)); } } /** * @private * @param {?=} dragStages * @return {?} */ unsubscribeMouseActions(dragStages = ['start', 'move', 'end']) { if (dragStages.indexOf('start') !== -1 && this.dragStartHandler) { this.dragStartHandler.unsubscribe(); this.dragStartHandler = null; } if (dragStages.indexOf('move') !== -1 && this.dragMoveHandler) { this.dragMoveHandler.unsubscribe(); this.dragMoveHandler = null; } if (dragStages.indexOf('end') !== -1 && this.dragEndHandler) { this.dragEndHandler.unsubscribe(); this.dragEndHandler = null; } } /** * @private * @param {?} movable * @return {?} */ handleController(movable) { if (movable) { this.isDragging = true; this.showValuePopover = this.showValuePopoverController(); this.subscribeMouseActions(['move', 'end']); } else { this.isDragging = false; this.showValuePopover = this.showValuePopoverController(); this.unsubscribeMouseActions(['move', 'end']); } } /** * @private * @param {?} disabled * @return {?} */ toggleDisabled(disabled) { if (disabled) { this.unsubscribeMouseActions(); } else { this.subscribeMouseActions(['start']); } } /** * @private * @param {?} value * @return {?} */ setValue(value) { if (this.value !== value) { this.value = value; this.updateTrackAndHandle(); } this.onChangeCallback(this.value); } /** * @private * @param {?} value * @return {?} */ ensureValueInRange(value) { /** @type {?} */ let safeValue; if (!this.valueMustBeValid(value)) { safeValue = this.min; } else { safeValue = this.clamp(this.min, (/** @type {?} */ (value)), this.max); } return safeValue; } /** * @private * @return {?} */ updateTrackAndHandle() { /** @type {?} */ const value = this.value; /** @type {?} */ const offset = this.valueToOffset(value); this.updateStyle(offset / 100); this.cdr.markForCheck(); } /** * @private * @param {?} value * @return {?} */ valueMustBeValid(value) { return !isNaN(typeof value !== 'number' ? parseFloat(value) : value); } /** * @private * @param {?} value * @return {?} */ valueToOffset(value) { return ((value - this.min) / (this.max - this.min)) * 100; } /** * @private * @return {?} */ registerHandleHoverPopoverListener() { /** @type {?} */ const mouseOverListener = fromEvent(this.sliderHandle.nativeElement, 'mouseover'); /** @type {?} */ const mouseLeaveListener = fromEvent(this.sliderHandle.nativeElement, 'mouseout'); this.mouseOverHandler = mouseOverListener.subscribe(this.sliderHandlePopoverOnMouseHover.bind(this)); this.mouseLeaveHandler = mouseLeaveListener.subscribe(this.sliderHandlePopoverOnMouseLeave.bind(this)); } /** * @private * @return {?} */ sliderHandlePopoverOnMouseHover() { this.isHovering = true; this.showValuePopover = this.showValuePopoverController(); this.cdr.markForCheck(); } /** * @private * @return {?} */ sliderHandlePopoverOnMouseLeave() { this.isHovering = false; this.showValuePopover = this.showValuePopoverController(); this.cdr.markForCheck(); } /** * @private * @return {?} */ unregisterHandleHoverTooltip() { this.mouseOverHandler.unsubscribe(); this.mouseLeaveHandler.unsubscribe(); } /** * @private * @return {?} */ showValuePopoverController() { return this.isDragging || this.isHovering; } /** * @return {?} */ ngOnDestroy() { this.unsubscribeMouseActions(); this.unregisterHandleHoverTooltip(); } } SliderComponent.decorators = [ { type: Component, args: [{ selector: 'd-slider', template: "<div class=\"devui-slider\" #slider [ngClass]=\"{ disabled: disabled }\">\r\n <div class=\"devui-slider-rail\" #sliderRail [ngClass]=\"{ disabled: disabled }\"></div>\r\n <div class=\"devui-slider-track\" #sliderTrack [ngClass]=\"{ disabled: disabled }\"></div>\r\n <div\r\n class=\"devui-slider-handle\"\r\n #sliderHandle\r\n [ngClass]=\"{ disabled: disabled }\"\r\n dPopover\r\n position=\"top\"\r\n [content]=\"showValuePopover && tipsRenderer ? tipsRenderer(value) : ''\"\r\n [showAnimate]=\"false\"\r\n [visible]=\"tipsRenderer && showValuePopover\"\r\n ></div>\r\n</div>\r\n", providers: [SLIDER_CONTROL_VALUE_ACCESSOR], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.devui-slider{position:relative;width:100%;padding:5px 0;margin:5px 0;cursor:pointer;box-sizing:border-box;height:15px}.devui-slider .devui-slider-rail{position:absolute;background-color:#f8f8f8;height:5px;width:100%;-webkit-transition:background-color .2s ease-in-out;transition:background-color .2s ease-in-out}.devui-slider .devui-slider-rail.disabled,.devui-slider:hover .devui-slider-rail:not(.disabled){background-color:#f8f8f8}.devui-slider:hover .devui-slider-track:not(.disabled){background-color:#344899}.devui-slider:hover .devui-slider-handle:not(.disabled){border-color:#344899}.devui-slider .devui-slider-track{position:absolute;background-color:#5e7ce0;height:5px;width:0}.devui-slider .devui-slider-handle{position:absolute;background-color:#fff;width:14px;height:14px;border-radius:50%;margin-left:-7px;margin-top:-5px;left:0;-webkit-transition:-webkit-transform .2s ease-in-out;transition:transform .2s ease-in-out;transition:transform .2s ease-in-out,-webkit-transform .2s ease-in-out;border:2px solid #5e7ce0}.devui-slider .devui-slider-handle:not(.disabled):active,.devui-slider .devui-slider-handle:not(.disabled):hover{-webkit-transform:scale(1.3);transform:scale(1.3)}.devui-slider.disabled{cursor:not-allowed;opacity:.3}"] }] } ]; /** @nocollapse */ SliderComponent.ctorParameters = () => [ { type: ChangeDetectorRef } ]; SliderComponent.propDecorators = { slider: [{ type: ViewChild, args: ['slider', { static: true },] }], sliderHandle: [{ type: ViewChild, args: ['sliderHandle', { static: true },] }], sliderTrack: [{ type: ViewChild, args: ['sliderTrack', { static: true },] }], sliderRail: [{ type: ViewChild, args: ['sliderRail', { static: true },] }], max: [{ type: Input }], min: [{ type: Input }], step: [{ type: Input }], disabled: [{ type: Input }], tipsRenderer: [{ type: Input }] }; if (false) { /** * @type {?} * @private */ SliderComponent.prototype.dragStartListener; /** * @type {?} * @private */ SliderComponent.prototype.dragMoveListener; /** * @type {?} * @private */ SliderComponent.prototype.dragEndListener; /** * @type {?} * @private */ SliderComponent.prototype.dragStartHandler; /** * @type {?} * @private */ SliderComponent.prototype.dragMoveHandler; /** * @type {?} * @private */ SliderComponent.prototype.dragEndHandler; /** * @type {?} * @private */ SliderComponent.prototype.isDragging; /** * @type {?} * @private */ SliderComponent.prototype.isHovering; /** @type {?} */ SliderComponent.prototype.value; /** @type {?} */ SliderComponent.prototype.showValuePopover; /** * @type {?} * @private */ SliderComponent.prototype.mouseOverHandler; /** * @type {?} * @private */ SliderComponent.prototype.mouseLeaveHandler; /** @type {?} */ SliderComponent.prototype.slider; /** @type {?} */ SliderComponent.prototype.sliderHandle; /** @type {?} */ SliderComponent.prototype.sliderTrack; /** @type {?} */ SliderComponent.prototype.sliderRail; /** @type {?} */ SliderComponent.prototype.max; /** @type {?} */ SliderComponent.prototype.min; /** @type {?} */ SliderComponent.prototype.step; /** @type {?} */ SliderComponent.prototype.disabled; /** @type {?} */ SliderComponent.prototype.tipsRenderer; /** * @type {?} * @private */ SliderComponent.prototype.onTouchedCallback; /** * @type {?} * @private */ SliderComponent.prototype.onChangeCallback; /** * @type {?} * @private */ SliderComponent.prototype.cdr; } /** * @fileoverview added by tsickle * Generated from: slider.module.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class SliderModule { } SliderModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule, FormsModule, PopoverModule ], exports: [SliderComponent], declarations: [SliderComponent], providers: [], },] } ]; /** * @fileoverview added by tsickle * Generated from: public-api.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * Generated from: ng-devui-slider.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { SliderComponent, SliderModule }; //# sourceMappingURL=ng-devui-slider.js.map