UNPKG

igniteui-angular

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

1,297 lines (1,291 loc) 83.3 kB
import * as i0 from '@angular/core'; import { Directive, inject, ElementRef, booleanAttribute, HostBinding, Input, Component, EventEmitter, HostListener, Output, Pipe, Renderer2, ChangeDetectorRef, NgZone, QueryList, TemplateRef, ViewChildren, ViewChild, ContentChild, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { Subject, noop, fromEvent, interval, animationFrameScheduler, timer, merge } from 'rxjs'; import { takeUntil, throttleTime, throttle } from 'rxjs/operators'; import { ɵIgxDirectionality as _IgxDirectionality, resizeObservable } from 'igniteui-angular/core'; import { NgClass, NgTemplateOutlet } from '@angular/common'; /** * Template directive that allows you to set a custom template representing the lower label value of the {@link IgxSliderComponent} * * ```html * <igx-slider> * <ng-template igxSliderThumbFrom let-value let-labels>{{value}}</ng-template> * </igx-slider> * ``` * * @context {@link IgxSliderComponent.context} */ class IgxThumbFromTemplateDirective { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxThumbFromTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.2", type: IgxThumbFromTemplateDirective, isStandalone: true, selector: "[igxSliderThumbFrom]", ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxThumbFromTemplateDirective, decorators: [{ type: Directive, args: [{ selector: '[igxSliderThumbFrom]', standalone: true }] }] }); /** * Template directive that allows you to set a custom template representing the upper label value of the {@link IgxSliderComponent} * * ```html * <igx-slider> * <ng-template igxSliderThumbTo let-value let-labels>{{value}}</ng-template> * </igx-slider> * ``` * * @context {@link IgxSliderComponent.context} */ class IgxThumbToTemplateDirective { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxThumbToTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.2", type: IgxThumbToTemplateDirective, isStandalone: true, selector: "[igxSliderThumbTo]", ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxThumbToTemplateDirective, decorators: [{ type: Directive, args: [{ selector: '[igxSliderThumbTo]', standalone: true }] }] }); /** * Template directive that allows you to set a custom template, represeting primary/secondary tick labels of the {@link IgxSliderComponent} * * @context {@link IgxTicksComponent.context} */ class IgxTickLabelTemplateDirective { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTickLabelTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.2", type: IgxTickLabelTemplateDirective, isStandalone: true, selector: "[igxSliderTickLabel]", ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTickLabelTemplateDirective, decorators: [{ type: Directive, args: [{ selector: '[igxSliderTickLabel]', standalone: true }] }] }); const IgxSliderType = { /** * Slider with single thumb. */ SLIDER: 'slider', /** * Range slider with multiple thumbs, that can mark the range. */ RANGE: 'range' }; const SliderHandle = { FROM: 'from', TO: 'to' }; /** * Slider Tick labels Orientation */ const TickLabelsOrientation = { Horizontal: 'horizontal', TopToBottom: 'toptobottom', BottomToTop: 'bottomtotop' }; /** * Slider Ticks orientation */ const TicksOrientation = { Top: 'top', Bottom: 'bottom', Mirror: 'mirror' }; /** * @hidden */ class IgxThumbLabelComponent { constructor() { this._elementRef = inject(ElementRef); } get thumbFromClass() { return this.type === SliderHandle.FROM; } get thumbToClass() { return this.type === SliderHandle.TO; } get thumbFromActiveClass() { return this.type === SliderHandle.FROM && this.active; } get thumbToActiveClass() { return this.type === SliderHandle.TO && this.active; } get labelFromPressedClass() { return this.thumb?.thumbFromPressedClass; } get labelToPressedClass() { return this.thumb?.thumbToPressedClass; } get getLabelClass() { return { 'igx-slider-thumb-label-from__container': this.type === SliderHandle.FROM, 'igx-slider-thumb-label-to__container': this.type === SliderHandle.TO }; } get nativeElement() { return this._elementRef.nativeElement; } get active() { return this._active; } set active(val) { if (this.continuous || this.deactiveState) { this._active = false; } else { this._active = val; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxThumbLabelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.0.2", type: IgxThumbLabelComponent, isStandalone: true, selector: "igx-thumb-label", inputs: { value: "value", templateRef: "templateRef", context: "context", type: "type", continuous: ["continuous", "continuous", booleanAttribute], deactiveState: ["deactiveState", "deactiveState", booleanAttribute], thumb: "thumb" }, host: { properties: { "class.igx-slider-thumb-label-from": "this.thumbFromClass", "class.igx-slider-thumb-label-to": "this.thumbToClass", "class.igx-slider-thumb-label-from--active": "this.thumbFromActiveClass", "class.igx-slider-thumb-label-to--active": "this.thumbToActiveClass", "class.igx-slider-thumb-label-from--pressed": "this.labelFromPressedClass", "class.igx-slider-thumb-label-to--pressed": "this.labelToPressedClass" } }, ngImport: i0, template: "<div [ngClass]=\"getLabelClass\">\n <ng-container *ngTemplateOutlet=\"templateRef ? templateRef : thumbFromDefaultTemplate; context: context\"></ng-container>\n</div>\n\n<ng-template #thumbFromDefaultTemplate>\n {{ value }}\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxThumbLabelComponent, decorators: [{ type: Component, args: [{ selector: 'igx-thumb-label', imports: [NgClass, NgTemplateOutlet], template: "<div [ngClass]=\"getLabelClass\">\n <ng-container *ngTemplateOutlet=\"templateRef ? templateRef : thumbFromDefaultTemplate; context: context\"></ng-container>\n</div>\n\n<ng-template #thumbFromDefaultTemplate>\n {{ value }}\n</ng-template>\n" }] }], propDecorators: { value: [{ type: Input }], templateRef: [{ type: Input }], context: [{ type: Input }], type: [{ type: Input }], continuous: [{ type: Input, args: [{ transform: booleanAttribute }] }], deactiveState: [{ type: Input, args: [{ transform: booleanAttribute }] }], thumb: [{ type: Input }], thumbFromClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-label-from'] }], thumbToClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-label-to'] }], thumbFromActiveClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-label-from--active'] }], thumbToActiveClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-label-to--active'] }], labelFromPressedClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-label-from--pressed'] }], labelToPressedClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-label-to--pressed'] }] } }); /** * @hidden */ class IgxSliderThumbComponent { constructor() { this._elementRef = inject(ElementRef); this._dir = inject(_IgxDirectionality); this.thumbValueChange = new EventEmitter(); this.thumbChange = new EventEmitter(); this.thumbBlur = new EventEmitter(); this.hoverChange = new EventEmitter(); this.tabindex = 0; this.role = 'slider'; this.ariaOrientation = 'horizontal'; this.zIndex = 0; this.focused = false; this.isActive = false; this._isActive = false; this._isPressed = false; this._destroy$ = new Subject(); } get ariaValueNow() { return this.value; } get ariaValueMin() { return this.min; } get ariaValueMax() { return this.max; } get ariaValueText() { if (this.labels && this.labels[this.value] !== undefined) { return this.labels[this.value]; } return this.value; } get ariaLabelAttr() { return `Slider thumb ${this.type}`; } get ariaDisabled() { return this.disabled; } get thumbFromClass() { return this.type === SliderHandle.FROM; } get thumbToClass() { return this.type === SliderHandle.TO; } get thumbFromActiveClass() { return this.type === SliderHandle.FROM && this._isActive; } get thumbToActiveClass() { return this.type === SliderHandle.TO && this._isActive; } get thumbFromDisabledClass() { return this.type === SliderHandle.FROM && this.disabled; } get thumbToDisabledClass() { return this.type === SliderHandle.TO && this.disabled; } get thumbFromPressedClass() { return this.type === SliderHandle.FROM && this.isActive && this._isPressed; } get thumbToPressedClass() { return this.type === SliderHandle.TO && this.isActive && this._isPressed; } get getDotClass() { return { 'igx-slider-thumb-from__dot': this.type === SliderHandle.FROM, 'igx-slider-thumb-to__dot': this.type === SliderHandle.TO }; } get nativeElement() { return this._elementRef.nativeElement; } get destroy() { return this._destroy$; } get thumbPositionX() { const thumbBounderies = this.nativeElement.getBoundingClientRect(); const thumbCenter = (thumbBounderies.right - thumbBounderies.left) / 2; return thumbBounderies.left + thumbCenter; } onPointerEnter() { this.focused = false; this.hoverChange.emit(true); } onPointerLeave() { this.hoverChange.emit(false); } onKeyUp(event) { event.stopPropagation(); this.focused = true; } onKeyDown(event) { if (this.disabled) { return; } let increment = 0; const stepWithDir = (rtl) => rtl ? this.step * -1 : this.step; if (event.key.endsWith('Left')) { increment = stepWithDir(!this._dir.rtl); } else if (event.key.endsWith('Right')) { increment = stepWithDir(this._dir.rtl); } else { return; } this.thumbChange.emit(); this.thumbValueChange.emit(increment); } onBlur() { this.isActive = false; this.zIndex = 0; this.focused = false; this.thumbBlur.emit(); } onFocusListener() { this.isActive = true; this.zIndex = 1; } /** * @hidden */ ngOnInit() { this.onPan .pipe(takeUntil(this._destroy$)) .subscribe(mouseX => this.updateThumbValue(mouseX)); } /** * @hidden */ ngOnDestroy() { this._destroy$.next(true); this._destroy$.complete(); } /** * Show thumb label and ripple. */ showThumbIndicators() { this.toggleThumbIndicators(true); } /** * Hide thumb label and ripple. */ hideThumbIndicators() { this.toggleThumbIndicators(false); } updateThumbValue(mouseX) { const updateValue = this.calculateTrackUpdate(mouseX); if (this.isActive && updateValue !== 0) { this.thumbValueChange.emit(updateValue); } } calculateTrackUpdate(mouseX) { const scaleX = this._dir.rtl ? this.thumbPositionX - mouseX : mouseX - this.thumbPositionX; const stepDistanceCenter = this.stepDistance / 2; // If the thumb scale range (slider update) is less thàn a half step, // the position stays the same. const scaleXPositive = Math.abs(scaleX); if (scaleXPositive < stepDistanceCenter) { return 0; } return this.stepToProceed(scaleX, this.stepDistance); } stepToProceed(scaleX, stepDist) { return Math.round(scaleX / stepDist) * this.step; } toggleThumbIndicators(visible) { this._isPressed = visible; if (this.continuous || this.deactiveState) { this._isActive = false; } else { this._isActive = visible; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxSliderThumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.0.2", type: IgxSliderThumbComponent, isStandalone: true, selector: "igx-thumb", inputs: { value: "value", continuous: ["continuous", "continuous", booleanAttribute], thumbLabelVisibilityDuration: "thumbLabelVisibilityDuration", disabled: ["disabled", "disabled", booleanAttribute], onPan: "onPan", stepDistance: "stepDistance", step: "step", templateRef: "templateRef", context: "context", type: "type", deactiveState: ["deactiveState", "deactiveState", booleanAttribute], min: "min", max: "max", labels: "labels" }, outputs: { thumbValueChange: "thumbValueChange", thumbChange: "thumbChange", thumbBlur: "thumbBlur", hoverChange: "hoverChange" }, host: { listeners: { "pointerenter": "onPointerEnter()", "pointerleave": "onPointerLeave()", "keyup": "onKeyUp($event)", "keydown": "onKeyDown($event)", "blur": "onBlur()", "focus": "onFocusListener()" }, properties: { "attr.tabindex": "this.tabindex", "attr.role": "this.role", "attr.aria-valuenow": "this.ariaValueNow", "attr.aria-valuemin": "this.ariaValueMin", "attr.aria-valuemax": "this.ariaValueMax", "attr.aria-valuetext": "this.ariaValueText", "attr.aria-label": "this.ariaLabelAttr", "attr.aria-orientation": "this.ariaOrientation", "attr.aria-disabled": "this.ariaDisabled", "attr.z-index": "this.zIndex", "class.igx-slider-thumb-to--focused": "this.focused", "class.igx-slider-thumb-from": "this.thumbFromClass", "class.igx-slider-thumb-to": "this.thumbToClass", "class.igx-slider-thumb-from--active": "this.thumbFromActiveClass", "class.igx-slider-thumb-to--active": "this.thumbToActiveClass", "class.igx-slider-thumb-from--disabled": "this.thumbFromDisabledClass", "class.igx-slider-thumb-to--disabled": "this.thumbToDisabledClass", "class.igx-slider-thumb-from--pressed": "this.thumbFromPressedClass", "class.igx-slider-thumb-to--pressed": "this.thumbToPressedClass" } }, ngImport: i0, template: "<div [ngClass]=\"getDotClass\"></div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxSliderThumbComponent, decorators: [{ type: Component, args: [{ selector: 'igx-thumb', imports: [NgClass], template: "<div [ngClass]=\"getDotClass\"></div>\n" }] }], propDecorators: { value: [{ type: Input }], continuous: [{ type: Input, args: [{ transform: booleanAttribute }] }], thumbLabelVisibilityDuration: [{ type: Input }], disabled: [{ type: Input, args: [{ transform: booleanAttribute }] }], onPan: [{ type: Input }], stepDistance: [{ type: Input }], step: [{ type: Input }], templateRef: [{ type: Input }], context: [{ type: Input }], type: [{ type: Input }], deactiveState: [{ type: Input, args: [{ transform: booleanAttribute }] }], min: [{ type: Input }], max: [{ type: Input }], labels: [{ type: Input }], thumbValueChange: [{ type: Output }], thumbChange: [{ type: Output }], thumbBlur: [{ type: Output }], hoverChange: [{ type: Output }], tabindex: [{ type: HostBinding, args: ['attr.tabindex'] }], role: [{ type: HostBinding, args: ['attr.role'] }], ariaValueNow: [{ type: HostBinding, args: ['attr.aria-valuenow'] }], ariaValueMin: [{ type: HostBinding, args: ['attr.aria-valuemin'] }], ariaValueMax: [{ type: HostBinding, args: ['attr.aria-valuemax'] }], ariaValueText: [{ type: HostBinding, args: ['attr.aria-valuetext'] }], ariaLabelAttr: [{ type: HostBinding, args: ['attr.aria-label'] }], ariaOrientation: [{ type: HostBinding, args: ['attr.aria-orientation'] }], ariaDisabled: [{ type: HostBinding, args: [`attr.aria-disabled`] }], zIndex: [{ type: HostBinding, args: ['attr.z-index'] }], focused: [{ type: HostBinding, args: ['class.igx-slider-thumb-to--focused'] }], thumbFromClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-from'] }], thumbToClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-to'] }], thumbFromActiveClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-from--active'] }], thumbToActiveClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-to--active'] }], thumbFromDisabledClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-from--disabled'] }], thumbToDisabledClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-to--disabled'] }], thumbFromPressedClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-from--pressed'] }], thumbToPressedClass: [{ type: HostBinding, args: ['class.igx-slider-thumb-to--pressed'] }], onPointerEnter: [{ type: HostListener, args: ['pointerenter'] }], onPointerLeave: [{ type: HostListener, args: ['pointerleave'] }], onKeyUp: [{ type: HostListener, args: ['keyup', ['$event']] }], onKeyDown: [{ type: HostListener, args: ['keydown', ['$event']] }], onBlur: [{ type: HostListener, args: ['blur'] }], onFocusListener: [{ type: HostListener, args: ['focus'] }] } }); /** * @hidden */ class IgxTickLabelsPipe { transform(labels, secondaryTicks) { if (!labels) { return; } const result = []; labels.forEach(item => { result.push(item); for (let i = 0; i < secondaryTicks; i++) { result.push(''); } }); return result; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTickLabelsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); } static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.2", ngImport: i0, type: IgxTickLabelsPipe, isStandalone: true, name: "spreadTickLabels" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTickLabelsPipe, decorators: [{ type: Pipe, args: [{ name: 'spreadTickLabels', standalone: true }] }] }); /** * @hidden */ class IgxTicksComponent { constructor() { /** * @hidden */ this.ticksClass = true; } /** * @hidden */ get ticksTopClass() { return this.ticksOrientation === TicksOrientation.Top; } /** * @hidden */ get hasPrimaryClass() { return this.primaryTicks > 0; } /** * @hidden */ get labelsTopToBottomClass() { return this.tickLabelsOrientation === TickLabelsOrientation.TopToBottom; } /** * @hidden */ get labelsBottomToTopClass() { return this.tickLabelsOrientation === TickLabelsOrientation.BottomToTop; } /** * Returns the template context corresponding to * {@link IgxTickLabelTemplateDirective} * * ```typescript * return { * $implicit //returns the value per each tick label. * isPrimery //returns if the tick is primary. * labels // returns the {@link labels} collection. * index // returns the index per each tick of the whole sequence. * } * ``` * * @param idx the index per each tick label. */ context(idx) { return { $implicit: this.tickLabel(idx), isPrimary: this.isPrimary(idx), labels: this.labels, index: idx }; } /** * @hidden */ get ticksLength() { return this.primaryTicks > 0 ? ((this.primaryTicks - 1) * this.secondaryTicks) + this.primaryTicks : this.secondaryTicks > 0 ? this.secondaryTicks : 0; } hiddenTickLabels(idx) { return this.isPrimary(idx) ? this.primaryTickLabels : this.secondaryTickLabels; } /** * @hidden */ isPrimary(idx) { return this.primaryTicks <= 0 ? false : idx % (this.secondaryTicks + 1) === 0; } /** * @hidden */ tickLabel(idx) { if (this.labelsViewEnabled) { return this.labels[idx]; } const labelStep = (Math.max(this.minValue, this.maxValue) - Math.min(this.minValue, this.maxValue)) / (this.ticksLength - 1); const labelVal = labelStep * idx; return (this.minValue + labelVal).toFixed(2); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTicksComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.2", type: IgxTicksComponent, isStandalone: true, selector: "igx-ticks", inputs: { primaryTicks: "primaryTicks", secondaryTicks: "secondaryTicks", primaryTickLabels: ["primaryTickLabels", "primaryTickLabels", booleanAttribute], secondaryTickLabels: ["secondaryTickLabels", "secondaryTickLabels", booleanAttribute], ticksOrientation: "ticksOrientation", tickLabelsOrientation: "tickLabelsOrientation", maxValue: "maxValue", minValue: "minValue", labelsViewEnabled: ["labelsViewEnabled", "labelsViewEnabled", booleanAttribute], labels: "labels", tickLabelTemplateRef: "tickLabelTemplateRef" }, host: { properties: { "class.igx-slider__ticks": "this.ticksClass", "class.igx-slider__ticks--top": "this.ticksTopClass", "class.igx-slider__ticks--tall": "this.hasPrimaryClass", "class.igx-slider__tick-labels--top-bottom": "this.labelsTopToBottomClass", "class.igx-slider__tick-labels--bottom-top": "this.labelsBottomToTopClass" } }, ngImport: i0, template: "@for (n of [].constructor(ticksLength); track $index; let idx = $index) {\n <div class=\"igx-slider__ticks-group\" [ngClass]=\"{ 'igx-slider__ticks-group--tall': isPrimary(idx)}\">\n <div class=\"igx-slider__ticks-tick\">\n <span class=\"igx-slider__ticks-label\" [ngClass]=\"{ 'igx-slider__tick-label--hidden': !hiddenTickLabels(idx)}\">\n <ng-container *ngTemplateOutlet=\"tickLabelTemplateRef ? tickLabelTemplateRef : tickLabelDefaultTemplate; context: context(idx)\"></ng-container>\n </span>\n </div>\n </div>\n}\n\n<ng-template #tickLabelDefaultTemplate let-value>\n {{ value }}\n</ng-template>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.2", ngImport: i0, type: IgxTicksComponent, decorators: [{ type: Component, args: [{ selector: 'igx-ticks', imports: [NgClass, NgTemplateOutlet], template: "@for (n of [].constructor(ticksLength); track $index; let idx = $index) {\n <div class=\"igx-slider__ticks-group\" [ngClass]=\"{ 'igx-slider__ticks-group--tall': isPrimary(idx)}\">\n <div class=\"igx-slider__ticks-tick\">\n <span class=\"igx-slider__ticks-label\" [ngClass]=\"{ 'igx-slider__tick-label--hidden': !hiddenTickLabels(idx)}\">\n <ng-container *ngTemplateOutlet=\"tickLabelTemplateRef ? tickLabelTemplateRef : tickLabelDefaultTemplate; context: context(idx)\"></ng-container>\n </span>\n </div>\n </div>\n}\n\n<ng-template #tickLabelDefaultTemplate let-value>\n {{ value }}\n</ng-template>\n" }] }], propDecorators: { primaryTicks: [{ type: Input }], secondaryTicks: [{ type: Input }], primaryTickLabels: [{ type: Input, args: [{ transform: booleanAttribute }] }], secondaryTickLabels: [{ type: Input, args: [{ transform: booleanAttribute }] }], ticksOrientation: [{ type: Input }], tickLabelsOrientation: [{ type: Input }], maxValue: [{ type: Input }], minValue: [{ type: Input }], labelsViewEnabled: [{ type: Input, args: [{ transform: booleanAttribute }] }], labels: [{ type: Input }], tickLabelTemplateRef: [{ type: Input }], ticksClass: [{ type: HostBinding, args: ['class.igx-slider__ticks'] }], ticksTopClass: [{ type: HostBinding, args: ['class.igx-slider__ticks--top'] }], hasPrimaryClass: [{ type: HostBinding, args: ['class.igx-slider__ticks--tall'] }], labelsTopToBottomClass: [{ type: HostBinding, args: ['class.igx-slider__tick-labels--top-bottom'] }], labelsBottomToTopClass: [{ type: HostBinding, args: ['class.igx-slider__tick-labels--bottom-top'] }] } }); let NEXT_ID = 0; /** * **Ignite UI for Angular Slider** - * [Documentation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/slider/slider) * * The Ignite UI Slider allows selection in a given range by moving the thumb along the track. The track * can be defined as continuous or stepped, and you can choose between single and range slider types. * * Example: * ```html * <igx-slider id="slider" * [minValue]="0" [maxValue]="100" * [continuous]=true [(ngModel)]="volume"> * </igx-slider> * ``` */ class IgxSliderComponent { /** * @hidden */ get thumbFrom() { return this.thumbs.find(thumb => thumb.type === SliderHandle.FROM); } /** * @hidden */ get thumbTo() { return this.thumbs.find(thumb => thumb.type === SliderHandle.TO); } get labelFrom() { return this.labelRefs.find(label => label.type === SliderHandle.FROM); } get labelTo() { return this.labelRefs.find(label => label.type === SliderHandle.TO); } /** * @hidden */ get disabledClass() { return this.disabled; } /** * Gets the type of the `IgxSliderComponent`. * The slider can be IgxSliderType.SLIDER(default) or IgxSliderType.RANGE. * ```typescript * @ViewChild("slider2") * public slider: IgxSliderComponent; * ngAfterViewInit(){ * let type = this.slider.type; * } */ get type() { return this._type; } /** * Sets the type of the `IgxSliderComponent`. * The slider can be IgxSliderType.SLIDER(default) or IgxSliderType.RANGE. * ```typescript * sliderType: IgxSliderType = IgxSliderType.RANGE; * ``` * ```html * <igx-slider #slider2 [type]="sliderType" [(ngModel)]="rangeValue" [minValue]="0" [maxValue]="100"> * ``` */ set type(type) { this._type = type; if (type === IgxSliderType.SLIDER) { this.lowerValue = 0; } if (this._hasViewInit) { this.updateTrack(); } } /** * Enables `labelView`, by accepting a collection of primitive values with more than one element. * Each element will be equally spread over the slider and it will serve as a thumb label. * Once the property is set, it will precendence over {@link maxValue}, {@link minValue}, {@link step}. * This means that the manipulation for those properties won't be allowed. */ get labels() { return this._labels; } set labels(labels) { this._labels = labels; this._pMax = this.valueToFraction(this.upperBound, 0, 1); this._pMin = this.valueToFraction(this.lowerBound, 0, 1); this.positionHandlersAndUpdateTrack(); if (this._hasViewInit) { this.stepDistance = this.calculateStepDistance(); this.setTickInterval(); } } /** * Returns the template context corresponding * to {@link IgxThumbFromTemplateDirective} and {@link IgxThumbToTemplateDirective} templates. * * ```typescript * return { * $implicit // returns the value of the label, * labels // returns the labels collection the user has passed. * } * ``` */ get context() { return { $implicit: this.value, labels: this.labels }; } /** * Sets the incremental/decremental step of the value when dragging the thumb. * The default step is 1, and step should not be less or equal than 0. * ```html * <igx-slider #slider [(ngModel)]="task.percentCompleted" [step]="5"> * ``` */ set step(step) { this._step = step; if (this._hasViewInit) { this.stepDistance = this.calculateStepDistance(); this.normalizeByStep(this._value); this.setValue(this._value, true); this.positionHandlersAndUpdateTrack(); this.setTickInterval(); } } /** * Returns the incremental/decremental dragging step of the {@link IgxSliderComponent}. * ```typescript * @ViewChild("slider2") * public slider: IgxSliderComponent; * ngAfterViewInit(){ * let step = this.slider.step; * } * ``` */ get step() { return this.labelsViewEnabled ? 1 : this._step; } /** * Returns if the {@link IgxSliderComponent} is disabled. * ```typescript * @ViewChild("slider2") * public slider: IgxSliderComponent; * ngAfterViewInit(){ * let isDisabled = this.slider.disabled; * } * ``` */ get disabled() { return this._disabled; } /** * Disables the component. * ```html * <igx-slider #slider [disabled]="true" [(ngModel)]="task.percentCompleted" [step]="5" [lowerBound]="20"> * ``` */ set disabled(disable) { this._disabled = disable; if (this._hasViewInit) { this.changeThumbFocusableState(disable); } } /** * Returns if the {@link IgxSliderComponent} is set as continuous. * ```typescript * @ViewChild("slider2") * public slider: IgxSliderComponent; * ngAfterViewInit(){ * let continuous = this.slider.continuous; * } * ``` */ get continuous() { return this._continuous; } /** * Sets the {@link IgxSliderComponent} as continuous. * By default is considered that the {@link IgxSliderComponent} is discrete. * Discrete {@link IgxSliderComponent} slider has step indicators over the track and visible thumb labels during interaction. * Continuous {@link IgxSliderComponent} does not have ticks and does not show bubble labels for values. * ```html * <igx-slider #slider [continuous]="'true'" [(ngModel)]="task.percentCompleted" [step]="5" [lowerBound]="20"> * ``` */ set continuous(continuous) { this._continuous = continuous; if (this._hasViewInit) { this.setTickInterval(); } } /** * Returns the minimal displayed track value of the `IgxSliderComponent`. * ```typescript * @ViewChild("slider2") * public slider: IgxSliderComponent; * ngAfterViewInit(){ * let sliderMin = this.slider.minValue; * } * ``` */ get minValue() { if (this.labelsViewEnabled) { return 0; } return this._minValue; } /** * Sets the minimal displayed track value for the `IgxSliderComponent`. * The default minimal value is 0. * ```html * <igx-slider [type]="sliderType" [minValue]="56" [maxValue]="100"> * ``` */ set minValue(value) { if (value >= this.maxValue) { return; } else { this._minValue = value; } if (value > this._upperBound) { this.updateUpperBoundAndMaxTravelZone(); this.lowerBound = value; } // Refresh min travel zone limit. this._pMin = 0; // Recalculate step distance. this.positionHandlersAndUpdateTrack(); if (this._hasViewInit) { this.stepDistance = this.calculateStepDistance(); this.setTickInterval(); } } /** * Returns the maximum displayed track value for the {@link IgxSliderComponent}. * ```typescript * @ViewChild("slider") * public slider: IgxSliderComponent; * ngAfterViewInit(){ * let sliderMax = this.slider.maxValue; * } * ``` */ get maxValue() { return this.labelsViewEnabled ? this.labels.length - 1 : this._maxValue; } /** * Sets the maximal displayed track value for the `IgxSliderComponent`. * The default maximum value is 100. * ```html * <igx-slider [type]="sliderType" [minValue]="56" [maxValue]="256"> * ``` */ set maxValue(value) { if (value <= this._minValue) { return; } else { this._maxValue = value; } if (value < this._lowerBound) { this.updateLowerBoundAndMinTravelZone(); this.upperBound = value; } // refresh max travel zone limits. this._pMax = 1; // recalculate step distance. this.positionHandlersAndUpdateTrack(); if (this._hasViewInit) { this.stepDistance = this.calculateStepDistance(); this.setTickInterval(); } } /** * Returns the lower boundary of settable values of the `IgxSliderComponent`. * If not set, will return `minValue`. * ```typescript * @ViewChild("slider") * public slider: IgxSliderComponent; * ngAfterViewInit(){ * let sliderLowBound = this.slider.lowerBound; * } * ``` */ get lowerBound() { if (!Number.isNaN(this._lowerBound) && this._lowerBound !== undefined) { return this.valueInRange(this._lowerBound, this.minValue, this.maxValue); } return this.minValue; } /** * Sets the lower boundary of settable values of the `IgxSliderComponent`. * If not set is the same as min value. * ```html * <igx-slider [step]="5" [lowerBound]="20"> * ``` */ set lowerBound(value) { if (value >= this.upperBound || (this.labelsViewEnabled && value < 0)) { return; } this._lowerBound = this.valueInRange(value, this.minValue, this.maxValue); // Refresh min travel zone. this._pMin = this.valueToFraction(this._lowerBound, 0, 1); this.positionHandlersAndUpdateTrack(); } /** * Returns the upper boundary of settable values of the `IgxSliderComponent`. * If not set, will return `maxValue` * ```typescript * @ViewChild("slider") * public slider: IgxSliderComponent; * ngAfterViewInit(){ * let sliderUpBound = this.slider.upperBound; * } * ``` */ get upperBound() { if (!Number.isNaN(this._upperBound) && this._upperBound !== undefined) { return this.valueInRange(this._upperBound, this.minValue, this.maxValue); } return this.maxValue; } /** * Sets the upper boundary of the `IgxSliderComponent`. * If not set is the same as max value. * ```html * <igx-slider [step]="5" [upperBound]="20"> * ``` */ set upperBound(value) { if (value <= this.lowerBound || (this.labelsViewEnabled && value > this.labels.length - 1)) { return; } this._upperBound = this.valueInRange(value, this.minValue, this.maxValue); // Refresh time travel zone. this._pMax = this.valueToFraction(this._upperBound, 0, 1); this.positionHandlersAndUpdateTrack(); } /** * Returns the slider value. If the slider is of type {@link IgxSliderType.SLIDER} the returned value is number. * If the slider type is {@link IgxSliderType.RANGE}. * The returned value represents an object of {@link lowerValue} and {@link upperValue}. * ```typescript * @ViewChild("slider2") * public slider: IgxSliderComponent; * public sliderValue(event){ * let sliderVal = this.slider.value; * } * ``` */ get value() { if (this.isRange) { return { lower: this.valueInRange(this.lowerValue, this.lowerBound, this.upperBound), upper: this.valueInRange(this.upperValue, this.lowerBound, this.upperBound) }; } else { return this.valueInRange(this.upperValue, this.lowerBound, this.upperBound); } } /** * Sets the slider value. * If the slider is of type {@link IgxSliderType.SLIDER}. * The argument is number. By default the {@link value} gets the {@link lowerBound}. * If the slider type is {@link IgxSliderType.RANGE} the argument * represents an object of {@link lowerValue} and {@link upperValue} properties. * By default the object is associated with the {@link lowerBound} and {@link upperBound} property values. * ```typescript * rangeValue = { * lower: 30, * upper: 60 * }; * ``` * ```html * <igx-slider [type]="sliderType" [(ngModel)]="rangeValue" [minValue]="56" [maxValue]="256"> * ``` */ set value(value) { this.normalizeByStep(value); if (this._hasViewInit) { this.setValue(this._value, true); this.positionHandlersAndUpdateTrack(); } } /** * Returns the number of the presented primary ticks. * ```typescript * const primaryTicks = this.slider.primaryTicks; * ``` */ get primaryTicks() { if (this.labelsViewEnabled) { return this._primaryTicks = this.labels.length; } return this._primaryTicks; } /** * Sets the number of primary ticks. If {@link @labels} is enabled, this property won't function. * Insted enable ticks by {@link showTicks} property. * ```typescript * this.slider.primaryTicks = 5; * ``` */ set primaryTicks(val) { if (val <= 1) { return; } this._primaryTicks = val; } /** * Returns the number of the presented secondary ticks. * ```typescript * const secondaryTicks = this.slider.secondaryTicks; * ``` */ get secondaryTicks() { return this._secondaryTicks; } /** * Sets the number of secondary ticks. The property functions even when {@link labels} is enabled, * but all secondary ticks won't present any tick labels. * ```typescript * this.slider.secondaryTicks = 5; * ``` */ set secondaryTicks(val) { if (val < 1) { return; } this._secondaryTicks = val; } /** * @hidden */ get deactivateThumbLabel() { return ((this.primaryTicks && this.primaryTickLabels) || (this.secondaryTicks && this.secondaryTickLabels)) && (this.ticksOrientation === TicksOrientation.Top || this.ticksOrientation === TicksOrientation.Mirror); } constructor() { this.renderer = inject(Renderer2); this._el = inject(ElementRef); this._cdr = inject(ChangeDetectorRef); this._ngZone = inject(NgZone); this._dir = inject(_IgxDirectionality); /** * @hidden */ this.slierClass = true; /** * Sets the value of the `id` attribute. * If not provided it will be automatically generated. * ```html * <igx-slider [id]="'igx-slider-32'" [(ngModel)]="task.percentCompleted" [step]="5" [lowerBound]="20"> * ``` */ this.id = `igx-slider-${NEXT_ID++}`; /** * Sets the duration visibility of thumbs labels. The default value is 750 milliseconds. * ```html * <igx-slider #slider [thumbLabelVisibilityDuration]="3000" [(ngModel)]="task.percentCompleted" [step]="5"> * ``` */ this.thumbLabelVisibilityDuration = 750; /** * Show/hide slider ticks * ```html * <igx-slier [showTicks]="true" [primaryTicks]="5"></igx-slier> * ``` */ this.showTicks = false; /** * show/hide primary tick labels * ```html * <igx-slider [primaryTicks]="5" [primaryTickLabels]="false"></igx-slider> * ``` */ this.primaryTickLabels = true; /** * show/hide secondary tick labels * ```html * <igx-slider [secondaryTicks]="5" [secondaryTickLabels]="false"></igx-slider> * ``` */ this.secondaryTickLabels = true; /** * Changes ticks orientation: * bottom - The default orienation, below the slider track. * top - Above the slider track * mirror - combines top and bottom orientation. * ```html * <igx-slider [primaryTicks]="5" [ticksOrientation]="ticksOrientation"></igx-slider> * ``` */ this.ticksOrientation = TicksOrientation.Bottom; /** * Changes tick labels rotation: * horizontal - The default rotation * toptobottom - Rotates tick labels vertically to 90deg * bottomtotop - Rotate tick labels vertically to -90deg * ```html * <igx-slider [primaryTicks]="5" [secondaryTicks]="3" [tickLabelsOrientation]="tickLabelsOrientaiton"></igx-slider> * ``` */ this.tickLabelsOrientation = TickLabelsOrientation.Horizontal; /** * This event is emitted every time the value is changed. * ```typescript * public change(event){ * alert("The value has been changed!"); * } * ``` * ```html * <igx-slider (valueChange)="change($event)" #slider [(ngModel)]="task.percentCompleted" [step]="5"> * ``` */ this.valueChange = new EventEmitter(); /** * This event is emitted every time the lower value of a range slider is changed. * ```typescript * public change(value){ * alert(`The lower value has been changed to ${value}`); * } * ``` * ```html * <igx-slider [(lowerValue)]="model.lowervalue" (lowerValueChange)="change($event)" [step]="5"> * ``` */ this.lowerValueChange = new EventEmitter(); /** * This event is emitted every time the upper value of a range slider is changed. * ```typescript * public change(value){ * alert(`The upper value has been changed to ${value}`); * } * ``` * ```html * <igx-slider [(upperValue)]="model.uppervalue" (upperValueChange)="change($event)" [step]="5"> * ``` */ this.upperValueChange = new EventEmitter(); /** * This event is emitted at the end of every slide interaction. * ```typescript * public change(event){ * alert("The value has been changed!"); * } * ``` * ```html * <igx-slider (dragFinished)="change($event)" #slider [(ngModel)]="task.percentCompleted" [step]="5"> * ``` */ this.dragFinished = new EventEmitter(); /** * @hidden */ this.thumbs = new QueryList(); /** * @hidden */ this.labelRefs = new QueryList(); /** * @hidden */ this.onPan = new Subject(); // Limit handle travel zone this._pMin = 0; this._pMax = 1; // From/upperValue in percent values this._hasViewInit = false; this._minValue = 0; this._maxValue = 100; this._continuous = false; this._disabled = false; this._step = 1; this._value = 0; // ticks this._primaryTicks = 0; this._secondaryTicks = 0; this._sliding = false; this._labels = new Array(); this._type = IgxSliderType.SLIDER; this._destroyer$ = new Subject(); this._indicatorsDestroyer$ = new Subject(); this._onChangeCallback = noop; this._onTouchedCallback = noop; this.stepDistance = this._step; } /** * @hidden */ onFocus() { this.toggleSliderIndicators(); } /** * Returns whether the `IgxSliderComponent` type is RANGE. * ```typescript * @ViewChild("slider") * public slider: IgxSliderComponent; * ngAfterViewInit(){ * let sliderRange = this.slider.isRange; * } * ``` */ get isRange() { return this.type === IgxSliderType.RANGE; } /** * Returns the lower value of a RANGE `IgxSliderComponent`. * ```typescript * @ViewChild("slider") * public slider: IgxSliderComponent; * public lowValue(event){ * let sliderLowValue = this.slider.lowerValue; * } * ``` */ get lowerValue() { if (!Number.isNaN(this._lowerValue) && this._lowerValue !== undefined && this._lowerValue >= this.lowerBound) { return this._lowerValue; } return this.lowerBound; } /** * Sets the lower value of a RANGE `IgxSliderComponent`. * ```typescript * @ViewChild("slider") * public slider: IgxSliderComponent; * public lowValue(event){ * this.slider.lowerValue = value; * } * ``` */ set lowerValue(value) { const adjustedValue = this.valueInRange(value, this.lowerBound, this.upperBound); if (this._lowerValue !== adjustedValue) { this._lowerValue = adjustedValue; this.lowerValueChange.emit(this._lowerValue); this.value = { lower: this._lowerValue, upper: this._upperValue }; } } /** * Returns the upper value of a RANGE `IgxSliderComponent`. * Re