diff --git a/projects/cdk/date-time/test/time.spec.ts b/projects/cdk/date-time/test/time.spec.ts
index 007742a7da1e..b3fb25fcca5f 100644
--- a/projects/cdk/date-time/test/time.spec.ts
+++ b/projects/cdk/date-time/test/time.spec.ts
@@ -127,6 +127,35 @@ describe('TuiTime', () => {
expect(time.seconds).toBe(0);
expect(time.ms).toBe(888);
});
+
+ describe('mode with AM / PM', () => {
+ (
+ [
+ ['12:00 AM', {hours: 0, minutes: 0}],
+ ['12:34 AM', {hours: 0, minutes: 34}],
+ ['12:59 AM', {hours: 0, minutes: 59}],
+ ['01:00 AM', {hours: 1, minutes: 0}],
+ ['11:00 AM', {hours: 11, minutes: 0}],
+ ['11:59 AM', {hours: 11, minutes: 59}],
+ ['12:00 PM', {hours: 12, minutes: 0}],
+ ['12:01 PM', {hours: 12, minutes: 1}],
+ ['12:59 PM', {hours: 12, minutes: 59}],
+ ['01:00 PM', {hours: 13, minutes: 0}],
+ ['11:00 PM', {hours: 23, minutes: 0}],
+ ['11:59 PM', {hours: 23, minutes: 59}],
+ ['04:59', {hours: 4, minutes: 59}],
+ ] as const
+ ).forEach(([timeString, {hours, minutes}]) => {
+ it(`from ${timeString}`, () => {
+ const time = TuiTime.fromString(timeString);
+
+ expect(time.hours).toBe(hours);
+ expect(time.minutes).toBe(minutes);
+ expect(time.seconds).toBe(0);
+ expect(time.ms).toBe(0);
+ });
+ });
+ });
});
describe('current', () => {
@@ -334,22 +363,45 @@ describe('TuiTime', () => {
});
});
- it('stringify', () => {
- const time = new TuiTime(6, 36, 1, 1);
+ describe('toString(mode) method', () => {
+ it('without mode parameter', () => {
+ const time = new TuiTime(6, 36, 1, 1);
- expect(time.toString()).toBe('06:36:01.001');
- });
+ expect(time.toString()).toBe('06:36:01.001');
+ });
- it('stringify and fill zeros for seconds', () => {
- const time = new TuiTime(6, 36, 0, 0);
+ it('stringify and fill zeros for seconds', () => {
+ const time = new TuiTime(6, 36, 0, 0);
- expect(time.toString('HH:MM:SS')).toBe('06:36:00');
- });
+ expect(time.toString('HH:MM:SS')).toBe('06:36:00');
+ });
- it('stringify and fill zeros for seconds and ms', () => {
- const time = new TuiTime(6, 36, 0, 0);
+ it('stringify and fill zeros for seconds and ms', () => {
+ const time = new TuiTime(6, 36, 0, 0);
- expect(time.toString('HH:MM:SS.MSS')).toBe('06:36:00.000');
+ expect(time.toString('HH:MM:SS.MSS')).toBe('06:36:00.000');
+ });
+
+ describe('HH:MM AA', () => {
+ (
+ [
+ [new TuiTime(0, 0), '12:00 AM'],
+ [new TuiTime(0, 30), '12:30 AM'],
+ [new TuiTime(0, 59), '12:59 AM'],
+ [new TuiTime(1, 1), '01:01 AM'],
+ [new TuiTime(11, 11), '11:11 AM'],
+ [new TuiTime(11, 59), '11:59 AM'],
+ [new TuiTime(12, 0), '12:00 PM'],
+ [new TuiTime(13, 0), '01:00 PM'],
+ [new TuiTime(16, 0), '04:00 PM'],
+ [new TuiTime(23, 59), '11:59 PM'],
+ ] as const
+ ).forEach(([time, timeString]) => {
+ it(`{hours: ${time.hours}, minutes: ${time.minutes}} => ${timeString}`, () => {
+ expect(time.toString('HH:MM AA')).toBe(timeString);
+ });
+ });
+ });
});
describe('valueOf returns', () => {
diff --git a/projects/cdk/date-time/time.ts b/projects/cdk/date-time/time.ts
index 6637027977d1..d1257674baf2 100644
--- a/projects/cdk/date-time/time.ts
+++ b/projects/cdk/date-time/time.ts
@@ -1,5 +1,6 @@
///
+import {CHAR_NO_BREAK_SPACE} from '@taiga-ui/cdk/constants';
import {tuiInRange} from '@taiga-ui/cdk/utils/math';
import {
@@ -113,7 +114,7 @@ export class TuiTime implements TuiTimeLike {
* Parses string into TuiTime object
*/
public static fromString(time: string): TuiTime {
- const hours = Number(time.slice(0, 2));
+ const hours = this.parseHours(time);
const minutes = Number(time.slice(3, 5)) || 0;
const seconds = Number(time.slice(6, 8)) || 0;
const ms = Number(time.slice(9, 12)) || 0;
@@ -134,6 +135,29 @@ export class TuiTime implements TuiTimeLike {
);
}
+ private static parseMeridiemPeriod(time: string): 'AM' | 'PM' | null {
+ return (
+ (/[AP]M/.exec(time.toUpperCase().replaceAll(/\W/g, ''))?.[0] as
+ | 'AM'
+ | 'PM') || null
+ );
+ }
+
+ private static parseHours(time: string): number {
+ const hours = Number(time.slice(0, 2));
+ const meridiem = this.parseMeridiemPeriod(time);
+
+ if (!meridiem) {
+ return hours;
+ }
+
+ if (hours === 12) {
+ return meridiem === 'AM' ? 0 : 12;
+ }
+
+ return meridiem === 'PM' ? hours + 12 : hours;
+ }
+
/**
* Shifts time by hours and minutes
*/
@@ -165,14 +189,18 @@ export class TuiTime implements TuiTimeLike {
* Converts TuiTime to string
*/
public toString(mode?: TuiTimeMode): string {
- const needAddMs = mode === 'HH:MM:SS.MSS' || (!mode && this.ms > 0);
+ const needAddMs = mode?.startsWith('HH:MM:SS.MSS') || (!mode && this.ms > 0);
const needAddSeconds =
- needAddMs || mode === 'HH:MM:SS' || (!mode && this.seconds > 0);
- const hhMm = `${this.formatTime(this.hours)}:${this.formatTime(this.minutes)}`;
+ needAddMs || mode?.startsWith('HH:MM:SS') || (!mode && this.seconds > 0);
+ const {hours = this.hours, meridiem = ''} = mode?.includes('AA')
+ ? this.toTwelveHour(this.hours)
+ : {};
+ const hhMm = `${this.formatTime(hours)}:${this.formatTime(this.minutes)}`;
const ss = needAddSeconds ? `:${this.formatTime(this.seconds)}` : '';
const mss = needAddMs ? `.${this.formatTime(this.ms, 3)}` : '';
+ const aa = meridiem && `${CHAR_NO_BREAK_SPACE}${meridiem}`;
- return `${hhMm}${ss}${mss}`;
+ return `${hhMm}${ss}${mss}${aa}`;
}
public valueOf(): number {
@@ -203,4 +231,14 @@ export class TuiTime implements TuiTimeLike {
private formatTime(time: number, digits = 2): string {
return String(time).padStart(digits, '0');
}
+
+ private toTwelveHour(hours: number): {hours: number; meridiem: string} {
+ const meridiem = hours >= 12 ? 'PM' : 'AM';
+
+ if (hours === 0 || hours === 12) {
+ return {meridiem, hours: 12};
+ }
+
+ return {meridiem, hours: hours % 12};
+ }
}
diff --git a/projects/cdk/date-time/types.ts b/projects/cdk/date-time/types.ts
index bb17f30ff2b1..6e96f90de78c 100644
--- a/projects/cdk/date-time/types.ts
+++ b/projects/cdk/date-time/types.ts
@@ -4,7 +4,13 @@
* * YMD - yyyy.mm.dd
*/
export type TuiDateMode = 'DMY' | 'MDY' | 'YMD';
-export type TuiTimeMode = 'HH:MM:SS.MSS' | 'HH:MM:SS' | 'HH:MM';
+export type TuiTimeMode =
+ | 'HH:MM AA'
+ | 'HH:MM:SS AA'
+ | 'HH:MM:SS.MSS AA'
+ | 'HH:MM:SS.MSS'
+ | 'HH:MM:SS'
+ | 'HH:MM';
/**
* Optionally has year and/or month and/or day
diff --git a/projects/demo-playwright/tests/legacy/input-date-time/input-date-time.spec.ts b/projects/demo-playwright/tests/legacy/input-date-time/input-date-time.spec.ts
index fe3469f2b4ce..5bc1cc41da16 100644
--- a/projects/demo-playwright/tests/legacy/input-date-time/input-date-time.spec.ts
+++ b/projects/demo-playwright/tests/legacy/input-date-time/input-date-time.spec.ts
@@ -174,13 +174,19 @@ test.describe('InputDateTime', () => {
);
await timeModeSelect.textfield.click();
- await timeModeSelect.selectOptions([1]);
+ await timeModeSelect.selectOptions([2]);
+
+ await expect(timeModeSelect.textfield).toHaveValue('HH:MM:SS');
+
await inputDateTime.textfield.focus();
await expect(inputDateTime.host).toHaveScreenshot('03-timeMode=HH:MM.SS.png');
await timeModeSelect.textfield.click();
- await timeModeSelect.selectOptions([2]);
+ await timeModeSelect.selectOptions([4]);
+
+ await expect(timeModeSelect.textfield).toHaveValue('HH:MM:SS.MSS');
+
await inputDateTime.textfield.focus();
await expect(inputDateTime.host).toHaveScreenshot(
@@ -196,6 +202,27 @@ test.describe('InputDateTime', () => {
await expect(inputDateTime.textfield).toHaveValue('07.06.2024, 23:59:00.000');
});
+
+ test.describe('AM / PM', () => {
+ test.beforeEach(async ({page}) => {
+ await tuiGoto(page, `${DemoRoute.InputDateTime}/API?timeMode=HH:MM%20AA`);
+ await inputDateTime.textfield.pressSequentially('2092020');
+
+ await expect(inputDateTime.textfield).toHaveValue('20.09.2020');
+ });
+
+ test('330a => 03:30 AM', async () => {
+ await inputDateTime.textfield.pressSequentially('330a');
+
+ await expect(inputDateTime.textfield).toHaveValue('20.09.2020, 03:30 AM');
+ });
+
+ test('330p => 03:30 PM', async () => {
+ await inputDateTime.textfield.pressSequentially('330p');
+
+ await expect(inputDateTime.textfield).toHaveValue('20.09.2020, 03:30 PM');
+ });
+ });
});
test.describe('invalid date', () => {
diff --git a/projects/demo-playwright/tests/legacy/input-time/input-time.spec.ts b/projects/demo-playwright/tests/legacy/input-time/input-time.spec.ts
index 28bea16dd3e1..36dd6fffd588 100644
--- a/projects/demo-playwright/tests/legacy/input-time/input-time.spec.ts
+++ b/projects/demo-playwright/tests/legacy/input-time/input-time.spec.ts
@@ -52,9 +52,16 @@ test.describe('InputTime', () => {
inputTime = new TuiInputTimePO(apiPageExample.locator('tui-input-time'));
});
- ['HH:MM', 'HH:MM:SS', 'HH:MM:SS.MSS'].forEach((mode) => {
+ [
+ 'HH:MM',
+ 'HH:MM AA',
+ 'HH:MM:SS',
+ 'HH:MM:SS AA',
+ 'HH:MM:SS.MSS',
+ 'HH:MM:SS.MSS AA',
+ ].forEach((mode) => {
test(`the input is configured for ${mode} mode`, async ({page}) => {
- await tuiGoto(page, `components/input-time/API?mode=${mode}`, {
+ await tuiGoto(page, `${DemoRoute.InputTime}/API?mode=${mode}`, {
date: MOCK_DATE,
});
@@ -82,7 +89,7 @@ test.describe('InputTime', () => {
}) => {
await tuiGoto(
page,
- 'components/input-time/API?disabledItemHandler$=1&items$=1',
+ `${DemoRoute.InputTime}/API?disabledItemHandler$=1&items$=1`,
{
date: MOCK_DATE,
},
@@ -100,7 +107,7 @@ test.describe('InputTime', () => {
test(`the dropdown is configured for ${size} size`, async ({page}) => {
await tuiGoto(
page,
- `components/input-time/API?items$=1&itemSize=${size}`,
+ `${DemoRoute.InputTime}/API?items$=1&itemSize=${size}`,
{
date: MOCK_DATE,
},
@@ -130,61 +137,125 @@ test.describe('InputTime', () => {
});
test.describe('Basic typing from keyboard', () => {
- test.beforeEach(async ({page}) => {
- await tuiGoto(page, `${DemoRoute.InputTime}/API?mode=HH:MM`);
- await inputTime.textfield.clear();
+ test.describe('HH:MM', () => {
+ test.beforeEach(async ({page}) => {
+ await tuiGoto(page, `${DemoRoute.InputTime}/API?mode=HH:MM`);
+ await inputTime.textfield.clear();
- await expect(inputTime.textfield).toHaveValue('');
- });
+ await expect(inputTime.textfield).toHaveValue('');
+ });
- test('3 => 03', async () => {
- await inputTime.textfield.pressSequentially('3');
+ test('3 => 03', async () => {
+ await inputTime.textfield.pressSequentially('3');
- await expect(inputTime.textfield).toHaveValue('03');
- await expect(inputTime.textfield).toHaveJSProperty('selectionStart', 2);
- await expect(inputTime.textfield).toHaveJSProperty('selectionEnd', 2);
- });
+ await expect(inputTime.textfield).toHaveValue('03');
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionStart',
+ 2,
+ );
+ await expect(inputTime.textfield).toHaveJSProperty('selectionEnd', 2);
+ });
- test('1111 => 11:11', async () => {
- await inputTime.textfield.pressSequentially('1111');
+ test('1111 => 11:11', async () => {
+ await inputTime.textfield.pressSequentially('1111');
- await expect(inputTime.textfield).toHaveValue('11:11');
- await expect(inputTime.textfield).toHaveJSProperty(
- 'selectionStart',
- '11:11'.length,
- );
- await expect(inputTime.textfield).toHaveJSProperty(
- 'selectionEnd',
- '11:11'.length,
- );
- });
+ await expect(inputTime.textfield).toHaveValue('11:11');
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionStart',
+ '11:11'.length,
+ );
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionEnd',
+ '11:11'.length,
+ );
+ });
- test('0130 => 01:30', async () => {
- await inputTime.textfield.pressSequentially('0130');
+ test('0130 => 01:30', async () => {
+ await inputTime.textfield.pressSequentially('0130');
- await expect(inputTime.textfield).toHaveValue('01:30');
- await expect(inputTime.textfield).toHaveJSProperty(
- 'selectionStart',
- '01:30'.length,
- );
- await expect(inputTime.textfield).toHaveJSProperty(
- 'selectionEnd',
- '01:30'.length,
- );
+ await expect(inputTime.textfield).toHaveValue('01:30');
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionStart',
+ '01:30'.length,
+ );
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionEnd',
+ '01:30'.length,
+ );
+ });
+
+ test('99 => 09:09', async () => {
+ await inputTime.textfield.pressSequentially('99');
+
+ await expect(inputTime.textfield).toHaveValue('09:09');
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionStart',
+ '09:09'.length,
+ );
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionEnd',
+ '09:09'.length,
+ );
+ });
});
- test('99 => 09:09', async () => {
- await inputTime.textfield.pressSequentially('99');
+ test.describe('HH:MM AA', () => {
+ test.beforeEach(async ({page}) => {
+ await tuiGoto(page, `${DemoRoute.InputTime}/API?mode=HH:MM%20AA`);
+ await inputTime.textfield.clear();
- await expect(inputTime.textfield).toHaveValue('09:09');
- await expect(inputTime.textfield).toHaveJSProperty(
- 'selectionStart',
- '09:09'.length,
- );
- await expect(inputTime.textfield).toHaveJSProperty(
- 'selectionEnd',
- '09:09'.length,
- );
+ await expect(inputTime.textfield).toHaveValue('');
+ });
+
+ test('2 => 02', async () => {
+ await inputTime.textfield.pressSequentially('2');
+
+ await expect(inputTime.textfield).toHaveValue('02');
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionStart',
+ 2,
+ );
+ await expect(inputTime.textfield).toHaveJSProperty('selectionEnd', 2);
+ });
+
+ test('333a => 03:33 AM', async () => {
+ await inputTime.textfield.pressSequentially('333a');
+
+ await expect(inputTime.textfield).toHaveValue('03:33 AM');
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionStart',
+ '03:33 AM'.length,
+ );
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionEnd',
+ '03:33 AM'.length,
+ );
+ });
+
+ test('00 => 0', async () => {
+ await inputTime.textfield.pressSequentially('00');
+
+ await expect(inputTime.textfield).toHaveValue('0');
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionStart',
+ 1,
+ );
+ await expect(inputTime.textfield).toHaveJSProperty('selectionEnd', 1);
+ });
+
+ test('1234p => 12:34 PM', async () => {
+ await inputTime.textfield.pressSequentially('1234p');
+
+ await expect(inputTime.textfield).toHaveValue('12:34 PM');
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionStart',
+ '12:34 PM'.length,
+ );
+ await expect(inputTime.textfield).toHaveJSProperty(
+ 'selectionEnd',
+ '12:34 PM'.length,
+ );
+ });
});
});
@@ -204,7 +275,7 @@ test.describe('InputTime', () => {
test.describe('HH:MM', () => {
test.beforeEach(async ({page}) => {
- await tuiGoto(page, 'components/input-time/API?mode=HH:MM');
+ await tuiGoto(page, `${DemoRoute.InputTime}/API?mode=HH:MM`);
});
check('1', '01:00');
@@ -215,9 +286,20 @@ test.describe('InputTime', () => {
check('12:34', '12:34');
});
+ test.describe('HH:MM AA', () => {
+ test.beforeEach(async ({page}) => {
+ await tuiGoto(page, `${DemoRoute.InputTime}/API?mode=HH:MM%20AA`);
+ });
+
+ check('0', '12:00 AM');
+ check('01', '01:00 AM');
+ check('012', '01:02 AM');
+ check('0123', '01:23 AM');
+ });
+
test.describe('HH:MM:SS', () => {
test.beforeEach(async ({page}) => {
- await tuiGoto(page, 'components/input-time/API?mode=HH:MM:SS');
+ await tuiGoto(page, `${DemoRoute.InputTime}/API?mode=HH:MM:SS`);
});
check('1', '01:00:00');
@@ -233,7 +315,7 @@ test.describe('InputTime', () => {
test.describe('HH:MM:SS.MSS', () => {
test.beforeEach(async ({page}) => {
- await tuiGoto(page, 'components/input-time/API?mode=HH:MM:SS.MSS');
+ await tuiGoto(page, `${DemoRoute.InputTime}/API?mode=HH:MM:SS.MSS`);
});
check('1', '01:00:00.000');
diff --git a/projects/demo/src/modules/app/app.const.ts b/projects/demo/src/modules/app/app.const.ts
index da4aff85dc08..25cc5be60210 100644
--- a/projects/demo/src/modules/app/app.const.ts
+++ b/projects/demo/src/modules/app/app.const.ts
@@ -36,6 +36,7 @@ export const DEFAULT_LANGUAGE_PAGE = new Set([
'InputCardGroup',
'InputFiles',
'InputPhoneInternational',
+ 'InputTime',
'MobileCalendar',
'Table',
'TablePagination',
diff --git a/projects/demo/src/modules/components/input-date-time/examples/6/index.html b/projects/demo/src/modules/components/input-date-time/examples/6/index.html
new file mode 100644
index 000000000000..fd8d6852f267
--- /dev/null
+++ b/projects/demo/src/modules/components/input-date-time/examples/6/index.html
@@ -0,0 +1,9 @@
+
+ Enter 12-hour time format
+
+
+
Control value:
+{{ control.value | json }}
diff --git a/projects/demo/src/modules/components/input-date-time/examples/6/index.ts b/projects/demo/src/modules/components/input-date-time/examples/6/index.ts
new file mode 100644
index 000000000000..de4cc59900e6
--- /dev/null
+++ b/projects/demo/src/modules/components/input-date-time/examples/6/index.ts
@@ -0,0 +1,21 @@
+import {JsonPipe} from '@angular/common';
+import {Component} from '@angular/core';
+import {FormControl, ReactiveFormsModule} from '@angular/forms';
+import {changeDetection} from '@demo/emulate/change-detection';
+import {encapsulation} from '@demo/emulate/encapsulation';
+import {TuiDay, TuiTime} from '@taiga-ui/cdk';
+import {TuiInputDateTimeModule} from '@taiga-ui/legacy';
+
+@Component({
+ standalone: true,
+ imports: [JsonPipe, ReactiveFormsModule, TuiInputDateTimeModule],
+ templateUrl: './index.html',
+ encapsulation,
+ changeDetection,
+})
+export default class Example {
+ protected readonly control = new FormControl([
+ new TuiDay(2020, 8, 20),
+ new TuiTime(15, 30),
+ ] as const);
+}
diff --git a/projects/demo/src/modules/components/input-date-time/index.html b/projects/demo/src/modules/components/input-date-time/index.html
index 3d4024ba6cfd..bce43fee055c 100644
--- a/projects/demo/src/modules/components/input-date-time/index.html
+++ b/projects/demo/src/modules/components/input-date-time/index.html
@@ -99,6 +99,22 @@ DI-tokens for input-configurations:
Please note that native input datetime only supports HH:MM time mode
+
+
+
+ Any
+ timeMode
+ ending with
+ AA
+ is 12-hour time format with meridiem part
+
+
diff --git a/projects/demo/src/modules/components/input-date-time/index.ts b/projects/demo/src/modules/components/input-date-time/index.ts
index d1e63e051723..7ca5aebc57bb 100644
--- a/projects/demo/src/modules/components/input-date-time/index.ts
+++ b/projects/demo/src/modules/components/input-date-time/index.ts
@@ -84,13 +84,16 @@ export default class PageComponent extends AbstractExampleTuiControl {
protected items = this.itemsVariants[0]!;
- protected readonly modeVariants: readonly TuiTimeMode[] = [
+ protected readonly modeVariants = [
'HH:MM',
+ 'HH:MM AA',
'HH:MM:SS',
+ 'HH:MM:SS AA',
'HH:MM:SS.MSS',
- ];
+ 'HH:MM:SS.MSS AA',
+ ] as const satisfies readonly TuiTimeMode[];
- protected mode = this.modeVariants[0]!;
+ protected mode: TuiTimeMode = this.modeVariants[0];
public override cleaner = false;
diff --git a/projects/demo/src/modules/components/input-time/examples/5/index.html b/projects/demo/src/modules/components/input-time/examples/5/index.html
index 1fa28f6d5bd5..d511f60f1dee 100644
--- a/projects/demo/src/modules/components/input-time/examples/5/index.html
+++ b/projects/demo/src/modules/components/input-time/examples/5/index.html
@@ -1,15 +1,9 @@
-
+
+ Enter 12-hour time format
+
+
+Control value:
+{{ control.value | json }}
diff --git a/projects/demo/src/modules/components/input-time/examples/5/index.ts b/projects/demo/src/modules/components/input-time/examples/5/index.ts
index 3d4d7fe9f074..3ef640691dba 100644
--- a/projects/demo/src/modules/components/input-time/examples/5/index.ts
+++ b/projects/demo/src/modules/components/input-time/examples/5/index.ts
@@ -1,40 +1,18 @@
+import {JsonPipe} from '@angular/common';
import {Component} from '@angular/core';
-import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms';
+import {FormControl, ReactiveFormsModule} from '@angular/forms';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
-import type {TuiTime} from '@taiga-ui/cdk';
-import {TuiSwitch} from '@taiga-ui/kit';
-import {
- TuiInputTimeModule,
- tuiInputTimeOptionsProvider,
- TuiTextfieldControllerModule,
-} from '@taiga-ui/legacy';
+import {TuiTime} from '@taiga-ui/cdk';
+import {TuiInputTimeModule} from '@taiga-ui/legacy';
@Component({
standalone: true,
- imports: [
- ReactiveFormsModule,
- TuiInputTimeModule,
- TuiSwitch,
- TuiTextfieldControllerModule,
- ],
+ imports: [JsonPipe, ReactiveFormsModule, TuiInputTimeModule],
templateUrl: './index.html',
encapsulation,
changeDetection,
- providers: [
- tuiInputTimeOptionsProvider({
- mode: 'HH:MM',
- maxValues: {HH: 11, MM: 59, SS: 59, MS: 999},
- }),
- ],
})
export default class Example {
- protected readonly testForm = new FormGroup({
- testValue: new FormControl(null),
- isPm: new FormControl(false),
- });
-
- protected get postfix(): string {
- return this.testForm.value?.isPm ? 'PM' : 'AM';
- }
+ protected readonly control = new FormControl(new TuiTime(17, 0));
}
diff --git a/projects/demo/src/modules/components/input-time/index.html b/projects/demo/src/modules/components/input-time/index.html
index 01af37a33ab9..9609b9be4da8 100644
--- a/projects/demo/src/modules/components/input-time/index.html
+++ b/projects/demo/src/modules/components/input-time/index.html
@@ -61,11 +61,20 @@ DI-tokens for input-configurations:
/>
+ [description]="amPmDescription"
+ >
+
+ Any
+ mode
+ ending with
+ AA
+ is 12-hour time format with meridiem part
+
+
texts[mode]));
}
- protected onClick(): void {
- this.open = !this.open;
- }
-
protected onFocused(focused: boolean): void {
this.updateFocused(focused);
@@ -246,8 +242,9 @@ export class TuiInputTimeComponent
return maskitoTimeOptionsGenerator({
mode,
step: readOnly ? 0 : 1,
+ // TODO(v5): timeSegmentMaxValues: this.options.timeSegmentMaxValues
timeSegmentMaxValues: {
- hours: HH,
+ hours: mode.includes('AA') ? 12 : HH,
minutes: MM,
seconds: SS,
milliseconds: MS,
@@ -278,14 +275,10 @@ export class TuiInputTimeComponent
return this.items.find((item) => TUI_STRICT_MATCHER(item, value));
}
- private close(): void {
- this.open = false;
- }
-
private focusInput(preventScroll = false): void {
if (this.nativeFocusableElement) {
this.nativeFocusableElement.focus({preventScroll});
- this.close();
+ this.open = false;
}
}
}
diff --git a/projects/legacy/components/input-time/input-time.options.ts b/projects/legacy/components/input-time/input-time.options.ts
index 6c5ffef201b7..faadd4829e52 100644
--- a/projects/legacy/components/input-time/input-time.options.ts
+++ b/projects/legacy/components/input-time/input-time.options.ts
@@ -8,13 +8,16 @@ import type {PolymorpheusContent} from '@taiga-ui/polymorpheus';
export interface TuiInputTimeOptions {
readonly icon: PolymorpheusContent>;
readonly itemSize: TuiSizeL | TuiSizeS;
+ // TODO(v5): timeSegmentMaxValues: Partial>
readonly maxValues: Record;
readonly mode: TuiTimeMode;
readonly nativePicker?: boolean;
}
+// TODO(v5): delete it
export type TuiTimeFormatParts = 'HH' | 'MM' | 'MS' | 'SS';
+// TODO(v5): delete it
export const MAX_TIME_VALUES: Record = {
HH: 23,
MM: 59,
@@ -25,7 +28,7 @@ export const MAX_TIME_VALUES: Record = {
export const TUI_INPUT_TIME_DEFAULT_OPTIONS: TuiInputTimeOptions = {
icon: () => '@tui.clock',
mode: 'HH:MM',
- maxValues: MAX_TIME_VALUES,
+ maxValues: MAX_TIME_VALUES, // TODO(v5): use empty object
itemSize: 'm',
nativePicker: false,
};