UNPKG

@taiga-ui/kit

Version:

Taiga UI Angular main components kit

385 lines (375 loc) 36.7 kB
import { tuiRound } from '@taiga-ui/cdk/utils/math'; import { __decorate } from 'tslib'; import * as i0 from '@angular/core'; import { InjectionToken, inject, signal, computed, Component, ChangeDetectionStrategy, Input, INJECTOR, Directive, forwardRef, ContentChild } from '@angular/core'; import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { NgControl, NgModel } from '@angular/forms'; import { TuiControl } from '@taiga-ui/cdk/classes'; import { tuiWatch, tuiControlValue, tuiTypedFromEvent } from '@taiga-ui/cdk/observables'; import { tuiFallbackValueProvider } from '@taiga-ui/cdk/tokens'; import { tuiProvideOptions, tuiPure } from '@taiga-ui/cdk/utils/miscellaneous'; import { take, timer, switchMap, merge, tap, map, combineLatest, filter } from 'rxjs'; import { tuiInjectElement } from '@taiga-ui/cdk/utils/dom'; import { tuiAsAuxiliary } from '@taiga-ui/core/tokens'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { DOCUMENT, AsyncPipe, NgIf } from '@angular/common'; import { TUI_TRUE_HANDLER, TUI_FALSE_HANDLER } from '@taiga-ui/cdk/constants'; import { tuiHintOptionsProvider } from '@taiga-ui/core/directives/hint'; /** * Used as a limit for eliminating JS issues with floating point math */ const TUI_FLOATING_PRECISION = 7; function tuiFindKeyStepsBoundariesByFn(keySteps, fn) { const keyStepUpperIndex = keySteps.findIndex((keyStep, i) => i && fn(keyStep)); const lowerStep = keySteps[keyStepUpperIndex - 1] || keySteps[0]; const upperStep = keySteps[keyStepUpperIndex] || keySteps[keySteps.length - 1] || [0, 0]; return [lowerStep, upperStep]; } function tuiPercentageToKeyStepValue(valuePercentage, keySteps) { const [[lowerStepPercent, lowerStepValue], [upperStepPercent, upperStepValue]] = tuiFindKeyStepsBoundariesByFn(keySteps, ([keyStepPercentage, _]) => valuePercentage <= keyStepPercentage); const ratio = (valuePercentage - lowerStepPercent) / (upperStepPercent - lowerStepPercent); const controlValue = (upperStepValue - lowerStepValue) * ratio + lowerStepValue; return tuiRound(controlValue, TUI_FLOATING_PRECISION); } function tuiKeyStepValueToPercentage(value, keySteps) { const [[lowerStepPercent, lowerStepValue], [upperStepPercent, upperStepValue]] = tuiFindKeyStepsBoundariesByFn(keySteps, ([_, keyStepValue]) => value <= keyStepValue); const ratio = (value - lowerStepValue) / (upperStepValue - lowerStepValue) || 0; return (upperStepPercent - lowerStepPercent) * ratio + lowerStepPercent; } function tuiCreateKeyStepsTransformer(keySteps, slider) { return new (class { fromControlValue(controlValue) { const newValuePercentage = tuiKeyStepValueToPercentage(controlValue, keySteps); return (newValuePercentage * (slider.max - slider.min)) / 100 + slider.min; } toControlValue(nativeValue) { const valueRatio = (nativeValue - slider.min) / (slider.max - slider.min) || 0; return tuiPercentageToKeyStepValue(valueRatio * 100, keySteps); } })(); } const TUI_SLIDER_DEFAULT_OPTIONS = { size: 'm', trackColor: 'var(--tui-background-neutral-2)', }; /** * Default parameters for Slider component */ const TUI_SLIDER_OPTIONS = new InjectionToken(ngDevMode ? 'TUI_SLIDER_OPTIONS' : '', { factory: () => TUI_SLIDER_DEFAULT_OPTIONS, }); function tuiSliderOptionsProvider(options) { return tuiProvideOptions(TUI_SLIDER_OPTIONS, options, TUI_SLIDER_DEFAULT_OPTIONS); } class TuiSliderComponent { constructor() { this.control = inject(NgControl, { self: true, optional: true }); this.options = inject(TUI_SLIDER_OPTIONS); this.segments = signal([1]); this.ticksGradient = computed((segments = this.segments()) => this.getTicksGradient(segments)); this.size = this.options.size; this.el = tuiInjectElement(); this.keySteps = inject(TuiSliderKeyStepsBase, { self: true, optional: true, }); if (this.control instanceof NgModel) { /** * The ValueAccessor.writeValue method is called twice on any value accessor during component initialization, * when a control is bound using [(ngModel)], first time with a phantom null value. * With `changeDetection: ChangeDetectionStrategy.OnPush` the second call of writeValue with real value don't re-render the view. * ___ * See this {@link https://github.com/angular/angular/issues/14988 issue} */ this.control.valueChanges?.pipe(tuiWatch(), take(1)).subscribe(); } } // TODO(v5): use signal inputs set segmentsSetter(segments) { this.segments.set(segments); } get valueRatio() { return (this.value - this.min) / (this.max - this.min) || 0; } get min() { return Number(this.el.min); } set min(x) { this.el.min = String(x); } get max() { return Number(this.el.max || 100); } set max(x) { this.el.max = String(x); } get step() { if (!this.el.step) { return 1; } return this.el.step === 'any' ? 0 : Number(this.el.step); } set step(x) { this.el.step = String(x); } get value() { /** * If developer uses `[(ngModel)]` and programmatically change value, * the `el.nativeElement.value` is equal to the previous value at this moment * (it will be updated only in next microtask). * @see https://github.com/angular/angular/issues/13568 */ if (this.control instanceof NgModel) { const transformer = this.keySteps?.transformer(); const value = transformer ? transformer.fromControlValue(this.control.value) : this.control.viewModel; return this.step ? tuiRound(Math.round(value / this.step) * this.step, TUI_FLOATING_PRECISION) : value; } return Number(this.el.value) || 0; } set value(newValue) { this.el.value = `${newValue}`; } getTicksGradient(segments) { if (segments.length <= 1) { return 'linear-gradient(to right, transparent 0 100%)'; } const percentages = segments .filter((segment) => segment > 0 && segment < 1) .map((segment) => segment * 100); return percentages.reduce((acc, segment, index) => `${acc} var(--tui-text-tertiary) ${segment}% calc(${segment}% + var(--t-tick-thickness)), transparent ${segment}% ${percentages[index + 1] ?? 100}%${percentages[index + 1] ? ',' : ')'} `, `linear-gradient(to right, transparent 0 ${percentages[0]}%,`); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiSliderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "16.2.12", type: TuiSliderComponent, isStandalone: true, selector: "input[type=range][tuiSlider]", inputs: { size: "size", segmentsSetter: ["segments", "segmentsSetter", (x) => Array.isArray(x) ? x : new Array(x).fill(null).map((_, i) => i / x)] }, host: { listeners: { "input": "0" }, properties: { "style.--tui-slider-track-color": "options.trackColor", "style.--tui-ticks-gradient": "ticksGradient()", "style.--tui-slider-fill-ratio": "valueRatio", "attr.data-size": "size" } }, providers: [tuiAsAuxiliary(TuiSliderComponent)], ngImport: i0, template: '', isInline: true, styles: [":host{--t-tick-thickness: .25rem;position:relative;display:block;inline-size:100%;color:var(--tui-background-accent-1);cursor:pointer;-webkit-appearance:none;appearance:none;block-size:.125rem;padding:.4375rem 0;background-color:transparent;background-clip:content-box;outline:none;border-radius:var(--tui-radius-m)}:host:active{cursor:ew-resize}:host:disabled{opacity:var(--tui-disabled-opacity);cursor:auto}:host[data-size=s]:not(:disabled):before{transition-property:transform,opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:absolute;top:.25rem;left:var(--t-left);inset-inline-start:var(--t-left);inline-size:.5rem;block-size:.5rem;border-radius:50%;transform:var(--tui-slider-thumb-transform, scale(1));--t-left: calc(var(--tui-slider-fill-ratio) * 100% - var(--tui-slider-fill-ratio) * .5rem);content:\"\";cursor:ew-resize;background:currentColor;opacity:0}:host[data-size=s]:active:before{opacity:.2;transform:var(--tui-slider-thumb-transform, scale(1)) scale(2.33)}:host[data-size=m]:not(:disabled):before{transition-property:transform,opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:absolute;top:.125rem;left:var(--t-left);inset-inline-start:var(--t-left);inline-size:.75rem;block-size:.75rem;border-radius:50%;transform:var(--tui-slider-thumb-transform, scale(1));--t-left: calc(var(--tui-slider-fill-ratio) * 100% - var(--tui-slider-fill-ratio) * .75rem);content:\"\";cursor:ew-resize;background:currentColor;opacity:0}:host[data-size=m]:active:before{opacity:.2;transform:var(--tui-slider-thumb-transform, scale(1)) scale(2.33)}:host::-webkit-slider-container{border-radius:inherit}:host[data-size=m]::-webkit-slider-runnable-track{block-size:.125rem;border-radius:inherit;background-repeat:no-repeat;background-color:var(--tui-slider-track-color);background-image:var(--tui-ticks-gradient),linear-gradient(to var(--tui-inline-end),currentColor calc(100% * var(--tui-slider-fill-ratio)),transparent calc(100% * var(--tui-slider-fill-ratio)));background-position-x:calc((.75rem - var(--t-tick-thickness)) / 2),0;background-size:calc(100% - .75rem),auto}:host[data-size=s]::-webkit-slider-runnable-track{block-size:.125rem;border-radius:inherit;background-repeat:no-repeat;background-color:var(--tui-slider-track-color);background-image:var(--tui-ticks-gradient),linear-gradient(to var(--tui-inline-end),currentColor calc(100% * var(--tui-slider-fill-ratio)),transparent calc(100% * var(--tui-slider-fill-ratio)));background-position-x:calc((.5rem - var(--t-tick-thickness)) / 2),0;background-size:calc(100% - .5rem),auto}:host[data-size=m]::-moz-range-track{block-size:.125rem;border-radius:inherit;background-repeat:no-repeat;background-color:var(--tui-slider-track-color);background-image:var(--tui-ticks-gradient);background-position-x:calc((.75rem - var(--t-tick-thickness)) / 2);background-size:calc(100% - .75rem)}:host[data-size=s]::-moz-range-track{block-size:.125rem;border-radius:inherit;background-repeat:no-repeat;background-color:var(--tui-slider-track-color);background-image:var(--tui-ticks-gradient);background-position-x:calc((.5rem - var(--t-tick-thickness)) / 2);background-size:calc(100% - .5rem)}:host[data-size=m]::-webkit-slider-thumb{-webkit-transition-property:transform;transition-property:transform;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;isolation:isolate;-webkit-appearance:none;appearance:none;background-color:currentColor;box-shadow:none;border-radius:50%;block-size:.75rem;inline-size:.75rem;box-sizing:content-box;background-clip:content-box;border:.125rem solid transparent;border-inline-start:0;border-inline-end:0;transform:var(--tui-slider-thumb-transform, scale(1));margin-block-start:-.4375rem}:not(:disabled):host[data-size=m]::-webkit-slider-thumb{cursor:ew-resize}:not(:disabled):host[data-size=m]::-webkit-slider-thumb:hover,:active:not(:disabled):host[data-size=m]::-webkit-slider-thumb{transform:var(--tui-slider-thumb-transform, scale(1)) scale(1.333)}:focus-visible:host[data-size=m]::-webkit-slider-thumb{box-shadow:0 0 0 2px inset var(--tui-border-focus)}:host[data-size=s]::-webkit-slider-thumb{-webkit-transition-property:transform;transition-property:transform;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;isolation:isolate;-webkit-appearance:none;appearance:none;background-color:currentColor;box-shadow:none;border-radius:50%;block-size:.5rem;inline-size:.5rem;box-sizing:content-box;background-clip:content-box;border:.25rem solid transparent;border-inline-start:0;border-inline-end:0;transform:var(--tui-slider-thumb-transform, scale(1));margin-block-start:-.4375rem}:not(:disabled):host[data-size=s]::-webkit-slider-thumb{cursor:ew-resize}:not(:disabled):host[data-size=s]::-webkit-slider-thumb:hover,:active:not(:disabled):host[data-size=s]::-webkit-slider-thumb{transform:var(--tui-slider-thumb-transform, scale(1)) scale(1.5)}:focus-visible:host[data-size=s]::-webkit-slider-thumb{box-shadow:0 0 0 2px inset var(--tui-border-focus)}:host[data-size=m]::-moz-range-thumb{-moz-transition-property:transform;transition-property:transform;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;isolation:isolate;-webkit-appearance:none;appearance:none;background-color:currentColor;box-shadow:none;border-radius:50%;block-size:.75rem;inline-size:.75rem;box-sizing:content-box;background-clip:content-box;border:.125rem solid transparent;border-inline-start:0;border-inline-end:0;transform:var(--tui-slider-thumb-transform, scale(1))}:not(:disabled):host[data-size=m]::-moz-range-thumb{cursor:ew-resize}:not(:disabled):host[data-size=m]::-moz-range-thumb:hover,:active:not(:disabled):host[data-size=m]::-moz-range-thumb{transform:var(--tui-slider-thumb-transform, scale(1)) scale(1.333)}:focus-visible:host[data-size=m]::-moz-range-thumb{box-shadow:0 0 0 2px inset var(--tui-border-focus)}:host[data-size=s]::-moz-range-thumb{-moz-transition-property:transform;transition-property:transform;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;isolation:isolate;-webkit-appearance:none;appearance:none;background-color:currentColor;box-shadow:none;border-radius:50%;block-size:.5rem;inline-size:.5rem;box-sizing:content-box;background-clip:content-box;border:.25rem solid transparent;border-inline-start:0;border-inline-end:0;transform:var(--tui-slider-thumb-transform, scale(1))}:not(:disabled):host[data-size=s]::-moz-range-thumb{cursor:ew-resize}:not(:disabled):host[data-size=s]::-moz-range-thumb:hover,:active:not(:disabled):host[data-size=s]::-moz-range-thumb{transform:var(--tui-slider-thumb-transform, scale(1)) scale(1.5)}:focus-visible:host[data-size=s]::-moz-range-thumb{box-shadow:0 0 0 2px inset var(--tui-border-focus)}:host::-moz-range-progress{border-radius:inherit}:host::-moz-range-progress{block-size:.125rem;background:currentColor;border-top-right-radius:0;border-bottom-right-radius:0}:host-context(tui-textfield) :host([type=\"range\"]){--tui-radius: var(--tui-radius-m);position:absolute;top:100%;left:calc(var(--tui-radius) / 2);right:calc(var(--tui-radius) / 2);inline-size:calc(100% - calc(var(--tui-radius) / 2) * 2);box-sizing:border-box;block-size:1rem;margin:-.5625rem 0 0;padding:0;border-top-left-radius:0;border-bottom-left-radius:calc(var(--tui-radius) * 10) calc(var(--tui-radius) * 2);pointer-events:auto}:host-context(tui-textfield[data-size=\"l\"]) :host([type=\"range\"]){--tui-radius: var(--tui-radius-l)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiSliderComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: 'input[type=range][tuiSlider]', template: '', changeDetection: ChangeDetectionStrategy.OnPush, providers: [tuiAsAuxiliary(TuiSliderComponent)], host: { /** * For change detection. * Webkit does not have built-in method for customization of filling progress (as Firefox). * We draw filling of progress by `background: linear-gradient(...)` of the track. * This function triggers change detection (for {@link valueRatio} getter) when we drag thumb of the input. */ '(input)': '0', '[style.--tui-slider-track-color]': 'options.trackColor', '[style.--tui-ticks-gradient]': 'ticksGradient()', '[style.--tui-slider-fill-ratio]': 'valueRatio', '[attr.data-size]': 'size', }, styles: [":host{--t-tick-thickness: .25rem;position:relative;display:block;inline-size:100%;color:var(--tui-background-accent-1);cursor:pointer;-webkit-appearance:none;appearance:none;block-size:.125rem;padding:.4375rem 0;background-color:transparent;background-clip:content-box;outline:none;border-radius:var(--tui-radius-m)}:host:active{cursor:ew-resize}:host:disabled{opacity:var(--tui-disabled-opacity);cursor:auto}:host[data-size=s]:not(:disabled):before{transition-property:transform,opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:absolute;top:.25rem;left:var(--t-left);inset-inline-start:var(--t-left);inline-size:.5rem;block-size:.5rem;border-radius:50%;transform:var(--tui-slider-thumb-transform, scale(1));--t-left: calc(var(--tui-slider-fill-ratio) * 100% - var(--tui-slider-fill-ratio) * .5rem);content:\"\";cursor:ew-resize;background:currentColor;opacity:0}:host[data-size=s]:active:before{opacity:.2;transform:var(--tui-slider-thumb-transform, scale(1)) scale(2.33)}:host[data-size=m]:not(:disabled):before{transition-property:transform,opacity;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;position:absolute;top:.125rem;left:var(--t-left);inset-inline-start:var(--t-left);inline-size:.75rem;block-size:.75rem;border-radius:50%;transform:var(--tui-slider-thumb-transform, scale(1));--t-left: calc(var(--tui-slider-fill-ratio) * 100% - var(--tui-slider-fill-ratio) * .75rem);content:\"\";cursor:ew-resize;background:currentColor;opacity:0}:host[data-size=m]:active:before{opacity:.2;transform:var(--tui-slider-thumb-transform, scale(1)) scale(2.33)}:host::-webkit-slider-container{border-radius:inherit}:host[data-size=m]::-webkit-slider-runnable-track{block-size:.125rem;border-radius:inherit;background-repeat:no-repeat;background-color:var(--tui-slider-track-color);background-image:var(--tui-ticks-gradient),linear-gradient(to var(--tui-inline-end),currentColor calc(100% * var(--tui-slider-fill-ratio)),transparent calc(100% * var(--tui-slider-fill-ratio)));background-position-x:calc((.75rem - var(--t-tick-thickness)) / 2),0;background-size:calc(100% - .75rem),auto}:host[data-size=s]::-webkit-slider-runnable-track{block-size:.125rem;border-radius:inherit;background-repeat:no-repeat;background-color:var(--tui-slider-track-color);background-image:var(--tui-ticks-gradient),linear-gradient(to var(--tui-inline-end),currentColor calc(100% * var(--tui-slider-fill-ratio)),transparent calc(100% * var(--tui-slider-fill-ratio)));background-position-x:calc((.5rem - var(--t-tick-thickness)) / 2),0;background-size:calc(100% - .5rem),auto}:host[data-size=m]::-moz-range-track{block-size:.125rem;border-radius:inherit;background-repeat:no-repeat;background-color:var(--tui-slider-track-color);background-image:var(--tui-ticks-gradient);background-position-x:calc((.75rem - var(--t-tick-thickness)) / 2);background-size:calc(100% - .75rem)}:host[data-size=s]::-moz-range-track{block-size:.125rem;border-radius:inherit;background-repeat:no-repeat;background-color:var(--tui-slider-track-color);background-image:var(--tui-ticks-gradient);background-position-x:calc((.5rem - var(--t-tick-thickness)) / 2);background-size:calc(100% - .5rem)}:host[data-size=m]::-webkit-slider-thumb{-webkit-transition-property:transform;transition-property:transform;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;isolation:isolate;-webkit-appearance:none;appearance:none;background-color:currentColor;box-shadow:none;border-radius:50%;block-size:.75rem;inline-size:.75rem;box-sizing:content-box;background-clip:content-box;border:.125rem solid transparent;border-inline-start:0;border-inline-end:0;transform:var(--tui-slider-thumb-transform, scale(1));margin-block-start:-.4375rem}:not(:disabled):host[data-size=m]::-webkit-slider-thumb{cursor:ew-resize}:not(:disabled):host[data-size=m]::-webkit-slider-thumb:hover,:active:not(:disabled):host[data-size=m]::-webkit-slider-thumb{transform:var(--tui-slider-thumb-transform, scale(1)) scale(1.333)}:focus-visible:host[data-size=m]::-webkit-slider-thumb{box-shadow:0 0 0 2px inset var(--tui-border-focus)}:host[data-size=s]::-webkit-slider-thumb{-webkit-transition-property:transform;transition-property:transform;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;isolation:isolate;-webkit-appearance:none;appearance:none;background-color:currentColor;box-shadow:none;border-radius:50%;block-size:.5rem;inline-size:.5rem;box-sizing:content-box;background-clip:content-box;border:.25rem solid transparent;border-inline-start:0;border-inline-end:0;transform:var(--tui-slider-thumb-transform, scale(1));margin-block-start:-.4375rem}:not(:disabled):host[data-size=s]::-webkit-slider-thumb{cursor:ew-resize}:not(:disabled):host[data-size=s]::-webkit-slider-thumb:hover,:active:not(:disabled):host[data-size=s]::-webkit-slider-thumb{transform:var(--tui-slider-thumb-transform, scale(1)) scale(1.5)}:focus-visible:host[data-size=s]::-webkit-slider-thumb{box-shadow:0 0 0 2px inset var(--tui-border-focus)}:host[data-size=m]::-moz-range-thumb{-moz-transition-property:transform;transition-property:transform;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;isolation:isolate;-webkit-appearance:none;appearance:none;background-color:currentColor;box-shadow:none;border-radius:50%;block-size:.75rem;inline-size:.75rem;box-sizing:content-box;background-clip:content-box;border:.125rem solid transparent;border-inline-start:0;border-inline-end:0;transform:var(--tui-slider-thumb-transform, scale(1))}:not(:disabled):host[data-size=m]::-moz-range-thumb{cursor:ew-resize}:not(:disabled):host[data-size=m]::-moz-range-thumb:hover,:active:not(:disabled):host[data-size=m]::-moz-range-thumb{transform:var(--tui-slider-thumb-transform, scale(1)) scale(1.333)}:focus-visible:host[data-size=m]::-moz-range-thumb{box-shadow:0 0 0 2px inset var(--tui-border-focus)}:host[data-size=s]::-moz-range-thumb{-moz-transition-property:transform;transition-property:transform;transition-duration:var(--tui-duration, .3s);transition-timing-function:ease-in-out;isolation:isolate;-webkit-appearance:none;appearance:none;background-color:currentColor;box-shadow:none;border-radius:50%;block-size:.5rem;inline-size:.5rem;box-sizing:content-box;background-clip:content-box;border:.25rem solid transparent;border-inline-start:0;border-inline-end:0;transform:var(--tui-slider-thumb-transform, scale(1))}:not(:disabled):host[data-size=s]::-moz-range-thumb{cursor:ew-resize}:not(:disabled):host[data-size=s]::-moz-range-thumb:hover,:active:not(:disabled):host[data-size=s]::-moz-range-thumb{transform:var(--tui-slider-thumb-transform, scale(1)) scale(1.5)}:focus-visible:host[data-size=s]::-moz-range-thumb{box-shadow:0 0 0 2px inset var(--tui-border-focus)}:host::-moz-range-progress{border-radius:inherit}:host::-moz-range-progress{block-size:.125rem;background:currentColor;border-top-right-radius:0;border-bottom-right-radius:0}:host-context(tui-textfield) :host([type=\"range\"]){--tui-radius: var(--tui-radius-m);position:absolute;top:100%;left:calc(var(--tui-radius) / 2);right:calc(var(--tui-radius) / 2);inline-size:calc(100% - calc(var(--tui-radius) / 2) * 2);box-sizing:border-box;block-size:1rem;margin:-.5625rem 0 0;padding:0;border-top-left-radius:0;border-bottom-left-radius:calc(var(--tui-radius) * 10) calc(var(--tui-radius) * 2);pointer-events:auto}:host-context(tui-textfield[data-size=\"l\"]) :host([type=\"range\"]){--tui-radius: var(--tui-radius-l)}\n"] }] }], ctorParameters: function () { return []; }, propDecorators: { size: [{ type: Input }], segmentsSetter: [{ type: Input, args: [{ alias: 'segments', transform: (x) => Array.isArray(x) ? x : new Array(x).fill(null).map((_, i) => i / x), }] }] } }); class TuiSliderKeyStepsBase { constructor() { this.injector = inject(INJECTOR); this.control = inject(NgControl, { self: true, optional: true }); this.step = 1; this.transformer = signal(null); this.value = toSignal(timer(0) // https://github.com/angular/angular/issues/54418 .pipe(switchMap(() => tuiControlValue(this.control)))); } get slider() { return this.injector.get(TuiSliderComponent); } set keySteps(steps) { this.transformer.set(steps && tuiCreateKeyStepsTransformer(steps, this.slider)); this.min = steps?.[0][1]; this.max = steps?.[steps.length - 1]?.[1]; } /** * TODO(v5): standardize logic between `TuiSlider` & `TuiInputSlider` (for non-linear slider `step` means percentage) * Add these host-bindings to `TuiSliderKeyStepsBase`: * ``` * host: { * '[attr.min]': '0', * '[attr.step]': '1', * '[attr.max]': 'totalSteps', * }, * ``` */ get totalSteps() { /** * Not-integer amount of steps is invalid usage of native sliders * ```html * <input type="range" [max]="100" [step]="3.33" /> * ``` * (impossible to select 100; 99.9 is max allowed value) */ return this.step ? Math.round(100 / this.step) : Infinity; } takeStep(coefficient) { const newValue = this.slider.value + coefficient; return (this.transformer()?.toControlValue(this.slider.value + coefficient) ?? newValue); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiSliderKeyStepsBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "16.2.12", type: TuiSliderKeyStepsBase, isStandalone: true, selector: "input[tuiSlider][keySteps]", inputs: { step: ["step", "step", (x) => (x === 'any' ? null : x)], keySteps: "keySteps" }, host: { properties: { "attr.aria-valuemin": "min", "attr.aria-valuemax": "max", "attr.aria-valuenow": "value()" } }, ngImport: i0 }); } } __decorate([ tuiPure ], TuiSliderKeyStepsBase.prototype, "slider", null); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiSliderKeyStepsBase, decorators: [{ type: Directive, args: [{ standalone: true, selector: 'input[tuiSlider][keySteps]', host: { '[attr.aria-valuemin]': 'min', '[attr.aria-valuemax]': 'max', '[attr.aria-valuenow]': 'value()', }, }] }], propDecorators: { step: [{ type: Input, args: [{ transform: (x) => (x === 'any' ? null : x) }] }], slider: [], keySteps: [{ type: Input }] } }); class TuiSliderKeySteps extends TuiControl { constructor() { super(...arguments); this.slider = inject(forwardRef(() => TuiSliderComponent)); } set keySteps(steps) { this.transformer = tuiCreateKeyStepsTransformer(steps, this.slider); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiSliderKeySteps, deps: null, target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TuiSliderKeySteps, isStandalone: true, selector: "input[tuiSlider][keySteps][ngModel],input[tuiSlider][keySteps][formControl],input[tuiSlider][keySteps][formControlName]", inputs: { keySteps: "keySteps" }, host: { listeners: { "blur": "onTouched()", "input": "onChange($event.target.value)", "change": "onChange($event.target.value)" }, properties: { "value": "value()", "disabled": "disabled()" } }, providers: [tuiFallbackValueProvider(0)], usesInheritance: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiSliderKeySteps, decorators: [{ type: Directive, args: [{ standalone: true, selector: 'input[tuiSlider][keySteps][ngModel],input[tuiSlider][keySteps][formControl],input[tuiSlider][keySteps][formControlName]', providers: [tuiFallbackValueProvider(0)], host: { '[value]': 'value()', '[disabled]': 'disabled()', '(blur)': 'onTouched()', '(input)': 'onChange($event.target.value)', '(change)': 'onChange($event.target.value)', }, }] }], propDecorators: { keySteps: [{ type: Input }] } }); const SLIDER_INTERACTION_KEYS = new Set([ 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'End', 'Home', 'PageDown', 'PageUp', ]); /** * Native <input type='range' readonly> doesn't work. * This directive imitates this native behaviour. */ class TuiSliderReadonly { constructor() { this.el = tuiInjectElement(); this.doc = inject(DOCUMENT); this.readonly = true; const touchStart$ = tuiTypedFromEvent(this.el, 'touchstart', { passive: false, }); const touchMove$ = tuiTypedFromEvent(this.doc, 'touchmove', { passive: false, }); const touchEnd$ = tuiTypedFromEvent(this.doc, 'touchend', { passive: true, }); const shouldPreventMove$ = merge(touchStart$.pipe(tap((e) => this.preventEvent(e)), map(TUI_TRUE_HANDLER)), touchEnd$.pipe(map(TUI_FALSE_HANDLER))); /** * @bad TODO think about another solution. * Keep in mind that preventing touch event (on slider) inside `@HostListener('touchstart')` doesn't work for mobile chrome. */ combineLatest([touchMove$, shouldPreventMove$]) .pipe(filter(([_, shouldPreventMove]) => shouldPreventMove), takeUntilDestroyed()) .subscribe(([moveEvent]) => this.preventEvent(moveEvent)); } preventEvent(event) { if (event.cancelable && this.readonly) { event.preventDefault(); } } preventKeyboardInteraction(event) { if (SLIDER_INTERACTION_KEYS.has(event.key)) { this.preventEvent(event); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiSliderReadonly, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "16.2.12", type: TuiSliderReadonly, isStandalone: true, selector: "input[tuiSlider][readonly]", inputs: { readonly: ["readonly", "readonly", coerceBooleanProperty] }, host: { listeners: { "keydown": "preventKeyboardInteraction($event)", "mousedown": "preventEvent($event)" } }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiSliderReadonly, decorators: [{ type: Directive, args: [{ standalone: true, selector: 'input[tuiSlider][readonly]', host: { '(keydown)': 'preventKeyboardInteraction($event)', '(mousedown)': 'preventEvent($event)', }, }] }], ctorParameters: function () { return []; }, propDecorators: { readonly: [{ type: Input, args: [{ transform: coerceBooleanProperty }] }] } }); /// <reference types="@taiga-ui/tsconfig/ng-dev-mode" /> /// <reference types="@taiga-ui/tsconfig/ng-dev-mode" /> class TuiSliderThumbLabel { ngAfterContentInit() { ngDevMode && console.assert(Boolean(this.control?.valueChanges), '\n[tuiSliderThumbLabel] expected <input tuiSlider type="range" /> to use Angular Forms.\n' + 'Use [(ngModel)] or [formControl] or formControlName for correct work.'); } get size() { return this.slider?.size || 'm'; } get ratio() { return this.slider?.valueRatio || 0; } get ghostStart() { return this.ratio * (this.slider?.el.offsetWidth || 0); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiSliderThumbLabel, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TuiSliderThumbLabel, isStandalone: true, selector: "[tuiSliderThumbLabel]", providers: [tuiHintOptionsProvider({ direction: 'top', appearance: 'dark' })], queries: [{ propertyName: "slider", first: true, predicate: TuiSliderComponent, descendants: true }, { propertyName: "control", first: true, predicate: NgControl, descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"control?.valueChanges | async\" />\n\n<div\n class=\"t-ghost\"\n [attr.data-size]=\"size\"\n [style.--tui-slider-thumb-ratio]=\"ratio\"\n [style.inset-inline-start.px]=\"ghostStart\"\n [style.left.px]=\"ghostStart\"\n>\n <ng-content />\n</div>\n\n<ng-content select=\"input[type=range]\" />\n", styles: [":host{position:relative}.t-ghost{position:absolute;top:0;bottom:0;margin:auto;border-radius:50%;pointer-events:none}.t-ghost[data-size=s]{inline-size:.5rem;block-size:.5rem;transform:translate(calc(var(--tui-slider-thumb-ratio) * -.5rem * var(--tui-inline)))}.t-ghost[data-size=m]{inline-size:.75rem;block-size:.75rem;transform:translate(calc(var(--tui-slider-thumb-ratio) * -.75rem * var(--tui-inline)))}@supports (inset-inline-end: 0){:host-context([dir=\"rtl\"]) .t-ghost{left:unset!important}}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiSliderThumbLabel, decorators: [{ type: Component, args: [{ standalone: true, selector: '[tuiSliderThumbLabel]', imports: [AsyncPipe, NgIf], changeDetection: ChangeDetectionStrategy.OnPush, providers: [tuiHintOptionsProvider({ direction: 'top', appearance: 'dark' })], template: "<ng-container *ngIf=\"control?.valueChanges | async\" />\n\n<div\n class=\"t-ghost\"\n [attr.data-size]=\"size\"\n [style.--tui-slider-thumb-ratio]=\"ratio\"\n [style.inset-inline-start.px]=\"ghostStart\"\n [style.left.px]=\"ghostStart\"\n>\n <ng-content />\n</div>\n\n<ng-content select=\"input[type=range]\" />\n", styles: [":host{position:relative}.t-ghost{position:absolute;top:0;bottom:0;margin:auto;border-radius:50%;pointer-events:none}.t-ghost[data-size=s]{inline-size:.5rem;block-size:.5rem;transform:translate(calc(var(--tui-slider-thumb-ratio) * -.5rem * var(--tui-inline)))}.t-ghost[data-size=m]{inline-size:.75rem;block-size:.75rem;transform:translate(calc(var(--tui-slider-thumb-ratio) * -.75rem * var(--tui-inline)))}@supports (inset-inline-end: 0){:host-context([dir=\"rtl\"]) .t-ghost{left:unset!important}}\n"] }] }], propDecorators: { slider: [{ type: ContentChild, args: [TuiSliderComponent] }], control: [{ type: ContentChild, args: [NgControl] }] } }); const TuiSlider = [ TuiSliderComponent, TuiSliderThumbLabel, TuiSliderKeyStepsBase, TuiSliderKeySteps, TuiSliderReadonly, ]; /** * Generated bundle index. Do not edit. */ export { TUI_FLOATING_PRECISION, TUI_SLIDER_DEFAULT_OPTIONS, TUI_SLIDER_OPTIONS, TuiSlider, TuiSliderComponent, TuiSliderKeySteps, TuiSliderKeyStepsBase, TuiSliderReadonly, TuiSliderThumbLabel, tuiCreateKeyStepsTransformer, tuiKeyStepValueToPercentage, tuiPercentageToKeyStepValue, tuiSliderOptionsProvider }; //# sourceMappingURL=taiga-ui-kit-components-slider.mjs.map