UNPKG

@taiga-ui/kit

Version:

Taiga UI Angular main components kit

231 lines (224 loc) 13.9 kB
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