From ff694ee1630f691db688ff81b8bf5fe03b4033c3 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Fri, 26 Apr 2024 08:58:56 +0300 Subject: [PATCH 01/29] feat(kit): added strict mode for min-max-date-postprocessor --- .../lib/processors/min-max-date-postprocessor.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts index 55bb7fece..ebb581984 100644 --- a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts +++ b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts @@ -18,12 +18,14 @@ export function createMinMaxDatePostprocessor({ max = DEFAULT_MAX_DATE, rangeSeparator = '', dateSegmentSeparator = '.', + strict = true, }: { dateModeTemplate: string; min?: Date; max?: Date; rangeSeparator?: string; dateSegmentSeparator?: string; + strict?: boolean; }): MaskitoPostprocessor { return ({value, selection}) => { const endsWithRangeSeparator = rangeSeparator && value.endsWith(rangeSeparator); @@ -51,6 +53,18 @@ export function createMinMaxDatePostprocessor({ const date = segmentsToDate(parsedDate); const clampedDate = clamp(date, min, max); + if (!strict) { + validatedValue += toDateString( + clampedDate.getTime() === max.getTime() || + clampedDate.getTime() === min.getTime() + ? dateToSegments(clampedDate) + : parsedDate, + {dateMode: dateModeTemplate}, + ); + + continue; + } + validatedValue += toDateString(dateToSegments(clampedDate), { dateMode: dateModeTemplate, }); From da6847b0d41f476ac6892711d4c4b9ffd71aed4a Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Fri, 26 Apr 2024 09:08:18 +0300 Subject: [PATCH 02/29] feat(kit): added strcit for date, date-range, changed for min-max strict required --- .../src/pages/kit/date-range/date-range-mask-doc.component.ts | 1 + projects/demo/src/pages/kit/date/date-mask-doc.component.ts | 2 ++ projects/kit/src/lib/masks/date-range/date-range-mask.ts | 3 +++ projects/kit/src/lib/masks/date/date-mask.ts | 3 +++ projects/kit/src/lib/processors/min-max-date-postprocessor.ts | 4 ++-- 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts index 56c8b9795..58275c8cf 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts @@ -101,6 +101,7 @@ export class DateRangeMaskDocComponent implements GeneratorOptions { public maxLength: Partial> = {}; public dateSeparator = '.'; public rangeSeparator = ' – '; + public strict = true; protected maskitoOptions: MaskitoOptions = maskitoDateRangeOptionsGenerator(this); diff --git a/projects/demo/src/pages/kit/date/date-mask-doc.component.ts b/projects/demo/src/pages/kit/date/date-mask-doc.component.ts index fe409f47f..86cb2e493 100644 --- a/projects/demo/src/pages/kit/date/date-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date/date-mask-doc.component.ts @@ -72,6 +72,8 @@ export class DateMaskDocComponent implements GeneratorOptions { public min = new Date(this.minStr); public max = new Date(this.maxStr); + public strict = true; + protected maskitoOptions: MaskitoOptions = maskitoDateOptionsGenerator(this); protected updateDate(): void { diff --git a/projects/kit/src/lib/masks/date-range/date-range-mask.ts b/projects/kit/src/lib/masks/date-range/date-range-mask.ts index f634a4b52..6d5b11f1f 100644 --- a/projects/kit/src/lib/masks/date-range/date-range-mask.ts +++ b/projects/kit/src/lib/masks/date-range/date-range-mask.ts @@ -25,6 +25,7 @@ export function maskitoDateRangeOptionsGenerator({ maxLength, dateSeparator = '.', rangeSeparator = `${CHAR_NO_BREAK_SPACE}${CHAR_EN_DASH}${CHAR_NO_BREAK_SPACE}`, + strict = true, }: { mode: MaskitoDateMode; min?: Date; @@ -33,6 +34,7 @@ export function maskitoDateRangeOptionsGenerator({ maxLength?: Partial>; dateSeparator?: string; rangeSeparator?: string; + strict?: boolean; }): Required { const dateModeTemplate = mode.split('/').join(dateSeparator); const dateMask = Array.from(dateModeTemplate).map(char => @@ -91,6 +93,7 @@ export function maskitoDateRangeOptionsGenerator({ dateModeTemplate, rangeSeparator, dateSegmentSeparator: dateSeparator, + strict, }), createMinMaxRangeLengthPostprocessor({ dateModeTemplate, diff --git a/projects/kit/src/lib/masks/date/date-mask.ts b/projects/kit/src/lib/masks/date/date-mask.ts index 525f8aa31..b4da7d2d5 100644 --- a/projects/kit/src/lib/masks/date/date-mask.ts +++ b/projects/kit/src/lib/masks/date/date-mask.ts @@ -16,11 +16,13 @@ export function maskitoDateOptionsGenerator({ separator = '.', max, min, + strict = true, }: { mode: MaskitoDateMode; separator?: string; max?: Date; min?: Date; + strict?: boolean; }): Required { const dateModeTemplate = mode.split('/').join(separator); @@ -54,6 +56,7 @@ export function maskitoDateOptionsGenerator({ max, dateModeTemplate, dateSegmentSeparator: separator, + strict, }), ], }; diff --git a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts index ebb581984..9c06a38ef 100644 --- a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts +++ b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts @@ -18,14 +18,14 @@ export function createMinMaxDatePostprocessor({ max = DEFAULT_MAX_DATE, rangeSeparator = '', dateSegmentSeparator = '.', - strict = true, + strict, }: { dateModeTemplate: string; min?: Date; max?: Date; rangeSeparator?: string; dateSegmentSeparator?: string; - strict?: boolean; + strict: boolean; }): MaskitoPostprocessor { return ({value, selection}) => { const endsWithRangeSeparator = rangeSeparator && value.endsWith(rangeSeparator); From 6f0c16ee4f36c57b5a6656efe749d57b27466aa7 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Fri, 26 Apr 2024 09:37:12 +0300 Subject: [PATCH 03/29] feat(kit): added strict mode for min-max-date-time-postprocessor, and date-time-mask --- .../date-time/date-time-mask-doc.component.ts | 1 + .../src/lib/masks/date-time/date-time-mask.ts | 3 + .../min-max-date-time-postprocessor.ts | 66 +++++++++++++++++-- 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts index ead832f3a..3c181cd29 100644 --- a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts @@ -83,6 +83,7 @@ export class DateTimeMaskDocComponent implements GeneratorOptions { public dateSeparator = '.'; public min = new Date(this.minStr); public max = new Date(this.maxStr); + public strict = true; protected maskitoOptions: MaskitoOptions = maskitoDateTimeOptionsGenerator(this); diff --git a/projects/kit/src/lib/masks/date-time/date-time-mask.ts b/projects/kit/src/lib/masks/date-time/date-time-mask.ts index 2cad6759b..d64a3da8d 100644 --- a/projects/kit/src/lib/masks/date-time/date-time-mask.ts +++ b/projects/kit/src/lib/masks/date-time/date-time-mask.ts @@ -23,6 +23,7 @@ export function maskitoDateTimeOptionsGenerator({ min, max, dateTimeSeparator = DATE_TIME_SEPARATOR, + strict = true, }: { dateMode: MaskitoDateMode; timeMode: MaskitoTimeMode; @@ -30,6 +31,7 @@ export function maskitoDateTimeOptionsGenerator({ max?: Date; min?: Date; dateTimeSeparator?: string; + strict?: boolean; }): Required { const dateModeTemplate = dateMode.split('/').join(dateSeparator); @@ -88,6 +90,7 @@ export function maskitoDateTimeOptionsGenerator({ dateModeTemplate, timeMode, dateTimeSeparator, + strict, }), ], }; diff --git a/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts b/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts index 61a807fd5..e59b50ff2 100644 --- a/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts +++ b/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts @@ -1,7 +1,7 @@ import type {MaskitoPostprocessor} from '@maskito/core'; import {DEFAULT_MAX_DATE, DEFAULT_MIN_DATE} from '../../../constants'; -import type {MaskitoTimeMode} from '../../../types'; +import type {MaskitoDateSegments, MaskitoTimeMode} from '../../../types'; import { clamp, dateToSegments, @@ -20,12 +20,14 @@ export function createMinMaxDateTimePostprocessor({ min = DEFAULT_MIN_DATE, max = DEFAULT_MAX_DATE, dateTimeSeparator, + strict, }: { dateModeTemplate: string; timeMode: MaskitoTimeMode; min?: Date; max?: Date; dateTimeSeparator: string; + strict: boolean; }): MaskitoPostprocessor { return ({value, selection}) => { const [dateString, timeString] = parseDateTimeString(value, { @@ -43,9 +45,14 @@ export function createMinMaxDateTimePostprocessor({ }) ) { const fixedDate = raiseSegmentValueToMin(parsedDate, dateModeTemplate); - const {year, month, day} = isDateStringComplete(dateString, dateModeTemplate) - ? dateToSegments(clamp(segmentsToDate(fixedDate), min, max)) - : fixedDate; + const {year, month, day} = getDateSegments({ + strict, + fixedDate, + dateModeTemplate, + dateString, + min, + max, + }); const fixedValue = toDateString( { @@ -67,6 +74,25 @@ export function createMinMaxDateTimePostprocessor({ const date = segmentsToDate(parsedDate, parsedTime); const clampedDate = clamp(date, min, max); + if (!strict) { + const validatedValue = toDateString( + clampedDate.getTime() === min.getTime() || + clampedDate.getTime() === max.getTime() + ? dateToSegments(clampedDate) + : {...parsedDate, ...parsedTime}, + { + dateMode: dateModeTemplate, + dateTimeSeparator, + timeMode, + }, + ); + + return { + selection, + value: validatedValue, + }; + } + const validatedValue = toDateString(dateToSegments(clampedDate), { dateMode: dateModeTemplate, dateTimeSeparator, @@ -79,3 +105,35 @@ export function createMinMaxDateTimePostprocessor({ }; }; } + +function getDateSegments({ + strict, + dateModeTemplate, + dateString, + fixedDate, + min, + max, +}: { + strict: boolean; + dateModeTemplate: string; + dateString: string; + fixedDate: Partial; + min: Date; + max: Date; +}): Partial { + const isComplete = isDateStringComplete(dateString, dateModeTemplate); + const clampedDate = clamp(segmentsToDate(fixedDate), min, max); + + if (strict) { + return isComplete ? dateToSegments(clampedDate) : fixedDate; + } + + if (!isComplete) { + return fixedDate; + } + + return clampedDate.getTime() === min.getTime() || + clampedDate.getTime() === max.getTime() + ? dateToSegments(clampedDate) + : fixedDate; +} From a18f3f42093be15063738e3f12fae30a4639fd9c Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Fri, 26 Apr 2024 10:24:14 +0300 Subject: [PATCH 04/29] feat(kit): general logic is moved to a separate function --- .../date/strict-date-time-mode-validation.ts | 35 +++++++++++++++++++ projects/kit/src/lib/utils/index.ts | 1 + 2 files changed, 36 insertions(+) create mode 100644 projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts diff --git a/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts b/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts new file mode 100644 index 000000000..0461df1f3 --- /dev/null +++ b/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts @@ -0,0 +1,35 @@ +import {MaskitoDateSegments, MaskitoTimeSegments} from '../../types'; +import {dateToSegments} from './date-to-segments'; + +export function strictDateTimeModeValidation({ + clampedDate, + min, + max, + strict, + dateSegments, + timeSegments = {}, + isDateComplete = true, +}: { + clampedDate: Date; + min: Date; + max: Date; + strict: boolean; + dateSegments: Partial; + timeSegments?: Partial; + isDateComplete?: boolean; +}): Partial { + if (strict) { + return isDateComplete + ? dateToSegments(clampedDate) + : {...dateSegments, ...timeSegments}; + } + + if (!isDateComplete) { + return {...dateSegments, ...timeSegments}; + } + + return clampedDate.getTime() === min.getTime() || + clampedDate.getTime() === max.getTime() + ? dateToSegments(clampedDate) + : {...dateSegments, ...timeSegments}; +} diff --git a/projects/kit/src/lib/utils/index.ts b/projects/kit/src/lib/utils/index.ts index a3ceb0e74..9bf50b0c2 100644 --- a/projects/kit/src/lib/utils/index.ts +++ b/projects/kit/src/lib/utils/index.ts @@ -8,6 +8,7 @@ export * from './date/is-date-string-complete'; export * from './date/parse-date-range-string'; export * from './date/parse-date-string'; export * from './date/segments-to-date'; +export * from './date/strict-date-time-mode-validation'; export * from './date/to-date-string'; export * from './date/validate-date-string'; export * from './escape-reg-exp'; From 36fa0e90a85965767457f6ed07c2910ad3376daf Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Fri, 26 Apr 2024 10:25:11 +0300 Subject: [PATCH 05/29] refactor(kit): applied general logic function --- .../min-max-date-time-postprocessor.ts | 86 +++++-------------- .../processors/min-max-date-postprocessor.ts | 29 +++---- 2 files changed, 36 insertions(+), 79 deletions(-) diff --git a/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts b/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts index e59b50ff2..6505c945d 100644 --- a/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts +++ b/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts @@ -1,13 +1,13 @@ import type {MaskitoPostprocessor} from '@maskito/core'; import {DEFAULT_MAX_DATE, DEFAULT_MIN_DATE} from '../../../constants'; -import type {MaskitoDateSegments, MaskitoTimeMode} from '../../../types'; +import type {MaskitoTimeMode} from '../../../types'; import { clamp, - dateToSegments, isDateStringComplete, parseDateString, segmentsToDate, + strictDateTimeModeValidation, toDateString, } from '../../../utils'; import {raiseSegmentValueToMin} from '../../../utils/date/raise-segment-value-to-min'; @@ -45,13 +45,14 @@ export function createMinMaxDateTimePostprocessor({ }) ) { const fixedDate = raiseSegmentValueToMin(parsedDate, dateModeTemplate); - const {year, month, day} = getDateSegments({ - strict, - fixedDate, - dateModeTemplate, - dateString, + + const {year, month, day} = strictDateTimeModeValidation({ + clampedDate: clamp(segmentsToDate(fixedDate), min, max), min, max, + strict, + dateSegments: fixedDate, + isDateComplete: isDateStringComplete(dateString, dateModeTemplate), }); const fixedValue = toDateString( @@ -74,30 +75,21 @@ export function createMinMaxDateTimePostprocessor({ const date = segmentsToDate(parsedDate, parsedTime); const clampedDate = clamp(date, min, max); - if (!strict) { - const validatedValue = toDateString( - clampedDate.getTime() === min.getTime() || - clampedDate.getTime() === max.getTime() - ? dateToSegments(clampedDate) - : {...parsedDate, ...parsedTime}, - { - dateMode: dateModeTemplate, - dateTimeSeparator, - timeMode, - }, - ); - - return { - selection, - value: validatedValue, - }; - } - - const validatedValue = toDateString(dateToSegments(clampedDate), { - dateMode: dateModeTemplate, - dateTimeSeparator, - timeMode, - }); + const validatedValue = toDateString( + strictDateTimeModeValidation({ + clampedDate, + min, + max, + strict, + dateSegments: parsedDate, + timeSegments: parsedTime, + }), + { + dateMode: dateModeTemplate, + dateTimeSeparator, + timeMode, + }, + ); return { selection, @@ -105,35 +97,3 @@ export function createMinMaxDateTimePostprocessor({ }; }; } - -function getDateSegments({ - strict, - dateModeTemplate, - dateString, - fixedDate, - min, - max, -}: { - strict: boolean; - dateModeTemplate: string; - dateString: string; - fixedDate: Partial; - min: Date; - max: Date; -}): Partial { - const isComplete = isDateStringComplete(dateString, dateModeTemplate); - const clampedDate = clamp(segmentsToDate(fixedDate), min, max); - - if (strict) { - return isComplete ? dateToSegments(clampedDate) : fixedDate; - } - - if (!isComplete) { - return fixedDate; - } - - return clampedDate.getTime() === min.getTime() || - clampedDate.getTime() === max.getTime() - ? dateToSegments(clampedDate) - : fixedDate; -} diff --git a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts index 9c06a38ef..d06242476 100644 --- a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts +++ b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts @@ -3,11 +3,11 @@ import type {MaskitoPostprocessor} from '@maskito/core'; import {DEFAULT_MAX_DATE, DEFAULT_MIN_DATE} from '../constants'; import { clamp, - dateToSegments, isDateStringComplete, parseDateRangeString, parseDateString, segmentsToDate, + strictDateTimeModeValidation, toDateString, } from '../utils'; import {raiseSegmentValueToMin} from '../utils/date/raise-segment-value-to-min'; @@ -53,21 +53,18 @@ export function createMinMaxDatePostprocessor({ const date = segmentsToDate(parsedDate); const clampedDate = clamp(date, min, max); - if (!strict) { - validatedValue += toDateString( - clampedDate.getTime() === max.getTime() || - clampedDate.getTime() === min.getTime() - ? dateToSegments(clampedDate) - : parsedDate, - {dateMode: dateModeTemplate}, - ); - - continue; - } - - validatedValue += toDateString(dateToSegments(clampedDate), { - dateMode: dateModeTemplate, - }); + validatedValue += toDateString( + strictDateTimeModeValidation({ + clampedDate, + min, + max, + strict, + dateSegments: parsedDate, + }), + { + dateMode: dateModeTemplate, + }, + ); } return { From 35de2226773cbded9e2dc4c71a85b3cef49e91e2 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Fri, 26 Apr 2024 10:30:24 +0300 Subject: [PATCH 06/29] docs(demo): added strict to docs api date, date-time, date-range --- .../kit/date-range/date-range-mask-doc.template.html | 10 ++++++++++ .../kit/date-time/date-time-mask-doc.template.html | 10 ++++++++++ .../src/pages/kit/date/date-mask-doc.template.html | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html index 585c9daff..49f161546 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html @@ -97,6 +97,16 @@ + + Strict mode + + + Strict mode + + + Strict mode + Date: Mon, 29 Apr 2024 11:31:03 +0300 Subject: [PATCH 07/29] feat(kit): created Date and DateTime segments validation postprocessors --- .../lib/masks/date-range/date-range-mask.ts | 8 +- .../src/lib/masks/date-time/date-time-mask.ts | 12 ++- ...-time-segments-validation-postprocessor.ts | 86 +++++++++++++++++++ .../masks/date-time/postprocessors/index.ts | 1 + .../min-max-date-time-postprocessor.ts | 36 ++------ projects/kit/src/lib/masks/date/date-mask.ts | 7 +- .../date-segments-validation-postprocessor.ts | 62 +++++++++++++ projects/kit/src/lib/processors/index.ts | 1 + .../processors/min-max-date-postprocessor.ts | 19 +--- .../date/strict-date-time-mode-validation.ts | 21 +---- 10 files changed, 190 insertions(+), 63 deletions(-) create mode 100644 projects/kit/src/lib/masks/date-time/postprocessors/date-time-segments-validation-postprocessor.ts create mode 100644 projects/kit/src/lib/processors/date-segments-validation-postprocessor.ts diff --git a/projects/kit/src/lib/masks/date-range/date-range-mask.ts b/projects/kit/src/lib/masks/date-range/date-range-mask.ts index 6d5b11f1f..6969e87e3 100644 --- a/projects/kit/src/lib/masks/date-range/date-range-mask.ts +++ b/projects/kit/src/lib/masks/date-range/date-range-mask.ts @@ -3,6 +3,7 @@ import {MASKITO_DEFAULT_OPTIONS} from '@maskito/core'; import {CHAR_EN_DASH, CHAR_NO_BREAK_SPACE} from '../../constants'; import { + createDateSegmentsValidationPostprocessor, createDateSegmentsZeroPaddingPostprocessor, createFirstDateEndSeparatorPreprocessor, createFullWidthToHalfWidthPreprocessor, @@ -66,6 +67,12 @@ export function maskitoDateRangeOptionsGenerator({ }), ], postprocessors: [ + createDateSegmentsValidationPostprocessor({ + dateModeTemplate, + rangeSeparator, + dateSegmentSeparator: dateSeparator, + strict, + }), createDateSegmentsZeroPaddingPostprocessor({ dateModeTemplate, dateSegmentSeparator: dateSeparator, @@ -93,7 +100,6 @@ export function maskitoDateRangeOptionsGenerator({ dateModeTemplate, rangeSeparator, dateSegmentSeparator: dateSeparator, - strict, }), createMinMaxRangeLengthPostprocessor({ dateModeTemplate, diff --git a/projects/kit/src/lib/masks/date-time/date-time-mask.ts b/projects/kit/src/lib/masks/date-time/date-time-mask.ts index d64a3da8d..fb20eaec6 100644 --- a/projects/kit/src/lib/masks/date-time/date-time-mask.ts +++ b/projects/kit/src/lib/masks/date-time/date-time-mask.ts @@ -12,7 +12,10 @@ import { } from '../../processors'; import type {MaskitoDateMode, MaskitoTimeMode} from '../../types'; import {DATE_TIME_SEPARATOR} from './constants'; -import {createMinMaxDateTimePostprocessor} from './postprocessors'; +import { + createDateTimeSegmentsValidationPostProcessor, + createMinMaxDateTimePostprocessor, +} from './postprocessors'; import {createValidDateTimePreprocessor} from './preprocessors'; import {parseDateTimeString} from './utils'; @@ -69,6 +72,12 @@ export function maskitoDateTimeOptionsGenerator({ }), ], postprocessors: [ + createDateTimeSegmentsValidationPostProcessor({ + dateModeTemplate, + timeMode, + dateTimeSeparator, + strict, + }), createDateSegmentsZeroPaddingPostprocessor({ dateModeTemplate, dateSegmentSeparator: dateSeparator, @@ -90,7 +99,6 @@ export function maskitoDateTimeOptionsGenerator({ dateModeTemplate, timeMode, dateTimeSeparator, - strict, }), ], }; diff --git a/projects/kit/src/lib/masks/date-time/postprocessors/date-time-segments-validation-postprocessor.ts b/projects/kit/src/lib/masks/date-time/postprocessors/date-time-segments-validation-postprocessor.ts new file mode 100644 index 000000000..5d735fc67 --- /dev/null +++ b/projects/kit/src/lib/masks/date-time/postprocessors/date-time-segments-validation-postprocessor.ts @@ -0,0 +1,86 @@ +import type {MaskitoPostprocessor} from '@maskito/core'; + +import type {MaskitoTimeMode} from '../../../types'; +import { + isDateStringComplete, + parseDateString, + segmentsToDate, + strictDateTimeModeValidation, + toDateString, +} from '../../../utils'; +import {raiseSegmentValueToMin} from '../../../utils/date/raise-segment-value-to-min'; +import {parseTimeString} from '../../../utils/time'; +import {isDateTimeStringComplete, parseDateTimeString} from '../utils'; + +export function createDateTimeSegmentsValidationPostProcessor({ + dateModeTemplate, + timeMode, + dateTimeSeparator, + strict, +}: { + dateModeTemplate: string; + timeMode: MaskitoTimeMode; + dateTimeSeparator: string; + strict: boolean; +}): MaskitoPostprocessor { + return ({value, selection}) => { + const [dateString, timeString] = parseDateTimeString(value, { + dateModeTemplate, + dateTimeSeparator, + }); + const parsedDate = parseDateString(dateString, dateModeTemplate); + const parsedTime = parseTimeString(timeString); + + if ( + !isDateTimeStringComplete(value, { + dateMode: dateModeTemplate, + timeMode, + dateTimeSeparator, + }) + ) { + const fixedDate = raiseSegmentValueToMin(parsedDate, dateModeTemplate); + + const {year, month, day} = strictDateTimeModeValidation({ + date: segmentsToDate(fixedDate), + strict, + dateSegments: fixedDate, + isDateComplete: isDateStringComplete(dateString, dateModeTemplate), + }); + + const fixedValue = toDateString( + { + year, + month, + day, + ...parsedTime, + }, + {dateMode: dateModeTemplate, dateTimeSeparator, timeMode}, + ); + const tail = value.slice(fixedValue.length); + + return { + selection, + value: fixedValue + tail, + }; + } + + const validatedValue = toDateString( + strictDateTimeModeValidation({ + date: segmentsToDate(parsedDate, parsedTime), + strict, + dateSegments: parsedDate, + timeSegments: parsedTime, + }), + { + dateMode: dateModeTemplate, + dateTimeSeparator, + timeMode, + }, + ); + + return { + selection, + value: validatedValue, + }; + }; +} diff --git a/projects/kit/src/lib/masks/date-time/postprocessors/index.ts b/projects/kit/src/lib/masks/date-time/postprocessors/index.ts index 4b57683a9..805adfb99 100644 --- a/projects/kit/src/lib/masks/date-time/postprocessors/index.ts +++ b/projects/kit/src/lib/masks/date-time/postprocessors/index.ts @@ -1 +1,2 @@ +export * from './date-time-segments-validation-postprocessor'; export * from './min-max-date-time-postprocessor'; diff --git a/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts b/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts index 6505c945d..61a807fd5 100644 --- a/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts +++ b/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts @@ -4,10 +4,10 @@ import {DEFAULT_MAX_DATE, DEFAULT_MIN_DATE} from '../../../constants'; import type {MaskitoTimeMode} from '../../../types'; import { clamp, + dateToSegments, isDateStringComplete, parseDateString, segmentsToDate, - strictDateTimeModeValidation, toDateString, } from '../../../utils'; import {raiseSegmentValueToMin} from '../../../utils/date/raise-segment-value-to-min'; @@ -20,14 +20,12 @@ export function createMinMaxDateTimePostprocessor({ min = DEFAULT_MIN_DATE, max = DEFAULT_MAX_DATE, dateTimeSeparator, - strict, }: { dateModeTemplate: string; timeMode: MaskitoTimeMode; min?: Date; max?: Date; dateTimeSeparator: string; - strict: boolean; }): MaskitoPostprocessor { return ({value, selection}) => { const [dateString, timeString] = parseDateTimeString(value, { @@ -45,15 +43,9 @@ export function createMinMaxDateTimePostprocessor({ }) ) { const fixedDate = raiseSegmentValueToMin(parsedDate, dateModeTemplate); - - const {year, month, day} = strictDateTimeModeValidation({ - clampedDate: clamp(segmentsToDate(fixedDate), min, max), - min, - max, - strict, - dateSegments: fixedDate, - isDateComplete: isDateStringComplete(dateString, dateModeTemplate), - }); + const {year, month, day} = isDateStringComplete(dateString, dateModeTemplate) + ? dateToSegments(clamp(segmentsToDate(fixedDate), min, max)) + : fixedDate; const fixedValue = toDateString( { @@ -75,21 +67,11 @@ export function createMinMaxDateTimePostprocessor({ const date = segmentsToDate(parsedDate, parsedTime); const clampedDate = clamp(date, min, max); - const validatedValue = toDateString( - strictDateTimeModeValidation({ - clampedDate, - min, - max, - strict, - dateSegments: parsedDate, - timeSegments: parsedTime, - }), - { - dateMode: dateModeTemplate, - dateTimeSeparator, - timeMode, - }, - ); + const validatedValue = toDateString(dateToSegments(clampedDate), { + dateMode: dateModeTemplate, + dateTimeSeparator, + timeMode, + }); return { selection, diff --git a/projects/kit/src/lib/masks/date/date-mask.ts b/projects/kit/src/lib/masks/date/date-mask.ts index b4da7d2d5..42374a2b1 100644 --- a/projects/kit/src/lib/masks/date/date-mask.ts +++ b/projects/kit/src/lib/masks/date/date-mask.ts @@ -2,6 +2,7 @@ import type {MaskitoOptions} from '@maskito/core'; import {MASKITO_DEFAULT_OPTIONS} from '@maskito/core'; import { + createDateSegmentsValidationPostprocessor, createDateSegmentsZeroPaddingPostprocessor, createFullWidthToHalfWidthPreprocessor, createMinMaxDatePostprocessor, @@ -45,6 +46,11 @@ export function maskitoDateOptionsGenerator({ }), ], postprocessors: [ + createDateSegmentsValidationPostprocessor({ + dateModeTemplate, + dateSegmentSeparator: separator, + strict, + }), createDateSegmentsZeroPaddingPostprocessor({ dateModeTemplate, dateSegmentSeparator: separator, @@ -56,7 +62,6 @@ export function maskitoDateOptionsGenerator({ max, dateModeTemplate, dateSegmentSeparator: separator, - strict, }), ], }; diff --git a/projects/kit/src/lib/processors/date-segments-validation-postprocessor.ts b/projects/kit/src/lib/processors/date-segments-validation-postprocessor.ts new file mode 100644 index 000000000..909386761 --- /dev/null +++ b/projects/kit/src/lib/processors/date-segments-validation-postprocessor.ts @@ -0,0 +1,62 @@ +import type {MaskitoPostprocessor} from '@maskito/core'; + +import {isDateStringComplete} from '../utils/date/is-date-string-complete'; +import {parseDateRangeString} from '../utils/date/parse-date-range-string'; +import {parseDateString} from '../utils/date/parse-date-string'; +import {raiseSegmentValueToMin} from '../utils/date/raise-segment-value-to-min'; +import {segmentsToDate} from '../utils/date/segments-to-date'; +import {strictDateTimeModeValidation} from '../utils/date/strict-date-time-mode-validation'; +import {toDateString} from '../utils/date/to-date-string'; + +export function createDateSegmentsValidationPostprocessor({ + dateModeTemplate, + rangeSeparator = '', + dateSegmentSeparator = '.', + strict, +}: { + dateModeTemplate: string; + rangeSeparator?: string; + dateSegmentSeparator?: string; + strict: boolean; +}): MaskitoPostprocessor { + return ({value, selection}) => { + const endsWithRangeSeparator = rangeSeparator && value.endsWith(rangeSeparator); + const dateStrings = parseDateRangeString(value, dateModeTemplate, rangeSeparator); + + let validatedValue = ''; + + for (const dateString of dateStrings) { + validatedValue += validatedValue ? rangeSeparator : ''; + + const parsedDate = parseDateString(dateString, dateModeTemplate); + + if (!isDateStringComplete(dateString, dateModeTemplate)) { + const fixedDate = raiseSegmentValueToMin(parsedDate, dateModeTemplate); + + const fixedValue = toDateString(fixedDate, {dateMode: dateModeTemplate}); + const tail = dateString.endsWith(dateSegmentSeparator) + ? dateSegmentSeparator + : ''; + + validatedValue += fixedValue + tail; + continue; + } + + validatedValue += toDateString( + strictDateTimeModeValidation({ + date: segmentsToDate(parsedDate), + strict, + dateSegments: parsedDate, + }), + { + dateMode: dateModeTemplate, + }, + ); + } + + return { + selection, + value: validatedValue + (endsWithRangeSeparator ? rangeSeparator : ''), + }; + }; +} diff --git a/projects/kit/src/lib/processors/index.ts b/projects/kit/src/lib/processors/index.ts index 1c88274e6..e9067732a 100644 --- a/projects/kit/src/lib/processors/index.ts +++ b/projects/kit/src/lib/processors/index.ts @@ -1,4 +1,5 @@ export {createColonConvertPreprocessor} from './colon-convert-preprocessor'; +export {createDateSegmentsValidationPostprocessor} from './date-segments-validation-postprocessor'; export {createDateSegmentsZeroPaddingPostprocessor} from './date-segments-zero-padding-postprocessor'; export {createFirstDateEndSeparatorPreprocessor} from './first-date-end-separator-preprocessor'; export {createFullWidthToHalfWidthPreprocessor} from './fullwidth-to-halfwidth-preprocessor'; diff --git a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts index d06242476..55bb7fece 100644 --- a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts +++ b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts @@ -3,11 +3,11 @@ import type {MaskitoPostprocessor} from '@maskito/core'; import {DEFAULT_MAX_DATE, DEFAULT_MIN_DATE} from '../constants'; import { clamp, + dateToSegments, isDateStringComplete, parseDateRangeString, parseDateString, segmentsToDate, - strictDateTimeModeValidation, toDateString, } from '../utils'; import {raiseSegmentValueToMin} from '../utils/date/raise-segment-value-to-min'; @@ -18,14 +18,12 @@ export function createMinMaxDatePostprocessor({ max = DEFAULT_MAX_DATE, rangeSeparator = '', dateSegmentSeparator = '.', - strict, }: { dateModeTemplate: string; min?: Date; max?: Date; rangeSeparator?: string; dateSegmentSeparator?: string; - strict: boolean; }): MaskitoPostprocessor { return ({value, selection}) => { const endsWithRangeSeparator = rangeSeparator && value.endsWith(rangeSeparator); @@ -53,18 +51,9 @@ export function createMinMaxDatePostprocessor({ const date = segmentsToDate(parsedDate); const clampedDate = clamp(date, min, max); - validatedValue += toDateString( - strictDateTimeModeValidation({ - clampedDate, - min, - max, - strict, - dateSegments: parsedDate, - }), - { - dateMode: dateModeTemplate, - }, - ); + validatedValue += toDateString(dateToSegments(clampedDate), { + dateMode: dateModeTemplate, + }); } return { diff --git a/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts b/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts index 0461df1f3..8dd025fc5 100644 --- a/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts +++ b/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts @@ -2,34 +2,21 @@ import {MaskitoDateSegments, MaskitoTimeSegments} from '../../types'; import {dateToSegments} from './date-to-segments'; export function strictDateTimeModeValidation({ - clampedDate, - min, - max, + date, strict, dateSegments, timeSegments = {}, isDateComplete = true, }: { - clampedDate: Date; - min: Date; - max: Date; + date: Date; strict: boolean; dateSegments: Partial; timeSegments?: Partial; isDateComplete?: boolean; }): Partial { if (strict) { - return isDateComplete - ? dateToSegments(clampedDate) - : {...dateSegments, ...timeSegments}; + return isDateComplete ? dateToSegments(date) : {...dateSegments, ...timeSegments}; } - if (!isDateComplete) { - return {...dateSegments, ...timeSegments}; - } - - return clampedDate.getTime() === min.getTime() || - clampedDate.getTime() === max.getTime() - ? dateToSegments(clampedDate) - : {...dateSegments, ...timeSegments}; + return {...dateSegments, ...timeSegments}; } From dca1e684b98d1e98a7f564c4f82d92eb976faf38 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Mon, 29 Apr 2024 11:52:45 +0300 Subject: [PATCH 08/29] refactor(kit): removed date validation logic from min-max-date-time-postprocessor --- .../min-max-date-time-postprocessor.ts | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts b/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts index 61a807fd5..78a25b468 100644 --- a/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts +++ b/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts @@ -43,6 +43,15 @@ export function createMinMaxDateTimePostprocessor({ }) ) { const fixedDate = raiseSegmentValueToMin(parsedDate, dateModeTemplate); + + if (!isDateStringComplete(dateString, dateModeTemplate)) { + return { + value, + selection, + }; + } + + const clampedDate = clamp(segmentsToDate(fixedDate), min, max); const {year, month, day} = isDateStringComplete(dateString, dateModeTemplate) ? dateToSegments(clamp(segmentsToDate(fixedDate), min, max)) : fixedDate; @@ -60,7 +69,11 @@ export function createMinMaxDateTimePostprocessor({ return { selection, - value: fixedValue + tail, + value: + clampedDate.getTime() === min.getTime() || + clampedDate.getTime() === max.getTime() + ? fixedValue + tail + : value, }; } @@ -75,7 +88,11 @@ export function createMinMaxDateTimePostprocessor({ return { selection, - value: validatedValue, + value: + clampedDate.getTime() === min.getTime() || + clampedDate.getTime() === max.getTime() + ? validatedValue + : value, }; }; } From 258d189a76f13a963d2f8c85dd193c0f96b90592 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Mon, 29 Apr 2024 12:02:35 +0300 Subject: [PATCH 09/29] refactor(kit): removed date validation logic from min-max-date-postprocessor --- .../lib/masks/date-range/date-range-mask.ts | 1 - projects/kit/src/lib/masks/date/date-mask.ts | 1 - .../processors/min-max-date-postprocessor.ts | 25 +++++++------------ 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/projects/kit/src/lib/masks/date-range/date-range-mask.ts b/projects/kit/src/lib/masks/date-range/date-range-mask.ts index 6969e87e3..f3c3207e6 100644 --- a/projects/kit/src/lib/masks/date-range/date-range-mask.ts +++ b/projects/kit/src/lib/masks/date-range/date-range-mask.ts @@ -99,7 +99,6 @@ export function maskitoDateRangeOptionsGenerator({ max, dateModeTemplate, rangeSeparator, - dateSegmentSeparator: dateSeparator, }), createMinMaxRangeLengthPostprocessor({ dateModeTemplate, diff --git a/projects/kit/src/lib/masks/date/date-mask.ts b/projects/kit/src/lib/masks/date/date-mask.ts index 42374a2b1..b043d2ae4 100644 --- a/projects/kit/src/lib/masks/date/date-mask.ts +++ b/projects/kit/src/lib/masks/date/date-mask.ts @@ -61,7 +61,6 @@ export function maskitoDateOptionsGenerator({ min, max, dateModeTemplate, - dateSegmentSeparator: separator, }), ], }; diff --git a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts index 55bb7fece..34353cb24 100644 --- a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts +++ b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts @@ -10,20 +10,17 @@ import { segmentsToDate, toDateString, } from '../utils'; -import {raiseSegmentValueToMin} from '../utils/date/raise-segment-value-to-min'; export function createMinMaxDatePostprocessor({ dateModeTemplate, min = DEFAULT_MIN_DATE, max = DEFAULT_MAX_DATE, rangeSeparator = '', - dateSegmentSeparator = '.', }: { dateModeTemplate: string; min?: Date; max?: Date; rangeSeparator?: string; - dateSegmentSeparator?: string; }): MaskitoPostprocessor { return ({value, selection}) => { const endsWithRangeSeparator = rangeSeparator && value.endsWith(rangeSeparator); @@ -37,23 +34,19 @@ export function createMinMaxDatePostprocessor({ const parsedDate = parseDateString(dateString, dateModeTemplate); if (!isDateStringComplete(dateString, dateModeTemplate)) { - const fixedDate = raiseSegmentValueToMin(parsedDate, dateModeTemplate); - - const fixedValue = toDateString(fixedDate, {dateMode: dateModeTemplate}); - const tail = dateString.endsWith(dateSegmentSeparator) - ? dateSegmentSeparator - : ''; - - validatedValue += fixedValue + tail; + validatedValue += dateString; continue; } - const date = segmentsToDate(parsedDate); - const clampedDate = clamp(date, min, max); + const clampedDate = clamp(segmentsToDate(parsedDate), min, max); - validatedValue += toDateString(dateToSegments(clampedDate), { - dateMode: dateModeTemplate, - }); + validatedValue += + clampedDate.getTime() === min.getTime() || + clampedDate.getTime() === max.getTime() + ? toDateString(dateToSegments(clampedDate), { + dateMode: dateModeTemplate, + }) + : dateString; } return { From 1b195c56091e43a3e545bb35a4ded19b65479e87 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Mon, 29 Apr 2024 14:22:07 +0300 Subject: [PATCH 10/29] feat(kit): applied new logic for date-time, date, date-range --- .../kit/src/lib/masks/date-range/date-range-mask.ts | 12 ++++++------ .../kit/src/lib/masks/date-time/date-time-mask.ts | 12 ++++++------ projects/kit/src/lib/masks/date/date-mask.ts | 10 +++++----- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/projects/kit/src/lib/masks/date-range/date-range-mask.ts b/projects/kit/src/lib/masks/date-range/date-range-mask.ts index f3c3207e6..f9a24d3e0 100644 --- a/projects/kit/src/lib/masks/date-range/date-range-mask.ts +++ b/projects/kit/src/lib/masks/date-range/date-range-mask.ts @@ -67,12 +67,6 @@ export function maskitoDateRangeOptionsGenerator({ }), ], postprocessors: [ - createDateSegmentsValidationPostprocessor({ - dateModeTemplate, - rangeSeparator, - dateSegmentSeparator: dateSeparator, - strict, - }), createDateSegmentsZeroPaddingPostprocessor({ dateModeTemplate, dateSegmentSeparator: dateSeparator, @@ -94,6 +88,12 @@ export function maskitoDateRangeOptionsGenerator({ '', ), }), + createDateSegmentsValidationPostprocessor({ + dateModeTemplate, + rangeSeparator, + dateSegmentSeparator: dateSeparator, + strict, + }), createMinMaxDatePostprocessor({ min, max, diff --git a/projects/kit/src/lib/masks/date-time/date-time-mask.ts b/projects/kit/src/lib/masks/date-time/date-time-mask.ts index fb20eaec6..da91bc93d 100644 --- a/projects/kit/src/lib/masks/date-time/date-time-mask.ts +++ b/projects/kit/src/lib/masks/date-time/date-time-mask.ts @@ -72,12 +72,6 @@ export function maskitoDateTimeOptionsGenerator({ }), ], postprocessors: [ - createDateTimeSegmentsValidationPostProcessor({ - dateModeTemplate, - timeMode, - dateTimeSeparator, - strict, - }), createDateSegmentsZeroPaddingPostprocessor({ dateModeTemplate, dateSegmentSeparator: dateSeparator, @@ -93,6 +87,12 @@ export function maskitoDateTimeOptionsGenerator({ validatedDateString + (initialValue.includes(dateTimeSeparator) ? dateTimeSeparator : ''), }), + createDateTimeSegmentsValidationPostProcessor({ + dateModeTemplate, + timeMode, + dateTimeSeparator, + strict, + }), createMinMaxDateTimePostprocessor({ min, max, diff --git a/projects/kit/src/lib/masks/date/date-mask.ts b/projects/kit/src/lib/masks/date/date-mask.ts index b043d2ae4..1790b71a7 100644 --- a/projects/kit/src/lib/masks/date/date-mask.ts +++ b/projects/kit/src/lib/masks/date/date-mask.ts @@ -46,17 +46,17 @@ export function maskitoDateOptionsGenerator({ }), ], postprocessors: [ - createDateSegmentsValidationPostprocessor({ - dateModeTemplate, - dateSegmentSeparator: separator, - strict, - }), createDateSegmentsZeroPaddingPostprocessor({ dateModeTemplate, dateSegmentSeparator: separator, splitFn: value => ({dateStrings: [value]}), uniteFn: ([dateString]) => dateString, }), + createDateSegmentsValidationPostprocessor({ + dateModeTemplate, + dateSegmentSeparator: separator, + strict, + }), createMinMaxDatePostprocessor({ min, max, From 53e8f2364da4fabdbb155b7c139570193eac94e4 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Tue, 30 Apr 2024 08:25:13 +0300 Subject: [PATCH 11/29] refactor(kit): min-max-date and date-time postprocessors --- .../postprocessors/min-max-date-time-postprocessor.ts | 7 ++----- .../kit/src/lib/processors/min-max-date-postprocessor.ts | 3 +-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts b/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts index 78a25b468..4ec763676 100644 --- a/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts +++ b/projects/kit/src/lib/masks/date-time/postprocessors/min-max-date-time-postprocessor.ts @@ -42,8 +42,6 @@ export function createMinMaxDateTimePostprocessor({ dateTimeSeparator, }) ) { - const fixedDate = raiseSegmentValueToMin(parsedDate, dateModeTemplate); - if (!isDateStringComplete(dateString, dateModeTemplate)) { return { value, @@ -51,10 +49,9 @@ export function createMinMaxDateTimePostprocessor({ }; } + const fixedDate = raiseSegmentValueToMin(parsedDate, dateModeTemplate); const clampedDate = clamp(segmentsToDate(fixedDate), min, max); - const {year, month, day} = isDateStringComplete(dateString, dateModeTemplate) - ? dateToSegments(clamp(segmentsToDate(fixedDate), min, max)) - : fixedDate; + const {year, month, day} = dateToSegments(clampedDate); const fixedValue = toDateString( { diff --git a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts index 34353cb24..38bae05dc 100644 --- a/projects/kit/src/lib/processors/min-max-date-postprocessor.ts +++ b/projects/kit/src/lib/processors/min-max-date-postprocessor.ts @@ -31,13 +31,12 @@ export function createMinMaxDatePostprocessor({ for (const dateString of dateStrings) { validatedValue += validatedValue ? rangeSeparator : ''; - const parsedDate = parseDateString(dateString, dateModeTemplate); - if (!isDateStringComplete(dateString, dateModeTemplate)) { validatedValue += dateString; continue; } + const parsedDate = parseDateString(dateString, dateModeTemplate); const clampedDate = clamp(segmentsToDate(parsedDate), min, max); validatedValue += From 7bcdf6072df113d956bc7d134f14632b60e404e9 Mon Sep 17 00:00:00 2001 From: taiga-family-bot Date: Tue, 30 Apr 2024 05:30:58 +0000 Subject: [PATCH 12/29] chore: apply changes after linting [bot] --- .../kit/src/lib/utils/date/strict-date-time-mode-validation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts b/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts index 8dd025fc5..85f2743b0 100644 --- a/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts +++ b/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts @@ -1,4 +1,4 @@ -import {MaskitoDateSegments, MaskitoTimeSegments} from '../../types'; +import type {MaskitoDateSegments, MaskitoTimeSegments} from '../../types'; import {dateToSegments} from './date-to-segments'; export function strictDateTimeModeValidation({ From 13eae3c382876aaf1aa965b2a05a50e11636aed7 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Tue, 30 Apr 2024 08:56:24 +0300 Subject: [PATCH 13/29] test(demo-integrations): date-strict-mode --- .../src/tests/kit/date/date-strict-mode.cy.ts | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts diff --git a/projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts b/projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts new file mode 100644 index 000000000..5e7ceb88c --- /dev/null +++ b/projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts @@ -0,0 +1,86 @@ +import {DemoPath} from '@demo/constants'; + +describe('Date | Strict mode', () => { + describe('Disabled', () => { + describe("doesn't fix wrong dates", () => { + beforeEach(() => { + cy.visit(`/${DemoPath.Date}/API?strict=false`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('30.02.2004', () => { + cy.get('@input').type('30022004').should('have.value', '30.02.2004'); + }); + + it('31.02.2004', () => { + cy.get('@input').type('31022004').should('have.value', '31.02.2004'); + }); + + it('29.02.2003', () => { + cy.get('@input').type('29022003').should('have.value', '29.02.2003'); + }); + + it('31.04.2004', () => { + cy.get('@input').type('31042004').should('have.value', '31.04.2004'); + }); + + it('31.04.2004', () => { + cy.get('@input').type('31042004').should('have.value', '31.04.2004'); + }); + + it('31.06.2004', () => { + cy.get('@input').type('31062004').should('have.value', '31.06.2004'); + }); + + it('31.09.2004', () => { + cy.get('@input').type('31092004').should('have.value', '31.09.2004'); + }); + + it('31.11.2004', () => { + cy.get('@input').type('31112004').should('have.value', '31.11.2004'); + }); + }); + + describe('replaces dates to min, when date less min 01.01.2000', () => { + beforeEach(() => { + cy.visit(`/${DemoPath.Date}/API?strict=false&min=2000-01-01`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('30.02.2004 => 30.02.2004', () => { + cy.get('@input').type('30022004').should('have.value', '30.02.2004'); + }); + + it('31.11.1009 => 01.01.2000', () => { + cy.get('@input').type('31111009').should('have.value', '01.01.2000'); + }); + }); + + describe('replaces dates to max, when date greater max 10.05.2025', () => { + beforeEach(() => { + cy.visit(`/${DemoPath.Date}/API?strict=false&max=2025-05-10`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('31.04.2025 => 31.04.2025', () => { + cy.get('@input').type('31042025').should('have.value', '31.04.2025'); + }); + + it('29.02.2027 => 10.05.2004', () => { + cy.get('@input').type('29022027').should('have.value', '10.05.2025'); + }); + }); + }); +}); From 02f217b5d02ee96210119631b564a22308339f5e Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Tue, 30 Apr 2024 11:30:06 +0300 Subject: [PATCH 14/29] test(demo-integrations): date-range-strict-mode --- .../date-range/date-range-strict-mode.cy.ts | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 projects/demo-integrations/src/tests/kit/date-range/date-range-strict-mode.cy.ts diff --git a/projects/demo-integrations/src/tests/kit/date-range/date-range-strict-mode.cy.ts b/projects/demo-integrations/src/tests/kit/date-range/date-range-strict-mode.cy.ts new file mode 100644 index 000000000..1284e1faa --- /dev/null +++ b/projects/demo-integrations/src/tests/kit/date-range/date-range-strict-mode.cy.ts @@ -0,0 +1,94 @@ +import {DemoPath} from '@demo/constants'; + +describe('DateRange | Strict mode', () => { + describe('Disabled', () => { + describe("doesn't fix wrong dates", () => { + beforeEach(() => { + cy.visit(`/${DemoPath.DateRange}/API?strict=false`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('30.02.2004 => 30.02.2004 - 31.02.2004', () => { + cy.get('@input') + .type('30022004') + .should('have.value', '30.02.2004') + .type('31022004') + .should('have.value', '30.02.2004 – 31.02.2004'); + }); + + it('29.02.2003 => 29.02.2003 - 31.04.2004', () => { + cy.get('@input') + .type('29022003') + .should('have.value', '29.02.2003') + .type('31042004') + .should('have.value', '29.02.2003 – 31.04.2004'); + }); + + it('31.06.2004 => 31.06.2004 - 31.09.2004', () => { + cy.get('@input') + .type('31062004') + .should('have.value', '31.06.2004') + .type('31092004') + .should('have.value', '31.06.2004 – 31.09.2004'); + }); + }); + + describe('swaps range ends with wrong dates', () => { + beforeEach(() => { + cy.visit(`/${DemoPath.DateRange}/API?strict=false`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('31.02.2004 - 30.02.2004 => 30.02.2004 - 31.02.2004', () => { + cy.get('@input') + .type('3102200430022004') + .should('have.value', '30.02.2004 – 31.02.2004'); + }); + + it('31.04.2004 - 29.02.2003 => 29.02.2003 - 31.04.2004', () => { + cy.get('@input') + .type('3104200429022003') + .should('have.value', '29.02.2003 – 31.04.2004'); + }); + + it('01.01.2012 - 31.02.1999 => 31.02.1999 - 01.01.2012', () => { + cy.get('@input') + .type('0101201231021999') + .should('have.value', '31.02.1999 – 01.01.2012'); + }); + }); + + describe('replaces dates to max and min, when date greater max 10.05.2025 and less min 01.01.2000', () => { + beforeEach(() => { + cy.visit( + `/${DemoPath.DateRange}/API?strict=false&max=2025-05-10&min=2000-01-01`, + ); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('30.02.1999 - 31.11.2029 => 01.01.2000 - 10.05.2025', () => { + cy.get('@input') + .type('3002199931112029') + .should('have.value', '01.01.2000 – 10.05.2025'); + }); + + it('31.11.2029 - 30.02.1999 => 01.01.2000 - 10.05.2025', () => { + cy.get('@input') + .type('3111202930021999') + .should('have.value', '01.01.2000 – 10.05.2025'); + }); + }); + }); +}); From a27e4d1be24b20ce96a9140d06476b2cbfc97a0a Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Tue, 30 Apr 2024 11:54:41 +0300 Subject: [PATCH 15/29] test(demo-integrations): date-time-strict-mode --- .../kit/date-time/date-time-strict-mode.cy.ts | 118 ++++++++++++++++++ .../src/tests/kit/date/date-strict-mode.cy.ts | 2 +- 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts diff --git a/projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts b/projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts new file mode 100644 index 000000000..8479a6759 --- /dev/null +++ b/projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts @@ -0,0 +1,118 @@ +import {DemoPath} from '@demo/constants'; + +describe('Date | Strict mode', () => { + describe('Disabled', () => { + describe("doesn't fix wrong dates", () => { + beforeEach(() => { + cy.visit(`/${DemoPath.DateTime}/API?strict=false`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('30.02.2004, 23:21', () => { + cy.get('@input') + .type('300220042321') + .should('have.value', '30.02.2004, 23:21'); + }); + + it('31.02.2004, 12:21', () => { + cy.get('@input') + .type('310220041221') + .should('have.value', '31.02.2004, 12:21'); + }); + + it('29.02.2003, 00:00', () => { + cy.get('@input') + .type('290220030000') + .should('have.value', '29.02.2003, 00:00'); + }); + + it('31.04.2004, 10:00', () => { + cy.get('@input') + .type('310420041000') + .should('have.value', '31.04.2004, 10:00'); + }); + + it('31.04.2004, 23:21', () => { + cy.get('@input') + .type('310420042321') + .should('have.value', '31.04.2004, 23:21'); + }); + + it('31.06.2004, 23:21', () => { + cy.get('@input') + .type('310620042321') + .should('have.value', '31.06.2004, 23:21'); + }); + + it('31.09.2004, 23:21', () => { + cy.get('@input') + .type('310920042321') + .should('have.value', '31.09.2004, 23:21'); + }); + + it('31.11.2004, 23:21', () => { + cy.get('@input') + .type('311120042321') + .should('have.value', '31.11.2004, 23:21'); + }); + }); + + describe('replaces dates to min, when date less min 01.01.2000, 12:30', () => { + beforeEach(() => { + cy.visit(`/${DemoPath.DateTime}/API?strict=false&min=2000-01-01T12:30`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('30.02.2004 => 30.02.2004, 12:20', () => { + cy.get('@input') + .type('30022004') + .should('have.value', '30.02.2004') + .type('1220') + .should('have.value', '30.02.2004, 12:20'); + }); + + it('31.11.1009 => 01.01.2000 => 01.01.2000, 12:30', () => { + cy.get('@input') + .type('31111009') + .should('have.value', '01.01.2000') + .type('1220') + .should('have.value', '01.01.2000, 12:30'); + }); + }); + + describe('replaces dates to max, when date greater max 10.05.2025, 18:30', () => { + beforeEach(() => { + cy.visit(`/${DemoPath.DateTime}/API?strict=false&max=2025-05-10T18:30`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('31.04.2025 => 31.04.2025. 20:20', () => { + cy.get('@input') + .type('31042025') + .should('have.value', '31.04.2025') + .type('2020') + .should('have.value', '31.04.2025, 20:20'); + }); + + it('29.02.2027 => 10.05.2025 => 10.05.2025, 18:30,', () => { + cy.get('@input') + .type('29022027') + .should('have.value', '10.05.2025') + .type('19:19') + .should('have.value', '10.05.2025, 18:30'); + }); + }); + }); +}); diff --git a/projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts b/projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts index 5e7ceb88c..08f85c4e9 100644 --- a/projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts +++ b/projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts @@ -78,7 +78,7 @@ describe('Date | Strict mode', () => { cy.get('@input').type('31042025').should('have.value', '31.04.2025'); }); - it('29.02.2027 => 10.05.2004', () => { + it('29.02.2027 => 10.05.2025', () => { cy.get('@input').type('29022027').should('have.value', '10.05.2025'); }); }); From c5cfedb735c6859ac42c99e5b641834a5d447974 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Tue, 30 Apr 2024 12:02:38 +0300 Subject: [PATCH 16/29] refactor(demo): api --- .../src/pages/kit/date-range/date-range-mask-doc.template.html | 1 - .../src/pages/kit/date-time/date-time-mask-doc.template.html | 1 - projects/demo/src/pages/kit/date/date-mask-doc.template.html | 1 - 3 files changed, 3 deletions(-) diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html index 49f161546..2f69e0bad 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html @@ -101,7 +101,6 @@ documentationPropertyMode="input" documentationPropertyName="strict" documentationPropertyType="boolean" - [documentationPropertyValues]="[true, false]" [(documentationPropertyValue)]="strict" (documentationPropertyValueChange)="updateOptions()" > diff --git a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html index fabdaa8d9..ddc47d522 100644 --- a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html @@ -87,7 +87,6 @@ documentationPropertyMode="input" documentationPropertyName="strict" documentationPropertyType="boolean" - [documentationPropertyValues]="[true, false]" [(documentationPropertyValue)]="strict" (documentationPropertyValueChange)="updateOptions()" > diff --git a/projects/demo/src/pages/kit/date/date-mask-doc.template.html b/projects/demo/src/pages/kit/date/date-mask-doc.template.html index a8759e22f..39bed687e 100644 --- a/projects/demo/src/pages/kit/date/date-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date/date-mask-doc.template.html @@ -73,7 +73,6 @@ documentationPropertyMode="input" documentationPropertyName="strict" documentationPropertyType="boolean" - [documentationPropertyValues]="[true, false]" [(documentationPropertyValue)]="strict" (documentationPropertyValueChange)="updateOptions()" > From 20b6875ece62b2436a52d16be82722f294bbbb1b Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Thu, 2 May 2024 11:24:26 +0300 Subject: [PATCH 17/29] docs(demo): added docs for strict mode in date --- .../pages/kit/date/date-mask-doc.component.ts | 8 ++++ .../kit/date/date-mask-doc.template.html | 28 +++++++++++++ .../date/examples/3-strict-mode/component.ts | 39 +++++++++++++++++++ .../kit/date/examples/3-strict-mode/mask.ts | 6 +++ 4 files changed, 81 insertions(+) create mode 100644 projects/demo/src/pages/kit/date/examples/3-strict-mode/component.ts create mode 100644 projects/demo/src/pages/kit/date/examples/3-strict-mode/mask.ts diff --git a/projects/demo/src/pages/kit/date/date-mask-doc.component.ts b/projects/demo/src/pages/kit/date/date-mask-doc.component.ts index 86cb2e493..31a5cae91 100644 --- a/projects/demo/src/pages/kit/date/date-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date/date-mask-doc.component.ts @@ -12,6 +12,7 @@ import {TuiInputModule} from '@taiga-ui/kit'; import {DateMaskDocExample1} from './examples/1-localization/component'; import {DateMaskDocExample2} from './examples/2-min-max/component'; +import {DateMaskDocExample3} from './examples/3-strict-mode/component'; type GeneratorOptions = Required[0]>; @@ -23,6 +24,7 @@ type GeneratorOptions = Required[ TuiLinkModule, DateMaskDocExample1, DateMaskDocExample2, + DateMaskDocExample3, TuiInputModule, TuiTextfieldControllerModule, ReactiveFormsModule, @@ -45,6 +47,12 @@ export class DateMaskDocComponent implements GeneratorOptions { [DocExamplePrimaryTab.MaskitoOptions]: import('./examples/2-min-max/mask.ts?raw'), }; + protected readonly strictMode: TuiDocExample = { + [DocExamplePrimaryTab.MaskitoOptions]: import( + './examples/3-strict-mode/mask.ts?raw' + ), + }; + protected readonly modeOptions: MaskitoDateMode[] = [ 'dd/mm/yyyy', 'mm/dd/yyyy', diff --git a/projects/demo/src/pages/kit/date/date-mask-doc.template.html b/projects/demo/src/pages/kit/date/date-mask-doc.template.html index 39bed687e..4407c3ed9 100644 --- a/projects/demo/src/pages/kit/date/date-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date/date-mask-doc.template.html @@ -49,6 +49,30 @@ + + +

+ In + strict + mode, if a user tries to enter a non-valid date, the mask will either prevent the user from entering + such a date, or if it is possible to turn it into a valid date, it will change it to a valid date. + Textfield's value + NEVER + contains invalid date value. +

+

+ In + non-strict + mode, textfield sometimes can contains not-valid date (i.e. 31st day for month with only 30 days). +

+
+ +
@@ -77,6 +101,10 @@ (documentationPropertyValueChange)="updateOptions()" > Strict mode +

+ Default: + true +

+ Date + + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DateMaskDocExample3 { + protected value = '31.02.2004'; + protected readonly filler = 'dd.mm.yyyy'; + protected readonly mask = mask; +} diff --git a/projects/demo/src/pages/kit/date/examples/3-strict-mode/mask.ts b/projects/demo/src/pages/kit/date/examples/3-strict-mode/mask.ts new file mode 100644 index 000000000..e8ba3ce42 --- /dev/null +++ b/projects/demo/src/pages/kit/date/examples/3-strict-mode/mask.ts @@ -0,0 +1,6 @@ +import {maskitoDateOptionsGenerator} from '@maskito/kit'; + +export default maskitoDateOptionsGenerator({ + mode: 'dd/mm/yyyy', + strict: false, +}); From 9c529594b03720db815f08aa1a973677b5a32a99 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Thu, 2 May 2024 11:33:47 +0300 Subject: [PATCH 18/29] docs(demo): added strict mode doc for date range --- .../date-range-mask-doc.component.ts | 8 ++++ .../date-range-mask-doc.template.html | 25 ++++++++++++ .../examples/5-strict-mode/component.ts | 39 +++++++++++++++++++ .../date-range/examples/5-strict-mode/mask.ts | 6 +++ 4 files changed, 78 insertions(+) create mode 100644 projects/demo/src/pages/kit/date-range/examples/5-strict-mode/component.ts create mode 100644 projects/demo/src/pages/kit/date-range/examples/5-strict-mode/mask.ts diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts index 58275c8cf..03d251852 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts @@ -15,6 +15,7 @@ import {DateRangeMaskDocExample1} from './examples/1-date-localization/component import {DateRangeMaskDocExample2} from './examples/2-min-max/component'; import {DateRangeMaskDocExample3} from './examples/3-min-max-length/component'; import {DateRangeMaskDocExample4} from './examples/4-range-separator/component'; +import {DateRangeMaskDocExample5} from './examples/5-strict-mode/component'; type GeneratorOptions = Required< NonNullable[0]> @@ -34,6 +35,7 @@ type GeneratorOptions = Required< DateRangeMaskDocExample2, DateRangeMaskDocExample3, DateRangeMaskDocExample4, + DateRangeMaskDocExample5, ], templateUrl: './date-range-mask-doc.template.html', changeDetection: ChangeDetectionStrategy.OnPush, @@ -61,6 +63,12 @@ export class DateRangeMaskDocComponent implements GeneratorOptions { ), }; + protected readonly strictModeExample5: TuiDocExample = { + [DocExamplePrimaryTab.MaskitoOptions]: import( + './examples/5-strict-mode/mask.ts?raw' + ), + }; + protected apiPageControl = new FormControl(''); protected readonly modeOptions: MaskitoDateMode[] = [ diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html index 2f69e0bad..52794be76 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html @@ -77,6 +77,31 @@ + + + +

+ In + strict + mode, if a user tries to enter a non-valid date, the mask will either prevent the user from entering + such a date, or if it is possible to turn it into a valid date, it will change it to a valid date. + Textfield's value + NEVER + contains invalid date value. +

+

+ In + non-strict + mode, textfield sometimes can contains not-valid date (i.e. 31st day for month with only 30 days). +

+
+ +
diff --git a/projects/demo/src/pages/kit/date-range/examples/5-strict-mode/component.ts b/projects/demo/src/pages/kit/date-range/examples/5-strict-mode/component.ts new file mode 100644 index 000000000..0f4eb0067 --- /dev/null +++ b/projects/demo/src/pages/kit/date-range/examples/5-strict-mode/component.ts @@ -0,0 +1,39 @@ +import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {FormsModule} from '@angular/forms'; +import {MaskitoDirective} from '@maskito/angular'; +import {TuiTextfieldControllerModule} from '@taiga-ui/core'; +import {TuiInputModule} from '@taiga-ui/kit'; + +import mask from './mask'; + +@Component({ + standalone: true, + selector: 'date-range-mask-doc-example-5', + imports: [ + TuiInputModule, + TuiTextfieldControllerModule, + FormsModule, + MaskitoDirective, + ], + template: ` + + + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DateRangeMaskDocExample5 { + protected value = '30.02.2004 - 31.11.2007'; + protected readonly filler = 'dd.mm.yyyy - dd.mm.yyyy'; + protected readonly mask = mask; +} diff --git a/projects/demo/src/pages/kit/date-range/examples/5-strict-mode/mask.ts b/projects/demo/src/pages/kit/date-range/examples/5-strict-mode/mask.ts new file mode 100644 index 000000000..de60c522a --- /dev/null +++ b/projects/demo/src/pages/kit/date-range/examples/5-strict-mode/mask.ts @@ -0,0 +1,6 @@ +import {maskitoDateRangeOptionsGenerator} from '@maskito/kit'; + +export default maskitoDateRangeOptionsGenerator({ + mode: 'dd/mm/yyyy', + strict: false, +}); From 3aaa13c2938a473a42c5564629f34ae718da1699 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Thu, 2 May 2024 11:40:26 +0300 Subject: [PATCH 19/29] docs(demo): added docs for strict mode in datetime --- .../date-time/date-time-mask-doc.component.ts | 8 ++++ .../date-time-mask-doc.template.html | 25 ++++++++++++ .../examples/4-strict-mode/component.ts | 39 +++++++++++++++++++ .../date-time/examples/4-strict-mode/mask.ts | 7 ++++ 4 files changed, 79 insertions(+) create mode 100644 projects/demo/src/pages/kit/date-time/examples/4-strict-mode/component.ts create mode 100644 projects/demo/src/pages/kit/date-time/examples/4-strict-mode/mask.ts diff --git a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts index 3c181cd29..86398fbde 100644 --- a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts @@ -14,6 +14,7 @@ import {DATE_TIME_SEPARATOR, TuiInputModule} from '@taiga-ui/kit'; import {DateTimeMaskDocExample1} from './examples/1-date-time-localization/component'; import {DateTimeMaskDocExample2} from './examples/2-date-time-separator/component'; import {DateTimeMaskDocExample3} from './examples/3-min-max/component'; +import {DateTimeMaskDocExample4} from './examples/4-strict-mode/component'; type GeneratorOptions = Required< NonNullable[0]> @@ -32,6 +33,7 @@ type GeneratorOptions = Required< DateTimeMaskDocExample1, DateTimeMaskDocExample2, DateTimeMaskDocExample3, + DateTimeMaskDocExample4, ], templateUrl: './date-time-mask-doc.template.html', changeDetection: ChangeDetectionStrategy.OnPush, @@ -53,6 +55,12 @@ export class DateTimeMaskDocComponent implements GeneratorOptions { [DocExamplePrimaryTab.MaskitoOptions]: import('./examples/3-min-max/mask.ts?raw'), }; + protected readonly strictModeExample: TuiDocExample = { + [DocExamplePrimaryTab.MaskitoOptions]: import( + './examples/4-strict-mode/mask.ts?raw' + ), + }; + protected apiPageControl = new FormControl(''); protected readonly dateModeOptions: MaskitoDateMode[] = [ diff --git a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html index ddc47d522..84b6647a7 100644 --- a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html @@ -63,6 +63,31 @@ + + + +

+ In + strict + mode, if a user tries to enter a non-valid date, the mask will either prevent the user from entering + such a date, or if it is possible to turn it into a valid date, it will change it to a valid date. + Textfield's value + NEVER + contains invalid date value. +

+

+ In + non-strict + mode, textfield sometimes can contains not-valid date (i.e. 31st day for month with only 30 days). +

+
+ +
diff --git a/projects/demo/src/pages/kit/date-time/examples/4-strict-mode/component.ts b/projects/demo/src/pages/kit/date-time/examples/4-strict-mode/component.ts new file mode 100644 index 000000000..372fdd44e --- /dev/null +++ b/projects/demo/src/pages/kit/date-time/examples/4-strict-mode/component.ts @@ -0,0 +1,39 @@ +import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {FormsModule} from '@angular/forms'; +import {MaskitoDirective} from '@maskito/angular'; +import {TuiTextfieldControllerModule} from '@taiga-ui/core'; +import {TuiInputModule} from '@taiga-ui/kit'; + +import mask from './mask'; + +@Component({ + standalone: true, + selector: 'date-time-mask-doc-example-4', + imports: [ + TuiInputModule, + TuiTextfieldControllerModule, + FormsModule, + MaskitoDirective, + ], + template: ` + + Min-max + + + `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DateTimeMaskDocExample4 { + protected value = '31.02.2003, 15:30'; + protected readonly filler = 'dd.mm.yyyy, hh:mm'; + protected readonly mask = mask; +} diff --git a/projects/demo/src/pages/kit/date-time/examples/4-strict-mode/mask.ts b/projects/demo/src/pages/kit/date-time/examples/4-strict-mode/mask.ts new file mode 100644 index 000000000..09cfe5c07 --- /dev/null +++ b/projects/demo/src/pages/kit/date-time/examples/4-strict-mode/mask.ts @@ -0,0 +1,7 @@ +import {maskitoDateTimeOptionsGenerator} from '@maskito/kit'; + +export default maskitoDateTimeOptionsGenerator({ + dateMode: 'dd/mm/yyyy', + timeMode: 'HH:MM', + strict: false, +}); From bb26ad8708285313d6ef10a8c6ee7f9725671ce9 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Thu, 2 May 2024 11:44:30 +0300 Subject: [PATCH 20/29] docs(demo): added default values for date-time and date-range in api --- .../supported-input-types.template.html | 13 ++++++++++--- .../date-range/date-range-mask-doc.template.html | 4 ++++ .../kit/date-time/date-time-mask-doc.template.html | 4 ++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/projects/demo/src/pages/documentation/supported-input-types/supported-input-types.template.html b/projects/demo/src/pages/documentation/supported-input-types/supported-input-types.template.html index 101adbc8b..b020b9a4d 100644 --- a/projects/demo/src/pages/documentation/supported-input-types/supported-input-types.template.html +++ b/projects/demo/src/pages/documentation/supported-input-types/supported-input-types.template.html @@ -13,15 +13,22 @@

    -
  • selectionStart
  • -
  • selectionEnd
  • -
  • setSelectionRange
  • +
  • + selectionStart +
  • +
  • + selectionEnd +
  • +
  • + setSelectionRange +

According to the diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html index 52794be76..afb1bc23b 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html @@ -130,6 +130,10 @@ (documentationPropertyValueChange)="updateOptions()" > Strict mode +

+ Default: + true +

Strict mode +

+ Default: + true +

Date: Fri, 3 May 2024 10:55:02 +0300 Subject: [PATCH 21/29] test(demo-integrations): refactored --- .../src/tests/kit/date-time/date-time-strict-mode.cy.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts b/projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts index 8479a6759..ea8917cbf 100644 --- a/projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts +++ b/projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts @@ -1,6 +1,6 @@ import {DemoPath} from '@demo/constants'; -describe('Date | Strict mode', () => { +describe('DateTime | Strict mode', () => { describe('Disabled', () => { describe("doesn't fix wrong dates", () => { beforeEach(() => { @@ -88,7 +88,7 @@ describe('Date | Strict mode', () => { }); }); - describe('replaces dates to max, when date greater max 10.05.2025, 18:30', () => { + describe('replaces dates to max, when date greater max 10.05.2025, 18:30', () => { beforeEach(() => { cy.visit(`/${DemoPath.DateTime}/API?strict=false&max=2025-05-10T18:30`); cy.get('#demo-content input') From 9541993809bd64f846986cf8305c590c9b3375f9 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Fri, 3 May 2024 11:09:01 +0300 Subject: [PATCH 22/29] test(demo-integrations): created tests for enabled strict mode --- .../date-range/date-range-strict-mode.cy.ts | 37 +++++++++++++ .../kit/date-time/date-time-strict-mode.cy.ts | 55 +++++++++++++++++++ .../src/tests/kit/date/date-strict-mode.cy.ts | 45 +++++++++++++-- 3 files changed, 133 insertions(+), 4 deletions(-) diff --git a/projects/demo-integrations/src/tests/kit/date-range/date-range-strict-mode.cy.ts b/projects/demo-integrations/src/tests/kit/date-range/date-range-strict-mode.cy.ts index 1284e1faa..01989bba5 100644 --- a/projects/demo-integrations/src/tests/kit/date-range/date-range-strict-mode.cy.ts +++ b/projects/demo-integrations/src/tests/kit/date-range/date-range-strict-mode.cy.ts @@ -91,4 +91,41 @@ describe('DateRange | Strict mode', () => { }); }); }); + + describe('Enabled', () => { + describe('fixes wrong dates', () => { + beforeEach(() => { + cy.visit(`/${DemoPath.DateRange}/API?strict=true`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('30.02.2004 => 30.02.2004 - 31.02.2004', () => { + cy.get('@input') + .type('30022004') + .should('have.value', '01.03.2004') + .type('31022004') + .should('have.value', '01.03.2004 – 02.03.2004'); + }); + + it('29.02.2003 => 29.02.2003 - 31.04.2004', () => { + cy.get('@input') + .type('29022003') + .should('have.value', '01.03.2003') + .type('31042004') + .should('have.value', '01.03.2003 – 01.05.2004'); + }); + + it('31.06.2004 => 31.06.2004 - 31.09.2004', () => { + cy.get('@input') + .type('31062004') + .should('have.value', '01.07.2004') + .type('31092004') + .should('have.value', '01.07.2004 – 01.10.2004'); + }); + }); + }); }); diff --git a/projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts b/projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts index ea8917cbf..1bdd599ba 100644 --- a/projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts +++ b/projects/demo-integrations/src/tests/kit/date-time/date-time-strict-mode.cy.ts @@ -115,4 +115,59 @@ describe('DateTime | Strict mode', () => { }); }); }); + + describe('Enabled', () => { + describe('fixse wrong dates', () => { + beforeEach(() => { + cy.visit(`/${DemoPath.DateTime}/API?strict=true`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('30.02.2004, 23:21', () => { + cy.get('@input') + .type('300220042321') + .should('have.value', '01.03.2004, 23:21'); + }); + + it('31.02.2004, 12:21', () => { + cy.get('@input') + .type('310220041221') + .should('have.value', '02.03.2004, 12:21'); + }); + + it('29.02.2003, 00:00', () => { + cy.get('@input') + .type('290220030000') + .should('have.value', '01.03.2003, 00:00'); + }); + + it('31.04.2004, 10:00', () => { + cy.get('@input') + .type('310420041000') + .should('have.value', '01.05.2004, 10:00'); + }); + + it('31.06.2004, 23:21', () => { + cy.get('@input') + .type('310620042321') + .should('have.value', '01.07.2004, 23:21'); + }); + + it('31.09.2004, 23:21', () => { + cy.get('@input') + .type('310920042321') + .should('have.value', '01.10.2004, 23:21'); + }); + + it('31.11.2004, 23:21', () => { + cy.get('@input') + .type('311120042321') + .should('have.value', '01.12.2004, 23:21'); + }); + }); + }); }); diff --git a/projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts b/projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts index 08f85c4e9..a84f3e4a7 100644 --- a/projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts +++ b/projects/demo-integrations/src/tests/kit/date/date-strict-mode.cy.ts @@ -28,10 +28,6 @@ describe('Date | Strict mode', () => { cy.get('@input').type('31042004').should('have.value', '31.04.2004'); }); - it('31.04.2004', () => { - cy.get('@input').type('31042004').should('have.value', '31.04.2004'); - }); - it('31.06.2004', () => { cy.get('@input').type('31062004').should('have.value', '31.06.2004'); }); @@ -83,4 +79,45 @@ describe('Date | Strict mode', () => { }); }); }); + + describe('Enabled', () => { + describe('fixes wrong dates', () => { + beforeEach(() => { + cy.visit(`/${DemoPath.Date}/API?strict=true`); + cy.get('#demo-content input') + .should('be.visible') + .first() + .focus() + .as('input'); + }); + + it('30.02.2004', () => { + cy.get('@input').type('30022004').should('have.value', '01.03.2004'); + }); + + it('31.02.2004', () => { + cy.get('@input').type('31022004').should('have.value', '02.03.2004'); + }); + + it('29.02.2003', () => { + cy.get('@input').type('29022003').should('have.value', '01.03.2003'); + }); + + it('31.04.2004', () => { + cy.get('@input').type('31042004').should('have.value', '01.05.2004'); + }); + + it('31.06.2004', () => { + cy.get('@input').type('31062004').should('have.value', '01.07.2004'); + }); + + it('31.09.2004', () => { + cy.get('@input').type('31092004').should('have.value', '01.10.2004'); + }); + + it('31.11.2004', () => { + cy.get('@input').type('31112004').should('have.value', '01.12.2004'); + }); + }); + }); }); From 46155dd7357b8db23893cf96c9ebdc258e1474e9 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Fri, 3 May 2024 11:55:54 +0300 Subject: [PATCH 23/29] refactor(demo): removed min-max from strict --- .../src/pages/kit/date-time/examples/4-strict-mode/component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/demo/src/pages/kit/date-time/examples/4-strict-mode/component.ts b/projects/demo/src/pages/kit/date-time/examples/4-strict-mode/component.ts index 372fdd44e..0c19dff5a 100644 --- a/projects/demo/src/pages/kit/date-time/examples/4-strict-mode/component.ts +++ b/projects/demo/src/pages/kit/date-time/examples/4-strict-mode/component.ts @@ -22,7 +22,7 @@ import mask from './mask'; [tuiTextfieldFiller]="filler" [(ngModel)]="value" > - Min-max + Disabled strict mode Date: Fri, 3 May 2024 12:07:00 +0300 Subject: [PATCH 24/29] docs(demo-integrations): moved strict mode description into separate component --- .../strict-mode-description.component.ts | 9 +++++++++ .../strict-mode-description.template.html | 13 +++++++++++++ .../date-range/date-range-mask-doc.component.ts | 2 ++ .../date-range/date-range-mask-doc.template.html | 15 +-------------- .../kit/date-time/date-time-mask-doc.component.ts | 2 ++ .../date-time/date-time-mask-doc.template.html | 15 +-------------- .../src/pages/kit/date/date-mask-doc.component.ts | 2 ++ .../pages/kit/date/date-mask-doc.template.html | 15 +-------------- 8 files changed, 31 insertions(+), 42 deletions(-) create mode 100644 projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.component.ts create mode 100644 projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.template.html diff --git a/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.component.ts b/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.component.ts new file mode 100644 index 000000000..d4d19bf7f --- /dev/null +++ b/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.component.ts @@ -0,0 +1,9 @@ +import {ChangeDetectionStrategy, Component} from '@angular/core'; + +@Component({ + standalone: true, + selector: 'strict-mode-description', + templateUrl: './strict-mode-description.template.html', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class StrictModeDescriptionComponent {} diff --git a/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.template.html b/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.template.html new file mode 100644 index 000000000..8056a14b2 --- /dev/null +++ b/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.template.html @@ -0,0 +1,13 @@ +

+ In + strict + mode, if a user tries to enter a non-valid date, the mask will either prevent the user from entering such a date, or + if it is possible to turn it into a valid date, it will change it to a valid date. Textfield's value + NEVER + contains invalid date value. +

+

+ In + non-strict + mode, textfield sometimes can contains not-valid date (i.e. 31st day for month with only 30 days). +

diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts index 03d251852..255277d07 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts @@ -11,6 +11,7 @@ import {tuiPure} from '@taiga-ui/cdk'; import {TuiLinkModule, TuiTextfieldControllerModule} from '@taiga-ui/core'; import {TuiInputModule} from '@taiga-ui/kit'; +import {StrictModeDescriptionComponent} from '../components/strict-mode-descriptino/strict-mode-description.component'; import {DateRangeMaskDocExample1} from './examples/1-date-localization/component'; import {DateRangeMaskDocExample2} from './examples/2-min-max/component'; import {DateRangeMaskDocExample3} from './examples/3-min-max-length/component'; @@ -36,6 +37,7 @@ type GeneratorOptions = Required< DateRangeMaskDocExample3, DateRangeMaskDocExample4, DateRangeMaskDocExample5, + StrictModeDescriptionComponent, ], templateUrl: './date-range-mask-doc.template.html', changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html index afb1bc23b..720e5000a 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html @@ -85,20 +85,7 @@ [description]="strict" > -

- In - strict - mode, if a user tries to enter a non-valid date, the mask will either prevent the user from entering - such a date, or if it is possible to turn it into a valid date, it will change it to a valid date. - Textfield's value - NEVER - contains invalid date value. -

-

- In - non-strict - mode, textfield sometimes can contains not-valid date (i.e. 31st day for month with only 30 days). -

+
diff --git a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts index 86398fbde..2c20be3a9 100644 --- a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts @@ -11,6 +11,7 @@ import {tuiPure} from '@taiga-ui/cdk'; import {TuiLinkModule, TuiTextfieldControllerModule} from '@taiga-ui/core'; import {DATE_TIME_SEPARATOR, TuiInputModule} from '@taiga-ui/kit'; +import {StrictModeDescriptionComponent} from '../components/strict-mode-descriptino/strict-mode-description.component'; import {DateTimeMaskDocExample1} from './examples/1-date-time-localization/component'; import {DateTimeMaskDocExample2} from './examples/2-date-time-separator/component'; import {DateTimeMaskDocExample3} from './examples/3-min-max/component'; @@ -34,6 +35,7 @@ type GeneratorOptions = Required< DateTimeMaskDocExample2, DateTimeMaskDocExample3, DateTimeMaskDocExample4, + StrictModeDescriptionComponent, ], templateUrl: './date-time-mask-doc.template.html', changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html index 58827f41f..eba913606 100644 --- a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.template.html @@ -71,20 +71,7 @@ [description]="strict" > -

- In - strict - mode, if a user tries to enter a non-valid date, the mask will either prevent the user from entering - such a date, or if it is possible to turn it into a valid date, it will change it to a valid date. - Textfield's value - NEVER - contains invalid date value. -

-

- In - non-strict - mode, textfield sometimes can contains not-valid date (i.e. 31st day for month with only 30 days). -

+
diff --git a/projects/demo/src/pages/kit/date/date-mask-doc.component.ts b/projects/demo/src/pages/kit/date/date-mask-doc.component.ts index 31a5cae91..35bbe44a3 100644 --- a/projects/demo/src/pages/kit/date/date-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date/date-mask-doc.component.ts @@ -10,6 +10,7 @@ import {TuiAddonDocModule} from '@taiga-ui/addon-doc'; import {TuiLinkModule, TuiTextfieldControllerModule} from '@taiga-ui/core'; import {TuiInputModule} from '@taiga-ui/kit'; +import {StrictModeDescriptionComponent} from '../components/strict-mode-descriptino/strict-mode-description.component'; import {DateMaskDocExample1} from './examples/1-localization/component'; import {DateMaskDocExample2} from './examples/2-min-max/component'; import {DateMaskDocExample3} from './examples/3-strict-mode/component'; @@ -29,6 +30,7 @@ type GeneratorOptions = Required[ TuiTextfieldControllerModule, ReactiveFormsModule, MaskitoDirective, + StrictModeDescriptionComponent, ], templateUrl: './date-mask-doc.template.html', styleUrls: ['./date-mask-doc.style.less'], diff --git a/projects/demo/src/pages/kit/date/date-mask-doc.template.html b/projects/demo/src/pages/kit/date/date-mask-doc.template.html index 4407c3ed9..c0d88bef9 100644 --- a/projects/demo/src/pages/kit/date/date-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date/date-mask-doc.template.html @@ -56,20 +56,7 @@ [description]="strict" > -

- In - strict - mode, if a user tries to enter a non-valid date, the mask will either prevent the user from entering - such a date, or if it is possible to turn it into a valid date, it will change it to a valid date. - Textfield's value - NEVER - contains invalid date value. -

-

- In - non-strict - mode, textfield sometimes can contains not-valid date (i.e. 31st day for month with only 30 days). -

+
From cd74e26407235e4eca2a1eddc0bfb0c7895c2fd6 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Sat, 11 May 2024 13:23:56 +0300 Subject: [PATCH 25/29] refactor(kit): refactored validation processors --- .../kit/src/lib/masks/date-time/date-time-mask.ts | 4 ++-- ...date-time-segments-validation-postprocessor.ts | 2 +- .../date-segments-validation-postprocessor.ts | 15 ++++++++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/projects/kit/src/lib/masks/date-time/date-time-mask.ts b/projects/kit/src/lib/masks/date-time/date-time-mask.ts index da91bc93d..63318a993 100644 --- a/projects/kit/src/lib/masks/date-time/date-time-mask.ts +++ b/projects/kit/src/lib/masks/date-time/date-time-mask.ts @@ -13,7 +13,7 @@ import { import type {MaskitoDateMode, MaskitoTimeMode} from '../../types'; import {DATE_TIME_SEPARATOR} from './constants'; import { - createDateTimeSegmentsValidationPostProcessor, + createDateTimeSegmentsValidationPostprocessor, createMinMaxDateTimePostprocessor, } from './postprocessors'; import {createValidDateTimePreprocessor} from './preprocessors'; @@ -87,7 +87,7 @@ export function maskitoDateTimeOptionsGenerator({ validatedDateString + (initialValue.includes(dateTimeSeparator) ? dateTimeSeparator : ''), }), - createDateTimeSegmentsValidationPostProcessor({ + createDateTimeSegmentsValidationPostprocessor({ dateModeTemplate, timeMode, dateTimeSeparator, diff --git a/projects/kit/src/lib/masks/date-time/postprocessors/date-time-segments-validation-postprocessor.ts b/projects/kit/src/lib/masks/date-time/postprocessors/date-time-segments-validation-postprocessor.ts index 5d735fc67..14fc3992c 100644 --- a/projects/kit/src/lib/masks/date-time/postprocessors/date-time-segments-validation-postprocessor.ts +++ b/projects/kit/src/lib/masks/date-time/postprocessors/date-time-segments-validation-postprocessor.ts @@ -12,7 +12,7 @@ import {raiseSegmentValueToMin} from '../../../utils/date/raise-segment-value-to import {parseTimeString} from '../../../utils/time'; import {isDateTimeStringComplete, parseDateTimeString} from '../utils'; -export function createDateTimeSegmentsValidationPostProcessor({ +export function createDateTimeSegmentsValidationPostprocessor({ dateModeTemplate, timeMode, dateTimeSeparator, diff --git a/projects/kit/src/lib/processors/date-segments-validation-postprocessor.ts b/projects/kit/src/lib/processors/date-segments-validation-postprocessor.ts index 909386761..2b6098ef9 100644 --- a/projects/kit/src/lib/processors/date-segments-validation-postprocessor.ts +++ b/projects/kit/src/lib/processors/date-segments-validation-postprocessor.ts @@ -28,12 +28,17 @@ export function createDateSegmentsValidationPostprocessor({ for (const dateString of dateStrings) { validatedValue += validatedValue ? rangeSeparator : ''; - const parsedDate = parseDateString(dateString, dateModeTemplate); + const parsedDateSegments = parseDateString(dateString, dateModeTemplate); if (!isDateStringComplete(dateString, dateModeTemplate)) { - const fixedDate = raiseSegmentValueToMin(parsedDate, dateModeTemplate); + const fixedDateSegments = raiseSegmentValueToMin( + parsedDateSegments, + dateModeTemplate, + ); - const fixedValue = toDateString(fixedDate, {dateMode: dateModeTemplate}); + const fixedValue = toDateString(fixedDateSegments, { + dateMode: dateModeTemplate, + }); const tail = dateString.endsWith(dateSegmentSeparator) ? dateSegmentSeparator : ''; @@ -44,9 +49,9 @@ export function createDateSegmentsValidationPostprocessor({ validatedValue += toDateString( strictDateTimeModeValidation({ - date: segmentsToDate(parsedDate), + date: segmentsToDate(parsedDateSegments), strict, - dateSegments: parsedDate, + dateSegments: parsedDateSegments, }), { dateMode: dateModeTemplate, From 8e5bf0ee70bc3b2234826a30e156921fa9396b20 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Sat, 11 May 2024 13:32:37 +0300 Subject: [PATCH 26/29] docs(demo): added description for strict mode --- .../strict-mode-api-description.component.ts | 20 +++++++++++++++++++ .../date-range-mask-doc.component.ts | 2 ++ .../date-range-mask-doc.template.html | 6 ++---- .../date-time/date-time-mask-doc.component.ts | 2 ++ .../date-time-mask-doc.template.html | 6 ++---- .../pages/kit/date/date-mask-doc.component.ts | 2 ++ 6 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-api-description.component.ts diff --git a/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-api-description.component.ts b/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-api-description.component.ts new file mode 100644 index 000000000..80ee9408e --- /dev/null +++ b/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-api-description.component.ts @@ -0,0 +1,20 @@ +import {ChangeDetectionStrategy, Component} from '@angular/core'; + +@Component({ + standalone: true, + selector: 'strict-mode-api-description', + template: ` +

+ In + strict + mode the date is autocorrected (i.e. there will never be an incorrect date in + this field). +

+

+ Default: + true +

+ `, + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class StrictModeApiDescriptionComponent {} diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts index 255277d07..753c0d5b4 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts @@ -11,6 +11,7 @@ import {tuiPure} from '@taiga-ui/cdk'; import {TuiLinkModule, TuiTextfieldControllerModule} from '@taiga-ui/core'; import {TuiInputModule} from '@taiga-ui/kit'; +import {StrictModeApiDescriptionComponent} from '../components/strict-mode-descriptino/strict-mode-api-description.component'; import {StrictModeDescriptionComponent} from '../components/strict-mode-descriptino/strict-mode-description.component'; import {DateRangeMaskDocExample1} from './examples/1-date-localization/component'; import {DateRangeMaskDocExample2} from './examples/2-min-max/component'; @@ -38,6 +39,7 @@ type GeneratorOptions = Required< DateRangeMaskDocExample4, DateRangeMaskDocExample5, StrictModeDescriptionComponent, + StrictModeApiDescriptionComponent, ], templateUrl: './date-range-mask-doc.template.html', changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html index 720e5000a..44beff5c0 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.template.html @@ -117,10 +117,8 @@ (documentationPropertyValueChange)="updateOptions()" > Strict mode -

- Default: - true -

+ +
Strict mode -

- Default: - true -

+ +
[ ReactiveFormsModule, MaskitoDirective, StrictModeDescriptionComponent, + StrictModeApiDescriptionComponent, ], templateUrl: './date-mask-doc.template.html', styleUrls: ['./date-mask-doc.style.less'], From ed4d917318e1830cc11cb6ce73fa1f3c6c35a016 Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Sat, 11 May 2024 13:37:14 +0300 Subject: [PATCH 27/29] docs(demo): added full description for strict mode --- .../strict-mode-description.template.html | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.template.html b/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.template.html index 8056a14b2..d9c6ce9b9 100644 --- a/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.template.html +++ b/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.template.html @@ -6,6 +6,14 @@ NEVER contains invalid date value.

+

+ Example: + if you type + 29.02.2003 + it will turn into + 01.03.2003 + . +

In non-strict From c2b166bab3a13852577759b3dda15bf4a0ed67eb Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Sat, 11 May 2024 13:38:19 +0300 Subject: [PATCH 28/29] refactor(demo): renamed folder --- .../strict-mode-api-description.component.ts | 0 .../strict-mode-description.component.ts | 0 .../strict-mode-description.template.html | 0 .../src/pages/kit/date-range/date-range-mask-doc.component.ts | 4 ++-- .../src/pages/kit/date-time/date-time-mask-doc.component.ts | 4 ++-- projects/demo/src/pages/kit/date/date-mask-doc.component.ts | 4 ++-- 6 files changed, 6 insertions(+), 6 deletions(-) rename projects/demo/src/pages/kit/components/{strict-mode-descriptino => strict-mode-description}/strict-mode-api-description.component.ts (100%) rename projects/demo/src/pages/kit/components/{strict-mode-descriptino => strict-mode-description}/strict-mode-description.component.ts (100%) rename projects/demo/src/pages/kit/components/{strict-mode-descriptino => strict-mode-description}/strict-mode-description.template.html (100%) diff --git a/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-api-description.component.ts b/projects/demo/src/pages/kit/components/strict-mode-description/strict-mode-api-description.component.ts similarity index 100% rename from projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-api-description.component.ts rename to projects/demo/src/pages/kit/components/strict-mode-description/strict-mode-api-description.component.ts diff --git a/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.component.ts b/projects/demo/src/pages/kit/components/strict-mode-description/strict-mode-description.component.ts similarity index 100% rename from projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.component.ts rename to projects/demo/src/pages/kit/components/strict-mode-description/strict-mode-description.component.ts diff --git a/projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.template.html b/projects/demo/src/pages/kit/components/strict-mode-description/strict-mode-description.template.html similarity index 100% rename from projects/demo/src/pages/kit/components/strict-mode-descriptino/strict-mode-description.template.html rename to projects/demo/src/pages/kit/components/strict-mode-description/strict-mode-description.template.html diff --git a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts index 753c0d5b4..c1d12e2fd 100644 --- a/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date-range/date-range-mask-doc.component.ts @@ -11,8 +11,8 @@ import {tuiPure} from '@taiga-ui/cdk'; import {TuiLinkModule, TuiTextfieldControllerModule} from '@taiga-ui/core'; import {TuiInputModule} from '@taiga-ui/kit'; -import {StrictModeApiDescriptionComponent} from '../components/strict-mode-descriptino/strict-mode-api-description.component'; -import {StrictModeDescriptionComponent} from '../components/strict-mode-descriptino/strict-mode-description.component'; +import {StrictModeApiDescriptionComponent} from '../components/strict-mode-description/strict-mode-api-description.component'; +import {StrictModeDescriptionComponent} from '../components/strict-mode-description/strict-mode-description.component'; import {DateRangeMaskDocExample1} from './examples/1-date-localization/component'; import {DateRangeMaskDocExample2} from './examples/2-min-max/component'; import {DateRangeMaskDocExample3} from './examples/3-min-max-length/component'; diff --git a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts index e1e3103d7..e81157dfe 100644 --- a/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date-time/date-time-mask-doc.component.ts @@ -11,8 +11,8 @@ import {tuiPure} from '@taiga-ui/cdk'; import {TuiLinkModule, TuiTextfieldControllerModule} from '@taiga-ui/core'; import {DATE_TIME_SEPARATOR, TuiInputModule} from '@taiga-ui/kit'; -import {StrictModeApiDescriptionComponent} from '../components/strict-mode-descriptino/strict-mode-api-description.component'; -import {StrictModeDescriptionComponent} from '../components/strict-mode-descriptino/strict-mode-description.component'; +import {StrictModeApiDescriptionComponent} from '../components/strict-mode-description/strict-mode-api-description.component'; +import {StrictModeDescriptionComponent} from '../components/strict-mode-description/strict-mode-description.component'; import {DateTimeMaskDocExample1} from './examples/1-date-time-localization/component'; import {DateTimeMaskDocExample2} from './examples/2-date-time-separator/component'; import {DateTimeMaskDocExample3} from './examples/3-min-max/component'; diff --git a/projects/demo/src/pages/kit/date/date-mask-doc.component.ts b/projects/demo/src/pages/kit/date/date-mask-doc.component.ts index 93e507a5f..e15db1241 100644 --- a/projects/demo/src/pages/kit/date/date-mask-doc.component.ts +++ b/projects/demo/src/pages/kit/date/date-mask-doc.component.ts @@ -10,8 +10,8 @@ import {TuiAddonDocModule} from '@taiga-ui/addon-doc'; import {TuiLinkModule, TuiTextfieldControllerModule} from '@taiga-ui/core'; import {TuiInputModule} from '@taiga-ui/kit'; -import {StrictModeApiDescriptionComponent} from '../components/strict-mode-descriptino/strict-mode-api-description.component'; -import {StrictModeDescriptionComponent} from '../components/strict-mode-descriptino/strict-mode-description.component'; +import {StrictModeApiDescriptionComponent} from '../components/strict-mode-description/strict-mode-api-description.component'; +import {StrictModeDescriptionComponent} from '../components/strict-mode-description/strict-mode-description.component'; import {DateMaskDocExample1} from './examples/1-localization/component'; import {DateMaskDocExample2} from './examples/2-min-max/component'; import {DateMaskDocExample3} from './examples/3-strict-mode/component'; From 978c3fd91b11de178bf3816f2ecf9ac6d328cc7c Mon Sep 17 00:00:00 2001 From: Stanslav Zaytsev Date: Sat, 11 May 2024 13:41:47 +0300 Subject: [PATCH 29/29] refactor(kit): strictdateTimeModeValidation --- .../lib/utils/date/strict-date-time-mode-validation.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts b/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts index 85f2743b0..4301b39e6 100644 --- a/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts +++ b/projects/kit/src/lib/utils/date/strict-date-time-mode-validation.ts @@ -14,9 +14,7 @@ export function strictDateTimeModeValidation({ timeSegments?: Partial; isDateComplete?: boolean; }): Partial { - if (strict) { - return isDateComplete ? dateToSegments(date) : {...dateSegments, ...timeSegments}; - } - - return {...dateSegments, ...timeSegments}; + return strict && isDateComplete + ? dateToSegments(date) + : {...dateSegments, ...timeSegments}; }