@taiga-ui/kit
Version:
Taiga UI Angular main components kit
140 lines (136 loc) • 14.5 kB
JavaScript
import * as i0 from '@angular/core';
import { viewChildren, ElementRef, viewChild, inject, computed, input, ChangeDetectionStrategy, Component } from '@angular/core';
import * as i1 from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { WA_IS_MOBILE } from '@ng-web-apis/platform';
import { TuiControl, tuiAsControl } from '@taiga-ui/cdk/classes';
import { CHAR_NO_BREAK_SPACE, CHAR_EN_DASH } from '@taiga-ui/cdk/constants';
import { tuiFallbackValueProvider } from '@taiga-ui/cdk/tokens';
import { tuiIsFocused } from '@taiga-ui/cdk/utils/focus';
import { tuiIsString, tuiIsNumber } from '@taiga-ui/cdk/utils/miscellaneous';
import * as i4 from '@taiga-ui/core/components/textfield';
import { TUI_TEXTFIELD_OPTIONS, TuiTextfield } from '@taiga-ui/core/components/textfield';
import * as i2 from '@taiga-ui/kit/components/input-number';
import { TuiInputNumberDirective, TUI_INPUT_NUMBER_OPTIONS, TuiQuantumValueTransformerBase, TuiInputNumber } from '@taiga-ui/kit/components/input-number';
import { TuiRange } from '@taiga-ui/kit/components/range';
import { PolymorpheusOutlet } from '@taiga-ui/polymorpheus';
import * as i3 from '@taiga-ui/core/components/label';
const transform = (x) => x ?? ['', ''];
class TuiInputRange extends TuiControl {
constructor() {
super(...arguments);
this.inputs = viewChildren(TuiInputNumberDirective, { read: ElementRef });
this.range = viewChild(TuiRange);
this.options = inject(TUI_INPUT_NUMBER_OPTIONS);
this.isMobile = inject(WA_IS_MOBILE);
this.quantumTransformer = computed(() => new TuiQuantumValueTransformerBase(this.quantum()));
this.size = inject(TUI_TEXTFIELD_OPTIONS).size;
this.start = this.value()[0];
this.end = this.value()[1];
this.side = 'start';
this.contentStart = computed(() => {
const [start, end] = this.content().map((x, i) => {
const value = this.value()[i];
return typeof x === 'function' ? x({ $implicit: value }) : x || value;
});
return this.interactive() || !this.isPrimitive(start) || !this.isPrimitive(end)
? this.content()[0]
: `${start}${CHAR_NO_BREAK_SPACE}${CHAR_EN_DASH}${CHAR_NO_BREAK_SPACE}${end}`;
});
this.contentEnd = computed(() => this.contentStart() === this.content()[0] ? this.content()[1] : '');
this.min = input(0);
this.max = input(100);
this.step = input(1);
this.segments = input(1);
this.keySteps = input();
this.quantum = input(0);
this.prefix = input([this.options.prefix, this.options.prefix], {
transform,
});
this.postfix = input([this.options.postfix, this.options.postfix], {
transform,
});
this.content = input(['', '']);
}
writeValue(value) {
super.writeValue(value);
this.setTextfieldValues(this.value());
}
get contentStartHidden() {
return this.interactive() && tuiIsFocused(this.textfieldStart);
}
get contentEndHidden() {
return (!this.content()[1] || (this.interactive() && tuiIsFocused(this.textfieldEnd)));
}
takeStep(event, coefficients) {
if (!this.interactive() || !this.range()) {
return;
}
event.preventDefault();
const [start, end] = this.value();
const newValue = this.valueGuard(this.range().takeStep(coefficients));
if (newValue[0] !== start || newValue[1] !== end) {
this.onExternalValueUpdate(newValue);
}
}
onInput([start, end]) {
this.setValue([start ?? this.value()[0], end ?? this.value()[1]]);
}
onExternalValueUpdate(value) {
this.setValue(value);
this.setTextfieldValues(this.value());
setTimeout((end = Number.MAX_SAFE_INTEGER) => {
if (tuiIsFocused(this.activeTextfield)) {
this.activeTextfield?.setSelectionRange(end, end);
}
});
}
focusToTextfield() {
if (!this.isMobile) {
this.activeTextfield?.focus();
}
}
onBlur() {
this.onTouched();
this.setTextfieldValues(this.value());
}
setTextfieldValues([start, end]) {
this.start = start;
this.end = end;
}
get textfieldStart() {
return this.inputs()[0]?.nativeElement || null;
}
get textfieldEnd() {
return this.inputs()[this.inputs().length - 1]?.nativeElement || null;
}
get activeTextfield() {
return this.side === 'start' ? this.textfieldStart : this.textfieldEnd;
}
setValue(value) {
this.onChange(this.valueGuard(value));
}
valueGuard(value) {
const [prevStart, prevEnd] = this.value();
const [start, end] = value.map((x) => this.quantumTransformer().toControlValue(x) ?? x);
return [Math.min(start, prevEnd), Math.max(end, prevStart)];
}
isPrimitive(x) {
return !x || tuiIsString(x) || tuiIsNumber(x);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiInputRange, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TuiInputRange, isStandalone: true, selector: "tui-input-range", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, segments: { classPropertyName: "segments", publicName: "segments", isSignal: true, isRequired: false, transformFunction: null }, keySteps: { classPropertyName: "keySteps", publicName: "keySteps", isSignal: true, isRequired: false, transformFunction: null }, quantum: { classPropertyName: "quantum", publicName: "quantum", isSignal: true, isRequired: false, transformFunction: null }, prefix: { classPropertyName: "prefix", publicName: "prefix", isSignal: true, isRequired: false, transformFunction: null }, postfix: { classPropertyName: "postfix", publicName: "postfix", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-size": "size()", "style.--t-icon-lock": "contentEnd() ? \"none\" : null" } }, providers: [tuiAsControl(TuiInputRange), tuiFallbackValueProvider([0, 0])], viewQueries: [{ propertyName: "inputs", predicate: TuiInputNumberDirective, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "range", first: true, predicate: TuiRange, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<tui-textfield [content]=\"contentStartHidden ? '' : contentStart()\">\n <label tuiLabel>\n <ng-content />\n </label>\n\n <input\n tuiInputNumber\n [disabled]=\"disabled()\"\n [invalid]=\"invalid()\"\n [max]=\"value()[1]\"\n [min]=\"min()\"\n [postfix]=\"postfix()[0]\"\n [prefix]=\"prefix()[0]\"\n [readOnly]=\"readOnly()\"\n [(ngModel)]=\"start\"\n (blur)=\"onBlur()\"\n (keydown.arrowDown)=\"takeStep($event, [-1, 0])\"\n (keydown.arrowUp)=\"takeStep($event, [1, 0])\"\n (ngModelChange)=\"onInput([$event, null])\"\n />\n\n <input\n tuiInputNumber\n class=\"t-end\"\n [class._hidden]=\"!contentEndHidden || !this.interactive()\"\n [disabled]=\"disabled()\"\n [invalid]=\"invalid()\"\n [max]=\"max()\"\n [min]=\"value()[0]\"\n [postfix]=\"postfix()[1]\"\n [prefix]=\"prefix()[1]\"\n [readOnly]=\"readOnly()\"\n [(ngModel)]=\"end\"\n (blur)=\"onBlur()\"\n (keydown.arrowDown)=\"takeStep($event, [0, -1])\"\n (keydown.arrowUp)=\"takeStep($event, [0, 1])\"\n (ngModelChange)=\"onInput([null, $event])\"\n />\n\n @if (!contentEndHidden && contentEnd()) {\n <div class=\"t-content-end\">\n <ng-container *polymorpheusOutlet=\"contentEnd() as text; context: {$implicit: value()[1]}\">\n {{ text }}\n </ng-container>\n </div>\n }\n\n @if (interactive()) {\n <tui-range\n [focusable]=\"false\"\n [keySteps]=\"keySteps()\"\n [max]=\"max()\"\n [min]=\"min()\"\n [ngModel]=\"value()\"\n [segments]=\"segments()\"\n [step]=\"step()\"\n (activeThumbChange)=\"side = $event\"\n (ngModelChange)=\"onExternalValueUpdate($event)\"\n (pointerdown.prevent.stop)=\"focusToTextfield()\"\n />\n }\n</tui-textfield>\n", styles: [":host{position:relative;display:block}:host-context([tuiTable]){block-size:100%}.t-end{inset-inline:auto 0;inline-size:50%;text-align:end;padding-inline-start:0}.t-content-end{color:var(--tui-text-primary)}tui-textfield._with-label .t-content-end{padding-block-start:calc(var(--t-height) / 3)}._hidden._hidden{opacity:0}tui-range{position:absolute;inset:100% var(--t-padding) auto;z-index:1;margin:calc(-1*max(calc(calc(var(--tui-thumb-size, .75rem) / 2) - .25rem),.125rem)) 0 0;pointer-events:auto;background-color:transparent}tui-textfield::ng-deep [tuiButtonX]{display:none!important}tui-textfield::ng-deep .t-content{margin-inline-end:0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "directive", type: i2.TuiInputNumberDirective, selector: "input[tuiInputNumber]" }, { kind: "directive", type: i3.TuiLabel, selector: "label[tuiLabel]" }, { kind: "component", type: i4.TuiTextfieldComponent, selector: "tui-textfield:not([multi])", inputs: ["content", "filler"] }, { kind: "component", type: TuiRange, selector: "tui-range", inputs: ["min", "max", "step", "segments", "keySteps", "focusable", "margin", "limit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TuiInputRange, decorators: [{
type: Component,
args: [{ selector: 'tui-input-range', imports: [FormsModule, PolymorpheusOutlet, TuiInputNumber, TuiRange, TuiTextfield], changeDetection: ChangeDetectionStrategy.OnPush, providers: [tuiAsControl(TuiInputRange), tuiFallbackValueProvider([0, 0])], host: {
'[attr.data-size]': 'size()',
// TODO: Delete this line and put `tui-input-range:has(.t-content-end) {--t-icon-lock: none}` to proprietary styles
'[style.--t-icon-lock]': 'contentEnd() ? "none" : null',
}, template: "<tui-textfield [content]=\"contentStartHidden ? '' : contentStart()\">\n <label tuiLabel>\n <ng-content />\n </label>\n\n <input\n tuiInputNumber\n [disabled]=\"disabled()\"\n [invalid]=\"invalid()\"\n [max]=\"value()[1]\"\n [min]=\"min()\"\n [postfix]=\"postfix()[0]\"\n [prefix]=\"prefix()[0]\"\n [readOnly]=\"readOnly()\"\n [(ngModel)]=\"start\"\n (blur)=\"onBlur()\"\n (keydown.arrowDown)=\"takeStep($event, [-1, 0])\"\n (keydown.arrowUp)=\"takeStep($event, [1, 0])\"\n (ngModelChange)=\"onInput([$event, null])\"\n />\n\n <input\n tuiInputNumber\n class=\"t-end\"\n [class._hidden]=\"!contentEndHidden || !this.interactive()\"\n [disabled]=\"disabled()\"\n [invalid]=\"invalid()\"\n [max]=\"max()\"\n [min]=\"value()[0]\"\n [postfix]=\"postfix()[1]\"\n [prefix]=\"prefix()[1]\"\n [readOnly]=\"readOnly()\"\n [(ngModel)]=\"end\"\n (blur)=\"onBlur()\"\n (keydown.arrowDown)=\"takeStep($event, [0, -1])\"\n (keydown.arrowUp)=\"takeStep($event, [0, 1])\"\n (ngModelChange)=\"onInput([null, $event])\"\n />\n\n @if (!contentEndHidden && contentEnd()) {\n <div class=\"t-content-end\">\n <ng-container *polymorpheusOutlet=\"contentEnd() as text; context: {$implicit: value()[1]}\">\n {{ text }}\n </ng-container>\n </div>\n }\n\n @if (interactive()) {\n <tui-range\n [focusable]=\"false\"\n [keySteps]=\"keySteps()\"\n [max]=\"max()\"\n [min]=\"min()\"\n [ngModel]=\"value()\"\n [segments]=\"segments()\"\n [step]=\"step()\"\n (activeThumbChange)=\"side = $event\"\n (ngModelChange)=\"onExternalValueUpdate($event)\"\n (pointerdown.prevent.stop)=\"focusToTextfield()\"\n />\n }\n</tui-textfield>\n", styles: [":host{position:relative;display:block}:host-context([tuiTable]){block-size:100%}.t-end{inset-inline:auto 0;inline-size:50%;text-align:end;padding-inline-start:0}.t-content-end{color:var(--tui-text-primary)}tui-textfield._with-label .t-content-end{padding-block-start:calc(var(--t-height) / 3)}._hidden._hidden{opacity:0}tui-range{position:absolute;inset:100% var(--t-padding) auto;z-index:1;margin:calc(-1*max(calc(calc(var(--tui-thumb-size, .75rem) / 2) - .25rem),.125rem)) 0 0;pointer-events:auto;background-color:transparent}tui-textfield::ng-deep [tuiButtonX]{display:none!important}tui-textfield::ng-deep .t-content{margin-inline-end:0}\n"] }]
}] });
/**
* Generated bundle index. Do not edit.
*/
export { TuiInputRange };
//# sourceMappingURL=taiga-ui-kit-components-input-range.mjs.map