@tacdaed/fragments 1.0.0-beta.3 → 1.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/ng-package.json +20 -0
- package/package.json +22 -29
- package/src/lib/components/accordion/accordion.component.html +103 -0
- package/src/lib/components/accordion/accordion.component.scss +382 -0
- package/src/lib/components/accordion/accordion.component.spec.ts +147 -0
- package/src/lib/components/accordion/accordion.component.ts +211 -0
- package/src/lib/components/accordion/accordion.type.ts +82 -0
- package/src/lib/components/breadcrumb/breadcrumb.component.html +43 -0
- package/src/lib/components/breadcrumb/breadcrumb.component.scss +112 -0
- package/src/lib/components/breadcrumb/breadcrumb.component.spec.ts +33 -0
- package/src/lib/components/breadcrumb/breadcrumb.component.ts +103 -0
- package/src/lib/components/breadcrumb/breadcrumb.interface.ts +7 -0
- package/src/lib/components/button/button.component.html +57 -0
- package/src/lib/components/button/button.component.scss +445 -0
- package/src/lib/components/button/button.component.spec.ts +99 -0
- package/src/lib/components/button/button.component.ts +143 -0
- package/src/lib/components/button/button.type.ts +7 -0
- package/src/lib/components/card/card.component.html +44 -0
- package/src/lib/components/card/card.component.scss +114 -0
- package/src/lib/components/card/card.component.spec.ts +65 -0
- package/src/lib/components/card/card.component.ts +21 -0
- package/src/lib/components/card/card.type.ts +3 -0
- package/src/lib/components/code-block/code-block.component.html +55 -0
- package/src/lib/components/code-block/code-block.component.scss +122 -0
- package/src/lib/components/code-block/code-block.component.spec.ts +81 -0
- package/src/lib/components/code-block/code-block.component.ts +302 -0
- package/src/lib/components/code-block/code-block.interface.ts +28 -0
- package/src/lib/components/code-block/code-block.type.ts +73 -0
- package/src/lib/components/decorative/sparkle-field/sparkle-field.component.html +14 -0
- package/src/lib/components/decorative/sparkle-field/sparkle-field.component.scss +20 -0
- package/src/lib/components/decorative/sparkle-field/sparkle-field.component.spec.ts +38 -0
- package/src/lib/components/decorative/sparkle-field/sparkle-field.component.ts +181 -0
- package/src/lib/components/input/input-base.ts +187 -0
- package/src/lib/components/input/input-calendar/input-calendar.component.html +76 -0
- package/src/lib/components/input/input-calendar/input-calendar.component.scss +179 -0
- package/src/lib/components/input/input-calendar/input-calendar.component.spec.ts +44 -0
- package/src/lib/components/input/input-calendar/input-calendar.component.ts +299 -0
- package/src/lib/components/input/input-checkbox/input-checkbox.component.html +37 -0
- package/src/lib/components/input/input-checkbox/input-checkbox.component.scss +128 -0
- package/src/lib/components/input/input-checkbox/input-checkbox.component.spec.ts +43 -0
- package/src/lib/components/input/input-checkbox/input-checkbox.component.ts +112 -0
- package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.html +43 -0
- package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.scss +140 -0
- package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.spec.ts +62 -0
- package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.ts +136 -0
- package/src/lib/components/input/input-clock-picker/input-clock-picker.component.html +81 -0
- package/src/lib/components/input/input-clock-picker/input-clock-picker.component.scss +228 -0
- package/src/lib/components/input/input-clock-picker/input-clock-picker.component.spec.ts +62 -0
- package/src/lib/components/input/input-clock-picker/input-clock-picker.component.ts +178 -0
- package/src/lib/components/input/input-consts.ts +132 -0
- package/src/lib/components/input/input-date/input-date-validators.ts +41 -0
- package/src/lib/components/input/input-date/input-date.component.html +41 -0
- package/src/lib/components/input/input-date/input-date.component.scss +95 -0
- package/src/lib/components/input/input-date/input-date.component.spec.ts +43 -0
- package/src/lib/components/input/input-date/input-date.component.ts +359 -0
- package/src/lib/components/input/input-date-time/input-date-time.component.html +70 -0
- package/src/lib/components/input/input-date-time/input-date-time.component.scss +133 -0
- package/src/lib/components/input/input-date-time/input-date-time.component.spec.ts +36 -0
- package/src/lib/components/input/input-date-time/input-date-time.component.ts +387 -0
- package/src/lib/components/input/input-file-upload/input-file-upload.component.html +89 -0
- package/src/lib/components/input/input-file-upload/input-file-upload.component.scss +171 -0
- package/src/lib/components/input/input-file-upload/input-file-upload.component.spec.ts +43 -0
- package/src/lib/components/input/input-file-upload/input-file-upload.component.ts +351 -0
- package/src/lib/components/input/input-interface.ts +8 -0
- package/src/lib/components/input/input-number/input-number-validators.ts +0 -0
- package/src/lib/components/input/input-number/input-number.component.html +51 -0
- package/src/lib/components/input/input-number/input-number.component.scss +140 -0
- package/src/lib/components/input/input-number/input-number.component.spec.ts +44 -0
- package/src/lib/components/input/input-number/input-number.component.ts +343 -0
- package/src/lib/components/input/input-radio-group/input-radio-group.component.html +44 -0
- package/src/lib/components/input/input-radio-group/input-radio-group.component.scss +139 -0
- package/src/lib/components/input/input-radio-group/input-radio-group.component.spec.ts +58 -0
- package/src/lib/components/input/input-radio-group/input-radio-group.component.ts +132 -0
- package/src/lib/components/input/input-slider/input-slider.component.html +111 -0
- package/src/lib/components/input/input-slider/input-slider.component.scss +203 -0
- package/src/lib/components/input/input-slider/input-slider.component.spec.ts +46 -0
- package/src/lib/components/input/input-slider/input-slider.component.ts +410 -0
- package/src/lib/components/input/input-text/input-text-validators.ts +67 -0
- package/src/lib/components/input/input-text/input-text.component.html +71 -0
- package/src/lib/components/input/input-text/input-text.component.scss +118 -0
- package/src/lib/components/input/input-text/input-text.component.spec.ts +55 -0
- package/src/lib/components/input/input-text/input-text.component.ts +215 -0
- package/src/lib/components/input/input-time/input-time-validators.ts +42 -0
- package/src/lib/components/input/input-time/input-time.component.html +92 -0
- package/src/lib/components/input/input-time/input-time.component.scss +191 -0
- package/src/lib/components/input/input-time/input-time.component.spec.ts +39 -0
- package/src/lib/components/input/input-time/input-time.component.ts +691 -0
- package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.html +36 -0
- package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.scss +121 -0
- package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.spec.ts +54 -0
- package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.ts +117 -0
- package/src/lib/components/input/input-type.ts +18 -0
- package/src/lib/components/input/input-validation/input-validation.component.html +19 -0
- package/src/lib/components/input/input-validation/input-validation.component.scss +39 -0
- package/src/lib/components/input/input-validation/input-validation.component.spec.ts +45 -0
- package/src/lib/components/input/input-validation/input-validation.component.ts +13 -0
- package/src/lib/components/input/input.pipe.ts +14 -0
- package/src/lib/components/layout/container/container.component.html +1 -0
- package/src/lib/components/layout/container/container.component.scss +33 -0
- package/src/lib/components/layout/container/container.component.ts +32 -0
- package/src/lib/components/layout/container/container.type.ts +1 -0
- package/src/lib/components/layout/divider/divider.component.html +1 -0
- package/src/lib/components/layout/divider/divider.component.scss +60 -0
- package/src/lib/components/layout/divider/divider.component.ts +38 -0
- package/src/lib/components/layout/divider/divider.type.ts +2 -0
- package/src/lib/components/layout/section/section.component.html +21 -0
- package/src/lib/components/layout/section/section.component.scss +43 -0
- package/src/lib/components/layout/section/section.component.ts +33 -0
- package/src/lib/components/layout/section/section.type.ts +2 -0
- package/src/lib/components/layout/separator/separator.component.html +9 -0
- package/src/lib/components/layout/separator/separator.component.scss +52 -0
- package/src/lib/components/layout/separator/separator.component.ts +25 -0
- package/src/lib/components/layout/separator/separator.type.ts +1 -0
- package/src/lib/components/loader/content-blur/content-blur.component.html +13 -0
- package/src/lib/components/loader/content-blur/content-blur.component.scss +43 -0
- package/src/lib/components/loader/content-blur/content-blur.component.spec.ts +42 -0
- package/src/lib/components/loader/content-blur/content-blur.component.ts +34 -0
- package/src/lib/components/loader/loader.type.ts +2 -0
- package/src/lib/components/loader/progress-bar/progress-bar.component.html +26 -0
- package/src/lib/components/loader/progress-bar/progress-bar.component.scss +151 -0
- package/src/lib/components/loader/progress-bar/progress-bar.component.spec.ts +47 -0
- package/src/lib/components/loader/progress-bar/progress-bar.component.ts +28 -0
- package/src/lib/components/loader/progress-bar/progress-bar.type.ts +8 -0
- package/src/lib/components/loader/pulse-loader/pulse-loader.component.html +12 -0
- package/src/lib/components/loader/pulse-loader/pulse-loader.component.scss +202 -0
- package/src/lib/components/loader/pulse-loader/pulse-loader.component.spec.ts +55 -0
- package/src/lib/components/loader/pulse-loader/pulse-loader.component.ts +73 -0
- package/src/lib/components/loader/pulse-loader/pulse-loader.type.ts +6 -0
- package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.html +13 -0
- package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.scss +113 -0
- package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.spec.ts +37 -0
- package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.ts +51 -0
- package/src/lib/components/loader/skeleton-loader/skeleton-loader.type.ts +6 -0
- package/src/lib/components/loader/spinner/spinner.component.html +20 -0
- package/src/lib/components/loader/spinner/spinner.component.scss +137 -0
- package/src/lib/components/loader/spinner/spinner.component.spec.ts +43 -0
- package/src/lib/components/loader/spinner/spinner.component.ts +32 -0
- package/src/lib/components/loader/spinner/spinner.type.ts +6 -0
- package/src/lib/components/modal/modal.component.html +47 -0
- package/src/lib/components/modal/modal.component.scss +139 -0
- package/src/lib/components/modal/modal.component.spec.ts +60 -0
- package/src/lib/components/modal/modal.component.ts +83 -0
- package/src/lib/components/modal/modal.type.ts +9 -0
- package/src/lib/components/morph/blob-moph/blob-moprh.component.spec.ts +79 -0
- package/src/lib/components/morph/blob-moph/blob-moprh.component.ts +96 -0
- package/src/lib/components/morph/blob-moph/blob-morph.component.html +34 -0
- package/src/lib/components/morph/blob-moph/blob-morph.component.scss +7 -0
- package/src/lib/components/morph/morph.abstract.ts +13 -0
- package/src/lib/components/pagination/pagination.interface.ts +4 -0
- package/src/lib/components/pagination/small-pagination/small-pagination.component.html +61 -0
- package/src/lib/components/pagination/small-pagination/small-pagination.component.scss +187 -0
- package/src/lib/components/pagination/small-pagination/small-pagination.component.spec.ts +88 -0
- package/src/lib/components/pagination/small-pagination/small-pagination.component.ts +177 -0
- package/src/lib/components/selection-lists/multi-select/multi-select.component.html +170 -0
- package/src/lib/components/selection-lists/multi-select/multi-select.component.scss +312 -0
- package/src/lib/components/selection-lists/multi-select/multi-select.component.spec.ts +61 -0
- package/src/lib/components/selection-lists/multi-select/multi-select.component.ts +372 -0
- package/src/lib/components/selection-lists/selection-list/selection-list.component.html +125 -0
- package/src/lib/components/selection-lists/selection-list/selection-list.component.scss +267 -0
- package/src/lib/components/selection-lists/selection-list/selection-list.component.spec.ts +66 -0
- package/src/lib/components/selection-lists/selection-list/selection-list.component.ts +315 -0
- package/src/lib/components/selection-lists/selection-lists-base.ts +35 -0
- package/src/lib/components/selection-lists/selection-lists-const.ts +17 -0
- package/src/lib/components/selection-lists/selection-lists-interface.ts +7 -0
- package/src/lib/components/selection-lists/selection-lists.type.ts +1 -0
- package/src/lib/components/side-nav/side-nav.component.html +101 -0
- package/src/lib/components/side-nav/side-nav.component.scss +295 -0
- package/src/lib/components/side-nav/side-nav.component.spec.ts +0 -0
- package/src/lib/components/side-nav/side-nav.component.ts +18 -0
- package/src/lib/components/side-nav/side-nav.type.ts +28 -0
- package/src/lib/components/snackbar/snackbar.component.html +33 -0
- package/src/lib/components/snackbar/snackbar.component.scss +195 -0
- package/src/lib/components/snackbar/snackbar.component.ts +112 -0
- package/src/lib/components/snackbar/snackbar.type.ts +27 -0
- package/src/lib/components/status/chip/chip.component.html +51 -0
- package/src/lib/components/status/chip/chip.component.scss +149 -0
- package/src/lib/components/status/chip/chip.component.spec.ts +62 -0
- package/src/lib/components/status/chip/chip.component.ts +83 -0
- package/src/lib/components/status/chip/chip.type.ts +42 -0
- package/src/lib/components/status/directives/badge/badge.directive.spec.ts +60 -0
- package/src/lib/components/status/directives/badge/badge.directive.ts +190 -0
- package/src/lib/components/status/directives/badge/badge.interface.ts +19 -0
- package/src/lib/components/status/pill/pill.component.html +40 -0
- package/src/lib/components/status/pill/pill.component.scss +113 -0
- package/src/lib/components/status/pill/pill.component.spec.ts +47 -0
- package/src/lib/components/status/pill/pill.component.ts +83 -0
- package/src/lib/components/status/pill/pill.type.ts +42 -0
- package/src/lib/components/status/status.interface.ts +57 -0
- package/src/lib/components/status/status.type.ts +62 -0
- package/src/lib/components/status/tag/tag.component.html +39 -0
- package/src/lib/components/status/tag/tag.component.scss +140 -0
- package/src/lib/components/status/tag/tag.component.spec.ts +47 -0
- package/src/lib/components/status/tag/tag.component.ts +83 -0
- package/src/lib/components/status/tag/tag.type.ts +42 -0
- package/src/lib/components/stepper/stepper.component.html +83 -0
- package/src/lib/components/stepper/stepper.component.scss +196 -0
- package/src/lib/components/stepper/stepper.component.ts +482 -0
- package/src/lib/components/stepper/stepper.type.ts +60 -0
- package/src/lib/components/table/table.component.html +438 -0
- package/src/lib/components/table/table.component.scss +259 -0
- package/src/lib/components/table/table.component.spec.ts +117 -0
- package/src/lib/components/table/table.component.ts +215 -0
- package/src/lib/components/table/table.enum.ts +4 -0
- package/src/lib/components/table/table.function.ts +47 -0
- package/src/lib/components/table/table.interface.ts +143 -0
- package/src/lib/components/table/table.pipe.ts +62 -0
- package/src/lib/components/table/table.type.ts +15 -0
- package/src/lib/components/tabs/tabs.component.html +88 -0
- package/src/lib/components/tabs/tabs.component.scss +305 -0
- package/src/lib/components/tabs/tabs.component.spec.ts +94 -0
- package/src/lib/components/tabs/tabs.component.ts +282 -0
- package/src/lib/components/tabs/tabs.type.ts +81 -0
- package/src/lib/components/title-bar/title-bar.component.html +21 -0
- package/src/lib/components/title-bar/title-bar.component.scss +139 -0
- package/src/lib/components/title-bar/title-bar.component.spec.ts +44 -0
- package/src/lib/components/title-bar/title-bar.component.ts +13 -0
- package/src/lib/components/toast/toast.component.html +36 -0
- package/src/lib/components/toast/toast.component.scss +241 -0
- package/src/lib/components/toast/toast.component.ts +165 -0
- package/src/lib/components/toast/toast.type.ts +37 -0
- package/src/lib/components/toast-stack/toast-stack.component.html +30 -0
- package/src/lib/components/toast-stack/toast-stack.component.scss +35 -0
- package/src/lib/components/toast-stack/toast-stack.component.ts +51 -0
- package/src/lib/consts/country-prefix.ts +244 -0
- package/src/lib/directives/tooltip/popover.directive.ts +274 -0
- package/src/lib/directives/tooltip/tooltip.directive.spec.ts +86 -0
- package/src/lib/directives/tooltip/tooltip.directive.ts +234 -0
- package/src/lib/directives/tooltip/tooltip.interface.ts +29 -0
- package/src/lib/directives/tooltip/tooltip.type.ts +9 -0
- package/src/lib/interfaces/common.interfaces.ts +4 -0
- package/src/lib/pipes/chunk.pipe.ts +16 -0
- package/src/lib/pipes/safe-html.pipe.ts +14 -0
- package/src/lib/pipes/sanitize-html.pipe.ts +23 -0
- package/src/lib/types/base.types.ts +23 -0
- package/src/lib/types/common.types.ts +98 -0
- package/src/lib/types/form.types.ts +5 -0
- package/src/lib/utils/common.utils.ts +53 -0
- package/src/lib/utils/date.utils.ts +474 -0
- package/src/lib/utils/number.utils.ts +16 -0
- package/src/lib/utils/uuid.utils.ts +39 -0
- package/src/public-api.ts +114 -0
- package/tsconfig.lib.json +17 -0
- package/tsconfig.lib.prod.json +10 -0
- package/tsconfig.spec.json +9 -0
- package/fesm2022/tacdaed-fragments.mjs +0 -8928
- package/fesm2022/tacdaed-fragments.mjs.map +0 -1
- package/index.d.ts +0 -3929
|
@@ -0,0 +1,691 @@
|
|
|
1
|
+
import { NgClass, NgTemplateOutlet } from '@angular/common';
|
|
2
|
+
import { Component, Input } from '@angular/core';
|
|
3
|
+
import { Validators } from '@angular/forms';
|
|
4
|
+
import { TimeFormat } from '../../../types/common.types';
|
|
5
|
+
import { buildTimeFormatRegex, convertStringToTime, formatTimeToString } from '../../../utils/date.utils';
|
|
6
|
+
import { InputBase } from '../input-base';
|
|
7
|
+
import { DEFAULT_INPUT_TIME_ERROR_MESSAGES, DEFAULT_INPUT_TIME_WARNINGS_MESSAGES } from '../input-consts';
|
|
8
|
+
import { InputTimeMeridiem, InputTimePartial, InputTimeType } from '../input-type';
|
|
9
|
+
import { InputValidationComponent } from '../input-validation/input-validation.component';
|
|
10
|
+
import { InputRequiredLabelPipe } from '../input.pipe';
|
|
11
|
+
import { maxTime, minTime } from './input-time-validators';
|
|
12
|
+
import { InputTimeParts } from '../input-interface';
|
|
13
|
+
|
|
14
|
+
@Component({
|
|
15
|
+
selector: 'frg-input-time',
|
|
16
|
+
imports: [InputRequiredLabelPipe, InputValidationComponent, NgClass, NgTemplateOutlet],
|
|
17
|
+
templateUrl: './input-time.component.html',
|
|
18
|
+
styleUrl: './input-time.component.scss',
|
|
19
|
+
})
|
|
20
|
+
export class InputTimeComponent extends InputBase<string> {
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @inheritdoc
|
|
24
|
+
*/
|
|
25
|
+
@Input() public override label: string = '';
|
|
26
|
+
/**
|
|
27
|
+
* @inheritdoc
|
|
28
|
+
*/
|
|
29
|
+
@Input() public override placeholder: string = '';
|
|
30
|
+
/**
|
|
31
|
+
* @inheritdoc
|
|
32
|
+
*/
|
|
33
|
+
@Input() public override required: boolean = false;
|
|
34
|
+
/**
|
|
35
|
+
* @inheritdoc
|
|
36
|
+
*/
|
|
37
|
+
@Input() public override showValidation: boolean = true;
|
|
38
|
+
/**
|
|
39
|
+
* @inheritdoc
|
|
40
|
+
*/
|
|
41
|
+
@Input() public override errorMessages: Record<string, string> = {};
|
|
42
|
+
/**
|
|
43
|
+
* The type of the input element.
|
|
44
|
+
* Can be 'text', 'password', 'email', 'tel', etc.
|
|
45
|
+
* Defaults to 'text'.
|
|
46
|
+
*
|
|
47
|
+
* @see InputTextType
|
|
48
|
+
*/
|
|
49
|
+
@Input() public type: InputTimeType = 'time';
|
|
50
|
+
/**
|
|
51
|
+
* Minimum year selectable in the calendar
|
|
52
|
+
*/
|
|
53
|
+
@Input() public minTime: string = '00:00:00';
|
|
54
|
+
/**
|
|
55
|
+
* Maximum year selectable in the calendar
|
|
56
|
+
*/
|
|
57
|
+
@Input() public maxTime: string = '23:59:59';
|
|
58
|
+
/**
|
|
59
|
+
* The format of time
|
|
60
|
+
*/
|
|
61
|
+
@Input() public format: TimeFormat = 'HH:mm';
|
|
62
|
+
/**
|
|
63
|
+
* Enables strict mode for email validation.
|
|
64
|
+
* When set to true, the email validator will use a more stringent pattern.
|
|
65
|
+
* Defaults to false.
|
|
66
|
+
*/
|
|
67
|
+
@Input() public validatorStrictMode: boolean = false;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Determines the actual input type to be used in the template.
|
|
71
|
+
* If the type is 'password', it toggles between 'text' and 'password'
|
|
72
|
+
* based on the showPassword property.
|
|
73
|
+
*
|
|
74
|
+
* @returns The input type as a string.
|
|
75
|
+
*/
|
|
76
|
+
public get inputType(): string {
|
|
77
|
+
return this.type;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Minimum hour based on minTime
|
|
82
|
+
*/
|
|
83
|
+
public get minHour(): number {
|
|
84
|
+
return Number(this.minTime.split(':')[0] || 0);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Maximum hour based on maxTime and format
|
|
89
|
+
*/
|
|
90
|
+
public get maxHour(): number {
|
|
91
|
+
return Number(this.maxTime.split(':')[0] || (this.format.includes('HH') ? 23 : 12));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Minimum minute allowed based on `minTime`
|
|
96
|
+
*/
|
|
97
|
+
public get minMinute(): number {
|
|
98
|
+
return Number(this.minTime.split(':')[1] || 0);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Maximum minute allowed based on `maxTime`
|
|
103
|
+
*/
|
|
104
|
+
public get maxMinute(): number {
|
|
105
|
+
return Number(this.maxTime.split(':')[1] || 59);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Minimum second allowed based on `minTime`
|
|
110
|
+
*/
|
|
111
|
+
public get minSecond(): number {
|
|
112
|
+
const parts = this.minTime.split(':');
|
|
113
|
+
return parts[2] ? Number(parts[2]) : 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Maximum second allowed based on `maxTime`
|
|
118
|
+
*/
|
|
119
|
+
public get maxSecond(): number {
|
|
120
|
+
const parts = this.maxTime.split(':');
|
|
121
|
+
return parts[2] ? Number(parts[2]) : 59;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Internal store for warnings */
|
|
125
|
+
private warnings: Record<string, boolean> = {};
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @inheritdoc
|
|
129
|
+
*/
|
|
130
|
+
public override ngOnInit(): void {
|
|
131
|
+
super.ngOnInit();
|
|
132
|
+
this.initPlaceholder();
|
|
133
|
+
this.initValidators();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public onKeydown(event: Event) {
|
|
137
|
+
if (event) {
|
|
138
|
+
event.preventDefault();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const checkbox = document.getElementById(this.id + '-meridiem') as HTMLInputElement;
|
|
142
|
+
if (!checkbox) return;
|
|
143
|
+
|
|
144
|
+
checkbox.checked = !checkbox.checked;
|
|
145
|
+
|
|
146
|
+
const fakeEvent = { target: checkbox } as unknown as Event;
|
|
147
|
+
this.onInput(fakeEvent);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @inheritdoc
|
|
152
|
+
*/
|
|
153
|
+
public override onBlur(event: FocusEvent): void {
|
|
154
|
+
const target = event.target as HTMLInputElement;
|
|
155
|
+
const partialTime = target.dataset['partialtime'] as InputTimePartial;
|
|
156
|
+
const inputValue = target.value.trim() || null;
|
|
157
|
+
|
|
158
|
+
this.value = inputValue ? this.mergePartialInput(partialTime, inputValue) : '';
|
|
159
|
+
this.validate(this.value);
|
|
160
|
+
this.updateInputsFromValue();
|
|
161
|
+
this.onTouched();
|
|
162
|
+
this.onChange(this.value);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @inheritdoc
|
|
167
|
+
*/
|
|
168
|
+
public override onInput(event: Event): void {
|
|
169
|
+
const target = event.target as HTMLInputElement;
|
|
170
|
+
const partialTime = target.dataset['partialtime'] as InputTimePartial;
|
|
171
|
+
|
|
172
|
+
let inputValue: string | null;
|
|
173
|
+
if (partialTime === 'meridiem') {
|
|
174
|
+
inputValue = target.checked ? 'PM' : 'AM';
|
|
175
|
+
} else {
|
|
176
|
+
inputValue = target.value.trim() || null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.value = this.mergePartialInput(partialTime, inputValue);
|
|
180
|
+
this.updateInputsFromValue();
|
|
181
|
+
this.onTouched();
|
|
182
|
+
this.onChange(this.value);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Decrements a specific part of the time (hour, minute, or second)
|
|
187
|
+
* and updates the input value accordingly.
|
|
188
|
+
*
|
|
189
|
+
* @param partialTime - The time part to decrement: 'hour', 'minute', or 'second'.
|
|
190
|
+
*/
|
|
191
|
+
protected decrease(partialTime: InputTimePartial): void {
|
|
192
|
+
const valueParts = this.parseValueToParts();
|
|
193
|
+
|
|
194
|
+
switch (partialTime) {
|
|
195
|
+
case 'hour':
|
|
196
|
+
valueParts.hour = this.decrementHour(valueParts.hour ?? this.minHour);
|
|
197
|
+
break;
|
|
198
|
+
case 'minute':
|
|
199
|
+
valueParts.minute = this.decrementMinute(valueParts.minute ?? this.minMinute);
|
|
200
|
+
break;
|
|
201
|
+
case 'second':
|
|
202
|
+
valueParts.second = this.decrementSecond(valueParts.second ?? this.minSecond);
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
this.value = this.formatPartsToTimeString(valueParts);
|
|
207
|
+
this.updateInputsFromValue();
|
|
208
|
+
this.onTouched();
|
|
209
|
+
this.onChange(this.value);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Format value for input display
|
|
214
|
+
* @param value Date value
|
|
215
|
+
* @returns Formatted time string
|
|
216
|
+
*/
|
|
217
|
+
protected formatTime(value: string | null, partialTime?: InputTimePartial): string {
|
|
218
|
+
if (value) {
|
|
219
|
+
return formatTimeToString(value, this.format, partialTime);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return '';
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Increments a specific part of the time (hour, minute, or second)
|
|
227
|
+
* and updates the input value accordingly.
|
|
228
|
+
*
|
|
229
|
+
* @param partialTime - The time part to increment: 'hour', 'minute', or 'second'.
|
|
230
|
+
*/
|
|
231
|
+
protected increase(partialTime: InputTimePartial): void {
|
|
232
|
+
const valueParts = this.parseValueToParts();
|
|
233
|
+
|
|
234
|
+
switch (partialTime) {
|
|
235
|
+
case 'hour':
|
|
236
|
+
valueParts.hour = this.incrementHour(valueParts.hour);
|
|
237
|
+
break;
|
|
238
|
+
case 'minute':
|
|
239
|
+
valueParts.minute = this.incrementMinute(valueParts.minute);
|
|
240
|
+
break;
|
|
241
|
+
case 'second':
|
|
242
|
+
valueParts.second = this.incrementSecond(valueParts.second);
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
this.value = this.formatPartsToTimeString(valueParts);
|
|
247
|
+
this.updateInputsFromValue();
|
|
248
|
+
this.onTouched();
|
|
249
|
+
this.onChange(this.value);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* @inheritdoc
|
|
254
|
+
*/
|
|
255
|
+
protected updateView(_value: string | null): void {
|
|
256
|
+
// Handled by Angular binding
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* @inheritdoc
|
|
261
|
+
*/
|
|
262
|
+
protected updateDisabledState(_isDisabled: boolean): void {
|
|
263
|
+
// Handled by Angular binding
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* @inheritdoc
|
|
268
|
+
*/
|
|
269
|
+
protected override get errorList(): string[] {
|
|
270
|
+
if (!this.control?.errors) return [];
|
|
271
|
+
|
|
272
|
+
const errors = this.control.errors;
|
|
273
|
+
return Object.keys(errors)
|
|
274
|
+
.filter(key => !key.startsWith('warning_'))
|
|
275
|
+
.map(key => {
|
|
276
|
+
if (this.errorMessages[key]) {
|
|
277
|
+
return this.errorMessages[key];
|
|
278
|
+
}
|
|
279
|
+
let template = this.errorMessages[key] || DEFAULT_INPUT_TIME_ERROR_MESSAGES[key] || 'Invalid field.';
|
|
280
|
+
|
|
281
|
+
switch (key) {
|
|
282
|
+
case 'min':
|
|
283
|
+
template = template.replace('{{time}}', formatTimeToString(this.minTime, this.format));
|
|
284
|
+
break;
|
|
285
|
+
case 'max':
|
|
286
|
+
template = template.replace('{{time}}', formatTimeToString(this.maxTime, this.format));
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return template;
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Returns dynamic warning messages, replacing {{limit}} with actual values.
|
|
296
|
+
*/
|
|
297
|
+
protected override get warningList(): string[] {
|
|
298
|
+
return Object.keys(this.warnings).map(key => {
|
|
299
|
+
const template = DEFAULT_INPUT_TIME_WARNINGS_MESSAGES[key] || 'Check this value.';
|
|
300
|
+
|
|
301
|
+
let replacement: string | undefined;
|
|
302
|
+
|
|
303
|
+
switch (key) {
|
|
304
|
+
case 'format':
|
|
305
|
+
replacement = this.format;
|
|
306
|
+
break;
|
|
307
|
+
case 'min':
|
|
308
|
+
replacement = formatTimeToString(this.minTime, this.format);
|
|
309
|
+
break;
|
|
310
|
+
case 'max':
|
|
311
|
+
replacement = formatTimeToString(this.maxTime, this.format);
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (replacement != null) {
|
|
316
|
+
const placeholder = key === 'format' ? '{{format}}' : '{{limit}}';
|
|
317
|
+
return template.replace(placeholder, replacement.toString());
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return template;
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Returns whether any warnings are active.
|
|
326
|
+
*/
|
|
327
|
+
protected get hasWarning(): boolean {
|
|
328
|
+
return this.warningList.length > 0;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Adds a warning flag
|
|
333
|
+
* @param key Warning key
|
|
334
|
+
*/
|
|
335
|
+
private addWarning(key: string): void {
|
|
336
|
+
this.warnings[key] = true;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Builds a formatted time string from the given time parts.
|
|
341
|
+
* - Undefined numeric parts are represented as "undefined".
|
|
342
|
+
* - Meridiem is always included if the format includes 'a'.
|
|
343
|
+
*
|
|
344
|
+
* @param parts Object containing hour, minute, second, and optional meridiem
|
|
345
|
+
* @returns Formatted time string according to the current format
|
|
346
|
+
*/
|
|
347
|
+
private formatPartsToTimeString(parts: InputTimeParts): string {
|
|
348
|
+
const segments: string[] = [];
|
|
349
|
+
|
|
350
|
+
if (this.format.includes('HH') || this.format.includes('hh')) {
|
|
351
|
+
segments.push(parts.hour !== undefined ? String(parts.hour).padStart(2, '0') : 'undefined');
|
|
352
|
+
}
|
|
353
|
+
if (this.format.includes('mm')) {
|
|
354
|
+
segments.push(parts.minute !== undefined ? String(parts.minute).padStart(2, '0') : 'undefined');
|
|
355
|
+
}
|
|
356
|
+
if (this.format.includes('ss')) {
|
|
357
|
+
segments.push(parts.second !== undefined ? String(parts.second).padStart(2, '0') : 'undefined');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const timeString = segments.join(':');
|
|
361
|
+
|
|
362
|
+
if (this.format.includes('a')) {
|
|
363
|
+
const meridiem = parts.meridiem || 'AM';
|
|
364
|
+
return `${timeString} ${meridiem}`;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return timeString;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Clamps a numeric value between a minimum and maximum.
|
|
372
|
+
* @param value The number to clamp.
|
|
373
|
+
* @param min Minimum allowed value.
|
|
374
|
+
* @param max Maximum allowed value.
|
|
375
|
+
* @returns The clamped number, or undefined if input was undefined.
|
|
376
|
+
*/
|
|
377
|
+
private clamp(value: number | undefined, min: number, max: number): number | undefined {
|
|
378
|
+
if (value === undefined) return undefined;
|
|
379
|
+
return Math.max(min, Math.min(max, value));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Decrement hour based on format (12h or 24h)
|
|
384
|
+
* @param hour Current hour
|
|
385
|
+
* @returns Decremented hour
|
|
386
|
+
*/
|
|
387
|
+
private decrementHour(hour: number): number {
|
|
388
|
+
if (this.format.includes('a')) {
|
|
389
|
+
hour--;
|
|
390
|
+
if (hour < 1) {
|
|
391
|
+
hour = 12;
|
|
392
|
+
this.toggleMeridiem();
|
|
393
|
+
}
|
|
394
|
+
return hour;
|
|
395
|
+
} else {
|
|
396
|
+
hour--;
|
|
397
|
+
if (hour < this.minHour) return this.maxHour;
|
|
398
|
+
return hour;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Decrement minute with wrapping
|
|
404
|
+
* @param minute Current minute
|
|
405
|
+
* @returns Decremented minute
|
|
406
|
+
*/
|
|
407
|
+
private decrementMinute(minute: number): number {
|
|
408
|
+
minute--;
|
|
409
|
+
if (minute < this.minMinute) return this.maxMinute;
|
|
410
|
+
return minute;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Decrement second with wrapping
|
|
415
|
+
* @param second Current second
|
|
416
|
+
* @returns Decremented second
|
|
417
|
+
*/
|
|
418
|
+
private decrementSecond(second: number): number {
|
|
419
|
+
second--;
|
|
420
|
+
if (second < this.minSecond) return this.maxSecond;
|
|
421
|
+
return second;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Returns the current time parts extracted from the component's value.
|
|
426
|
+
* Numeric parts are converted to numbers; meridiem defaults to 'AM' if format includes 'a'.
|
|
427
|
+
* @returns An object containing hour, minute, second, and meridiem (if applicable).
|
|
428
|
+
*/
|
|
429
|
+
private getCurrentParts(): InputTimeParts {
|
|
430
|
+
return {
|
|
431
|
+
hour: this.parseNumberOrUndefined(this.formatTime(this.value, 'hour')),
|
|
432
|
+
minute: this.parseNumberOrUndefined(this.formatTime(this.value, 'minute')),
|
|
433
|
+
second: this.parseNumberOrUndefined(this.formatTime(this.value, 'second')),
|
|
434
|
+
meridiem: this.format.includes('a')
|
|
435
|
+
? ((this.formatTime(this.value, 'meridiem') as InputTimeMeridiem) || 'AM')
|
|
436
|
+
: undefined,
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Initialize the placeholder based on the time format
|
|
442
|
+
*/
|
|
443
|
+
private initPlaceholder() {
|
|
444
|
+
this.placeholder = 'HH:mm';
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Increment hour based on format (12h or 24h)
|
|
449
|
+
* @param hour Current hour
|
|
450
|
+
* @returns Incremented hour
|
|
451
|
+
*/
|
|
452
|
+
private incrementHour(hour: number | undefined): number {
|
|
453
|
+
if (hour === undefined) {
|
|
454
|
+
return Number(this.format.includes('a'));
|
|
455
|
+
}
|
|
456
|
+
if (this.format.includes('a')) {
|
|
457
|
+
hour++;
|
|
458
|
+
if (hour > 12) {
|
|
459
|
+
hour = 1;
|
|
460
|
+
this.toggleMeridiem();
|
|
461
|
+
}
|
|
462
|
+
return hour;
|
|
463
|
+
} else {
|
|
464
|
+
hour++;
|
|
465
|
+
if (hour > this.maxHour) return this.minHour;
|
|
466
|
+
return hour;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Increment minute with wrapping
|
|
472
|
+
* @param minute Current minute
|
|
473
|
+
* @returns Incremented minute
|
|
474
|
+
*/
|
|
475
|
+
private incrementMinute(minute: number | undefined): number {
|
|
476
|
+
if (minute === undefined) {
|
|
477
|
+
return 0;
|
|
478
|
+
}
|
|
479
|
+
minute++;
|
|
480
|
+
if (minute > this.maxMinute) return this.minMinute;
|
|
481
|
+
return minute;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Increment second with wrapping
|
|
486
|
+
* @param second Current second
|
|
487
|
+
* @returns Incremented second
|
|
488
|
+
*/
|
|
489
|
+
private incrementSecond(second: number | undefined): number {
|
|
490
|
+
if (second === undefined) {
|
|
491
|
+
return 0;
|
|
492
|
+
}
|
|
493
|
+
second++;
|
|
494
|
+
if (second > this.maxSecond) return this.minSecond;
|
|
495
|
+
return second;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Initialize validators based on inputs
|
|
500
|
+
*/
|
|
501
|
+
private initValidators(): void {
|
|
502
|
+
if (this.control) {
|
|
503
|
+
const validators = [];
|
|
504
|
+
|
|
505
|
+
if (this.required) {
|
|
506
|
+
validators.push(Validators.required);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (this.minTime) {
|
|
510
|
+
validators.push(minTime(this.minTime));
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (this.maxTime) {
|
|
514
|
+
validators.push(maxTime(this.maxTime));
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
this.control.setValidators(validators);
|
|
518
|
+
this.control.updateValueAndValidity();
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Merges a partial time input into the current value and returns the resulting full time string.
|
|
524
|
+
* @param partial The time part being updated ('hour', 'minute', 'second', 'meridiem').
|
|
525
|
+
* @param partialValue The new value for the specified part.
|
|
526
|
+
* @returns The merged full time string.
|
|
527
|
+
*/
|
|
528
|
+
private mergePartialInput(partial: InputTimePartial, partialValue: string | null): string {
|
|
529
|
+
const parts = this.getCurrentParts();
|
|
530
|
+
this.setPartialValue(parts, partial, partialValue);
|
|
531
|
+
return this.formatPartsToTimeString(parts);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Converts a string to a number or returns undefined if the value is invalid.
|
|
536
|
+
* @param value The string to parse.
|
|
537
|
+
* @returns The number value, or undefined if input is null, 'undefined', or NaN.
|
|
538
|
+
*/
|
|
539
|
+
private parseNumberOrUndefined(value: string | null): number | undefined {
|
|
540
|
+
if (!value || value === 'undefined') return undefined;
|
|
541
|
+
const n = Number(value);
|
|
542
|
+
return isNaN(n) ? undefined : n;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Parse the current value to its components
|
|
547
|
+
* @returns An object containing hour, minute, second, and meridiem (if applicable)
|
|
548
|
+
*/
|
|
549
|
+
private parseValueToParts(): InputTimeParts {
|
|
550
|
+
const result: InputTimeParts = {};
|
|
551
|
+
if (!this.value) return result;
|
|
552
|
+
|
|
553
|
+
let coreValue = this.value.trim();
|
|
554
|
+
let meridiem: InputTimeMeridiem | undefined;
|
|
555
|
+
|
|
556
|
+
const meridiemMatch = /\s?(AM|PM)$/i.exec(coreValue);
|
|
557
|
+
if (meridiemMatch) {
|
|
558
|
+
meridiem = meridiemMatch[1].toUpperCase() as InputTimeMeridiem;
|
|
559
|
+
coreValue = coreValue.replace(/\s?(AM|PM)$/i, '').trim();
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
const segments = coreValue.split(':').map(s => (s === 'undefined' ? undefined : s));
|
|
563
|
+
|
|
564
|
+
const tokenMap: [string, keyof InputTimeParts][] = [
|
|
565
|
+
['HH', 'hour'],
|
|
566
|
+
['hh', 'hour'],
|
|
567
|
+
['mm', 'minute'],
|
|
568
|
+
['ss', 'second'],
|
|
569
|
+
];
|
|
570
|
+
|
|
571
|
+
let index = 0;
|
|
572
|
+
for (const [token, key] of tokenMap) {
|
|
573
|
+
if (this.format.includes(token)) {
|
|
574
|
+
const segment = segments[index++];
|
|
575
|
+
result[key as 'hour' | 'minute' | 'second'] =
|
|
576
|
+
segment !== undefined ? Number(segment) : undefined;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if (this.format.includes('a')) {
|
|
581
|
+
result.meridiem = meridiem;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return result;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Updates a specific part of a time parts object with a new partial value and clamps numeric values.
|
|
589
|
+
* @param parts The time parts object to update.
|
|
590
|
+
* @param partial The part to update ('hour', 'minute', 'second', 'meridiem').
|
|
591
|
+
* @param partialValue The new value for the part.
|
|
592
|
+
*/
|
|
593
|
+
private setPartialValue(parts: InputTimeParts, partial: InputTimePartial, partialValue: string | null): void {
|
|
594
|
+
switch (partial) {
|
|
595
|
+
case 'hour':
|
|
596
|
+
parts.hour = partialValue !== null ? Number(partialValue) : undefined;
|
|
597
|
+
break;
|
|
598
|
+
case 'minute':
|
|
599
|
+
parts.minute = partialValue !== null ? Number(partialValue) : 0;
|
|
600
|
+
break;
|
|
601
|
+
case 'second':
|
|
602
|
+
parts.second = partialValue !== null ? Number(partialValue) : 0;
|
|
603
|
+
break;
|
|
604
|
+
case 'meridiem':
|
|
605
|
+
parts.meridiem = partialValue === 'AM' || partialValue === 'PM' ? partialValue : 'AM';
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
parts.hour = this.clamp(parts.hour, this.minHour, this.maxHour);
|
|
610
|
+
parts.minute = this.clamp(parts.minute, this.minMinute, this.maxMinute);
|
|
611
|
+
parts.second = this.clamp(parts.second, this.minSecond, this.maxSecond);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Toggle the meridiem (AM/PM) in the current value
|
|
616
|
+
* This is used when incrementing hours in 12-hour format.
|
|
617
|
+
*/
|
|
618
|
+
private toggleMeridiem(): void {
|
|
619
|
+
if (!this.value) return;
|
|
620
|
+
const parts = this.value.split(' ');
|
|
621
|
+
if (parts[1] === 'AM') parts[1] = 'PM';
|
|
622
|
+
else parts[1] = 'AM';
|
|
623
|
+
this.value = parts.join(' ');
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Update individual input fields based on the current full time value
|
|
628
|
+
* This ensures that each part (hour, minute, second, meridiem) reflects the current value
|
|
629
|
+
* and is properly formatted.
|
|
630
|
+
*/
|
|
631
|
+
private updateInputsFromValue(): void {
|
|
632
|
+
const hoursInput = document.getElementById(this.id + '-hour') as HTMLInputElement;
|
|
633
|
+
const minutesInput = document.getElementById(this.id + '-minute') as HTMLInputElement;
|
|
634
|
+
const secondsInput = document.getElementById(this.id + '-second') as HTMLInputElement;
|
|
635
|
+
const meridiemInput = document.getElementById(this.id + '-meridiem') as HTMLInputElement;
|
|
636
|
+
|
|
637
|
+
const safeValue = (part: InputTimePartial): string => {
|
|
638
|
+
const formatted = this.formatTime(this.value, part);
|
|
639
|
+
return formatted && !['HH', 'mm', 'ss'].includes(formatted) ? formatted : '';
|
|
640
|
+
};
|
|
641
|
+
|
|
642
|
+
if (hoursInput) hoursInput.value = safeValue('hour');
|
|
643
|
+
if (minutesInput) minutesInput.value = safeValue('minute');
|
|
644
|
+
if (secondsInput) secondsInput.value = safeValue('second');
|
|
645
|
+
if (meridiemInput) meridiemInput.value = safeValue('meridiem');
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Validate the input value against the specified format
|
|
650
|
+
* @param value Input value
|
|
651
|
+
*/
|
|
652
|
+
private validate(value: string): void {
|
|
653
|
+
this.removeWarning('format');
|
|
654
|
+
this.removeWarning('min');
|
|
655
|
+
this.removeWarning('max');
|
|
656
|
+
|
|
657
|
+
if (!value) return;
|
|
658
|
+
|
|
659
|
+
if (this.format) {
|
|
660
|
+
const regex = buildTimeFormatRegex(this.format);
|
|
661
|
+
if (!regex.test(value)) {
|
|
662
|
+
this.addWarning('format');
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const valueSeconds = convertStringToTime(value, this.format);
|
|
668
|
+
if (valueSeconds === null) {
|
|
669
|
+
this.addWarning('invalidFormat');
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const minSeconds = this.minTime ? convertStringToTime(this.minTime, this.format) : null;
|
|
674
|
+
const maxSeconds = this.maxTime ? convertStringToTime(this.maxTime, this.format) : null;
|
|
675
|
+
|
|
676
|
+
if (minSeconds !== null && valueSeconds < minSeconds) {
|
|
677
|
+
this.addWarning('min');
|
|
678
|
+
}
|
|
679
|
+
if (maxSeconds !== null && valueSeconds > maxSeconds) {
|
|
680
|
+
this.addWarning('max');
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Remove a warning flag
|
|
686
|
+
* @param key Warning key
|
|
687
|
+
*/
|
|
688
|
+
private removeWarning(key: string): void {
|
|
689
|
+
delete this.warnings[key];
|
|
690
|
+
}
|
|
691
|
+
}
|