diff --git a/projects/addon-mobile/components/mobile-calendar-dropdown/mobile-calendar-dropdown.component.ts b/projects/addon-mobile/components/mobile-calendar-dropdown/mobile-calendar-dropdown.component.ts index bae4f23a9251..4b6a045c746a 100644 --- a/projects/addon-mobile/components/mobile-calendar-dropdown/mobile-calendar-dropdown.component.ts +++ b/projects/addon-mobile/components/mobile-calendar-dropdown/mobile-calendar-dropdown.component.ts @@ -4,15 +4,19 @@ import {TuiMobileCalendar} from '@taiga-ui/addon-mobile/components/mobile-calend import {TuiKeyboardService} from '@taiga-ui/addon-mobile/services'; import {TuiControl} from '@taiga-ui/cdk/classes'; import {TUI_FALSE_HANDLER} from '@taiga-ui/cdk/constants'; -import type {TuiDay} from '@taiga-ui/cdk/date-time'; -import {TUI_FIRST_DAY, TUI_LAST_DAY} from '@taiga-ui/cdk/date-time'; +import type {TuiDayLike} from '@taiga-ui/cdk/date-time'; +import {TUI_FIRST_DAY, TUI_LAST_DAY, TuiDay, TuiDayRange} from '@taiga-ui/cdk/date-time'; import {TuiActiveZone} from '@taiga-ui/cdk/directives/active-zone'; import type {TuiBooleanHandler} from '@taiga-ui/cdk/types'; +import {tuiPure} from '@taiga-ui/cdk/utils/miscellaneous'; import {tuiFadeIn, tuiSlideInTop} from '@taiga-ui/core/animations'; import {TuiDropdownDirective} from '@taiga-ui/core/directives/dropdown'; import {TUI_ANIMATIONS_SPEED} from '@taiga-ui/core/tokens'; import {tuiGetDuration} from '@taiga-ui/core/utils/miscellaneous'; -import {TUI_DAY_CAPS_MAPPER} from '@taiga-ui/kit/components/calendar-range'; +import { + calculateDisabledItemHandler, + TUI_DAY_CAPS_MAPPER, +} from '@taiga-ui/kit/components/calendar-range'; import {TUI_MOBILE_CALENDAR} from '@taiga-ui/kit/tokens'; import {injectContext} from '@taiga-ui/polymorpheus'; import type {Observer} from 'rxjs'; @@ -47,6 +51,8 @@ export class TuiMobileCalendarDropdown { private readonly observer?: Observer = this.context?.$implicit; private readonly data: TuiMobileCalendarData = this.context?.data || {}; + private selectedPeriod: TuiDayRange | null = null; + protected readonly animation = { value: '', params: { @@ -62,39 +68,62 @@ export class TuiMobileCalendarDropdown { protected readonly single = this.data.single || this.is('tui-input-date:not([multiple])'); - protected readonly min = - this.data.min || - (this.range - ? TUI_DAY_CAPS_MAPPER( - this.control.min, - this.control.value, - this.control.maxLength, - true, - ) - : this.control?.min) || - TUI_FIRST_DAY; - - protected readonly max = - this.data.max || - (this.range - ? TUI_DAY_CAPS_MAPPER( - this.control.max, - this.control.value, - this.control.maxLength, - false, - ) - : this.control?.max) || - TUI_LAST_DAY; - - protected readonly disabledItemHandler = - this.data.disabledItemHandler || - this.control?.disabledItemHandler || - TUI_FALSE_HANDLER; - constructor() { this.keyboard.hide(); } + public max(): TuiDay { + return ( + this.data.max || + (this.range + ? TUI_DAY_CAPS_MAPPER( + this.control.max, + this.selectedPeriod, + this.control.maxLength, + false, + ) + : this.control?.max) || + TUI_LAST_DAY + ); + } + + public min(): TuiDay { + return ( + this.data.min || + (this.range + ? TUI_DAY_CAPS_MAPPER( + this.control.min, + this.selectedPeriod, + this.control.maxLength, + true, + ) + : this.control?.min) || + TUI_FIRST_DAY + ); + } + + public onValueChange(value: TuiDay | TuiDayRange | readonly TuiDay[] | null): void { + if (!this.range) { + return; + } + + if (value === null || value instanceof TuiDayRange) { + this.selectedPeriod = value; + } else if (value instanceof TuiDay) { + this.selectedPeriod = new TuiDayRange(value, value); + } + } + + protected get calculatedDisabledItemHandler(): TuiBooleanHandler { + return this.calculateDisabledItemHandler( + this.data.disabledItemHandler || + this.control?.disabledItemHandler || + TUI_FALSE_HANDLER, + this.selectedPeriod, + this.control?.minLength ?? null, + ); + } + protected close(): void { this.dropdown?.toggle(false); this.observer?.complete(); @@ -110,6 +139,15 @@ export class TuiMobileCalendarDropdown { this.close(); } + @tuiPure + private calculateDisabledItemHandler( + disabledItemHandler: TuiBooleanHandler, + value: TuiDayRange | null, + minLength: TuiDayLike | null, + ): TuiBooleanHandler { + return calculateDisabledItemHandler(disabledItemHandler, value, minLength); + } + private is(selector: string): boolean { return !!this.dropdown?.el.closest(selector); } diff --git a/projects/addon-mobile/components/mobile-calendar-dropdown/mobile-calendar-dropdown.template.html b/projects/addon-mobile/components/mobile-calendar-dropdown/mobile-calendar-dropdown.template.html index 42500e9fd11e..0e38e96bf346 100644 --- a/projects/addon-mobile/components/mobile-calendar-dropdown/mobile-calendar-dropdown.template.html +++ b/projects/addon-mobile/components/mobile-calendar-dropdown/mobile-calendar-dropdown.template.html @@ -1,9 +1,10 @@ diff --git a/projects/kit/components/calendar-range/calculate-disabled-item-handler.ts b/projects/kit/components/calendar-range/calculate-disabled-item-handler.ts new file mode 100644 index 000000000000..970ad1f909a1 --- /dev/null +++ b/projects/kit/components/calendar-range/calculate-disabled-item-handler.ts @@ -0,0 +1,22 @@ +import type {TuiDay, TuiDayLike, TuiDayRange} from '@taiga-ui/cdk/date-time'; +import type {TuiBooleanHandler} from '@taiga-ui/cdk/types'; + +export const calculateDisabledItemHandler: ( + disabledItemHandler: TuiBooleanHandler, + value: TuiDayRange | null, + minLength: TuiDayLike | null, +) => TuiBooleanHandler = (disabledItemHandler, value, minLength) => (item) => { + if (!value?.isSingleDay || !minLength) { + return disabledItemHandler(item); + } + + const negativeMinLength = Object.fromEntries( + Object.entries(minLength).map(([key, value]) => [key, -value]), + ); + const disabledBefore = value.from.append(negativeMinLength).append({day: 1}); + const disabledAfter = value.from.append(minLength).append({day: -1}); + const inDisabledRange = + disabledBefore.dayBefore(item) && disabledAfter.dayAfter(item); + + return inDisabledRange || disabledItemHandler(item); +}; diff --git a/projects/kit/components/calendar-range/calendar-range.component.ts b/projects/kit/components/calendar-range/calendar-range.component.ts index e251c181bddd..6ccd8b9b276a 100644 --- a/projects/kit/components/calendar-range/calendar-range.component.ts +++ b/projects/kit/components/calendar-range/calendar-range.component.ts @@ -30,6 +30,7 @@ import {TUI_COMMON_ICONS} from '@taiga-ui/core/tokens'; import {TUI_CALENDAR_DATE_STREAM, TUI_OTHER_DATE_TEXT} from '@taiga-ui/kit/tokens'; import type {Observable} from 'rxjs'; +import {calculateDisabledItemHandler} from './calculate-disabled-item-handler'; import {TUI_DAY_CAPS_MAPPER} from './day-caps-mapper'; import type {TuiDayRangePeriod} from './day-range-period'; @@ -235,21 +236,7 @@ export class TuiCalendarRange implements OnInit, OnChanges { value: TuiDayRange | null, minLength: TuiDayLike | null, ): TuiBooleanHandler { - return (item) => { - if (!value?.isSingleDay || !minLength) { - return disabledItemHandler(item); - } - - const negativeMinLength = Object.fromEntries( - Object.entries(minLength).map(([key, value]) => [key, -value]), - ); - const disabledBefore = value.from.append(negativeMinLength).append({day: 1}); - const disabledAfter = value.from.append(minLength).append({day: -1}); - const inDisabledRange = - disabledBefore.dayBefore(item) && disabledAfter.dayAfter(item); - - return inDisabledRange || disabledItemHandler(item); - }; + return calculateDisabledItemHandler(disabledItemHandler, value, minLength); } private initDefaultViewedMonth(): void { diff --git a/projects/kit/components/calendar-range/index.ts b/projects/kit/components/calendar-range/index.ts index 1c1206fb4e82..f78f19f8d926 100644 --- a/projects/kit/components/calendar-range/index.ts +++ b/projects/kit/components/calendar-range/index.ts @@ -1,3 +1,4 @@ +export * from './calculate-disabled-item-handler'; export * from './calendar-range.component'; export * from './day-caps-mapper'; export * from './day-range-period';