Skip to content

Commit

Permalink
feat(kit): DateTime supports configurable parameter `dateTimeSepara…
Browse files Browse the repository at this point in the history
…tor` (#1143)
  • Loading branch information
KrollikRoddzer authored Mar 27, 2024
1 parent 8e853a2 commit ec86284
Show file tree
Hide file tree
Showing 19 changed files with 315 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {DemoPath} from '@demo/constants';
import type {MaskitoTimeMode} from '@maskito/kit';

describe('DateTime | dateTimeSeparator', () => {
const dateTimeSeparators = [':', ';_', '_-_', '_at_'];

dateTimeSeparators.forEach(dateTimeSeparator => {
const testCases: Array<{
typedDigits: string;
formattedDate: string;
formattedValue: string;
timeMode: MaskitoTimeMode;
}> = [
{
typedDigits: '522004341',
formattedValue: `05.02.2004${dateTimeSeparator}03:41`,
formattedDate: '05.02.2004',
timeMode: 'HH:MM',
},
{
typedDigits: '233123434111',
formattedValue: `23.03.1234${dateTimeSeparator}03:41:11`,
formattedDate: '23.03.1234',
timeMode: 'HH:MM:SS',
},
{
typedDigits: '69200734111111',
formattedValue: `06.09.2007${dateTimeSeparator}03:41:11.111`,
formattedDate: '06.09.2007',
timeMode: 'HH:MM:SS.MSS',
},
];

describe(`correctly applies "${dateTimeSeparator}" as dateTimeSeparator`, () => {
testCases.forEach(
({typedDigits, formattedDate, formattedValue, timeMode}) => {
const timeDigitsCount = timeMode.replaceAll(/[:.]/g, '').length;

beforeEach(() => {
cy.visit(
`/${DemoPath.DateTime}/API?dateTimeSeparator=${encodeURIComponent(dateTimeSeparator)}&timeMode=${encodeURIComponent(timeMode)}`,
);
cy.get('#demo-content input')
.should('be.visible')
.first()
.focus()
.as('input');
});

it(`${typedDigits} => ${formattedValue} => {backspace} * ${timeDigitsCount} => ${formattedDate}`, () => {
cy.get('@input')
.type(typedDigits)
.should('have.value', formattedValue)
.type('{backspace}'.repeat(timeDigitsCount))
.should('have.value', formattedDate);
});
},
);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import type {MaskitoDateMode, MaskitoTimeMode} from '@maskito/kit';
import {maskitoDateTimeOptionsGenerator} from '@maskito/kit';
import type {TuiDocExample} from '@taiga-ui/addon-doc';
import {TuiAddonDocModule} from '@taiga-ui/addon-doc';
import {CHAR_NO_BREAK_SPACE, tuiPure} from '@taiga-ui/cdk';
import {tuiPure} from '@taiga-ui/cdk';
import {TuiLinkModule, TuiTextfieldControllerModule} from '@taiga-ui/core';
import {TuiInputModule} from '@taiga-ui/kit';
import {DATE_TIME_SEPARATOR, TuiInputModule} from '@taiga-ui/kit';

import {DateTimeMaskDocExample1} from './examples/1-date-time-localization/component';
import {DateTimeMaskDocExample2} from './examples/2-min-max/component';
import {DateTimeMaskDocExample2} from './examples/2-date-time-separator/component';
import {DateTimeMaskDocExample3} from './examples/3-min-max/component';

type GeneratorOptions = Required<
NonNullable<Parameters<typeof maskitoDateTimeOptionsGenerator>[0]>
Expand All @@ -30,19 +31,26 @@ type GeneratorOptions = Required<
TuiTextfieldControllerModule,
DateTimeMaskDocExample1,
DateTimeMaskDocExample2,
DateTimeMaskDocExample3,
],
templateUrl: './date-time-mask-doc.template.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DateTimeMaskDocComponent implements GeneratorOptions {
protected readonly dateTimeLocalization: TuiDocExample = {
protected readonly dateTimeLocalizationExample: TuiDocExample = {
[DocExamplePrimaryTab.MaskitoOptions]: import(
'./examples/1-date-time-localization/mask.ts?raw'
),
};

protected readonly dateTimeMinMax: TuiDocExample = {
[DocExamplePrimaryTab.MaskitoOptions]: import('./examples/2-min-max/mask.ts?raw'),
protected readonly dateTimeSeparatorExample: TuiDocExample = {
[DocExamplePrimaryTab.MaskitoOptions]: import(
'./examples/2-date-time-separator/mask.ts?raw'
),
};

protected readonly dateTimeMinMaxExample: TuiDocExample = {
[DocExamplePrimaryTab.MaskitoOptions]: import('./examples/3-min-max/mask.ts?raw'),
};

protected apiPageControl = new FormControl('');
Expand Down Expand Up @@ -71,6 +79,7 @@ export class DateTimeMaskDocComponent implements GeneratorOptions {

public dateMode: MaskitoDateMode = this.dateModeOptions[0];
public timeMode: MaskitoTimeMode = this.timeModeOptions[0];
public dateTimeSeparator = DATE_TIME_SEPARATOR;
public dateSeparator = '.';
public min = new Date(this.minStr);
public max = new Date(this.maxStr);
Expand All @@ -82,10 +91,9 @@ export class DateTimeMaskDocComponent implements GeneratorOptions {
dateMode: MaskitoDateMode,
timeMode: MaskitoTimeMode,
separator: string,
dateTimeSeparator: string,
): string {
const dateTimeSep = `,${CHAR_NO_BREAK_SPACE}`;

return `${dateMode.replaceAll('/', separator)}${dateTimeSep}${timeMode}`;
return `${dateMode.replaceAll('/', separator)}${dateTimeSeparator}${timeMode}`;
}

protected updateOptions(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<tui-doc-example
id="localization"
heading="Localization"
[content]="dateTimeLocalization"
[content]="dateTimeLocalizationExample"
[description]="localizationDescription"
>
<ng-template #localizationDescription>
Expand All @@ -25,10 +25,24 @@
<date-time-mask-doc-example-1 />
</tui-doc-example>

<tui-doc-example
id="date-time-separator"
heading="Custom separator between date and time"
[content]="dateTimeSeparatorExample"
[description]="dateTimeSeparatorDescription"
>
<ng-template #dateTimeSeparatorDescription>
Use
<code>dateTimeSeparator</code>
parameter to configure separator between date and time strings.
</ng-template>
<date-time-mask-doc-example-2 />
</tui-doc-example>

<tui-doc-example
id="min-max"
heading="Min and max"
[content]="dateTimeMinMax"
[content]="dateTimeMinMaxExample"
[description]="minMaxDescription"
>
<ng-template #minMaxDescription>
Expand All @@ -47,7 +61,7 @@
</a>
.
</ng-template>
<date-time-mask-doc-example-2 />
<date-time-mask-doc-example-3 />
</tui-doc-example>
</ng-template>

Expand All @@ -57,7 +71,7 @@
<tui-input
tuiTextfieldCustomContent="tuiIconCalendarLarge"
[formControl]="apiPageControl"
[tuiTextfieldFiller]="getPlaceholder(dateMode, timeMode, dateSeparator)"
[tuiTextfieldFiller]="getPlaceholder(dateMode, timeMode, dateSeparator, dateTimeSeparator)"
>
Enter date and time
<input
Expand Down Expand Up @@ -107,6 +121,22 @@
</p>
</ng-template>

<ng-template
documentationPropertyMode="input"
documentationPropertyName="dateTimeSeparator"
documentationPropertyType="string"
[(documentationPropertyValue)]="dateTimeSeparator"
(documentationPropertyValueChange)="updateOptions()"
>
Separator between date and time

<p>
<strong>Default:</strong>
<code>,&nbsp;</code>
(comma and space)
</p>
</ng-template>

<ng-template
documentationPropertyMode="input"
documentationPropertyName="min"
Expand Down
Original file line number Diff line number Diff line change
@@ -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-2',
imports: [
TuiInputModule,
TuiTextfieldControllerModule,
FormsModule,
MaskitoDirective,
],
template: `
<tui-input
tuiTextfieldCustomContent="tuiIconCalendarLarge"
[style.max-width.rem]="30"
[tuiTextfieldFiller]="filler"
[(ngModel)]="value"
>
Custom date and time separator
<input
inputmode="decimal"
tuiTextfield
[maskito]="mask"
/>
</tui-input>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DateTimeMaskDocExample2 {
protected value = '05.02.2004; 10:10';
protected readonly filler = 'dd.mm.yyyy; hh:mm';
protected readonly mask = mask;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {maskitoDateTimeOptionsGenerator} from '@maskito/kit';

export default maskitoDateTimeOptionsGenerator({
dateMode: 'dd/mm/yyyy',
timeMode: 'HH:MM',
dateTimeSeparator: '; ',
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import mask from './mask';

@Component({
standalone: true,
selector: 'date-time-mask-doc-example-2',
selector: 'date-time-mask-doc-example-3',
imports: [
TuiInputModule,
TuiTextfieldControllerModule,
Expand All @@ -32,7 +32,7 @@ import mask from './mask';
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DateTimeMaskDocExample2 {
export class DateTimeMaskDocExample3 {
protected value = '09-01-2018, 15:30';
protected readonly filler = 'dd-mm-yyyy, hh:mm';
protected readonly mask = mask;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ export function createMinMaxRangeLengthPostprocessor({
value:
dateStrings[0] +
rangeSeparator +
toDateString(dateToSegments(minMaxLengthClampedToDate), dateModeTemplate),
toDateString(dateToSegments(minMaxLengthClampedToDate), {
dateMode: dateModeTemplate,
}),
};
};
}
23 changes: 13 additions & 10 deletions projects/kit/src/lib/masks/date-time/date-time-mask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
normalizeDatePreprocessor,
} from '../../processors';
import type {MaskitoDateMode, MaskitoTimeMode} from '../../types';
import {DATE_TIME_SEPARATOR, POSSIBLE_DATE_TIME_SEPARATOR} from './constants';
import {DATE_TIME_SEPARATOR} from './constants';
import {createMinMaxDateTimePostprocessor} from './postprocessors';
import {createValidDateTimePreprocessor} from './preprocessors';
import {parseDateTimeString} from './utils';
Expand All @@ -22,12 +22,14 @@ export function maskitoDateTimeOptionsGenerator({
dateSeparator = '.',
min,
max,
dateTimeSeparator = DATE_TIME_SEPARATOR,
}: {
dateMode: MaskitoDateMode;
timeMode: MaskitoTimeMode;
dateSeparator?: string;
max?: Date;
min?: Date;
dateTimeSeparator?: string;
}): Required<MaskitoOptions> {
const dateModeTemplate = dateMode.split('/').join(dateSeparator);

Expand All @@ -37,7 +39,7 @@ export function maskitoDateTimeOptionsGenerator({
...Array.from(dateModeTemplate).map(char =>
char === dateSeparator ? char : /\d/,
),
...DATE_TIME_SEPARATOR.split(''),
...dateTimeSeparator.split(''),
...Array.from(timeMode).map(char =>
TIME_FIXED_CHARACTERS.includes(char) ? char : /\d/,
),
Expand All @@ -49,42 +51,43 @@ export function maskitoDateTimeOptionsGenerator({
createFirstDateEndSeparatorPreprocessor({
dateModeTemplate,
dateSegmentSeparator: dateSeparator,
firstDateEndSeparator: DATE_TIME_SEPARATOR,
pseudoFirstDateEndSeparators: POSSIBLE_DATE_TIME_SEPARATOR,
firstDateEndSeparator: dateTimeSeparator,
pseudoFirstDateEndSeparators: dateTimeSeparator.split(''),
}),
createZeroPlaceholdersPreprocessor(),
normalizeDatePreprocessor({
dateModeTemplate,
dateSegmentsSeparator: dateSeparator,
dateTimeSeparator,
}),
createValidDateTimePreprocessor({
dateModeTemplate,
dateSegmentsSeparator: dateSeparator,
dateTimeSeparator,
}),
],
postprocessors: [
createDateSegmentsZeroPaddingPostprocessor({
dateModeTemplate,
dateSegmentSeparator: dateSeparator,
splitFn: value => {
const [dateString, timeString] = parseDateTimeString(
value,
const [dateString, timeString] = parseDateTimeString(value, {
dateModeTemplate,
);
dateTimeSeparator,
});

return {dateStrings: [dateString], restPart: timeString};
},
uniteFn: ([validatedDateString], initialValue) =>
validatedDateString +
(initialValue.includes(DATE_TIME_SEPARATOR)
? DATE_TIME_SEPARATOR
: ''),
(initialValue.includes(dateTimeSeparator) ? dateTimeSeparator : ''),
}),
createMinMaxDateTimePostprocessor({
min,
max,
dateModeTemplate,
timeMode,
dateTimeSeparator,
}),
],
};
Expand Down
Loading

0 comments on commit ec86284

Please sign in to comment.