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