slider.mjs 99 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642
  1. import * as i2$1 from '@angular/cdk/bidi';
  2. import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
  3. import * as i1 from '@angular/cdk/platform';
  4. import * as i0 from '@angular/core';
  5. import { InjectionToken, Component, ChangeDetectionStrategy, ViewEncapsulation, Inject, Input, ViewChild, Optional, ViewChildren, ContentChild, ContentChildren, forwardRef, EventEmitter, Directive, Output, NgModule } from '@angular/core';
  6. import * as i2 from '@angular/material/core';
  7. import { MatRipple, mixinColor, mixinDisableRipple, MAT_RIPPLE_GLOBAL_OPTIONS, MatCommonModule, MatRippleModule } from '@angular/material/core';
  8. import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';
  9. import * as i3 from '@angular/common';
  10. import { CommonModule } from '@angular/common';
  11. import { NG_VALUE_ACCESSOR } from '@angular/forms';
  12. import { Subject } from 'rxjs';
  13. /**
  14. * Injection token that can be used for a `MatSlider` to provide itself as a
  15. * parent to the `MatSliderThumb` and `MatSliderRangeThumb`.
  16. * Used primarily to avoid circular imports.
  17. * @docs-private
  18. */
  19. const MAT_SLIDER = new InjectionToken('_MatSlider');
  20. /**
  21. * Injection token that can be used to query for a `MatSliderThumb`.
  22. * Used primarily to avoid circular imports.
  23. * @docs-private
  24. */
  25. const MAT_SLIDER_THUMB = new InjectionToken('_MatSliderThumb');
  26. /**
  27. * Injection token that can be used to query for a `MatSliderRangeThumb`.
  28. * Used primarily to avoid circular imports.
  29. * @docs-private
  30. */
  31. const MAT_SLIDER_RANGE_THUMB = new InjectionToken('_MatSliderRangeThumb');
  32. /**
  33. * Injection token that can be used to query for a `MatSliderVisualThumb`.
  34. * Used primarily to avoid circular imports.
  35. * @docs-private
  36. */
  37. const MAT_SLIDER_VISUAL_THUMB = new InjectionToken('_MatSliderVisualThumb');
  38. /**
  39. * A simple change event emitted by the MatSlider component.
  40. * @deprecated Use event bindings directly on the MatSliderThumbs for `change` and `input` events. See https://material.angular.io/guide/mdc-migration for information about migrating.
  41. * @breaking-change 17.0.0
  42. */
  43. class MatSliderChange {
  44. }
  45. /**
  46. * The visual slider thumb.
  47. *
  48. * Handles the slider thumb ripple states (hover, focus, and active),
  49. * and displaying the value tooltip on discrete sliders.
  50. * @docs-private
  51. */
  52. class MatSliderVisualThumb {
  53. constructor(_cdr, _ngZone, _elementRef, _slider) {
  54. this._cdr = _cdr;
  55. this._ngZone = _ngZone;
  56. this._slider = _slider;
  57. /** Whether the slider thumb is currently being hovered. */
  58. this._isHovered = false;
  59. /** Whether the slider thumb is currently being pressed. */
  60. this._isActive = false;
  61. /** Whether the value indicator tooltip is visible. */
  62. this._isValueIndicatorVisible = false;
  63. this._onPointerMove = (event) => {
  64. if (this._sliderInput._isFocused) {
  65. return;
  66. }
  67. const rect = this._hostElement.getBoundingClientRect();
  68. const isHovered = this._isSliderThumbHovered(event, rect);
  69. this._isHovered = isHovered;
  70. if (isHovered) {
  71. this._showHoverRipple();
  72. }
  73. else {
  74. this._hideRipple(this._hoverRippleRef);
  75. }
  76. };
  77. this._onMouseLeave = () => {
  78. this._isHovered = false;
  79. this._hideRipple(this._hoverRippleRef);
  80. };
  81. this._onFocus = () => {
  82. // We don't want to show the hover ripple on top of the focus ripple.
  83. // Happen when the users cursor is over a thumb and then the user tabs to it.
  84. this._hideRipple(this._hoverRippleRef);
  85. this._showFocusRipple();
  86. this._hostElement.classList.add('mdc-slider__thumb--focused');
  87. };
  88. this._onBlur = () => {
  89. // Happens when the user tabs away while still dragging a thumb.
  90. if (!this._isActive) {
  91. this._hideRipple(this._focusRippleRef);
  92. }
  93. // Happens when the user tabs away from a thumb but their cursor is still over it.
  94. if (this._isHovered) {
  95. this._showHoverRipple();
  96. }
  97. this._hostElement.classList.remove('mdc-slider__thumb--focused');
  98. };
  99. this._onDragStart = (event) => {
  100. if (event.button !== 0) {
  101. return;
  102. }
  103. this._isActive = true;
  104. this._showActiveRipple();
  105. };
  106. this._onDragEnd = () => {
  107. this._isActive = false;
  108. this._hideRipple(this._activeRippleRef);
  109. // Happens when the user starts dragging a thumb, tabs away, and then stops dragging.
  110. if (!this._sliderInput._isFocused) {
  111. this._hideRipple(this._focusRippleRef);
  112. }
  113. };
  114. this._hostElement = _elementRef.nativeElement;
  115. }
  116. ngAfterViewInit() {
  117. this._ripple.radius = 24;
  118. this._sliderInput = this._slider._getInput(this.thumbPosition);
  119. this._sliderInputEl = this._sliderInput._hostElement;
  120. const input = this._sliderInputEl;
  121. // These listeners don't update any data bindings so we bind them outside
  122. // of the NgZone to prevent Angular from needlessly running change detection.
  123. this._ngZone.runOutsideAngular(() => {
  124. input.addEventListener('pointermove', this._onPointerMove);
  125. input.addEventListener('pointerdown', this._onDragStart);
  126. input.addEventListener('pointerup', this._onDragEnd);
  127. input.addEventListener('pointerleave', this._onMouseLeave);
  128. input.addEventListener('focus', this._onFocus);
  129. input.addEventListener('blur', this._onBlur);
  130. });
  131. }
  132. ngOnDestroy() {
  133. const input = this._sliderInputEl;
  134. input.removeEventListener('pointermove', this._onPointerMove);
  135. input.removeEventListener('pointerdown', this._onDragStart);
  136. input.removeEventListener('pointerup', this._onDragEnd);
  137. input.removeEventListener('pointerleave', this._onMouseLeave);
  138. input.removeEventListener('focus', this._onFocus);
  139. input.removeEventListener('blur', this._onBlur);
  140. }
  141. /** Handles displaying the hover ripple. */
  142. _showHoverRipple() {
  143. if (!this._isShowingRipple(this._hoverRippleRef)) {
  144. this._hoverRippleRef = this._showRipple({ enterDuration: 0, exitDuration: 0 });
  145. this._hoverRippleRef?.element.classList.add('mat-mdc-slider-hover-ripple');
  146. }
  147. }
  148. /** Handles displaying the focus ripple. */
  149. _showFocusRipple() {
  150. // Show the focus ripple event if noop animations are enabled.
  151. if (!this._isShowingRipple(this._focusRippleRef)) {
  152. this._focusRippleRef = this._showRipple({ enterDuration: 0, exitDuration: 0 }, true);
  153. this._focusRippleRef?.element.classList.add('mat-mdc-slider-focus-ripple');
  154. }
  155. }
  156. /** Handles displaying the active ripple. */
  157. _showActiveRipple() {
  158. if (!this._isShowingRipple(this._activeRippleRef)) {
  159. this._activeRippleRef = this._showRipple({ enterDuration: 225, exitDuration: 400 });
  160. this._activeRippleRef?.element.classList.add('mat-mdc-slider-active-ripple');
  161. }
  162. }
  163. /** Whether the given rippleRef is currently fading in or visible. */
  164. _isShowingRipple(rippleRef) {
  165. return rippleRef?.state === 0 /* RippleState.FADING_IN */ || rippleRef?.state === 1 /* RippleState.VISIBLE */;
  166. }
  167. /** Manually launches the slider thumb ripple using the specified ripple animation config. */
  168. _showRipple(animation, ignoreGlobalRippleConfig) {
  169. if (this._slider.disabled) {
  170. return;
  171. }
  172. this._showValueIndicator();
  173. if (this._slider._isRange) {
  174. const sibling = this._slider._getThumb(this.thumbPosition === 1 /* _MatThumb.START */ ? 2 /* _MatThumb.END */ : 1 /* _MatThumb.START */);
  175. sibling._showValueIndicator();
  176. }
  177. if (this._slider._globalRippleOptions?.disabled && !ignoreGlobalRippleConfig) {
  178. return;
  179. }
  180. return this._ripple.launch({
  181. animation: this._slider._noopAnimations ? { enterDuration: 0, exitDuration: 0 } : animation,
  182. centered: true,
  183. persistent: true,
  184. });
  185. }
  186. /**
  187. * Fades out the given ripple.
  188. * Also hides the value indicator if no ripple is showing.
  189. */
  190. _hideRipple(rippleRef) {
  191. rippleRef?.fadeOut();
  192. if (this._isShowingAnyRipple()) {
  193. return;
  194. }
  195. if (!this._slider._isRange) {
  196. this._hideValueIndicator();
  197. }
  198. const sibling = this._getSibling();
  199. if (!sibling._isShowingAnyRipple()) {
  200. this._hideValueIndicator();
  201. sibling._hideValueIndicator();
  202. }
  203. }
  204. /** Shows the value indicator ui. */
  205. _showValueIndicator() {
  206. this._hostElement.classList.add('mdc-slider__thumb--with-indicator');
  207. }
  208. /** Hides the value indicator ui. */
  209. _hideValueIndicator() {
  210. this._hostElement.classList.remove('mdc-slider__thumb--with-indicator');
  211. }
  212. _getSibling() {
  213. return this._slider._getThumb(this.thumbPosition === 1 /* _MatThumb.START */ ? 2 /* _MatThumb.END */ : 1 /* _MatThumb.START */);
  214. }
  215. /** Gets the value indicator container's native HTML element. */
  216. _getValueIndicatorContainer() {
  217. return this._valueIndicatorContainer?.nativeElement;
  218. }
  219. /** Gets the native HTML element of the slider thumb knob. */
  220. _getKnob() {
  221. return this._knob.nativeElement;
  222. }
  223. _isShowingAnyRipple() {
  224. return (this._isShowingRipple(this._hoverRippleRef) ||
  225. this._isShowingRipple(this._focusRippleRef) ||
  226. this._isShowingRipple(this._activeRippleRef));
  227. }
  228. _isSliderThumbHovered(event, rect) {
  229. const radius = rect.width / 2;
  230. const centerX = rect.x + radius;
  231. const centerY = rect.y + radius;
  232. const dx = event.clientX - centerX;
  233. const dy = event.clientY - centerY;
  234. return Math.pow(dx, 2) + Math.pow(dy, 2) < Math.pow(radius, 2);
  235. }
  236. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatSliderVisualThumb, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i0.ElementRef }, { token: MAT_SLIDER }], target: i0.ɵɵFactoryTarget.Component }); }
  237. static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: MatSliderVisualThumb, selector: "mat-slider-visual-thumb", inputs: { discrete: "discrete", thumbPosition: "thumbPosition", valueIndicatorText: "valueIndicatorText" }, host: { classAttribute: "mdc-slider__thumb mat-mdc-slider-visual-thumb" }, providers: [{ provide: MAT_SLIDER_VISUAL_THUMB, useExisting: MatSliderVisualThumb }], viewQueries: [{ propertyName: "_ripple", first: true, predicate: MatRipple, descendants: true }, { propertyName: "_knob", first: true, predicate: ["knob"], descendants: true }, { propertyName: "_valueIndicatorContainer", first: true, predicate: ["valueIndicatorContainer"], descendants: true }], ngImport: i0, template: "<div class=\"mdc-slider__value-indicator-container\" *ngIf=\"discrete\" #valueIndicatorContainer>\n <div class=\"mdc-slider__value-indicator\">\n <span class=\"mdc-slider__value-indicator-text\">{{valueIndicatorText}}</span>\n </div>\n</div>\n<div class=\"mdc-slider__thumb-knob\" #knob></div>\n<div matRipple class=\"mat-mdc-focus-indicator\" [matRippleDisabled]=\"true\"></div>\n", styles: [".mat-mdc-slider-visual-thumb .mat-ripple{height:100%;width:100%}.mat-mdc-slider .mdc-slider__tick-marks{justify-content:start}.mat-mdc-slider .mdc-slider__tick-marks .mdc-slider__tick-mark--active,.mat-mdc-slider .mdc-slider__tick-marks .mdc-slider__tick-mark--inactive{position:absolute;left:2px}"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
  238. }
  239. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatSliderVisualThumb, decorators: [{
  240. type: Component,
  241. args: [{ selector: 'mat-slider-visual-thumb', host: {
  242. 'class': 'mdc-slider__thumb mat-mdc-slider-visual-thumb',
  243. }, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [{ provide: MAT_SLIDER_VISUAL_THUMB, useExisting: MatSliderVisualThumb }], template: "<div class=\"mdc-slider__value-indicator-container\" *ngIf=\"discrete\" #valueIndicatorContainer>\n <div class=\"mdc-slider__value-indicator\">\n <span class=\"mdc-slider__value-indicator-text\">{{valueIndicatorText}}</span>\n </div>\n</div>\n<div class=\"mdc-slider__thumb-knob\" #knob></div>\n<div matRipple class=\"mat-mdc-focus-indicator\" [matRippleDisabled]=\"true\"></div>\n", styles: [".mat-mdc-slider-visual-thumb .mat-ripple{height:100%;width:100%}.mat-mdc-slider .mdc-slider__tick-marks{justify-content:start}.mat-mdc-slider .mdc-slider__tick-marks .mdc-slider__tick-mark--active,.mat-mdc-slider .mdc-slider__tick-marks .mdc-slider__tick-mark--inactive{position:absolute;left:2px}"] }]
  244. }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.ElementRef }, { type: undefined, decorators: [{
  245. type: Inject,
  246. args: [MAT_SLIDER]
  247. }] }]; }, propDecorators: { discrete: [{
  248. type: Input
  249. }], thumbPosition: [{
  250. type: Input
  251. }], valueIndicatorText: [{
  252. type: Input
  253. }], _ripple: [{
  254. type: ViewChild,
  255. args: [MatRipple]
  256. }], _knob: [{
  257. type: ViewChild,
  258. args: ['knob']
  259. }], _valueIndicatorContainer: [{
  260. type: ViewChild,
  261. args: ['valueIndicatorContainer']
  262. }] } });
  263. // TODO(wagnermaciel): maybe handle the following edge case:
  264. // 1. start dragging discrete slider
  265. // 2. tab to disable checkbox
  266. // 3. without ending drag, disable the slider
  267. // Boilerplate for applying mixins to MatSlider.
  268. const _MatSliderMixinBase = mixinColor(mixinDisableRipple(class {
  269. constructor(_elementRef) {
  270. this._elementRef = _elementRef;
  271. }
  272. }), 'primary');
  273. /**
  274. * Allows users to select from a range of values by moving the slider thumb. It is similar in
  275. * behavior to the native `<input type="range">` element.
  276. */
  277. class MatSlider extends _MatSliderMixinBase {
  278. /** Whether the slider is disabled. */
  279. get disabled() {
  280. return this._disabled;
  281. }
  282. set disabled(v) {
  283. this._disabled = coerceBooleanProperty(v);
  284. const endInput = this._getInput(2 /* _MatThumb.END */);
  285. const startInput = this._getInput(1 /* _MatThumb.START */);
  286. if (endInput) {
  287. endInput.disabled = this._disabled;
  288. }
  289. if (startInput) {
  290. startInput.disabled = this._disabled;
  291. }
  292. }
  293. /** Whether the slider displays a numeric value label upon pressing the thumb. */
  294. get discrete() {
  295. return this._discrete;
  296. }
  297. set discrete(v) {
  298. this._discrete = coerceBooleanProperty(v);
  299. this._updateValueIndicatorUIs();
  300. }
  301. /** Whether the slider displays tick marks along the slider track. */
  302. get showTickMarks() {
  303. return this._showTickMarks;
  304. }
  305. set showTickMarks(v) {
  306. this._showTickMarks = coerceBooleanProperty(v);
  307. }
  308. /** The minimum value that the slider can have. */
  309. get min() {
  310. return this._min;
  311. }
  312. set min(v) {
  313. const min = coerceNumberProperty(v, this._min);
  314. if (this._min !== min) {
  315. this._updateMin(min);
  316. }
  317. }
  318. _updateMin(min) {
  319. const prevMin = this._min;
  320. this._min = min;
  321. this._isRange ? this._updateMinRange({ old: prevMin, new: min }) : this._updateMinNonRange(min);
  322. this._onMinMaxOrStepChange();
  323. }
  324. _updateMinRange(min) {
  325. const endInput = this._getInput(2 /* _MatThumb.END */);
  326. const startInput = this._getInput(1 /* _MatThumb.START */);
  327. const oldEndValue = endInput.value;
  328. const oldStartValue = startInput.value;
  329. startInput.min = min.new;
  330. endInput.min = Math.max(min.new, startInput.value);
  331. startInput.max = Math.min(endInput.max, endInput.value);
  332. startInput._updateWidthInactive();
  333. endInput._updateWidthInactive();
  334. min.new < min.old
  335. ? this._onTranslateXChangeBySideEffect(endInput, startInput)
  336. : this._onTranslateXChangeBySideEffect(startInput, endInput);
  337. if (oldEndValue !== endInput.value) {
  338. this._onValueChange(endInput);
  339. }
  340. if (oldStartValue !== startInput.value) {
  341. this._onValueChange(startInput);
  342. }
  343. }
  344. _updateMinNonRange(min) {
  345. const input = this._getInput(2 /* _MatThumb.END */);
  346. if (input) {
  347. const oldValue = input.value;
  348. input.min = min;
  349. input._updateThumbUIByValue();
  350. this._updateTrackUI(input);
  351. if (oldValue !== input.value) {
  352. this._onValueChange(input);
  353. }
  354. }
  355. }
  356. /** The maximum value that the slider can have. */
  357. get max() {
  358. return this._max;
  359. }
  360. set max(v) {
  361. const max = coerceNumberProperty(v, this._max);
  362. if (this._max !== max) {
  363. this._updateMax(max);
  364. }
  365. }
  366. _updateMax(max) {
  367. const prevMax = this._max;
  368. this._max = max;
  369. this._isRange ? this._updateMaxRange({ old: prevMax, new: max }) : this._updateMaxNonRange(max);
  370. this._onMinMaxOrStepChange();
  371. }
  372. _updateMaxRange(max) {
  373. const endInput = this._getInput(2 /* _MatThumb.END */);
  374. const startInput = this._getInput(1 /* _MatThumb.START */);
  375. const oldEndValue = endInput.value;
  376. const oldStartValue = startInput.value;
  377. endInput.max = max.new;
  378. startInput.max = Math.min(max.new, endInput.value);
  379. endInput.min = startInput.value;
  380. endInput._updateWidthInactive();
  381. startInput._updateWidthInactive();
  382. max.new > max.old
  383. ? this._onTranslateXChangeBySideEffect(startInput, endInput)
  384. : this._onTranslateXChangeBySideEffect(endInput, startInput);
  385. if (oldEndValue !== endInput.value) {
  386. this._onValueChange(endInput);
  387. }
  388. if (oldStartValue !== startInput.value) {
  389. this._onValueChange(startInput);
  390. }
  391. }
  392. _updateMaxNonRange(max) {
  393. const input = this._getInput(2 /* _MatThumb.END */);
  394. if (input) {
  395. const oldValue = input.value;
  396. input.max = max;
  397. input._updateThumbUIByValue();
  398. this._updateTrackUI(input);
  399. if (oldValue !== input.value) {
  400. this._onValueChange(input);
  401. }
  402. }
  403. }
  404. /** The values at which the thumb will snap. */
  405. get step() {
  406. return this._step;
  407. }
  408. set step(v) {
  409. const step = coerceNumberProperty(v, this._step);
  410. if (this._step !== step) {
  411. this._updateStep(step);
  412. }
  413. }
  414. _updateStep(step) {
  415. this._step = step;
  416. this._isRange ? this._updateStepRange() : this._updateStepNonRange();
  417. this._onMinMaxOrStepChange();
  418. }
  419. _updateStepRange() {
  420. const endInput = this._getInput(2 /* _MatThumb.END */);
  421. const startInput = this._getInput(1 /* _MatThumb.START */);
  422. const oldEndValue = endInput.value;
  423. const oldStartValue = startInput.value;
  424. const prevStartValue = startInput.value;
  425. endInput.min = this._min;
  426. startInput.max = this._max;
  427. endInput.step = this._step;
  428. startInput.step = this._step;
  429. if (this._platform.SAFARI) {
  430. endInput.value = endInput.value;
  431. startInput.value = startInput.value;
  432. }
  433. endInput.min = Math.max(this._min, startInput.value);
  434. startInput.max = Math.min(this._max, endInput.value);
  435. startInput._updateWidthInactive();
  436. endInput._updateWidthInactive();
  437. endInput.value < prevStartValue
  438. ? this._onTranslateXChangeBySideEffect(startInput, endInput)
  439. : this._onTranslateXChangeBySideEffect(endInput, startInput);
  440. if (oldEndValue !== endInput.value) {
  441. this._onValueChange(endInput);
  442. }
  443. if (oldStartValue !== startInput.value) {
  444. this._onValueChange(startInput);
  445. }
  446. }
  447. _updateStepNonRange() {
  448. const input = this._getInput(2 /* _MatThumb.END */);
  449. if (input) {
  450. const oldValue = input.value;
  451. input.step = this._step;
  452. if (this._platform.SAFARI) {
  453. input.value = input.value;
  454. }
  455. input._updateThumbUIByValue();
  456. if (oldValue !== input.value) {
  457. this._onValueChange(input);
  458. }
  459. }
  460. }
  461. constructor(_ngZone, _cdr, _platform, elementRef, _dir, _globalRippleOptions, animationMode) {
  462. super(elementRef);
  463. this._ngZone = _ngZone;
  464. this._cdr = _cdr;
  465. this._platform = _platform;
  466. this._dir = _dir;
  467. this._globalRippleOptions = _globalRippleOptions;
  468. this._disabled = false;
  469. this._discrete = false;
  470. this._showTickMarks = false;
  471. this._min = 0;
  472. this._max = 100;
  473. this._step = 0;
  474. /**
  475. * Function that will be used to format the value before it is displayed
  476. * in the thumb label. Can be used to format very large number in order
  477. * for them to fit into the slider thumb.
  478. */
  479. this.displayWith = (value) => `${value}`;
  480. this._rippleRadius = 24;
  481. // The value indicator tooltip text for the visual slider thumb(s).
  482. /** @docs-private */
  483. this.startValueIndicatorText = '';
  484. /** @docs-private */
  485. this.endValueIndicatorText = '';
  486. this._isRange = false;
  487. /** Whether the slider is rtl. */
  488. this._isRtl = false;
  489. this._hasViewInitialized = false;
  490. /**
  491. * The width of the tick mark track.
  492. * The tick mark track width is different from full track width
  493. */
  494. this._tickMarkTrackWidth = 0;
  495. this._hasAnimation = false;
  496. this._resizeTimer = null;
  497. /** The radius of the native slider's knob. AFAIK there is no way to avoid hardcoding this. */
  498. this._knobRadius = 8;
  499. /** Whether or not the slider thumbs overlap. */
  500. this._thumbsOverlap = false;
  501. this._noopAnimations = animationMode === 'NoopAnimations';
  502. this._dirChangeSubscription = this._dir.change.subscribe(() => this._onDirChange());
  503. this._isRtl = this._dir.value === 'rtl';
  504. }
  505. ngAfterViewInit() {
  506. if (this._platform.isBrowser) {
  507. this._updateDimensions();
  508. }
  509. const eInput = this._getInput(2 /* _MatThumb.END */);
  510. const sInput = this._getInput(1 /* _MatThumb.START */);
  511. this._isRange = !!eInput && !!sInput;
  512. this._cdr.detectChanges();
  513. if (typeof ngDevMode === 'undefined' || ngDevMode) {
  514. _validateInputs(this._isRange, this._getInput(2 /* _MatThumb.END */), this._getInput(1 /* _MatThumb.START */));
  515. }
  516. const thumb = this._getThumb(2 /* _MatThumb.END */);
  517. this._rippleRadius = thumb._ripple.radius;
  518. this._inputPadding = this._rippleRadius - this._knobRadius;
  519. this._inputOffset = this._knobRadius;
  520. this._isRange
  521. ? this._initUIRange(eInput, sInput)
  522. : this._initUINonRange(eInput);
  523. this._updateTrackUI(eInput);
  524. this._updateTickMarkUI();
  525. this._updateTickMarkTrackUI();
  526. this._observeHostResize();
  527. this._cdr.detectChanges();
  528. }
  529. _initUINonRange(eInput) {
  530. eInput.initProps();
  531. eInput.initUI();
  532. this._updateValueIndicatorUI(eInput);
  533. this._hasViewInitialized = true;
  534. eInput._updateThumbUIByValue();
  535. }
  536. _initUIRange(eInput, sInput) {
  537. eInput.initProps();
  538. eInput.initUI();
  539. sInput.initProps();
  540. sInput.initUI();
  541. eInput._updateMinMax();
  542. sInput._updateMinMax();
  543. eInput._updateStaticStyles();
  544. sInput._updateStaticStyles();
  545. this._updateValueIndicatorUIs();
  546. this._hasViewInitialized = true;
  547. eInput._updateThumbUIByValue();
  548. sInput._updateThumbUIByValue();
  549. }
  550. ngOnDestroy() {
  551. this._dirChangeSubscription.unsubscribe();
  552. this._resizeObserver?.disconnect();
  553. this._resizeObserver = null;
  554. }
  555. /** Handles updating the slider ui after a dir change. */
  556. _onDirChange() {
  557. this._isRtl = this._dir.value === 'rtl';
  558. this._isRange ? this._onDirChangeRange() : this._onDirChangeNonRange();
  559. this._updateTickMarkUI();
  560. }
  561. _onDirChangeRange() {
  562. const endInput = this._getInput(2 /* _MatThumb.END */);
  563. const startInput = this._getInput(1 /* _MatThumb.START */);
  564. endInput._setIsLeftThumb();
  565. startInput._setIsLeftThumb();
  566. endInput.translateX = endInput._calcTranslateXByValue();
  567. startInput.translateX = startInput._calcTranslateXByValue();
  568. endInput._updateStaticStyles();
  569. startInput._updateStaticStyles();
  570. endInput._updateWidthInactive();
  571. startInput._updateWidthInactive();
  572. endInput._updateThumbUIByValue();
  573. startInput._updateThumbUIByValue();
  574. }
  575. _onDirChangeNonRange() {
  576. const input = this._getInput(2 /* _MatThumb.END */);
  577. input._updateThumbUIByValue();
  578. }
  579. /** Starts observing and updating the slider if the host changes its size. */
  580. _observeHostResize() {
  581. if (typeof ResizeObserver === 'undefined' || !ResizeObserver) {
  582. return;
  583. }
  584. this._ngZone.runOutsideAngular(() => {
  585. this._resizeObserver = new ResizeObserver(() => {
  586. if (this._isActive()) {
  587. return;
  588. }
  589. if (this._resizeTimer) {
  590. clearTimeout(this._resizeTimer);
  591. }
  592. this._onResize();
  593. });
  594. this._resizeObserver.observe(this._elementRef.nativeElement);
  595. });
  596. }
  597. /** Whether any of the thumbs are currently active. */
  598. _isActive() {
  599. return this._getThumb(1 /* _MatThumb.START */)._isActive || this._getThumb(2 /* _MatThumb.END */)._isActive;
  600. }
  601. _getValue(thumbPosition = 2 /* _MatThumb.END */) {
  602. const input = this._getInput(thumbPosition);
  603. if (!input) {
  604. return this.min;
  605. }
  606. return input.value;
  607. }
  608. _skipUpdate() {
  609. return !!(this._getInput(1 /* _MatThumb.START */)?._skipUIUpdate || this._getInput(2 /* _MatThumb.END */)?._skipUIUpdate);
  610. }
  611. /** Stores the slider dimensions. */
  612. _updateDimensions() {
  613. this._cachedWidth = this._elementRef.nativeElement.offsetWidth;
  614. this._cachedLeft = this._elementRef.nativeElement.getBoundingClientRect().left;
  615. }
  616. /** Sets the styles for the active portion of the track. */
  617. _setTrackActiveStyles(styles) {
  618. const trackStyle = this._trackActive.nativeElement.style;
  619. trackStyle.left = styles.left;
  620. trackStyle.right = styles.right;
  621. trackStyle.transformOrigin = styles.transformOrigin;
  622. trackStyle.transform = styles.transform;
  623. }
  624. /** Returns the translateX positioning for a tick mark based on it's index. */
  625. _calcTickMarkTransform(index) {
  626. // TODO(wagnermaciel): See if we can avoid doing this and just using flex to position these.
  627. const translateX = index * (this._tickMarkTrackWidth / (this._tickMarks.length - 1));
  628. return `translateX(${translateX}px`;
  629. }
  630. // Handlers for updating the slider ui.
  631. _onTranslateXChange(source) {
  632. if (!this._hasViewInitialized) {
  633. return;
  634. }
  635. this._updateThumbUI(source);
  636. this._updateTrackUI(source);
  637. this._updateOverlappingThumbUI(source);
  638. }
  639. _onTranslateXChangeBySideEffect(input1, input2) {
  640. if (!this._hasViewInitialized) {
  641. return;
  642. }
  643. input1._updateThumbUIByValue();
  644. input2._updateThumbUIByValue();
  645. }
  646. _onValueChange(source) {
  647. if (!this._hasViewInitialized) {
  648. return;
  649. }
  650. this._updateValueIndicatorUI(source);
  651. this._updateTickMarkUI();
  652. this._cdr.detectChanges();
  653. }
  654. _onMinMaxOrStepChange() {
  655. if (!this._hasViewInitialized) {
  656. return;
  657. }
  658. this._updateTickMarkUI();
  659. this._updateTickMarkTrackUI();
  660. this._cdr.markForCheck();
  661. }
  662. _onResize() {
  663. if (!this._hasViewInitialized) {
  664. return;
  665. }
  666. this._updateDimensions();
  667. if (this._isRange) {
  668. const eInput = this._getInput(2 /* _MatThumb.END */);
  669. const sInput = this._getInput(1 /* _MatThumb.START */);
  670. eInput._updateThumbUIByValue();
  671. sInput._updateThumbUIByValue();
  672. eInput._updateStaticStyles();
  673. sInput._updateStaticStyles();
  674. eInput._updateMinMax();
  675. sInput._updateMinMax();
  676. eInput._updateWidthInactive();
  677. sInput._updateWidthInactive();
  678. }
  679. else {
  680. const eInput = this._getInput(2 /* _MatThumb.END */);
  681. if (eInput) {
  682. eInput._updateThumbUIByValue();
  683. }
  684. }
  685. this._updateTickMarkUI();
  686. this._updateTickMarkTrackUI();
  687. this._cdr.detectChanges();
  688. }
  689. /** Returns true if the slider knobs are overlapping one another. */
  690. _areThumbsOverlapping() {
  691. const startInput = this._getInput(1 /* _MatThumb.START */);
  692. const endInput = this._getInput(2 /* _MatThumb.END */);
  693. if (!startInput || !endInput) {
  694. return false;
  695. }
  696. return endInput.translateX - startInput.translateX < 20;
  697. }
  698. /**
  699. * Updates the class names of overlapping slider thumbs so
  700. * that the current active thumb is styled to be on "top".
  701. */
  702. _updateOverlappingThumbClassNames(source) {
  703. const sibling = source.getSibling();
  704. const sourceThumb = this._getThumb(source.thumbPosition);
  705. const siblingThumb = this._getThumb(sibling.thumbPosition);
  706. siblingThumb._hostElement.classList.remove('mdc-slider__thumb--top');
  707. sourceThumb._hostElement.classList.toggle('mdc-slider__thumb--top', this._thumbsOverlap);
  708. }
  709. /** Updates the UI of slider thumbs when they begin or stop overlapping. */
  710. _updateOverlappingThumbUI(source) {
  711. if (!this._isRange || this._skipUpdate()) {
  712. return;
  713. }
  714. if (this._thumbsOverlap !== this._areThumbsOverlapping()) {
  715. this._thumbsOverlap = !this._thumbsOverlap;
  716. this._updateOverlappingThumbClassNames(source);
  717. }
  718. }
  719. // _MatThumb styles update conditions
  720. //
  721. // 1. TranslateX, resize, or dir change
  722. // - Reason: The thumb styles need to be updated according to the new translateX.
  723. // 2. Min, max, or step
  724. // - Reason: The value may have silently changed.
  725. /** Updates the translateX of the given thumb. */
  726. _updateThumbUI(source) {
  727. if (this._skipUpdate()) {
  728. return;
  729. }
  730. const thumb = this._getThumb(source.thumbPosition === 2 /* _MatThumb.END */ ? 2 /* _MatThumb.END */ : 1 /* _MatThumb.START */);
  731. thumb._hostElement.style.transform = `translateX(${source.translateX}px)`;
  732. }
  733. // Value indicator text update conditions
  734. //
  735. // 1. Value
  736. // - Reason: The value displayed needs to be updated.
  737. // 2. Min, max, or step
  738. // - Reason: The value may have silently changed.
  739. /** Updates the value indicator tooltip ui for the given thumb. */
  740. _updateValueIndicatorUI(source) {
  741. if (this._skipUpdate()) {
  742. return;
  743. }
  744. const valuetext = this.displayWith(source.value);
  745. this._hasViewInitialized
  746. ? (source._valuetext = valuetext)
  747. : source._hostElement.setAttribute('aria-valuetext', valuetext);
  748. if (this.discrete) {
  749. source.thumbPosition === 1 /* _MatThumb.START */
  750. ? (this.startValueIndicatorText = valuetext)
  751. : (this.endValueIndicatorText = valuetext);
  752. const visualThumb = this._getThumb(source.thumbPosition);
  753. valuetext.length < 3
  754. ? visualThumb._hostElement.classList.add('mdc-slider__thumb--short-value')
  755. : visualThumb._hostElement.classList.remove('mdc-slider__thumb--short-value');
  756. }
  757. }
  758. /** Updates all value indicator UIs in the slider. */
  759. _updateValueIndicatorUIs() {
  760. const eInput = this._getInput(2 /* _MatThumb.END */);
  761. const sInput = this._getInput(1 /* _MatThumb.START */);
  762. if (eInput) {
  763. this._updateValueIndicatorUI(eInput);
  764. }
  765. if (sInput) {
  766. this._updateValueIndicatorUI(sInput);
  767. }
  768. }
  769. // Update Tick Mark Track Width
  770. //
  771. // 1. Min, max, or step
  772. // - Reason: The maximum reachable value may have changed.
  773. // - Side note: The maximum reachable value is different from the maximum value set by the
  774. // user. For example, a slider with [min: 5, max: 100, step: 10] would have a maximum
  775. // reachable value of 95.
  776. // 2. Resize
  777. // - Reason: The position for the maximum reachable value needs to be recalculated.
  778. /** Updates the width of the tick mark track. */
  779. _updateTickMarkTrackUI() {
  780. if (!this.showTickMarks || this._skipUpdate()) {
  781. return;
  782. }
  783. const step = this._step && this._step > 0 ? this._step : 1;
  784. const maxValue = Math.floor(this.max / step) * step;
  785. const percentage = (maxValue - this.min) / (this.max - this.min);
  786. this._tickMarkTrackWidth = this._cachedWidth * percentage - 6;
  787. }
  788. // Track active update conditions
  789. //
  790. // 1. TranslateX
  791. // - Reason: The track active should line up with the new thumb position.
  792. // 2. Min or max
  793. // - Reason #1: The 'active' percentage needs to be recalculated.
  794. // - Reason #2: The value may have silently changed.
  795. // 3. Step
  796. // - Reason: The value may have silently changed causing the thumb(s) to shift.
  797. // 4. Dir change
  798. // - Reason: The track active will need to be updated according to the new thumb position(s).
  799. // 5. Resize
  800. // - Reason: The total width the 'active' tracks translateX is based on has changed.
  801. /** Updates the scale on the active portion of the track. */
  802. _updateTrackUI(source) {
  803. if (this._skipUpdate()) {
  804. return;
  805. }
  806. this._isRange
  807. ? this._updateTrackUIRange(source)
  808. : this._updateTrackUINonRange(source);
  809. }
  810. _updateTrackUIRange(source) {
  811. const sibling = source.getSibling();
  812. if (!sibling || !this._cachedWidth) {
  813. return;
  814. }
  815. const activePercentage = Math.abs(sibling.translateX - source.translateX) / this._cachedWidth;
  816. if (source._isLeftThumb && this._cachedWidth) {
  817. this._setTrackActiveStyles({
  818. left: 'auto',
  819. right: `${this._cachedWidth - sibling.translateX}px`,
  820. transformOrigin: 'right',
  821. transform: `scaleX(${activePercentage})`,
  822. });
  823. }
  824. else {
  825. this._setTrackActiveStyles({
  826. left: `${sibling.translateX}px`,
  827. right: 'auto',
  828. transformOrigin: 'left',
  829. transform: `scaleX(${activePercentage})`,
  830. });
  831. }
  832. }
  833. _updateTrackUINonRange(source) {
  834. this._isRtl
  835. ? this._setTrackActiveStyles({
  836. left: 'auto',
  837. right: '0px',
  838. transformOrigin: 'right',
  839. transform: `scaleX(${1 - source.fillPercentage})`,
  840. })
  841. : this._setTrackActiveStyles({
  842. left: '0px',
  843. right: 'auto',
  844. transformOrigin: 'left',
  845. transform: `scaleX(${source.fillPercentage})`,
  846. });
  847. }
  848. // Tick mark update conditions
  849. //
  850. // 1. Value
  851. // - Reason: a tick mark which was once active might now be inactive or vice versa.
  852. // 2. Min, max, or step
  853. // - Reason #1: the number of tick marks may have changed.
  854. // - Reason #2: The value may have silently changed.
  855. /** Updates the dots along the slider track. */
  856. _updateTickMarkUI() {
  857. if (!this.showTickMarks ||
  858. this.step === undefined ||
  859. this.min === undefined ||
  860. this.max === undefined) {
  861. return;
  862. }
  863. const step = this.step > 0 ? this.step : 1;
  864. this._isRange ? this._updateTickMarkUIRange(step) : this._updateTickMarkUINonRange(step);
  865. if (this._isRtl) {
  866. this._tickMarks.reverse();
  867. }
  868. }
  869. _updateTickMarkUINonRange(step) {
  870. const value = this._getValue();
  871. let numActive = Math.max(Math.round((value - this.min) / step), 0);
  872. let numInactive = Math.max(Math.round((this.max - value) / step), 0);
  873. this._isRtl ? numActive++ : numInactive++;
  874. this._tickMarks = Array(numActive)
  875. .fill(0 /* _MatTickMark.ACTIVE */)
  876. .concat(Array(numInactive).fill(1 /* _MatTickMark.INACTIVE */));
  877. }
  878. _updateTickMarkUIRange(step) {
  879. const endValue = this._getValue();
  880. const startValue = this._getValue(1 /* _MatThumb.START */);
  881. const numInactiveBeforeStartThumb = Math.max(Math.floor((startValue - this.min) / step), 0);
  882. const numActive = Math.max(Math.floor((endValue - startValue) / step) + 1, 0);
  883. const numInactiveAfterEndThumb = Math.max(Math.floor((this.max - endValue) / step), 0);
  884. this._tickMarks = Array(numInactiveBeforeStartThumb)
  885. .fill(1 /* _MatTickMark.INACTIVE */)
  886. .concat(Array(numActive).fill(0 /* _MatTickMark.ACTIVE */), Array(numInactiveAfterEndThumb).fill(1 /* _MatTickMark.INACTIVE */));
  887. }
  888. /** Gets the slider thumb input of the given thumb position. */
  889. _getInput(thumbPosition) {
  890. if (thumbPosition === 2 /* _MatThumb.END */ && this._input) {
  891. return this._input;
  892. }
  893. if (this._inputs?.length) {
  894. return thumbPosition === 1 /* _MatThumb.START */ ? this._inputs.first : this._inputs.last;
  895. }
  896. return;
  897. }
  898. /** Gets the slider thumb HTML input element of the given thumb position. */
  899. _getThumb(thumbPosition) {
  900. return thumbPosition === 2 /* _MatThumb.END */ ? this._thumbs?.last : this._thumbs?.first;
  901. }
  902. _setTransition(withAnimation) {
  903. this._hasAnimation = withAnimation && !this._noopAnimations;
  904. this._elementRef.nativeElement.classList.toggle('mat-mdc-slider-with-animation', this._hasAnimation);
  905. }
  906. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatSlider, deps: [{ token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i1.Platform }, { token: i0.ElementRef }, { token: i2$1.Directionality, optional: true }, { token: MAT_RIPPLE_GLOBAL_OPTIONS, optional: true }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
  907. static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: MatSlider, selector: "mat-slider", inputs: { color: "color", disableRipple: "disableRipple", disabled: "disabled", discrete: "discrete", showTickMarks: "showTickMarks", min: "min", max: "max", step: "step", displayWith: "displayWith" }, host: { properties: { "class.mdc-slider--range": "_isRange", "class.mdc-slider--disabled": "disabled", "class.mdc-slider--discrete": "discrete", "class.mdc-slider--tick-marks": "showTickMarks", "class._mat-animation-noopable": "_noopAnimations" }, classAttribute: "mat-mdc-slider mdc-slider" }, providers: [{ provide: MAT_SLIDER, useExisting: MatSlider }], queries: [{ propertyName: "_input", first: true, predicate: MAT_SLIDER_THUMB, descendants: true }, { propertyName: "_inputs", predicate: MAT_SLIDER_RANGE_THUMB }], viewQueries: [{ propertyName: "_trackActive", first: true, predicate: ["trackActive"], descendants: true }, { propertyName: "_thumbs", predicate: MAT_SLIDER_VISUAL_THUMB, descendants: true }], exportAs: ["matSlider"], usesInheritance: true, ngImport: i0, template: "<!-- Inputs -->\n<ng-content></ng-content>\n\n<!-- Track -->\n<div class=\"mdc-slider__track\">\n <div class=\"mdc-slider__track--inactive\"></div>\n <div class=\"mdc-slider__track--active\">\n <div #trackActive class=\"mdc-slider__track--active_fill\"></div>\n </div>\n <div *ngIf=\"showTickMarks\" class=\"mdc-slider__tick-marks\" #tickMarkContainer>\n <ng-container *ngIf=\"_cachedWidth\">\n <div\n *ngFor=\"let tickMark of _tickMarks; let i = index\"\n [class]=\"tickMark === 0 ? 'mdc-slider__tick-mark--active' : 'mdc-slider__tick-mark--inactive'\"\n [style.transform]=\"_calcTickMarkTransform(i)\"></div>\n </ng-container>\n </div>\n</div>\n\n<!-- Thumbs -->\n<mat-slider-visual-thumb\n *ngIf=\"_isRange\"\n [discrete]=\"discrete\"\n [thumbPosition]=\"1\"\n [valueIndicatorText]=\"startValueIndicatorText\">\n</mat-slider-visual-thumb>\n\n<mat-slider-visual-thumb\n [discrete]=\"discrete\"\n [thumbPosition]=\"2\"\n [valueIndicatorText]=\"endValueIndicatorText\">\n</mat-slider-visual-thumb>\n", styles: [".mdc-slider{cursor:pointer;height:48px;margin:0 24px;position:relative;touch-action:pan-y}.mdc-slider .mdc-slider__track{position:absolute;top:50%;transform:translateY(-50%);width:100%}.mdc-slider .mdc-slider__track--active,.mdc-slider .mdc-slider__track--inactive{display:flex;height:100%;position:absolute;width:100%}.mdc-slider .mdc-slider__track--active{overflow:hidden}.mdc-slider .mdc-slider__track--active_fill{border-top-style:solid;box-sizing:border-box;height:100%;width:100%;position:relative;-webkit-transform-origin:left;transform-origin:left}[dir=rtl] .mdc-slider .mdc-slider__track--active_fill,.mdc-slider .mdc-slider__track--active_fill[dir=rtl]{-webkit-transform-origin:right;transform-origin:right}.mdc-slider .mdc-slider__track--inactive{left:0;top:0}.mdc-slider .mdc-slider__track--inactive::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid rgba(0,0,0,0);border-radius:inherit;content:\"\";pointer-events:none}@media screen and (forced-colors: active){.mdc-slider .mdc-slider__track--inactive::before{border-color:CanvasText}}.mdc-slider .mdc-slider__value-indicator-container{bottom:44px;left:var(--slider-value-indicator-container-left, 50%);pointer-events:none;position:absolute;right:var(--slider-value-indicator-container-right);transform:var(--slider-value-indicator-container-transform, translateX(-50%))}.mdc-slider .mdc-slider__value-indicator{transition:transform 100ms 0ms cubic-bezier(0.4, 0, 1, 1);align-items:center;border-radius:4px;display:flex;height:32px;padding:0 12px;transform:scale(0);transform-origin:bottom}.mdc-slider .mdc-slider__value-indicator::before{border-left:6px solid rgba(0,0,0,0);border-right:6px solid rgba(0,0,0,0);border-top:6px solid;bottom:-5px;content:\"\";height:0;left:var(--slider-value-indicator-caret-left, 50%);position:absolute;right:var(--slider-value-indicator-caret-right);transform:var(--slider-value-indicator-caret-transform, translateX(-50%));width:0}.mdc-slider .mdc-slider__value-indicator::after{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid rgba(0,0,0,0);border-radius:inherit;content:\"\";pointer-events:none}@media screen and (forced-colors: active){.mdc-slider .mdc-slider__value-indicator::after{border-color:CanvasText}}.mdc-slider .mdc-slider__thumb--with-indicator .mdc-slider__value-indicator-container{pointer-events:auto}.mdc-slider .mdc-slider__thumb--with-indicator .mdc-slider__value-indicator{transition:transform 100ms 0ms cubic-bezier(0, 0, 0.2, 1);transform:scale(1)}@media(prefers-reduced-motion){.mdc-slider .mdc-slider__value-indicator,.mdc-slider .mdc-slider__thumb--with-indicator .mdc-slider__value-indicator{transition:none}}.mdc-slider .mdc-slider__thumb{display:flex;left:-24px;outline:none;position:absolute;user-select:none;height:48px;width:48px}.mdc-slider .mdc-slider__thumb--top{z-index:1}.mdc-slider .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-style:solid;border-width:1px;box-sizing:content-box}.mdc-slider .mdc-slider__thumb-knob{box-sizing:border-box;left:50%;position:absolute;top:50%;transform:translate(-50%, -50%)}.mdc-slider .mdc-slider__tick-marks{align-items:center;box-sizing:border-box;display:flex;height:100%;justify-content:space-between;padding:0 1px;position:absolute;width:100%}.mdc-slider--discrete .mdc-slider__thumb,.mdc-slider--discrete .mdc-slider__track--active_fill{transition:transform 80ms ease}@media(prefers-reduced-motion){.mdc-slider--discrete .mdc-slider__thumb,.mdc-slider--discrete .mdc-slider__track--active_fill{transition:none}}.mdc-slider--disabled{cursor:auto}.mdc-slider--disabled .mdc-slider__thumb{pointer-events:none}.mdc-slider__input{cursor:pointer;left:2px;margin:0;height:44px;opacity:0;pointer-events:none;position:absolute;top:2px;width:44px}.mat-mdc-slider{display:inline-block;box-sizing:border-box;outline:none;vertical-align:middle;margin-left:8px;margin-right:8px;width:auto;min-width:112px;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-slider .mdc-slider__thumb-knob{background-color:var(--mdc-slider-handle-color, var(--mdc-theme-primary, #6200ee));border-color:var(--mdc-slider-handle-color, var(--mdc-theme-primary, #6200ee))}.mat-mdc-slider .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:#fff}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__thumb-knob{background-color:var(--mdc-slider-disabled-handle-color, var(--mdc-theme-on-surface, #000));border-color:var(--mdc-slider-disabled-handle-color, var(--mdc-theme-on-surface, #000))}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider.mdc-slider--disabled .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider.mdc-slider--disabled .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:#fff}.mat-mdc-slider .mdc-slider__thumb::before,.mat-mdc-slider .mdc-slider__thumb::after{background-color:var(--mdc-slider-handle-color, var(--mdc-theme-primary, #6200ee))}.mat-mdc-slider .mdc-slider__thumb:hover::before,.mat-mdc-slider .mdc-slider__thumb.mdc-ripple-surface--hover::before{opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mat-mdc-slider .mdc-slider__thumb.mdc-ripple-upgraded--background-focused::before,.mat-mdc-slider .mdc-slider__thumb:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mat-mdc-slider .mdc-slider__thumb:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mat-mdc-slider .mdc-slider__thumb:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mat-mdc-slider .mdc-slider__thumb.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}.mat-mdc-slider .mdc-slider__track--active_fill{border-color:var(--mdc-slider-active-track-color, var(--mdc-theme-primary, #6200ee))}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__track--active_fill{border-color:var(--mdc-slider-disabled-active-track-color, var(--mdc-theme-on-surface, #000))}.mat-mdc-slider .mdc-slider__track--inactive{background-color:var(--mdc-slider-inactive-track-color, var(--mdc-theme-primary, #6200ee));opacity:.24}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__track--inactive{background-color:var(--mdc-slider-disabled-inactive-track-color, var(--mdc-theme-on-surface, #000));opacity:.24}.mat-mdc-slider .mdc-slider__tick-mark--active{background-color:var(--mdc-slider-with-tick-marks-active-container-color, var(--mdc-theme-on-primary, #fff));opacity:var(--mdc-slider-with-tick-marks-active-container-opacity, 0.6)}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__tick-mark--active{background-color:var(--mdc-slider-with-tick-marks-active-container-color, var(--mdc-theme-on-primary, #fff));opacity:var(--mdc-slider-with-tick-marks-active-container-opacity, 0.6)}.mat-mdc-slider .mdc-slider__tick-mark--inactive{background-color:var(--mdc-slider-with-tick-marks-inactive-container-color, var(--mdc-theme-primary, #6200ee));opacity:var(--mdc-slider-with-tick-marks-inactive-container-opacity, 0.6)}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__tick-mark--inactive{background-color:var(--mdc-slider-with-tick-marks-disabled-container-color, var(--mdc-theme-on-surface, #000));opacity:var(--mdc-slider-with-tick-marks-inactive-container-opacity, 0.6)}.mat-mdc-slider .mdc-slider__value-indicator{background-color:var(--mdc-slider-label-container-color, #666666);opacity:1}.mat-mdc-slider .mdc-slider__value-indicator::before{border-top-color:var(--mdc-slider-label-container-color, #666666)}.mat-mdc-slider .mdc-slider__value-indicator{color:var(--mdc-slider-label-label-text-color, var(--mdc-theme-on-primary, #fff))}.mat-mdc-slider .mdc-slider__track{height:var(--mdc-slider-inactive-track-height, 4px)}.mat-mdc-slider .mdc-slider__track--active{height:var(--mdc-slider-active-track-height, 6px);top:calc((var(--mdc-slider-inactive-track-height, 4px) - var(--mdc-slider-active-track-height, 6px)) / 2)}.mat-mdc-slider .mdc-slider__track--active_fill{border-top-width:var(--mdc-slider-active-track-height, 6px)}.mat-mdc-slider .mdc-slider__track--inactive{height:var(--mdc-slider-inactive-track-height, 4px)}.mat-mdc-slider .mdc-slider__tick-mark--active,.mat-mdc-slider .mdc-slider__tick-mark--inactive{height:var(--mdc-slider-with-tick-marks-container-size, 2px);width:var(--mdc-slider-with-tick-marks-container-size, 2px)}.mat-mdc-slider.mdc-slider--disabled{opacity:0.38}.mat-mdc-slider .mdc-slider__value-indicator-text{letter-spacing:var(--mdc-slider-label-label-text-tracking, 0.0071428571em);font-size:var(--mdc-slider-label-label-text-size, 0.875rem);font-family:var(--mdc-slider-label-label-text-font, Roboto, sans-serif);font-weight:var(--mdc-slider-label-label-text-weight, 500);line-height:var(--mdc-slider-label-label-text-line-height, 1.375rem)}.mat-mdc-slider .mdc-slider__track--active{border-radius:var(--mdc-slider-active-track-shape, 9999px)}.mat-mdc-slider .mdc-slider__track--inactive{border-radius:var(--mdc-slider-inactive-track-shape, 9999px)}.mat-mdc-slider .mdc-slider__thumb-knob{border-radius:var(--mdc-slider-handle-shape, 50%);width:var(--mdc-slider-handle-width, 20px);height:var(--mdc-slider-handle-height, 20px);border-style:solid;border-width:calc(var(--mdc-slider-handle-height, 20px) / 2) calc(var(--mdc-slider-handle-width, 20px) / 2)}.mat-mdc-slider .mdc-slider__tick-mark--active,.mat-mdc-slider .mdc-slider__tick-mark--inactive{border-radius:var(--mdc-slider-with-tick-marks-container-shape, 50%)}.mat-mdc-slider .mdc-slider__thumb-knob{box-shadow:var(--mdc-slider-handle-elevation, 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12))}.mat-mdc-slider .mdc-slider__thumb:hover .mdc-slider__thumb-knob{background-color:var(--mdc-slider-hover-handle-color, var(--mdc-theme-primary, #6200ee));border-color:var(--mdc-slider-hover-handle-color, var(--mdc-theme-primary, #6200ee))}.mat-mdc-slider .mdc-slider__thumb:hover .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb:hover .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb:hover .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:#fff}.mat-mdc-slider .mdc-slider__thumb--focused .mdc-slider__thumb-knob{background-color:var(--mdc-slider-focus-handle-color, var(--mdc-theme-primary, #6200ee));border-color:var(--mdc-slider-focus-handle-color, var(--mdc-theme-primary, #6200ee))}.mat-mdc-slider .mdc-slider__thumb--focused .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--focused .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--focused .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:#fff}.mat-mdc-slider .mdc-slider__thumb:not(:disabled):active .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb:not(:disabled):active .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb:not(:disabled):active .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:#fff}.mat-mdc-slider .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:var(--mdc-slider-with-overlap-handle-outline-color, #fff);border-width:var(--mdc-slider-with-overlap-handle-outline-width, 1px)}.mat-mdc-slider .mdc-slider__input{box-sizing:content-box;pointer-events:auto}.mat-mdc-slider .mdc-slider__input.mat-mdc-slider-input-no-pointer-events{pointer-events:none}.mat-mdc-slider .mdc-slider__input.mat-slider__right-input{left:auto;right:0}.mat-mdc-slider .mdc-slider__thumb,.mat-mdc-slider .mdc-slider__track--active_fill{transition-duration:0ms}.mat-mdc-slider.mat-mdc-slider-with-animation .mdc-slider__thumb,.mat-mdc-slider.mat-mdc-slider-with-animation .mdc-slider__track--active_fill{transition-duration:80ms}.mat-mdc-slider.mdc-slider--discrete .mdc-slider__thumb,.mat-mdc-slider.mdc-slider--discrete .mdc-slider__track--active_fill{transition-duration:0ms}.mat-mdc-slider.mat-mdc-slider-with-animation .mdc-slider__thumb,.mat-mdc-slider.mat-mdc-slider-with-animation .mdc-slider__track--active_fill{transition-duration:80ms}.mat-mdc-slider .mdc-slider__track,.mat-mdc-slider .mdc-slider__thumb{pointer-events:none}.mat-mdc-slider .mdc-slider__value-indicator{opacity:var(--mat-mdc-slider-value-indicator-opacity, 1)}.mat-mdc-slider .mat-ripple .mat-ripple-element{background-color:var(--mat-mdc-slider-ripple-color, transparent)}.mat-mdc-slider .mat-ripple .mat-mdc-slider-hover-ripple{background-color:var(--mat-mdc-slider-hover-ripple-color, transparent)}.mat-mdc-slider .mat-ripple .mat-mdc-slider-focus-ripple,.mat-mdc-slider .mat-ripple .mat-mdc-slider-active-ripple{background-color:var(--mat-mdc-slider-focus-ripple-color, transparent)}.mat-mdc-slider._mat-animation-noopable.mdc-slider--discrete .mdc-slider__thumb,.mat-mdc-slider._mat-animation-noopable.mdc-slider--discrete .mdc-slider__track--active_fill,.mat-mdc-slider._mat-animation-noopable .mdc-slider__value-indicator{transition:none}.mat-mdc-slider .mat-mdc-focus-indicator::before{border-radius:50%}.mdc-slider__thumb--focused .mat-mdc-focus-indicator::before{content:\"\"}"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: MatSliderVisualThumb, selector: "mat-slider-visual-thumb", inputs: ["discrete", "thumbPosition", "valueIndicatorText"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
  908. }
  909. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatSlider, decorators: [{
  910. type: Component,
  911. args: [{ selector: 'mat-slider', host: {
  912. 'class': 'mat-mdc-slider mdc-slider',
  913. '[class.mdc-slider--range]': '_isRange',
  914. '[class.mdc-slider--disabled]': 'disabled',
  915. '[class.mdc-slider--discrete]': 'discrete',
  916. '[class.mdc-slider--tick-marks]': 'showTickMarks',
  917. '[class._mat-animation-noopable]': '_noopAnimations',
  918. }, exportAs: 'matSlider', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, inputs: ['color', 'disableRipple'], providers: [{ provide: MAT_SLIDER, useExisting: MatSlider }], template: "<!-- Inputs -->\n<ng-content></ng-content>\n\n<!-- Track -->\n<div class=\"mdc-slider__track\">\n <div class=\"mdc-slider__track--inactive\"></div>\n <div class=\"mdc-slider__track--active\">\n <div #trackActive class=\"mdc-slider__track--active_fill\"></div>\n </div>\n <div *ngIf=\"showTickMarks\" class=\"mdc-slider__tick-marks\" #tickMarkContainer>\n <ng-container *ngIf=\"_cachedWidth\">\n <div\n *ngFor=\"let tickMark of _tickMarks; let i = index\"\n [class]=\"tickMark === 0 ? 'mdc-slider__tick-mark--active' : 'mdc-slider__tick-mark--inactive'\"\n [style.transform]=\"_calcTickMarkTransform(i)\"></div>\n </ng-container>\n </div>\n</div>\n\n<!-- Thumbs -->\n<mat-slider-visual-thumb\n *ngIf=\"_isRange\"\n [discrete]=\"discrete\"\n [thumbPosition]=\"1\"\n [valueIndicatorText]=\"startValueIndicatorText\">\n</mat-slider-visual-thumb>\n\n<mat-slider-visual-thumb\n [discrete]=\"discrete\"\n [thumbPosition]=\"2\"\n [valueIndicatorText]=\"endValueIndicatorText\">\n</mat-slider-visual-thumb>\n", styles: [".mdc-slider{cursor:pointer;height:48px;margin:0 24px;position:relative;touch-action:pan-y}.mdc-slider .mdc-slider__track{position:absolute;top:50%;transform:translateY(-50%);width:100%}.mdc-slider .mdc-slider__track--active,.mdc-slider .mdc-slider__track--inactive{display:flex;height:100%;position:absolute;width:100%}.mdc-slider .mdc-slider__track--active{overflow:hidden}.mdc-slider .mdc-slider__track--active_fill{border-top-style:solid;box-sizing:border-box;height:100%;width:100%;position:relative;-webkit-transform-origin:left;transform-origin:left}[dir=rtl] .mdc-slider .mdc-slider__track--active_fill,.mdc-slider .mdc-slider__track--active_fill[dir=rtl]{-webkit-transform-origin:right;transform-origin:right}.mdc-slider .mdc-slider__track--inactive{left:0;top:0}.mdc-slider .mdc-slider__track--inactive::before{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid rgba(0,0,0,0);border-radius:inherit;content:\"\";pointer-events:none}@media screen and (forced-colors: active){.mdc-slider .mdc-slider__track--inactive::before{border-color:CanvasText}}.mdc-slider .mdc-slider__value-indicator-container{bottom:44px;left:var(--slider-value-indicator-container-left, 50%);pointer-events:none;position:absolute;right:var(--slider-value-indicator-container-right);transform:var(--slider-value-indicator-container-transform, translateX(-50%))}.mdc-slider .mdc-slider__value-indicator{transition:transform 100ms 0ms cubic-bezier(0.4, 0, 1, 1);align-items:center;border-radius:4px;display:flex;height:32px;padding:0 12px;transform:scale(0);transform-origin:bottom}.mdc-slider .mdc-slider__value-indicator::before{border-left:6px solid rgba(0,0,0,0);border-right:6px solid rgba(0,0,0,0);border-top:6px solid;bottom:-5px;content:\"\";height:0;left:var(--slider-value-indicator-caret-left, 50%);position:absolute;right:var(--slider-value-indicator-caret-right);transform:var(--slider-value-indicator-caret-transform, translateX(-50%));width:0}.mdc-slider .mdc-slider__value-indicator::after{position:absolute;box-sizing:border-box;width:100%;height:100%;top:0;left:0;border:1px solid rgba(0,0,0,0);border-radius:inherit;content:\"\";pointer-events:none}@media screen and (forced-colors: active){.mdc-slider .mdc-slider__value-indicator::after{border-color:CanvasText}}.mdc-slider .mdc-slider__thumb--with-indicator .mdc-slider__value-indicator-container{pointer-events:auto}.mdc-slider .mdc-slider__thumb--with-indicator .mdc-slider__value-indicator{transition:transform 100ms 0ms cubic-bezier(0, 0, 0.2, 1);transform:scale(1)}@media(prefers-reduced-motion){.mdc-slider .mdc-slider__value-indicator,.mdc-slider .mdc-slider__thumb--with-indicator .mdc-slider__value-indicator{transition:none}}.mdc-slider .mdc-slider__thumb{display:flex;left:-24px;outline:none;position:absolute;user-select:none;height:48px;width:48px}.mdc-slider .mdc-slider__thumb--top{z-index:1}.mdc-slider .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-style:solid;border-width:1px;box-sizing:content-box}.mdc-slider .mdc-slider__thumb-knob{box-sizing:border-box;left:50%;position:absolute;top:50%;transform:translate(-50%, -50%)}.mdc-slider .mdc-slider__tick-marks{align-items:center;box-sizing:border-box;display:flex;height:100%;justify-content:space-between;padding:0 1px;position:absolute;width:100%}.mdc-slider--discrete .mdc-slider__thumb,.mdc-slider--discrete .mdc-slider__track--active_fill{transition:transform 80ms ease}@media(prefers-reduced-motion){.mdc-slider--discrete .mdc-slider__thumb,.mdc-slider--discrete .mdc-slider__track--active_fill{transition:none}}.mdc-slider--disabled{cursor:auto}.mdc-slider--disabled .mdc-slider__thumb{pointer-events:none}.mdc-slider__input{cursor:pointer;left:2px;margin:0;height:44px;opacity:0;pointer-events:none;position:absolute;top:2px;width:44px}.mat-mdc-slider{display:inline-block;box-sizing:border-box;outline:none;vertical-align:middle;margin-left:8px;margin-right:8px;width:auto;min-width:112px;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-slider .mdc-slider__thumb-knob{background-color:var(--mdc-slider-handle-color, var(--mdc-theme-primary, #6200ee));border-color:var(--mdc-slider-handle-color, var(--mdc-theme-primary, #6200ee))}.mat-mdc-slider .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:#fff}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__thumb-knob{background-color:var(--mdc-slider-disabled-handle-color, var(--mdc-theme-on-surface, #000));border-color:var(--mdc-slider-disabled-handle-color, var(--mdc-theme-on-surface, #000))}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider.mdc-slider--disabled .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider.mdc-slider--disabled .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:#fff}.mat-mdc-slider .mdc-slider__thumb::before,.mat-mdc-slider .mdc-slider__thumb::after{background-color:var(--mdc-slider-handle-color, var(--mdc-theme-primary, #6200ee))}.mat-mdc-slider .mdc-slider__thumb:hover::before,.mat-mdc-slider .mdc-slider__thumb.mdc-ripple-surface--hover::before{opacity:var(--mdc-ripple-hover-opacity, 0.04)}.mat-mdc-slider .mdc-slider__thumb.mdc-ripple-upgraded--background-focused::before,.mat-mdc-slider .mdc-slider__thumb:not(.mdc-ripple-upgraded):focus::before{transition-duration:75ms;opacity:var(--mdc-ripple-focus-opacity, 0.12)}.mat-mdc-slider .mdc-slider__thumb:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mat-mdc-slider .mdc-slider__thumb:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:var(--mdc-ripple-press-opacity, 0.12)}.mat-mdc-slider .mdc-slider__thumb.mdc-ripple-upgraded{--mdc-ripple-fg-opacity:var(--mdc-ripple-press-opacity, 0.12)}.mat-mdc-slider .mdc-slider__track--active_fill{border-color:var(--mdc-slider-active-track-color, var(--mdc-theme-primary, #6200ee))}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__track--active_fill{border-color:var(--mdc-slider-disabled-active-track-color, var(--mdc-theme-on-surface, #000))}.mat-mdc-slider .mdc-slider__track--inactive{background-color:var(--mdc-slider-inactive-track-color, var(--mdc-theme-primary, #6200ee));opacity:.24}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__track--inactive{background-color:var(--mdc-slider-disabled-inactive-track-color, var(--mdc-theme-on-surface, #000));opacity:.24}.mat-mdc-slider .mdc-slider__tick-mark--active{background-color:var(--mdc-slider-with-tick-marks-active-container-color, var(--mdc-theme-on-primary, #fff));opacity:var(--mdc-slider-with-tick-marks-active-container-opacity, 0.6)}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__tick-mark--active{background-color:var(--mdc-slider-with-tick-marks-active-container-color, var(--mdc-theme-on-primary, #fff));opacity:var(--mdc-slider-with-tick-marks-active-container-opacity, 0.6)}.mat-mdc-slider .mdc-slider__tick-mark--inactive{background-color:var(--mdc-slider-with-tick-marks-inactive-container-color, var(--mdc-theme-primary, #6200ee));opacity:var(--mdc-slider-with-tick-marks-inactive-container-opacity, 0.6)}.mat-mdc-slider.mdc-slider--disabled .mdc-slider__tick-mark--inactive{background-color:var(--mdc-slider-with-tick-marks-disabled-container-color, var(--mdc-theme-on-surface, #000));opacity:var(--mdc-slider-with-tick-marks-inactive-container-opacity, 0.6)}.mat-mdc-slider .mdc-slider__value-indicator{background-color:var(--mdc-slider-label-container-color, #666666);opacity:1}.mat-mdc-slider .mdc-slider__value-indicator::before{border-top-color:var(--mdc-slider-label-container-color, #666666)}.mat-mdc-slider .mdc-slider__value-indicator{color:var(--mdc-slider-label-label-text-color, var(--mdc-theme-on-primary, #fff))}.mat-mdc-slider .mdc-slider__track{height:var(--mdc-slider-inactive-track-height, 4px)}.mat-mdc-slider .mdc-slider__track--active{height:var(--mdc-slider-active-track-height, 6px);top:calc((var(--mdc-slider-inactive-track-height, 4px) - var(--mdc-slider-active-track-height, 6px)) / 2)}.mat-mdc-slider .mdc-slider__track--active_fill{border-top-width:var(--mdc-slider-active-track-height, 6px)}.mat-mdc-slider .mdc-slider__track--inactive{height:var(--mdc-slider-inactive-track-height, 4px)}.mat-mdc-slider .mdc-slider__tick-mark--active,.mat-mdc-slider .mdc-slider__tick-mark--inactive{height:var(--mdc-slider-with-tick-marks-container-size, 2px);width:var(--mdc-slider-with-tick-marks-container-size, 2px)}.mat-mdc-slider.mdc-slider--disabled{opacity:0.38}.mat-mdc-slider .mdc-slider__value-indicator-text{letter-spacing:var(--mdc-slider-label-label-text-tracking, 0.0071428571em);font-size:var(--mdc-slider-label-label-text-size, 0.875rem);font-family:var(--mdc-slider-label-label-text-font, Roboto, sans-serif);font-weight:var(--mdc-slider-label-label-text-weight, 500);line-height:var(--mdc-slider-label-label-text-line-height, 1.375rem)}.mat-mdc-slider .mdc-slider__track--active{border-radius:var(--mdc-slider-active-track-shape, 9999px)}.mat-mdc-slider .mdc-slider__track--inactive{border-radius:var(--mdc-slider-inactive-track-shape, 9999px)}.mat-mdc-slider .mdc-slider__thumb-knob{border-radius:var(--mdc-slider-handle-shape, 50%);width:var(--mdc-slider-handle-width, 20px);height:var(--mdc-slider-handle-height, 20px);border-style:solid;border-width:calc(var(--mdc-slider-handle-height, 20px) / 2) calc(var(--mdc-slider-handle-width, 20px) / 2)}.mat-mdc-slider .mdc-slider__tick-mark--active,.mat-mdc-slider .mdc-slider__tick-mark--inactive{border-radius:var(--mdc-slider-with-tick-marks-container-shape, 50%)}.mat-mdc-slider .mdc-slider__thumb-knob{box-shadow:var(--mdc-slider-handle-elevation, 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12))}.mat-mdc-slider .mdc-slider__thumb:hover .mdc-slider__thumb-knob{background-color:var(--mdc-slider-hover-handle-color, var(--mdc-theme-primary, #6200ee));border-color:var(--mdc-slider-hover-handle-color, var(--mdc-theme-primary, #6200ee))}.mat-mdc-slider .mdc-slider__thumb:hover .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb:hover .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb:hover .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:#fff}.mat-mdc-slider .mdc-slider__thumb--focused .mdc-slider__thumb-knob{background-color:var(--mdc-slider-focus-handle-color, var(--mdc-theme-primary, #6200ee));border-color:var(--mdc-slider-focus-handle-color, var(--mdc-theme-primary, #6200ee))}.mat-mdc-slider .mdc-slider__thumb--focused .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--focused .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--focused .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:#fff}.mat-mdc-slider .mdc-slider__thumb:not(:disabled):active .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb:not(:disabled):active .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb:not(:disabled):active .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:#fff}.mat-mdc-slider .mdc-slider__thumb--top .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb:hover .mdc-slider__thumb-knob,.mat-mdc-slider .mdc-slider__thumb--top.mdc-slider__thumb--focused .mdc-slider__thumb-knob{border-color:var(--mdc-slider-with-overlap-handle-outline-color, #fff);border-width:var(--mdc-slider-with-overlap-handle-outline-width, 1px)}.mat-mdc-slider .mdc-slider__input{box-sizing:content-box;pointer-events:auto}.mat-mdc-slider .mdc-slider__input.mat-mdc-slider-input-no-pointer-events{pointer-events:none}.mat-mdc-slider .mdc-slider__input.mat-slider__right-input{left:auto;right:0}.mat-mdc-slider .mdc-slider__thumb,.mat-mdc-slider .mdc-slider__track--active_fill{transition-duration:0ms}.mat-mdc-slider.mat-mdc-slider-with-animation .mdc-slider__thumb,.mat-mdc-slider.mat-mdc-slider-with-animation .mdc-slider__track--active_fill{transition-duration:80ms}.mat-mdc-slider.mdc-slider--discrete .mdc-slider__thumb,.mat-mdc-slider.mdc-slider--discrete .mdc-slider__track--active_fill{transition-duration:0ms}.mat-mdc-slider.mat-mdc-slider-with-animation .mdc-slider__thumb,.mat-mdc-slider.mat-mdc-slider-with-animation .mdc-slider__track--active_fill{transition-duration:80ms}.mat-mdc-slider .mdc-slider__track,.mat-mdc-slider .mdc-slider__thumb{pointer-events:none}.mat-mdc-slider .mdc-slider__value-indicator{opacity:var(--mat-mdc-slider-value-indicator-opacity, 1)}.mat-mdc-slider .mat-ripple .mat-ripple-element{background-color:var(--mat-mdc-slider-ripple-color, transparent)}.mat-mdc-slider .mat-ripple .mat-mdc-slider-hover-ripple{background-color:var(--mat-mdc-slider-hover-ripple-color, transparent)}.mat-mdc-slider .mat-ripple .mat-mdc-slider-focus-ripple,.mat-mdc-slider .mat-ripple .mat-mdc-slider-active-ripple{background-color:var(--mat-mdc-slider-focus-ripple-color, transparent)}.mat-mdc-slider._mat-animation-noopable.mdc-slider--discrete .mdc-slider__thumb,.mat-mdc-slider._mat-animation-noopable.mdc-slider--discrete .mdc-slider__track--active_fill,.mat-mdc-slider._mat-animation-noopable .mdc-slider__value-indicator{transition:none}.mat-mdc-slider .mat-mdc-focus-indicator::before{border-radius:50%}.mdc-slider__thumb--focused .mat-mdc-focus-indicator::before{content:\"\"}"] }]
  919. }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i1.Platform }, { type: i0.ElementRef }, { type: i2$1.Directionality, decorators: [{
  920. type: Optional
  921. }] }, { type: undefined, decorators: [{
  922. type: Optional
  923. }, {
  924. type: Inject,
  925. args: [MAT_RIPPLE_GLOBAL_OPTIONS]
  926. }] }, { type: undefined, decorators: [{
  927. type: Optional
  928. }, {
  929. type: Inject,
  930. args: [ANIMATION_MODULE_TYPE]
  931. }] }]; }, propDecorators: { _trackActive: [{
  932. type: ViewChild,
  933. args: ['trackActive']
  934. }], _thumbs: [{
  935. type: ViewChildren,
  936. args: [MAT_SLIDER_VISUAL_THUMB]
  937. }], _input: [{
  938. type: ContentChild,
  939. args: [MAT_SLIDER_THUMB]
  940. }], _inputs: [{
  941. type: ContentChildren,
  942. args: [MAT_SLIDER_RANGE_THUMB, { descendants: false }]
  943. }], disabled: [{
  944. type: Input
  945. }], discrete: [{
  946. type: Input
  947. }], showTickMarks: [{
  948. type: Input
  949. }], min: [{
  950. type: Input
  951. }], max: [{
  952. type: Input
  953. }], step: [{
  954. type: Input
  955. }], displayWith: [{
  956. type: Input
  957. }] } });
  958. /** Ensures that there is not an invalid configuration for the slider thumb inputs. */
  959. function _validateInputs(isRange, endInputElement, startInputElement) {
  960. const startValid = !isRange || startInputElement?._hostElement.hasAttribute('matSliderStartThumb');
  961. const endValid = endInputElement._hostElement.hasAttribute(isRange ? 'matSliderEndThumb' : 'matSliderThumb');
  962. if (!startValid || !endValid) {
  963. _throwInvalidInputConfigurationError();
  964. }
  965. }
  966. function _throwInvalidInputConfigurationError() {
  967. throw Error(`Invalid slider thumb input configuration!
  968. Valid configurations are as follows:
  969. <mat-slider>
  970. <input matSliderThumb>
  971. </mat-slider>
  972. or
  973. <mat-slider>
  974. <input matSliderStartThumb>
  975. <input matSliderEndThumb>
  976. </mat-slider>
  977. `);
  978. }
  979. /**
  980. * Provider that allows the slider thumb to register as a ControlValueAccessor.
  981. * @docs-private
  982. */
  983. const MAT_SLIDER_THUMB_VALUE_ACCESSOR = {
  984. provide: NG_VALUE_ACCESSOR,
  985. useExisting: forwardRef(() => MatSliderThumb),
  986. multi: true,
  987. };
  988. /**
  989. * Provider that allows the range slider thumb to register as a ControlValueAccessor.
  990. * @docs-private
  991. */
  992. const MAT_SLIDER_RANGE_THUMB_VALUE_ACCESSOR = {
  993. provide: NG_VALUE_ACCESSOR,
  994. useExisting: forwardRef(() => MatSliderRangeThumb),
  995. multi: true,
  996. };
  997. /**
  998. * Directive that adds slider-specific behaviors to an input element inside `<mat-slider>`.
  999. * Up to two may be placed inside of a `<mat-slider>`.
  1000. *
  1001. * If one is used, the selector `matSliderThumb` must be used, and the outcome will be a normal
  1002. * slider. If two are used, the selectors `matSliderStartThumb` and `matSliderEndThumb` must be
  1003. * used, and the outcome will be a range slider with two slider thumbs.
  1004. */
  1005. class MatSliderThumb {
  1006. get value() {
  1007. return coerceNumberProperty(this._hostElement.value);
  1008. }
  1009. set value(v) {
  1010. const val = coerceNumberProperty(v).toString();
  1011. if (!this._hasSetInitialValue) {
  1012. this._initialValue = val;
  1013. return;
  1014. }
  1015. if (this._isActive) {
  1016. return;
  1017. }
  1018. this._hostElement.value = val;
  1019. this._updateThumbUIByValue();
  1020. this._slider._onValueChange(this);
  1021. this._cdr.detectChanges();
  1022. }
  1023. /**
  1024. * The current translateX in px of the slider visual thumb.
  1025. * @docs-private
  1026. */
  1027. get translateX() {
  1028. if (this._slider.min >= this._slider.max) {
  1029. this._translateX = 0;
  1030. return this._translateX;
  1031. }
  1032. if (this._translateX === undefined) {
  1033. this._translateX = this._calcTranslateXByValue();
  1034. }
  1035. return this._translateX;
  1036. }
  1037. set translateX(v) {
  1038. this._translateX = v;
  1039. }
  1040. /** @docs-private */
  1041. get min() {
  1042. return coerceNumberProperty(this._hostElement.min);
  1043. }
  1044. set min(v) {
  1045. this._hostElement.min = coerceNumberProperty(v).toString();
  1046. this._cdr.detectChanges();
  1047. }
  1048. /** @docs-private */
  1049. get max() {
  1050. return coerceNumberProperty(this._hostElement.max);
  1051. }
  1052. set max(v) {
  1053. this._hostElement.max = coerceNumberProperty(v).toString();
  1054. this._cdr.detectChanges();
  1055. }
  1056. get step() {
  1057. return coerceNumberProperty(this._hostElement.step);
  1058. }
  1059. set step(v) {
  1060. this._hostElement.step = coerceNumberProperty(v).toString();
  1061. this._cdr.detectChanges();
  1062. }
  1063. /** @docs-private */
  1064. get disabled() {
  1065. return coerceBooleanProperty(this._hostElement.disabled);
  1066. }
  1067. set disabled(v) {
  1068. this._hostElement.disabled = coerceBooleanProperty(v);
  1069. this._cdr.detectChanges();
  1070. if (this._slider.disabled !== this.disabled) {
  1071. this._slider.disabled = this.disabled;
  1072. }
  1073. }
  1074. /** The percentage of the slider that coincides with the value. */
  1075. get percentage() {
  1076. if (this._slider.min >= this._slider.max) {
  1077. return this._slider._isRtl ? 1 : 0;
  1078. }
  1079. return (this.value - this._slider.min) / (this._slider.max - this._slider.min);
  1080. }
  1081. /** @docs-private */
  1082. get fillPercentage() {
  1083. if (!this._slider._cachedWidth) {
  1084. return this._slider._isRtl ? 1 : 0;
  1085. }
  1086. if (this._translateX === 0) {
  1087. return 0;
  1088. }
  1089. return this.translateX / this._slider._cachedWidth;
  1090. }
  1091. /** Used to relay updates to _isFocused to the slider visual thumbs. */
  1092. _setIsFocused(v) {
  1093. this._isFocused = v;
  1094. }
  1095. constructor(_ngZone, _elementRef, _cdr, _slider) {
  1096. this._ngZone = _ngZone;
  1097. this._elementRef = _elementRef;
  1098. this._cdr = _cdr;
  1099. this._slider = _slider;
  1100. /** Event emitted when the `value` is changed. */
  1101. this.valueChange = new EventEmitter();
  1102. /** Event emitted when the slider thumb starts being dragged. */
  1103. this.dragStart = new EventEmitter();
  1104. /** Event emitted when the slider thumb stops being dragged. */
  1105. this.dragEnd = new EventEmitter();
  1106. /**
  1107. * Indicates whether this thumb is the start or end thumb.
  1108. * @docs-private
  1109. */
  1110. this.thumbPosition = 2 /* _MatThumb.END */;
  1111. /** The radius of a native html slider's knob. */
  1112. this._knobRadius = 8;
  1113. /** Whether user's cursor is currently in a mouse down state on the input. */
  1114. this._isActive = false;
  1115. /** Whether the input is currently focused (either by tab or after clicking). */
  1116. this._isFocused = false;
  1117. /**
  1118. * Whether the initial value has been set.
  1119. * This exists because the initial value cannot be immediately set because the min and max
  1120. * must first be relayed from the parent MatSlider component, which can only happen later
  1121. * in the component lifecycle.
  1122. */
  1123. this._hasSetInitialValue = false;
  1124. /** Emits when the component is destroyed. */
  1125. this._destroyed = new Subject();
  1126. /**
  1127. * Indicates whether UI updates should be skipped.
  1128. *
  1129. * This flag is used to avoid flickering
  1130. * when correcting values on pointer up/down.
  1131. */
  1132. this._skipUIUpdate = false;
  1133. /** Callback called when the slider input has been touched. */
  1134. this._onTouchedFn = () => { };
  1135. /**
  1136. * Whether the NgModel has been initialized.
  1137. *
  1138. * This flag is used to ignore ghost null calls to
  1139. * writeValue which can break slider initialization.
  1140. *
  1141. * See https://github.com/angular/angular/issues/14988.
  1142. */
  1143. this._isControlInitialized = false;
  1144. this._hostElement = _elementRef.nativeElement;
  1145. this._ngZone.runOutsideAngular(() => {
  1146. this._hostElement.addEventListener('pointerdown', this._onPointerDown.bind(this));
  1147. this._hostElement.addEventListener('pointermove', this._onPointerMove.bind(this));
  1148. this._hostElement.addEventListener('pointerup', this._onPointerUp.bind(this));
  1149. });
  1150. }
  1151. ngOnDestroy() {
  1152. this._hostElement.removeEventListener('pointerdown', this._onPointerDown);
  1153. this._hostElement.removeEventListener('pointermove', this._onPointerMove);
  1154. this._hostElement.removeEventListener('pointerup', this._onPointerUp);
  1155. this._destroyed.next();
  1156. this._destroyed.complete();
  1157. this.dragStart.complete();
  1158. this.dragEnd.complete();
  1159. }
  1160. /** @docs-private */
  1161. initProps() {
  1162. this._updateWidthInactive();
  1163. // If this or the parent slider is disabled, just make everything disabled.
  1164. if (this.disabled !== this._slider.disabled) {
  1165. // The MatSlider setter for disabled will relay this and disable both inputs.
  1166. this._slider.disabled = true;
  1167. }
  1168. this.step = this._slider.step;
  1169. this.min = this._slider.min;
  1170. this.max = this._slider.max;
  1171. this._initValue();
  1172. }
  1173. /** @docs-private */
  1174. initUI() {
  1175. this._updateThumbUIByValue();
  1176. }
  1177. _initValue() {
  1178. this._hasSetInitialValue = true;
  1179. if (this._initialValue === undefined) {
  1180. this.value = this._getDefaultValue();
  1181. }
  1182. else {
  1183. this._hostElement.value = this._initialValue;
  1184. this._updateThumbUIByValue();
  1185. this._slider._onValueChange(this);
  1186. this._cdr.detectChanges();
  1187. }
  1188. }
  1189. _getDefaultValue() {
  1190. return this.min;
  1191. }
  1192. _onBlur() {
  1193. this._setIsFocused(false);
  1194. this._onTouchedFn();
  1195. }
  1196. _onFocus() {
  1197. this._setIsFocused(true);
  1198. }
  1199. _onChange() {
  1200. this.valueChange.emit(this.value);
  1201. // only used to handle the edge case where user
  1202. // mousedown on the slider then uses arrow keys.
  1203. if (this._isActive) {
  1204. this._updateThumbUIByValue({ withAnimation: true });
  1205. }
  1206. }
  1207. _onInput() {
  1208. this._onChangeFn?.(this.value);
  1209. // handles arrowing and updating the value when
  1210. // a step is defined.
  1211. if (this._slider.step || !this._isActive) {
  1212. this._updateThumbUIByValue({ withAnimation: true });
  1213. }
  1214. this._slider._onValueChange(this);
  1215. }
  1216. _onNgControlValueChange() {
  1217. // only used to handle when the value change
  1218. // originates outside of the slider.
  1219. if (!this._isActive || !this._isFocused) {
  1220. this._slider._onValueChange(this);
  1221. this._updateThumbUIByValue();
  1222. }
  1223. this._slider.disabled = this._formControl.disabled;
  1224. }
  1225. _onPointerDown(event) {
  1226. if (this.disabled || event.button !== 0) {
  1227. return;
  1228. }
  1229. this._isActive = true;
  1230. this._setIsFocused(true);
  1231. this._updateWidthActive();
  1232. this._slider._updateDimensions();
  1233. // Does nothing if a step is defined because we
  1234. // want the value to snap to the values on input.
  1235. if (!this._slider.step) {
  1236. this._updateThumbUIByPointerEvent(event, { withAnimation: true });
  1237. }
  1238. if (!this.disabled) {
  1239. this._handleValueCorrection(event);
  1240. this.dragStart.emit({ source: this, parent: this._slider, value: this.value });
  1241. }
  1242. }
  1243. /**
  1244. * Corrects the value of the slider on pointer up/down.
  1245. *
  1246. * Called on pointer down and up because the value is set based
  1247. * on the inactive width instead of the active width.
  1248. */
  1249. _handleValueCorrection(event) {
  1250. // Don't update the UI with the current value! The value on pointerdown
  1251. // and pointerup is calculated in the split second before the input(s)
  1252. // resize. See _updateWidthInactive() and _updateWidthActive() for more
  1253. // details.
  1254. this._skipUIUpdate = true;
  1255. // Note that this function gets triggered before the actual value of the
  1256. // slider is updated. This means if we were to set the value here, it
  1257. // would immediately be overwritten. Using setTimeout ensures the setting
  1258. // of the value happens after the value has been updated by the
  1259. // pointerdown event.
  1260. setTimeout(() => {
  1261. this._skipUIUpdate = false;
  1262. this._fixValue(event);
  1263. }, 0);
  1264. }
  1265. /** Corrects the value of the slider based on the pointer event's position. */
  1266. _fixValue(event) {
  1267. const xPos = event.clientX - this._slider._cachedLeft;
  1268. const width = this._slider._cachedWidth;
  1269. const step = this._slider.step === 0 ? 1 : this._slider.step;
  1270. const numSteps = Math.floor((this._slider.max - this._slider.min) / step);
  1271. const percentage = this._slider._isRtl ? 1 - xPos / width : xPos / width;
  1272. // To ensure the percentage is rounded to the necessary number of decimals.
  1273. const fixedPercentage = Math.round(percentage * numSteps) / numSteps;
  1274. const impreciseValue = fixedPercentage * (this._slider.max - this._slider.min) + this._slider.min;
  1275. const value = Math.round(impreciseValue / step) * step;
  1276. const prevValue = this.value;
  1277. if (value === prevValue) {
  1278. // Because we prevented UI updates, if it turns out that the race
  1279. // condition didn't happen and the value is already correct, we
  1280. // have to apply the ui updates now.
  1281. this._slider._onValueChange(this);
  1282. this._slider.step > 0
  1283. ? this._updateThumbUIByValue()
  1284. : this._updateThumbUIByPointerEvent(event, { withAnimation: this._slider._hasAnimation });
  1285. return;
  1286. }
  1287. this.value = value;
  1288. this.valueChange.emit(this.value);
  1289. this._onChangeFn?.(this.value);
  1290. this._slider._onValueChange(this);
  1291. this._slider.step > 0
  1292. ? this._updateThumbUIByValue()
  1293. : this._updateThumbUIByPointerEvent(event, { withAnimation: this._slider._hasAnimation });
  1294. }
  1295. _onPointerMove(event) {
  1296. // Again, does nothing if a step is defined because
  1297. // we want the value to snap to the values on input.
  1298. if (!this._slider.step && this._isActive) {
  1299. this._updateThumbUIByPointerEvent(event);
  1300. }
  1301. }
  1302. _onPointerUp() {
  1303. if (this._isActive) {
  1304. this._isActive = false;
  1305. this.dragEnd.emit({ source: this, parent: this._slider, value: this.value });
  1306. setTimeout(() => this._updateWidthInactive());
  1307. }
  1308. }
  1309. _clamp(v) {
  1310. return Math.max(Math.min(v, this._slider._cachedWidth), 0);
  1311. }
  1312. _calcTranslateXByValue() {
  1313. if (this._slider._isRtl) {
  1314. return (1 - this.percentage) * this._slider._cachedWidth;
  1315. }
  1316. return this.percentage * this._slider._cachedWidth;
  1317. }
  1318. _calcTranslateXByPointerEvent(event) {
  1319. return event.clientX - this._slider._cachedLeft;
  1320. }
  1321. /**
  1322. * Used to set the slider width to the correct
  1323. * dimensions while the user is dragging.
  1324. */
  1325. _updateWidthActive() {
  1326. this._hostElement.style.padding = `0 ${this._slider._inputPadding}px`;
  1327. this._hostElement.style.width = `calc(100% + ${this._slider._inputPadding}px)`;
  1328. }
  1329. /**
  1330. * Sets the slider input to disproportionate dimensions to allow for touch
  1331. * events to be captured on touch devices.
  1332. */
  1333. _updateWidthInactive() {
  1334. this._hostElement.style.padding = '0px';
  1335. this._hostElement.style.width = 'calc(100% + 48px)';
  1336. this._hostElement.style.left = '-24px';
  1337. }
  1338. _updateThumbUIByValue(options) {
  1339. this.translateX = this._clamp(this._calcTranslateXByValue());
  1340. this._updateThumbUI(options);
  1341. }
  1342. _updateThumbUIByPointerEvent(event, options) {
  1343. this.translateX = this._clamp(this._calcTranslateXByPointerEvent(event));
  1344. this._updateThumbUI(options);
  1345. }
  1346. _updateThumbUI(options) {
  1347. this._slider._setTransition(!!options?.withAnimation);
  1348. this._slider._onTranslateXChange(this);
  1349. }
  1350. /**
  1351. * Sets the input's value.
  1352. * @param value The new value of the input
  1353. * @docs-private
  1354. */
  1355. writeValue(value) {
  1356. if (this._isControlInitialized || value !== null) {
  1357. this.value = value;
  1358. }
  1359. }
  1360. /**
  1361. * Registers a callback to be invoked when the input's value changes from user input.
  1362. * @param fn The callback to register
  1363. * @docs-private
  1364. */
  1365. registerOnChange(fn) {
  1366. this._onChangeFn = fn;
  1367. this._isControlInitialized = true;
  1368. }
  1369. /**
  1370. * Registers a callback to be invoked when the input is blurred by the user.
  1371. * @param fn The callback to register
  1372. * @docs-private
  1373. */
  1374. registerOnTouched(fn) {
  1375. this._onTouchedFn = fn;
  1376. }
  1377. /**
  1378. * Sets the disabled state of the slider.
  1379. * @param isDisabled The new disabled state
  1380. * @docs-private
  1381. */
  1382. setDisabledState(isDisabled) {
  1383. this.disabled = isDisabled;
  1384. }
  1385. focus() {
  1386. this._hostElement.focus();
  1387. }
  1388. blur() {
  1389. this._hostElement.blur();
  1390. }
  1391. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatSliderThumb, deps: [{ token: i0.NgZone }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: MAT_SLIDER }], target: i0.ɵɵFactoryTarget.Directive }); }
  1392. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: MatSliderThumb, selector: "input[matSliderThumb]", inputs: { value: "value" }, outputs: { valueChange: "valueChange", dragStart: "dragStart", dragEnd: "dragEnd" }, host: { attributes: { "type": "range" }, listeners: { "change": "_onChange()", "input": "_onInput()", "blur": "_onBlur()", "focus": "_onFocus()" }, properties: { "attr.aria-valuetext": "_valuetext" }, classAttribute: "mdc-slider__input" }, providers: [
  1393. MAT_SLIDER_THUMB_VALUE_ACCESSOR,
  1394. { provide: MAT_SLIDER_THUMB, useExisting: MatSliderThumb },
  1395. ], exportAs: ["matSliderThumb"], ngImport: i0 }); }
  1396. }
  1397. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatSliderThumb, decorators: [{
  1398. type: Directive,
  1399. args: [{
  1400. selector: 'input[matSliderThumb]',
  1401. exportAs: 'matSliderThumb',
  1402. host: {
  1403. 'class': 'mdc-slider__input',
  1404. 'type': 'range',
  1405. '[attr.aria-valuetext]': '_valuetext',
  1406. '(change)': '_onChange()',
  1407. '(input)': '_onInput()',
  1408. // TODO(wagnermaciel): Consider using a global event listener instead.
  1409. // Reason: I have found a semi-consistent way to mouse up without triggering this event.
  1410. '(blur)': '_onBlur()',
  1411. '(focus)': '_onFocus()',
  1412. },
  1413. providers: [
  1414. MAT_SLIDER_THUMB_VALUE_ACCESSOR,
  1415. { provide: MAT_SLIDER_THUMB, useExisting: MatSliderThumb },
  1416. ],
  1417. }]
  1418. }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
  1419. type: Inject,
  1420. args: [MAT_SLIDER]
  1421. }] }]; }, propDecorators: { value: [{
  1422. type: Input
  1423. }], valueChange: [{
  1424. type: Output
  1425. }], dragStart: [{
  1426. type: Output
  1427. }], dragEnd: [{
  1428. type: Output
  1429. }] } });
  1430. class MatSliderRangeThumb extends MatSliderThumb {
  1431. /** @docs-private */
  1432. getSibling() {
  1433. if (!this._sibling) {
  1434. this._sibling = this._slider._getInput(this._isEndThumb ? 1 /* _MatThumb.START */ : 2 /* _MatThumb.END */);
  1435. }
  1436. return this._sibling;
  1437. }
  1438. /**
  1439. * Returns the minimum translateX position allowed for this slider input's visual thumb.
  1440. * @docs-private
  1441. */
  1442. getMinPos() {
  1443. const sibling = this.getSibling();
  1444. if (!this._isLeftThumb && sibling) {
  1445. return sibling.translateX;
  1446. }
  1447. return 0;
  1448. }
  1449. /**
  1450. * Returns the maximum translateX position allowed for this slider input's visual thumb.
  1451. * @docs-private
  1452. */
  1453. getMaxPos() {
  1454. const sibling = this.getSibling();
  1455. if (this._isLeftThumb && sibling) {
  1456. return sibling.translateX;
  1457. }
  1458. return this._slider._cachedWidth;
  1459. }
  1460. _setIsLeftThumb() {
  1461. this._isLeftThumb =
  1462. (this._isEndThumb && this._slider._isRtl) || (!this._isEndThumb && !this._slider._isRtl);
  1463. }
  1464. constructor(_ngZone, _slider, _elementRef, _cdr) {
  1465. super(_ngZone, _elementRef, _cdr, _slider);
  1466. this._cdr = _cdr;
  1467. this._isEndThumb = this._hostElement.hasAttribute('matSliderEndThumb');
  1468. this._setIsLeftThumb();
  1469. this.thumbPosition = this._isEndThumb ? 2 /* _MatThumb.END */ : 1 /* _MatThumb.START */;
  1470. }
  1471. _getDefaultValue() {
  1472. return this._isEndThumb && this._slider._isRange ? this.max : this.min;
  1473. }
  1474. _onInput() {
  1475. super._onInput();
  1476. this._updateSibling();
  1477. if (!this._isActive) {
  1478. this._updateWidthInactive();
  1479. }
  1480. }
  1481. _onNgControlValueChange() {
  1482. super._onNgControlValueChange();
  1483. this.getSibling()?._updateMinMax();
  1484. }
  1485. _onPointerDown(event) {
  1486. if (this.disabled || event.button !== 0) {
  1487. return;
  1488. }
  1489. if (this._sibling) {
  1490. this._sibling._updateWidthActive();
  1491. this._sibling._hostElement.classList.add('mat-mdc-slider-input-no-pointer-events');
  1492. }
  1493. super._onPointerDown(event);
  1494. }
  1495. _onPointerUp() {
  1496. super._onPointerUp();
  1497. if (this._sibling) {
  1498. setTimeout(() => {
  1499. this._sibling._updateWidthInactive();
  1500. this._sibling._hostElement.classList.remove('mat-mdc-slider-input-no-pointer-events');
  1501. });
  1502. }
  1503. }
  1504. _onPointerMove(event) {
  1505. super._onPointerMove(event);
  1506. if (!this._slider.step && this._isActive) {
  1507. this._updateSibling();
  1508. }
  1509. }
  1510. _fixValue(event) {
  1511. super._fixValue(event);
  1512. this._sibling?._updateMinMax();
  1513. }
  1514. _clamp(v) {
  1515. return Math.max(Math.min(v, this.getMaxPos()), this.getMinPos());
  1516. }
  1517. _updateMinMax() {
  1518. const sibling = this.getSibling();
  1519. if (!sibling) {
  1520. return;
  1521. }
  1522. if (this._isEndThumb) {
  1523. this.min = Math.max(this._slider.min, sibling.value);
  1524. this.max = this._slider.max;
  1525. }
  1526. else {
  1527. this.min = this._slider.min;
  1528. this.max = Math.min(this._slider.max, sibling.value);
  1529. }
  1530. }
  1531. _updateWidthActive() {
  1532. const minWidth = this._slider._rippleRadius * 2 - this._slider._inputPadding * 2;
  1533. const maxWidth = this._slider._cachedWidth + this._slider._inputPadding - minWidth;
  1534. const percentage = this._slider.min < this._slider.max
  1535. ? (this.max - this.min) / (this._slider.max - this._slider.min)
  1536. : 1;
  1537. const width = maxWidth * percentage + minWidth;
  1538. this._hostElement.style.width = `${width}px`;
  1539. this._hostElement.style.padding = `0 ${this._slider._inputPadding}px`;
  1540. }
  1541. _updateWidthInactive() {
  1542. const sibling = this.getSibling();
  1543. if (!sibling) {
  1544. return;
  1545. }
  1546. const maxWidth = this._slider._cachedWidth;
  1547. const midValue = this._isEndThumb
  1548. ? this.value - (this.value - sibling.value) / 2
  1549. : this.value + (sibling.value - this.value) / 2;
  1550. const _percentage = this._isEndThumb
  1551. ? (this.max - midValue) / (this._slider.max - this._slider.min)
  1552. : (midValue - this.min) / (this._slider.max - this._slider.min);
  1553. const percentage = this._slider.min < this._slider.max ? _percentage : 1;
  1554. const width = maxWidth * percentage + 24;
  1555. this._hostElement.style.width = `${width}px`;
  1556. this._hostElement.style.padding = '0px';
  1557. if (this._isLeftThumb) {
  1558. this._hostElement.style.left = '-24px';
  1559. this._hostElement.style.right = 'auto';
  1560. }
  1561. else {
  1562. this._hostElement.style.left = 'auto';
  1563. this._hostElement.style.right = '-24px';
  1564. }
  1565. }
  1566. _updateStaticStyles() {
  1567. this._hostElement.classList.toggle('mat-slider__right-input', !this._isLeftThumb);
  1568. }
  1569. _updateSibling() {
  1570. const sibling = this.getSibling();
  1571. if (!sibling) {
  1572. return;
  1573. }
  1574. sibling._updateMinMax();
  1575. if (this._isActive) {
  1576. sibling._updateWidthActive();
  1577. }
  1578. else {
  1579. sibling._updateWidthInactive();
  1580. }
  1581. }
  1582. /**
  1583. * Sets the input's value.
  1584. * @param value The new value of the input
  1585. * @docs-private
  1586. */
  1587. writeValue(value) {
  1588. if (this._isControlInitialized || value !== null) {
  1589. this.value = value;
  1590. this._updateWidthInactive();
  1591. this._updateSibling();
  1592. }
  1593. }
  1594. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatSliderRangeThumb, deps: [{ token: i0.NgZone }, { token: MAT_SLIDER }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
  1595. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: MatSliderRangeThumb, selector: "input[matSliderStartThumb], input[matSliderEndThumb]", providers: [
  1596. MAT_SLIDER_RANGE_THUMB_VALUE_ACCESSOR,
  1597. { provide: MAT_SLIDER_RANGE_THUMB, useExisting: MatSliderRangeThumb },
  1598. ], exportAs: ["matSliderRangeThumb"], usesInheritance: true, ngImport: i0 }); }
  1599. }
  1600. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatSliderRangeThumb, decorators: [{
  1601. type: Directive,
  1602. args: [{
  1603. selector: 'input[matSliderStartThumb], input[matSliderEndThumb]',
  1604. exportAs: 'matSliderRangeThumb',
  1605. providers: [
  1606. MAT_SLIDER_RANGE_THUMB_VALUE_ACCESSOR,
  1607. { provide: MAT_SLIDER_RANGE_THUMB, useExisting: MatSliderRangeThumb },
  1608. ],
  1609. }]
  1610. }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: undefined, decorators: [{
  1611. type: Inject,
  1612. args: [MAT_SLIDER]
  1613. }] }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; } });
  1614. class MatSliderModule {
  1615. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatSliderModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
  1616. static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.0.0", ngImport: i0, type: MatSliderModule, declarations: [MatSlider, MatSliderThumb, MatSliderRangeThumb, MatSliderVisualThumb], imports: [MatCommonModule, CommonModule, MatRippleModule], exports: [MatSlider, MatSliderThumb, MatSliderRangeThumb] }); }
  1617. static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatSliderModule, imports: [MatCommonModule, CommonModule, MatRippleModule] }); }
  1618. }
  1619. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatSliderModule, decorators: [{
  1620. type: NgModule,
  1621. args: [{
  1622. imports: [MatCommonModule, CommonModule, MatRippleModule],
  1623. exports: [MatSlider, MatSliderThumb, MatSliderRangeThumb],
  1624. declarations: [MatSlider, MatSliderThumb, MatSliderRangeThumb, MatSliderVisualThumb],
  1625. }]
  1626. }] });
  1627. /**
  1628. * Generated bundle index. Do not edit.
  1629. */
  1630. export { MatSlider, MatSliderChange, MatSliderModule, MatSliderRangeThumb, MatSliderThumb, MatSliderVisualThumb };
  1631. //# sourceMappingURL=slider.mjs.map