@taiga-ui/kit
Version:
Taiga UI Angular main components kit
231 lines (224 loc) • 13.9 kB
JavaScript
import { TuiCalendar } from '@taiga-ui/core/components/calendar';
import { NgIf } from '@angular/common';
import * as i0 from '@angular/core';
import { InjectionToken, inject, effect, computed, signal, Directive, Input, Component, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core';
import { TuiTime, MILLISECONDS_IN_DAY, DATE_FILLER_LENGTH, TuiDay } from '@taiga-ui/cdk/date-time';
import * as i4 from '@taiga-ui/core/components/textfield';
import { tuiAsTextfieldAccessor, TuiWithTextfield, TuiTextfieldContent, TuiWithNativePicker } from '@taiga-ui/core/components/textfield';
import { TuiNativeTimePicker } from '@taiga-ui/kit/components/input-time';
import { toSignal } from '@angular/core/rxjs-interop';
import * as i1 from '@maskito/angular';
import { MaskitoDirective } from '@maskito/angular';
import { maskitoDateTimeOptionsGenerator, maskitoSelectionChangeHandler } from '@maskito/kit';
import { TUI_IDENTITY_VALUE_TRANSFORMER, tuiAsControl, tuiValueTransformerFrom } from '@taiga-ui/cdk/classes';
import { tuiSum, tuiClamp } from '@taiga-ui/cdk/utils/math';
import { tuiProvideOptions, tuiDirectiveBinding } from '@taiga-ui/cdk/utils/miscellaneous';
import { tuiAsOptionContent } from '@taiga-ui/core/components/data-list';
import * as i2 from '@taiga-ui/core/directives/dropdown';
import { TuiDropdownAuto } from '@taiga-ui/core/directives/dropdown';
import * as i3 from '@taiga-ui/core/directives/items-handlers';
import { TuiItemsHandlersValidator } from '@taiga-ui/core/directives/items-handlers';
import { TUI_INPUT_DATE_OPTIONS_NEW, TUI_INPUT_DATE_DEFAULT_OPTIONS_NEW, TuiInputDateBase, tuiWithDateFiller, TUI_DATE_ADAPTER } from '@taiga-ui/kit/components/input-date';
import { TuiSelectOption } from '@taiga-ui/kit/components/select';
import { TUI_TIME_TEXTS } from '@taiga-ui/kit/tokens';
import { tuiMaskito } from '@taiga-ui/kit/utils';
import { noop } from 'rxjs';
const TUI_INPUT_DATE_TIME_DEFAULT_OPTIONS = {
valueTransformer: TUI_IDENTITY_VALUE_TRANSFORMER,
timeMode: 'HH:MM',
dateTimeSeparator: ', ',
};
const TUI_INPUT_DATE_TIME_OPTIONS = new InjectionToken(ngDevMode ? 'TUI_INPUT_DATE_TIME_OPTIONS' : '', {
factory: () => ({
...inject(TUI_INPUT_DATE_OPTIONS_NEW),
...TUI_INPUT_DATE_TIME_DEFAULT_OPTIONS,
}),
});
const tuiInputDateTimeOptionsProvider = (options) => tuiProvideOptions(TUI_INPUT_DATE_TIME_OPTIONS, options, {
...TUI_INPUT_DATE_DEFAULT_OPTIONS_NEW,
...TUI_INPUT_DATE_TIME_DEFAULT_OPTIONS,
});
const MIN_TIME = new TuiTime(0, 0);
const MAX_TIME = TuiTime.fromAbsoluteMilliseconds(MILLISECONDS_IN_DAY - 1);
class TuiInputDateTimeDirective extends TuiInputDateBase {
constructor() {
super(...arguments);
this.timeFillers = toSignal(inject(TUI_TIME_TEXTS));
this.options = inject(TUI_INPUT_DATE_TIME_OPTIONS);
this.filler = tuiWithDateFiller((date) => {
const time = this.timeFillers()?.[this.timeMode()] ?? '';
return `${date}${this.options.dateTimeSeparator}${time}`;
});
this.valueEffect = effect(noop);
this.identity = this.handlers.identityMatcher.set((a, b) => tuiSum(...a.map(Number)) === tuiSum(...b.map(Number)));
this.disabledItemHandler = tuiDirectiveBinding(TuiItemsHandlersValidator, 'disabledItemHandler', (value) => Boolean(value && this.handlers.disabledItemHandler()(value)));
this.mask = tuiMaskito(computed(() => this.computeMask({
dateMode: TUI_DATE_ADAPTER[this.format().mode],
timeMode: this.timeMode(),
min: this.toNativeDate([this.min(), this.minTime()]),
max: this.toNativeDate([this.max(), this.maxTime()]),
dateSeparator: this.format().separator,
dateTimeSeparator: this.options.dateTimeSeparator,
})));
this.timeMode = signal(this.options.timeMode);
this.minTime = signal(MIN_TIME);
this.maxTime = signal(MAX_TIME);
}
// TODO(v5): use signal inputs
set timeModeSetter(x) {
this.timeMode.set(x);
}
set minSetter(min) {
const [date, time] = Array.isArray(min) ? min : [min, null];
this.min.set(date || this.options.min);
this.minTime.set(time ?? MIN_TIME);
}
set maxSetter(max) {
const [date, time] = Array.isArray(max) ? max : [max, null];
this.max.set(date || this.options.max);
this.maxTime.set(time ?? MAX_TIME);
}
setValue(value) {
this.onChange(value);
this.textfield.value.set(this.stringify(value));
}
setDate(newDate) {
const [date, time] = this.clampTime([newDate, this.value()?.[1] ?? null]);
this.setValue([date, time]);
this.open.set(false);
setTimeout((caretIndex = DATE_FILLER_LENGTH + this.options.dateTimeSeparator.length) => this.el.setSelectionRange(caretIndex, caretIndex));
}
writeValue(value) {
super.writeValue(value);
this.textfield.value.set(this.stringify(this.value()));
}
processCalendar(calendar) {
super.processCalendar(calendar);
calendar.disabledItemHandler = (day) => this.handlers.disabledItemHandler()([day, null]);
}
onValueChange(value) {
this.textfield.value.set(value);
this.control?.control?.updateValueAndValidity({ emitEvent: false });
const [date = '', time = ''] = value.split(this.options.dateTimeSeparator);
const parsedDate = date.length >= DATE_FILLER_LENGTH
? TuiDay.normalizeParse(date, this.format().mode)
: null;
const parsedTime = time.length === this.timeMode().length ? TuiTime.fromString(time) : null;
if (!parsedDate || (time && !parsedTime)) {
return this.onChange(null);
}
const [prevDate, prevTime = null] = this.value() ?? [];
if (!prevDate?.daySame(parsedDate) || Number(parsedTime) !== Number(prevTime)) {
this.onChange([parsedDate, parsedTime]);
}
}
stringify(value) {
const [date, time] = value ?? [];
const dateString = date?.toString(this.format().mode, this.format().separator) ?? '';
const timeString = time?.toString(this.timeMode());
return timeString
? `${dateString}${this.options.dateTimeSeparator}${timeString}`
: dateString;
}
clampTime([date, time]) {
const min = date.daySame(this.min())
? this.minTime().toAbsoluteMilliseconds()
: -Infinity;
const max = date.daySame(this.max())
? this.maxTime().toAbsoluteMilliseconds()
: Infinity;
return [
date,
time &&
TuiTime.fromAbsoluteMilliseconds(tuiClamp(time.toAbsoluteMilliseconds(), min, max)),
];
}
computeMask(params) {
const options = maskitoDateTimeOptionsGenerator(params);
const { timeMode, dateMode, dateTimeSeparator } = params;
const inputModeSwitchPlugin = maskitoSelectionChangeHandler((element) => {
element.inputMode =
element.selectionStart >=
dateMode.length + dateTimeSeparator.length + timeMode.indexOf(' AA')
? 'text'
: 'numeric';
});
return {
...options,
plugins: options.plugins.concat(timeMode.includes('AA') ? inputModeSwitchPlugin : []),
};
}
toNativeDate([{ year, month, day }, { hours, minutes, seconds, ms }]) {
return new Date(year, month, day, hours, minutes, seconds, ms);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiInputDateTimeDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TuiInputDateTimeDirective, isStandalone: true, selector: "input[tuiInputDateTime]", inputs: { timeModeSetter: ["timeMode", "timeModeSetter"], minSetter: ["min", "minSetter"], maxSetter: ["max", "maxSetter"] }, providers: [
tuiAsOptionContent(TuiSelectOption),
tuiAsControl(TuiInputDateTimeDirective),
tuiAsTextfieldAccessor(TuiInputDateTimeDirective),
tuiValueTransformerFrom(TUI_INPUT_DATE_TIME_OPTIONS),
], usesInheritance: true, hostDirectives: [{ directive: i1.MaskitoDirective }, { directive: i2.TuiDropdownAuto }, { directive: i3.TuiItemsHandlersValidator }, { directive: i4.TuiWithTextfield }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiInputDateTimeDirective, decorators: [{
type: Directive,
args: [{
standalone: true,
selector: 'input[tuiInputDateTime]',
providers: [
tuiAsOptionContent(TuiSelectOption),
tuiAsControl(TuiInputDateTimeDirective),
tuiAsTextfieldAccessor(TuiInputDateTimeDirective),
tuiValueTransformerFrom(TUI_INPUT_DATE_TIME_OPTIONS),
],
hostDirectives: [
MaskitoDirective,
TuiDropdownAuto,
TuiItemsHandlersValidator,
TuiWithTextfield,
],
}]
}], propDecorators: { timeModeSetter: [{
type: Input,
args: ['timeMode']
}], minSetter: [{
type: Input,
args: ['min']
}], maxSetter: [{
type: Input,
args: ['max']
}] } });
class TuiInputDateTimeComponent extends TuiNativeTimePicker {
constructor() {
super(...arguments);
this.host = inject(TuiInputDateTimeDirective);
this.step = computed(() => this.getStep(this.host.timeMode()));
this.value = computed(() => this.toISOString(this.host.value()));
this.min = computed(() => this.toISOString([this.host.min(), this.host.minTime()]));
this.max = computed(() => this.toISOString([this.host.max(), this.host.maxTime()]));
}
onInput(value) {
if (!value) {
return this.host.setValue(null);
}
const date = new Date(value);
const day = TuiDay.fromLocalNativeDate(date);
const time = TuiTime.fromLocalNativeDate(date);
this.host.setValue([day, time]);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiInputDateTimeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TuiInputDateTimeComponent, isStandalone: true, selector: "input[tuiInputDateTime][type=\"datetime-local\"]", host: { attributes: { "ngSkipHydration": "true" } }, usesInheritance: true, hostDirectives: [{ directive: i4.TuiWithNativePicker }], ngImport: i0, template: "<ng-container *ngIf=\"host.native\">\n <input\n *tuiTextfieldContent\n type=\"datetime-local\"\n [attr.list]=\"list\"\n [max]=\"max()\"\n [min]=\"min()\"\n [step]=\"step()\"\n [value]=\"value()\"\n (click.stop.zoneless)=\"(0)\"\n (input)=\"onInput($any($event.target).value)\"\n (pointerdown.stop.zoneless)=\"(0)\"\n />\n</ng-container>\n", styles: ["tui-textfield input[tuiInputDateTime]~.t-content input[type=datetime-local]{position:absolute;top:0;left:auto;right:0;bottom:0;inline-size:2.5rem;padding:0;opacity:0}tui-textfield input[tuiInputDateTime]~.t-content input[type=datetime-local]::-webkit-calendar-picker-indicator{position:absolute;top:0;left:0;inline-size:100%;block-size:100%}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: TuiTextfieldContent, selector: "ng-template[tuiTextfieldContent]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiInputDateTimeComponent, decorators: [{
type: Component,
args: [{ standalone: true, selector: 'input[tuiInputDateTime][type="datetime-local"]', imports: [NgIf, TuiTextfieldContent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [TuiWithNativePicker], host: { ngSkipHydration: 'true' }, template: "<ng-container *ngIf=\"host.native\">\n <input\n *tuiTextfieldContent\n type=\"datetime-local\"\n [attr.list]=\"list\"\n [max]=\"max()\"\n [min]=\"min()\"\n [step]=\"step()\"\n [value]=\"value()\"\n (click.stop.zoneless)=\"(0)\"\n (input)=\"onInput($any($event.target).value)\"\n (pointerdown.stop.zoneless)=\"(0)\"\n />\n</ng-container>\n", styles: ["tui-textfield input[tuiInputDateTime]~.t-content input[type=datetime-local]{position:absolute;top:0;left:auto;right:0;bottom:0;inline-size:2.5rem;padding:0;opacity:0}tui-textfield input[tuiInputDateTime]~.t-content input[type=datetime-local]::-webkit-calendar-picker-indicator{position:absolute;top:0;left:0;inline-size:100%;block-size:100%}\n"] }]
}] });
const TuiInputDateTime = [
TuiInputDateTimeDirective,
TuiInputDateTimeComponent,
TuiCalendar,
];
/**
* Generated bundle index. Do not edit.
*/
export { TUI_INPUT_DATE_TIME_DEFAULT_OPTIONS, TUI_INPUT_DATE_TIME_OPTIONS, TuiInputDateTime, TuiInputDateTimeComponent, TuiInputDateTimeDirective, tuiInputDateTimeOptionsProvider };
//# sourceMappingURL=taiga-ui-kit-components-input-date-time.mjs.map